class Roby::DRoby::Logfile::Client

The client part of the event log distribution service

Attributes

buffer[R]

Data that is not a full cycle worth of data (i.e. buffer needed for packet reassembly)

host[R]

The host we are contacting

init_size[R]

The number of bytes that have to be transferred to finish initializing the connection

port[R]

The port on which a connection is created

rx[R]

The amount of bytes received so far

socket[R]

The socket through which we are connected to the remote host

Public Class Methods

new(host, port = Server::DEFAULT_PORT) click to toggle source
# 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

add_listener(&block) click to toggle source
# File lib/roby/droby/logfile/client.rb, line 80
def add_listener(&block)
    on_data(&block)
end
alive?() click to toggle source
# File lib/roby/droby/logfile/client.rb, line 84
def alive?
    @alive
end
close() click to toggle source
# File lib/roby/droby/logfile/client.rb, line 72
def close
    @socket.close
end
closed?() click to toggle source
# File lib/roby/droby/logfile/client.rb, line 76
def closed?
    @socket.closed?
end
disconnect() click to toggle source
# File lib/roby/droby/logfile/client.rb, line 68
def disconnect
    @socket.close
end
init_done?() click to toggle source
# File lib/roby/droby/logfile/client.rb, line 108
def init_done?
    @init_done
end
read_and_process_one_pending_cycle() click to toggle source

@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_pending(max: 0) click to toggle source

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
read_from_socket(size = Server::DATA_CHUNK_SIZE) click to toggle source

@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