class Redis::Client

def call(*args)

def call(*args)
  process(args) do
    read
  end
end

def call_loop(*args)

def call_loop(*args)
  without_socket_timeout do
    process(args) do
      loop { yield(read) }
    end
  end
end

def call_pipelined(commands)

def call_pipelined(commands)
  process(*commands) do
    Array.new(commands.size) { read }
  end
end

def call_without_timeout(*args)

def call_without_timeout(*args)
  without_socket_timeout do
    call(*args)
  end
rescue Errno::ECONNRESET
  retry
end

def connect

def connect
  connect_to(@host, @port)
  call(:auth, @password) if @password
  call(:select, @db) if @db != 0
  self
end

def connect_to(host, port)

def connect_to(host, port)
  with_timeout(@timeout) do
    connection.connect(host, port)
  end
  # If the timeout is set we set the low level socket options in order
  # to make sure a blocking read will return after the specified number
  # of seconds. This hack is from memcached ruby client.
  self.timeout = @timeout
rescue Errno::ECONNREFUSED
  raise Errno::ECONNREFUSED, "Unable to connect to Redis on #{host}:#{port}"
end

def connected?

def connected?
  connection.connected?
end

def deprecated(old, new = nil, trace = caller[0])

def deprecated(old, new = nil, trace = caller[0])
  message = "The method #{old} is deprecated and will be removed in 2.0"
  message << " - use #{new} instead" if new
  Redis.deprecate(message, trace)
end

def disconnect

def disconnect
  connection.disconnect if connection.connected?
end

def ensure_connected

def ensure_connected
  connect unless connected?
  begin
    yield
  rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED, Errno::EBADF
    if reconnect
      yield
    else
      raise Errno::ECONNRESET
    end
  rescue Exception
    disconnect
    raise
  end
end

def id

def id
  "redis://#{host}:#{port}/#{db}"
end

def initialize(options = {})

def initialize(options = {})
  @host = options[:host] || "127.0.0.1"
  @port = (options[:port] || 6379).to_i
  @db = (options[:db] || 0).to_i
  @timeout = (options[:timeout] || 5).to_i
  @password = options[:password]
  @logger = options[:logger]
  @connection = Connection.new
end

def logging(commands)

def logging(commands)
  return yield unless @logger && @logger.debug?
  begin
    commands.each do |name, *args|
      @logger.debug("Redis >> #{name.to_s.upcase} #{args.join(" ")}")
    end
    t1 = Time.now
    yield
  ensure
    @logger.debug("Redis >> %0.2fms" % ((Time.now - t1) * 1000))
  end
end

def process(*commands)

def process(*commands)
  logging(commands) do
    ensure_connected do
      commands.each do |command|
        connection.write(command)
      end
      yield if block_given?
    end
  end
end

def read

def read
  begin
    connection.read
  rescue Errno::EAGAIN
    # We want to make sure it reconnects on the next command after the
    # timeout. Otherwise the server may reply in the meantime leaving
    # the protocol in a desync status.
    disconnect
    raise Errno::EAGAIN, "Timeout reading from the socket"
  rescue Errno::ECONNRESET
    raise Errno::ECONNRESET, "Connection lost"
  end
end

def reconnect

def reconnect
  disconnect
  connect
end

def timeout=(timeout)

def timeout=(timeout)
  connection.timeout = Integer(timeout * 1_000_000)
end

def with_timeout(seconds, &block)

def with_timeout(seconds, &block)
  SystemTimer.timeout_after(seconds, &block)
end

def with_timeout(seconds, &block)

def with_timeout(seconds, &block)
  Timeout.timeout(seconds, &block)
end

def without_socket_timeout

def without_socket_timeout
  connect unless connected?
  begin
    self.timeout = 0
    yield
  ensure
    self.timeout = @timeout if connected?
  end
end