class Gearman::Connection

Constants

HEADER_FORMAT
HEADER_SIZE
IncompleteReadError
IncompleteWriteError
NULL_BYTE
NoConnectionError
REQ
ServerError
UnexpectedPacketError

Public Class Methods

new(address) click to toggle source
# File lib/gearman/connection.rb, line 24
def initialize(address)
  @address = address
  @repository = Packet::Repository.new
  @socket = nil
end

Public Instance Methods

disconnect() click to toggle source
# File lib/gearman/connection.rb, line 72
def disconnect
  if @socket
    @socket.close unless @socket.closed?
    @socket = nil
  end
end
next(*expected_packet_types) click to toggle source
# File lib/gearman/connection.rb, line 50
def next(*expected_packet_types)
  connect if disconnected?

  header = read(HEADER_SIZE)
  magic, type, length = header.unpack(HEADER_FORMAT)

  body = read(length)
  arguments = String(body).split(NULL_BYTE)

  @repository.load(type).new(arguments).tap do |packet|
    debug "Read #{packet.inspect}"

    if packet.is_a?(Packet::ERROR)
      message = "server sent error #{packet.error_code}: #{packet.text}"

      raise ServerError, message
    end

    verify packet, expected_packet_types
  end
end
write(packet) click to toggle source
# File lib/gearman/connection.rb, line 30
def write(packet)
  connect if disconnected?

  body = packet.arguments.join(NULL_BYTE)
  header = [REQ, packet.number, body.size].pack(HEADER_FORMAT)

  serialized_packet = header + body

  length_written = @socket.write(serialized_packet)

  debug "Wrote #{packet.inspect}"

  if length_written != serialized_packet.length
    lengths = [serialized_packet.length, lengths]
    message = "expected to write %d bytes, but only read %d" % lengths

    raise IncompleteWriteError, message
  end
end

Private Instance Methods

connect() click to toggle source
# File lib/gearman/connection.rb, line 98
def connect
  begin
    @socket = TCPSocket.new(@address.host, @address.port)

    info "Connected"
  rescue => error
    raise NoConnectionError.new("could not connect to #{@address}", error)
  end
end
debug(note) click to toggle source
# File lib/gearman/connection.rb, line 123
def debug(note)
  Celluloid.logger.debug "#{@address}: #{note}"
end
disconnected?() click to toggle source
# File lib/gearman/connection.rb, line 108
def disconnected?
  @socket.nil?
end
info(note) click to toggle source
# File lib/gearman/connection.rb, line 127
def info(note)
  Celluloid.logger.info "#{@address}: #{note}"
end
read(length) click to toggle source
# File lib/gearman/connection.rb, line 81
def read(length)
  return unless length > 0

  data = @socket.read(length)

  if data.nil?
    raise NoConnectionError, "lost connection to #{@address}"
  elsif data.length != length
    lengths = [length, data.length]
    message = "expected to read %d bytes, but only read %d" % lengths

    raise IncompleteReadError, message
  else
    data
  end
end
verify(packet, valid_packet_types) click to toggle source
# File lib/gearman/connection.rb, line 112
def verify(packet, valid_packet_types)
  return if valid_packet_types.empty?

  unless valid_packet_types.include?(packet.class)
    valid_type = valid_packet_types.join(' or ')
    message = "expected #{packet} to be a #{valid_type}"

    raise UnexpectedPacketError, message
  end
end