module Ethon::Multi::Operations

This module contains logic to run a multi.

Public Instance Methods

handle() click to toggle source

Return the multi handle. Inititialize multi handle, in case it didn't happened already.

@example Return multi handle.

multi.handle

@return [ FFI::Pointer ] The multi handle.

# File lib/ethon/multi/operations.rb, line 14
def handle
  @handle ||= Curl.multi_init
end
init_vars() click to toggle source

Initialize variables.

@example Initialize variables.

multi.init_vars

@return [ void ]

# File lib/ethon/multi/operations.rb, line 24
def init_vars
  @timeout = ::FFI::MemoryPointer.new(:long)
  @timeval = Curl::Timeval.new
  @fd_read = Curl::FDSet.new
  @fd_write = Curl::FDSet.new
  @fd_excep = Curl::FDSet.new
  @max_fd = ::FFI::MemoryPointer.new(:int)
end
perform() click to toggle source

Perform multi.

@return [ nil ]

@example Perform multi.

multi.perform
# File lib/ethon/multi/operations.rb, line 39
def perform
  Ethon.logger.debug("ETHON: started MULTI")
  while ongoing?
    run
    timeout = get_timeout
    next if timeout == 0
    reset_fds
    set_fds(timeout)
  end
  Ethon.logger.debug("ETHON: performed MULTI")
  nil
end
prepare() click to toggle source

Prepare multi.

@return [ nil ]

@example Prepare multi.

multi.prepare

@deprecated It is no longer necessary to call prepare.

# File lib/ethon/multi/operations.rb, line 60
def prepare
  Ethon.logger.warn(
    "ETHON: It is no longer necessay to call "+
    "Multi#prepare. Its going to be removed "+
    "in future versions."
  )
end

Private Instance Methods

check() click to toggle source

Check.

@example Check.

multi.check

@return [ void ]

# File lib/ethon/multi/operations.rb, line 137
def check
  msgs_left = ::FFI::MemoryPointer.new(:int)
  while true
    msg = Curl.multi_info_read(handle, msgs_left)
    break if msg.null?
    next if msg[:code] != :done
    easy = easy_handles.find{ |e| e.handle == msg[:easy_handle] }
    easy.return_code = msg[:data][:code]
    Ethon.logger.debug("ETHON:         performed #{easy.log_inspect}")
    delete(easy)
    easy.complete
  end
end
get_timeout() click to toggle source

Get timeout.

@example Get timeout.

multi.get_timeout

@return [ Integer ] The timeout.

@raise [ Ethon::Errors::MultiTimeout ] If getting the timeout fails.

# File lib/ethon/multi/operations.rb, line 88
def get_timeout
  code = Curl.multi_timeout(handle, @timeout)
  raise Errors::MultiTimeout.new(code) unless code == :ok
  timeout = @timeout.read_long
  timeout = 1 if timeout < 0
  timeout
end
ongoing?() click to toggle source

Return wether the multi still requests or not.

@example Return if ongoing.

multi.ongoing?

@return [ Boolean ] True if ongoing, else false.

# File lib/ethon/multi/operations.rb, line 76
def ongoing?
  easy_handles.size > 0 || (!defined?(@running_count) || running_count > 0)
end
reset_fds() click to toggle source

Reset file describtors.

@example Reset fds.

multi.reset_fds

@return [ void ]

# File lib/ethon/multi/operations.rb, line 102
def reset_fds
  @fd_read.clear
  @fd_write.clear
  @fd_excep.clear
end
run() click to toggle source

Run.

@example Run

multi.run

@return [ void ]

# File lib/ethon/multi/operations.rb, line 157
def run
  begin code = trigger end while code == :call_multi_perform
  check
end
running_count() click to toggle source

Return number of running requests.

@example Return count.

multi.running_count

@return [ Integer ] Number running requests.

# File lib/ethon/multi/operations.rb, line 181
def running_count
  @running_count ||= nil
end
set_fds(timeout) click to toggle source

Set fds.

@example Set fds.

multi.set_fds

@return [ void ]

@raise [ Ethon::Errors::MultiFdset ] If setting the file descriptors fails. @raise [ Ethon::Errors::Select ] If select fails.

# File lib/ethon/multi/operations.rb, line 117
def set_fds(timeout)
  code = Curl.multi_fdset(handle, @fd_read, @fd_write, @fd_excep, @max_fd)
  raise Errors::MultiFdset.new(code) unless code == :ok
  max_fd = @max_fd.read_int
  if max_fd == -1
    sleep(0.001)
  else
    @timeval[:sec] = timeout / 1000
    @timeval[:usec] = (timeout * 1000) % 1000000
    code = Curl.select(max_fd + 1, @fd_read, @fd_write, @fd_excep, @timeval)
    raise Errors::Select.new(::FFI.errno) if code < 0
  end
end
trigger() click to toggle source

Trigger.

@example Trigger.

multi.trigger

@return [ Symbol ] The Curl.multi_perform return code.

# File lib/ethon/multi/operations.rb, line 168
def trigger
  running_count = FFI::MemoryPointer.new(:int)
  code = Curl.multi_perform(handle, running_count)
  @running_count = running_count.read_int
  code
end