Permalink
Browse files

Reorganization of gem files and cleaning up.

* Created RedisRb module and scoped all classes under it
* Moved VERSION constant into RedisRb, bumped to 0.2.0
* Renamed Redis class to Redis::Client
* Keeping Redis/DistRedis constants for backwards compat
* Cleaned up lib directory to avoid polluting load path
* New edis.rb allows shortcut: irb -rubygems -redis
* Moved benchmarks into benchmarking folder
* Pulled out DistRedis example into examples dir
  • Loading branch information...
1 parent d61a1e9 commit c9820ab2bfa4357153cf7acb21afa011ed10df29 @qrush qrush committed Mar 15, 2010
View
@@ -5,3 +5,5 @@ pkg/*
coverage/*
.idea
*.gemspec
+*.rdb
+*.swp
View
@@ -5,10 +5,12 @@ require 'date'
require 'spec/rake/spectask'
require 'tasks/redis.tasks'
+$:.unshift File.join(File.dirname(__FILE__), 'lib')
+require 'redis'
GEM = 'redis'
GEM_NAME = 'redis'
-GEM_VERSION = '0.1.1'
+GEM_VERSION = RedisRb::VERSION
AUTHORS = ['Ezra Zygmuntowicz', 'Taylor Weibley', 'Matthew Clark', 'Brian McKinney', 'Salvatore Sanfilippo', 'Luca Guidi']
EMAIL = "ez@engineyard.com"
HOMEPAGE = "http://github.com/ezmobius/redis-rb"
File renamed without changes.
File renamed without changes.
View
@@ -21,4 +21,4 @@ def with_all_segments(&block)
with_all_segments do |start_index, end_index|
run_in_background "ruby worker.rb write #{start_index} #{end_index} 10"
run_in_background "ruby worker.rb read #{start_index} #{end_index} 1"
-end
+end
View
@@ -0,0 +1,41 @@
+require 'rubygems'
+require 'redis'
+require 'redis/dist_redis'
+
+r = DistRedis.new :hosts => %w[localhost:6379 localhost:6380 localhost:6381 localhost:6382]
+r['urmom'] = 'urmom'
+r['urdad'] = 'urdad'
+r['urmom1'] = 'urmom1'
+r['urdad1'] = 'urdad1'
+r['urmom2'] = 'urmom2'
+r['urdad2'] = 'urdad2'
+r['urmom3'] = 'urmom3'
+r['urdad3'] = 'urdad3'
+p r['urmom']
+p r['urdad']
+p r['urmom1']
+p r['urdad1']
+p r['urmom2']
+p r['urdad2']
+p r['urmom3']
+p r['urdad3']
+
+r.push_tail 'listor', 'foo1'
+r.push_tail 'listor', 'foo2'
+r.push_tail 'listor', 'foo3'
+r.push_tail 'listor', 'foo4'
+r.push_tail 'listor', 'foo5'
+
+p r.pop_tail('listor')
+p r.pop_tail('listor')
+p r.pop_tail('listor')
+p r.pop_tail('listor')
+p r.pop_tail('listor')
+
+puts "key distribution:"
+
+r.ring.nodes.each do |red|
+ p [red.server, red.keys("*")]
+end
+r.delete_cloud!
+p r.keys('*')
View
@@ -1,153 +0,0 @@
-require 'redis'
-require 'hash_ring'
-class DistRedis
- attr_reader :ring
- def initialize(opts={})
- hosts = []
-
- db = opts[:db] || nil
- timeout = opts[:timeout] || nil
-
- raise Error, "No hosts given" unless opts[:hosts]
-
- opts[:hosts].each do |h|
- host, port = h.split(':')
- hosts << Redis.new(:host => host, :port => port, :db => db, :timeout => timeout)
- end
-
- @ring = HashRing.new hosts
- end
-
- def node_for_key(key)
- key = $1 if key =~ /\{(.*)?\}/
- @ring.get_node(key)
- end
-
- def add_server(server)
- server, port = server.split(':')
- @ring.add_node Redis.new(:host => server, :port => port)
- end
-
- def method_missing(sym, *args, &blk)
- if redis = node_for_key(args.first.to_s)
- redis.send sym, *args, &blk
- else
- super
- end
- end
-
- def node_keys(glob)
- @ring.nodes.map do |red|
- red.keys(glob)
- end
- end
-
- def keys(glob)
- node_keys(glob).flatten
- end
-
- def save
- on_each_node :save
- end
-
- def bgsave
- on_each_node :bgsave
- end
-
- def quit
- on_each_node :quit
- end
-
- def flush_all
- on_each_node :flush_all
- end
- alias_method :flushall, :flush_all
-
- def flush_db
- on_each_node :flush_db
- end
- alias_method :flushdb, :flush_db
-
- def delete_cloud!
- @ring.nodes.each do |red|
- red.keys("*").each do |key|
- red.delete key
- end
- end
- end
-
- def on_each_node(command, *args)
- @ring.nodes.each do |red|
- red.send(command, *args)
- end
- end
-
- def mset()
-
- end
-
- def mget(*keyz)
- results = {}
- kbn = keys_by_node(keyz)
- kbn.each do |node, node_keyz|
- node.mapped_mget(*node_keyz).each do |k, v|
- results[k] = v
- end
- end
- keyz.flatten.map { |k| results[k] }
- end
-
- def keys_by_node(*keyz)
- keyz.flatten.inject({}) do |kbn, k|
- node = node_for_key(k)
- next if kbn[node] && kbn[node].include?(k)
- kbn[node] ||= []
- kbn[node] << k
- kbn
- end
- end
-
-end
-
-
-if __FILE__ == $0
-
-r = DistRedis.new 'localhost:6379', 'localhost:6380', 'localhost:6381', 'localhost:6382'
- r['urmom'] = 'urmom'
- r['urdad'] = 'urdad'
- r['urmom1'] = 'urmom1'
- r['urdad1'] = 'urdad1'
- r['urmom2'] = 'urmom2'
- r['urdad2'] = 'urdad2'
- r['urmom3'] = 'urmom3'
- r['urdad3'] = 'urdad3'
- p r['urmom']
- p r['urdad']
- p r['urmom1']
- p r['urdad1']
- p r['urmom2']
- p r['urdad2']
- p r['urmom3']
- p r['urdad3']
-
- r.push_tail 'listor', 'foo1'
- r.push_tail 'listor', 'foo2'
- r.push_tail 'listor', 'foo3'
- r.push_tail 'listor', 'foo4'
- r.push_tail 'listor', 'foo5'
-
- p r.pop_tail('listor')
- p r.pop_tail('listor')
- p r.pop_tail('listor')
- p r.pop_tail('listor')
- p r.pop_tail('listor')
-
- puts "key distribution:"
-
- r.ring.nodes.each do |red|
- p [red.port, red.keys("*")]
- end
- r.delete_cloud!
- p r.keys('*')
-
-end
View
@@ -0,0 +1,3 @@
+# This file allows for the running of rubygems with a nice
+# command line look-and-feel: irb -rubygems -redis foo.rb
+require 'redis'
View
@@ -1,135 +0,0 @@
-require 'zlib'
-
-class HashRing
-
- POINTS_PER_SERVER = 160 # this is the default in libmemcached
-
- attr_reader :ring, :sorted_keys, :replicas, :nodes
-
- # nodes is a list of objects that have a proper to_s representation.
- # replicas indicates how many virtual points should be used pr. node,
- # replicas are required to improve the distribution.
- def initialize(nodes=[], replicas=POINTS_PER_SERVER)
- @replicas = replicas
- @ring = {}
- @nodes = []
- @sorted_keys = []
- nodes.each do |node|
- add_node(node)
- end
- end
-
- # Adds a `node` to the hash ring (including a number of replicas).
- def add_node(node)
- @nodes << node
- @replicas.times do |i|
- key = Zlib.crc32("#{node}:#{i}")
- @ring[key] = node
- @sorted_keys << key
- end
- @sorted_keys.sort!
- end
-
- def remove_node(node)
- @nodes.reject!{|n| n.to_s == node.to_s}
- @replicas.times do |i|
- key = Zlib.crc32("#{node}:#{i}")
- @ring.delete(key)
- @sorted_keys.reject! {|k| k == key}
- end
- end
-
- # get the node in the hash ring for this key
- def get_node(key)
- get_node_pos(key)[0]
- end
-
- def get_node_pos(key)
- return [nil,nil] if @ring.size == 0
- crc = Zlib.crc32(key)
- idx = HashRing.binary_search(@sorted_keys, crc)
- return [@ring[@sorted_keys[idx]], idx]
- end
-
- def iter_nodes(key)
- return [nil,nil] if @ring.size == 0
- node, pos = get_node_pos(key)
- @sorted_keys[pos..-1].each do |k|
- yield @ring[k]
- end
- end
-
- class << self
-
- # gem install RubyInline to use this code
- # Native extension to perform the binary search within the hashring.
- # There's a pure ruby version below so this is purely optional
- # for performance. In testing 20k gets and sets, the native
- # binary search shaved about 12% off the runtime (9sec -> 8sec).
- begin
- require 'inline'
- inline do |builder|
- builder.c <<-EOM
- int binary_search(VALUE ary, unsigned int r) {
- int upper = RARRAY_LEN(ary) - 1;
- int lower = 0;
- int idx = 0;
-
- while (lower <= upper) {
- idx = (lower + upper) / 2;
-
- VALUE continuumValue = RARRAY_PTR(ary)[idx];
- unsigned int l = NUM2UINT(continuumValue);
- if (l == r) {
- return idx;
- }
- else if (l > r) {
- upper = idx - 1;
- }
- else {
- lower = idx + 1;
- }
- }
- if (upper < 0) {
- upper = RARRAY_LEN(ary) - 1;
- }
- return upper;
- }
- EOM
- end
- rescue Exception => e
- # Find the closest index in HashRing with value <= the given value
- def binary_search(ary, value, &block)
- upper = ary.size - 1
- lower = 0
- idx = 0
-
- while(lower <= upper) do
- idx = (lower + upper) / 2
- comp = ary[idx] <=> value
-
- if comp == 0
- return idx
- elsif comp > 0
- upper = idx - 1
- else
- lower = idx + 1
- end
- end
-
- if upper < 0
- upper = ary.size - 1
- end
- return upper
- end
-
- end
- end
-
-end
-
-# ring = HashRing.new ['server1', 'server2', 'server3']
-# p ring
-# #
-# p ring.get_node "kjhjkjlkjlkkh"
-#
Oops, something went wrong.

0 comments on commit c9820ab

Please sign in to comment.