class Einhorn::Event::AbstractTextDescriptor

Attributes

client_id[R]
read_buffer[RW]
write_buffer[RW]

Public Class Methods

new(sock) click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 12
def initialize(sock)
  @@instance_counter += 1

  @socket = sock
  @client_id = "#{@@instance_counter}:#{sock.fileno}"

  @read_buffer = ""
  @write_buffer = ""

  @closed = false

  register!
end
open(sock) click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 8
def self.open(sock)
  self.new(sock)
end

Public Instance Methods

close() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 26
def close
  @closed = true
  deregister!
  @socket.close
end
consume_record(record) click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 123
def consume_record(record)
  raise NotImplementedError.new
end
deregister!() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 99
def deregister!
  Einhorn::Event.deregister_readable(self)
  Einhorn::Event.deregister_writeable(self)
end
log_debug(msg) click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 127
def log_debug(msg)
  Einhorn.log_debug("[client #{client_id}] #{msg}")
end
log_error(msg) click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 135
def log_error(msg)
  Einhorn.log_error("[client #{client_id}] #{msg}")
end
log_info(msg) click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 131
def log_info(msg)
  Einhorn.log_info("[client #{client_id}] #{msg}")
end
notify_readable() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 42
def notify_readable
  while true
    begin
      return if @closed
      chunk = @socket.read_nonblock(1024)
    rescue Errno::EAGAIN
      break
    rescue EOFError, Errno::EPIPE, Errno::ECONNRESET
      close
      break
    rescue StandardError => e
      log_error("Caught unrecognized error while reading from socket: #{e} (#{e.class})")
      close
      break
    else
      log_debug("read #{chunk.length} bytes (#{chunk.inspect[0..20]})")
      @read_buffer << chunk
      process_read_buffer
    end
  end
end
notify_writeable() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 74
def notify_writeable
  begin
    return if @closed
    written = @socket.write_nonblock(@write_buffer)
  rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
  rescue Errno::EPIPE, Errno::ECONNRESET
    close
  rescue StandardError => e
    log_error("Caught unrecognized error while writing to socket: #{e} (#{e.class})")
    close
  else
    log_debug("wrote #{written} bytes")
    @write_buffer = @write_buffer[written..-1]
  end
end
parse_record() click to toggle source

Override in subclass. This lets you do streaming reads.

# File lib/einhorn/event/abstract_text_descriptor.rb, line 119
def parse_record
  [@read_buffer, '']
end
process_read_buffer() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 104
def process_read_buffer
  while true
    if @read_buffer.length > 0
      break unless split = parse_record
      record, remainder = split
      log_debug("Read a record of #{record.length} bytes.")
      @read_buffer = remainder
      consume_record(record)
    else
      break
    end
  end
end
read(&blk) click to toggle source

API method

# File lib/einhorn/event/abstract_text_descriptor.rb, line 33
def read(&blk)
  raise "Already registered a read block" if @read_blk
  raise "No block provided" unless blk
  raise "Must provide a block that accepts two arguments" unless blk.arity == 2

  @read_blk = blk
  notify_readable # Read what you can
end
register!() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 94
def register!
  Einhorn::Event.register_readable(self)
  Einhorn::Event.register_writeable(self)
end
to_io() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 90
def to_io
  @socket
end
write(data) click to toggle source

API method

# File lib/einhorn/event/abstract_text_descriptor.rb, line 65
def write(data)
  @write_buffer << data
  notify_writeable # Write what you can
end
write_pending?() click to toggle source
# File lib/einhorn/event/abstract_text_descriptor.rb, line 70
def write_pending?
  @write_buffer.length > 0
end