X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/d90b352ded98b79fdddca6e057445237531835f3..69664139b5a57d08b2a17f624d5e9940761c9a3f:/client-libraries/ruby_2/rubyredis.rb diff --git a/client-libraries/ruby_2/rubyredis.rb b/client-libraries/ruby_2/rubyredis.rb deleted file mode 100644 index ca73d817..00000000 --- a/client-libraries/ruby_2/rubyredis.rb +++ /dev/null @@ -1,238 +0,0 @@ -# RubyRedis is an alternative implementatin of Ruby client library written -# by Salvatore Sanfilippo. -# -# The aim of this library is to create an alternative client library that is -# much simpler and does not implement every command explicitly but uses -# method_missing instead. - -require 'socket' -require 'set' - -begin - if (RUBY_VERSION >= '1.9') - require 'timeout' - RedisTimer = Timeout - else - require 'system_timer' - RedisTimer = SystemTimer - end -rescue LoadError - RedisTimer = nil -end - -class RedisClient - BulkCommands = { - "set"=>true, "setnx"=>true, "rpush"=>true, "lpush"=>true, "lset"=>true, - "lrem"=>true, "sadd"=>true, "srem"=>true, "sismember"=>true, - "echo"=>true, "getset"=>true, "smove"=>true - } - - ConvertToBool = lambda{|r| r == 0 ? false : r} - - ReplyProcessor = { - "exists" => ConvertToBool, - "sismember"=> ConvertToBool, - "sadd"=> ConvertToBool, - "srem"=> ConvertToBool, - "smove"=> ConvertToBool, - "move"=> ConvertToBool, - "setnx"=> ConvertToBool, - "del"=> ConvertToBool, - "renamenx"=> ConvertToBool, - "expire"=> ConvertToBool, - "keys" => lambda{|r| r.split(" ")}, - "info" => lambda{|r| - info = {} - r.each_line {|kv| - k,v = kv.split(":",2).map{|x| x.chomp} - info[k.to_sym] = v - } - info - } - } - - Aliases = { - "flush_db" => "flushdb", - "flush_all" => "flushall", - "last_save" => "lastsave", - "key?" => "exists", - "delete" => "del", - "randkey" => "randomkey", - "list_length" => "llen", - "push_tail" => "rpush", - "push_head" => "lpush", - "pop_tail" => "rpop", - "pop_head" => "lpop", - "list_set" => "lset", - "list_range" => "lrange", - "list_trim" => "ltrim", - "list_index" => "lindex", - "list_rm" => "lrem", - "set_add" => "sadd", - "set_delete" => "srem", - "set_count" => "scard", - "set_member?" => "sismember", - "set_members" => "smembers", - "set_intersect" => "sinter", - "set_intersect_store" => "sinterstore", - "set_inter_store" => "sinterstore", - "set_union" => "sunion", - "set_union_store" => "sunionstore", - "set_diff" => "sdiff", - "set_diff_store" => "sdiffstore", - "set_move" => "smove", - "set_unless_exists" => "setnx", - "rename_unless_exists" => "renamenx" - } - - def initialize(opts={}) - @host = opts[:host] || '127.0.0.1' - @port = opts[:port] || 6379 - @db = opts[:db] || 0 - @timeout = opts[:timeout] || 0 - connect_to_server - end - - def to_s - "Redis Client connected to #{@host}:#{@port} against DB #{@db}" - end - - def connect_to_server - @sock = connect_to(@host,@port,@timeout == 0 ? nil : @timeout) - call_command(["select",@db]) if @db != 0 - end - - def connect_to(host, port, timeout=nil) - # We support connect() timeout only if system_timer is availabe - # or if we are running against Ruby >= 1.9 - # Timeout reading from the socket instead will be supported anyway. - if @timeout != 0 and RedisTimer - begin - sock = TCPSocket.new(host, port, 0) - rescue Timeout::Error - @sock = nil - raise Timeout::Error, "Timeout connecting to the server" - end - else - sock = TCPSocket.new(host, port, 0) - end - sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 - - # 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. - if timeout - secs = Integer(timeout) - usecs = Integer((timeout - secs) * 1_000_000) - optval = [secs, usecs].pack("l_2") - sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval - sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval - end - sock - end - - def method_missing(*argv) - call_command(argv) - end - - def call_command(argv) - # this wrapper to raw_call_command handle reconnection on socket - # error. We try to reconnect just one time, otherwise let the error - # araise. - connect_to_server if !@sock - begin - raw_call_command(argv) - rescue Errno::ECONNRESET - @sock.close - connect_to_server - raw_call_command(argv) - end - end - - def raw_call_command(argv) - bulk = nil - argv[0] = argv[0].to_s.downcase - argv[0] = Aliases[argv[0]] if Aliases[argv[0]] - if BulkCommands[argv[0]] and argv.length > 1 - bulk = argv[-1].to_s - argv[-1] = bulk.length - end - @sock.write(argv.join(" ")+"\r\n") - @sock.write(bulk+"\r\n") if bulk - - # Post process the reply if needed - processor = ReplyProcessor[argv[0]] - processor ? processor.call(read_reply) : read_reply - end - - def select(*args) - raise "SELECT not allowed, use the :db option when creating the object" - end - - def [](key) - get(key) - end - - def []=(key,value) - set(key,value) - end - - def sort(key, opts={}) - cmd = [] - cmd << "SORT #{key}" - cmd << "BY #{opts[:by]}" if opts[:by] - cmd << "GET #{[opts[:get]].flatten * ' GET '}" if opts[:get] - cmd << "#{opts[:order]}" if opts[:order] - cmd << "LIMIT #{opts[:limit].join(' ')}" if opts[:limit] - call_command(cmd) - end - - def incr(key,increment=nil) - call_command(increment ? ["incrby",key,increment] : ["incr",key]) - end - - def decr(key,decrement=nil) - call_command(decrement ? ["decrby",key,decrement] : ["decr",key]) - end - - def read_reply - # We read the first byte using read() mainly because gets() is - # immune to raw socket timeouts. - begin - rtype = @sock.read(1) - 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. - @sock = nil - raise Errno::EAGAIN, "Timeout reading from the socket" - end - - raise Errno::ECONNRESET,"Connection lost" if !rtype - line = @sock.gets - case rtype - when "-" - raise "-"+line.strip - when "+" - line.strip - when ":" - line.to_i - when "$" - bulklen = line.to_i - return nil if bulklen == -1 - data = @sock.read(bulklen) - @sock.read(2) # CRLF - data - when "*" - objects = line.to_i - return nil if bulklen == -1 - res = [] - objects.times { - res << read_reply - } - res - else - raise "Protocol error, got '#{rtype}' as initial reply byte" - end - end -end