class Roby::DRoby::Logfile::Client
The client part of the event log distribution service
Attributes
Data that is not a full cycle worth of data (i.e. buffer needed for packet reassembly)
The host we are contacting
The number of bytes that have to be transferred to finish initializing the connection
The port on which a connection is created
The amount of bytes received so far
The socket through which we are connected to the remote host
Public Class Methods
# File lib/roby/droby/logfile/client.rb, line 50 def initialize(host, port = Server::DEFAULT_PORT) @host = host @port = port @buffer = "" @rx = 0 @socket = begin TCPSocket.new(host, port) rescue Errno::ECONNREFUSED => e raise Interface::ConnectionError, "cannot contact Roby log server at '#{host}:#{port}': #{e.message}" end socket.fcntl(Fcntl::FD_CLOEXEC, 1) socket.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK) rescue Exception socket.close if socket raise end
Public Instance Methods
# File lib/roby/droby/logfile/client.rb, line 80 def add_listener(&block) on_data(&block) end
# File lib/roby/droby/logfile/client.rb, line 84 def alive? @alive end
# File lib/roby/droby/logfile/client.rb, line 72 def close @socket.close end
# File lib/roby/droby/logfile/client.rb, line 76 def closed? @socket.closed? end
# File lib/roby/droby/logfile/client.rb, line 68 def disconnect @socket.close end
# File lib/roby/droby/logfile/client.rb, line 108 def init_done? @init_done end
@api private
Reads the socket and processes at most one cycle of data
@return [Boolean] whether there might be one more cyc
# File lib/roby/droby/logfile/client.rb, line 131 def read_and_process_one_pending_cycle Logfile.debug "#{buffer.size} bytes of data in buffer" while true if buffer.size > 4 data_size = buffer.unpack('L<').first Logfile.debug "expecting data block of #{data_size} bytes" if buffer.size >= data_size + 4 break end return if !read_from_socket([Server::DATA_CHUNK_SIZE, buffer.size - data_size].max) else return if !read_from_socket end end if data_size && (buffer.size >= data_size + 4) cycle_data = buffer[4, data_size] @buffer = buffer[(data_size + 4)..-1] data = ::Marshal.load_with_missing_constants(cycle_data) if data.kind_of?(Hash) Reader.process_options_hash(data) elsif data == Server::CONNECTION_INIT_DONE @init_done = true run_hook :on_init_done elsif data[0] == Server::CONNECTION_INIT @init_size = data[1] else @rx += (data_size + 4) if !init_done? run_hook :on_init_progress, rx, init_size end run_hook :on_data, data end Logfile.debug "processed #{data_size} bytes of data, #{@buffer.size} remaining in buffer" true end rescue Errno::EAGAIN end
Read and process data
@param [Numeric] max max time we can spend processing. The method
will at least process one cycle worth of data regardless of this parameter
@return [Boolean] true if the last call processed something and
false otherwise. It is an indicator of whether there could be still some data pending
# File lib/roby/droby/logfile/client.rb, line 96 def read_and_process_pending(max: 0) current_time = start = Time.now while (processed_one_cycle = read_and_process_one_pending_cycle) && (current_time - start) <= max current_time = Time.now end processed_one_cycle end
@api private
Read data from the underlying socket
@return [Boolean] true if some data was read, false otherwise
# File lib/roby/droby/logfile/client.rb, line 117 def read_from_socket(size = Server::DATA_CHUNK_SIZE) @buffer.concat(socket.read_nonblock(size)) true rescue EOFError, Errno::ECONNRESET, Errno::EPIPE => e raise Interface::ComError, e.message, e.backtrace rescue Errno::EAGAIN false end