mitchellh-hash_ring 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +7 -0
- data/lib/hash_ring.rb +21 -7
- data/spec/hash_ring_spec.rb +6 -0
- data/spec/spec_base.rb +1 -0
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -12,6 +12,9 @@ http://amix.dk/blog/viewEntry/19367
|
|
12
12
|
|
13
13
|
== Usage
|
14
14
|
|
15
|
+
require 'rubygems'
|
16
|
+
require 'hash_ring'
|
17
|
+
|
15
18
|
memcache_servers = ['192.168.0.111:14107',
|
16
19
|
'192.168.0.112:14107',
|
17
20
|
'192.168.0.113:14108']
|
@@ -22,3 +25,7 @@ http://amix.dk/blog/viewEntry/19367
|
|
22
25
|
|
23
26
|
ring = HashRing.new(memcache_servers, weights)
|
24
27
|
server = ring.get_node('my_key')
|
28
|
+
|
29
|
+
== Installation
|
30
|
+
|
31
|
+
sudo gem install mitchellh-hash_ring
|
data/lib/hash_ring.rb
CHANGED
@@ -41,7 +41,7 @@ require 'digest/md5'
|
|
41
41
|
# server = ring.get_node('my_key')
|
42
42
|
#
|
43
43
|
class HashRing
|
44
|
-
VERSION = '0.
|
44
|
+
VERSION = '0.2'
|
45
45
|
|
46
46
|
#
|
47
47
|
# Creates a HashRing instance
|
@@ -67,16 +67,18 @@ class HashRing
|
|
67
67
|
end
|
68
68
|
|
69
69
|
#
|
70
|
-
# Generates the
|
70
|
+
# Generates the ring.
|
71
|
+
#
|
72
|
+
# This is for internal use only.
|
71
73
|
def _generate_circle
|
72
74
|
total_weight = 0
|
73
75
|
|
74
76
|
@nodes.each do |node|
|
75
|
-
total_weight += @weights[node] || 1
|
77
|
+
total_weight += @weights[node.to_s] || 1
|
76
78
|
end
|
77
79
|
|
78
80
|
@nodes.each do |node|
|
79
|
-
weight = @weights[node] || 1
|
81
|
+
weight = @weights[node.to_s] || 1
|
80
82
|
factor = ((40 * @nodes.length * weight) / total_weight.to_f).floor.to_i
|
81
83
|
|
82
84
|
factor.times do |j|
|
@@ -153,15 +155,23 @@ class HashRing
|
|
153
155
|
return self._hash_val(b_key) { |x| x }
|
154
156
|
end
|
155
157
|
|
158
|
+
#
|
159
|
+
# Converts a hex digest to a value based on certain parts of
|
160
|
+
# the digest determined by the block. The block will be called
|
161
|
+
# 4 times (with paramter 3, then 2, then 1, then 0) and is
|
162
|
+
# expected to return a valid index into the digest with which
|
163
|
+
# to pull a single character from.
|
164
|
+
#
|
165
|
+
# This function is meant for use internally.
|
156
166
|
def _hash_val(b_key, &block)
|
157
167
|
return ((b_key[block.call(3)] << 24) |
|
158
168
|
(b_key[block.call(2)] << 16) |
|
159
169
|
(b_key[block.call(1)] << 8) |
|
160
170
|
(b_key[block.call(0)]))
|
161
|
-
|
171
|
+
end
|
162
172
|
|
163
173
|
#
|
164
|
-
# Returns raw MD5 digest
|
174
|
+
# Returns raw MD5 digest of a key.
|
165
175
|
def _hash_digest(key)
|
166
176
|
m = Digest::MD5.new
|
167
177
|
m.update(key)
|
@@ -172,7 +182,11 @@ class HashRing
|
|
172
182
|
end
|
173
183
|
|
174
184
|
#
|
175
|
-
#
|
185
|
+
# Bisects an array, returning the index where the key would
|
186
|
+
# need to be inserted to maintain sorted order of the array.
|
187
|
+
#
|
188
|
+
# That being said, it is assumed that the array is already
|
189
|
+
# in sorted order before calling this method.
|
176
190
|
def bisect(arr, key)
|
177
191
|
arr.each_index do |i|
|
178
192
|
return i if key < arr[i]
|
data/spec/hash_ring_spec.rb
CHANGED
@@ -9,6 +9,12 @@ WEIGHTED_ERROR_BOUND = 0.05
|
|
9
9
|
describe HashRing do
|
10
10
|
include HashRingHelpers
|
11
11
|
|
12
|
+
it "should allow the creation of a hash ring with non-string objects" do
|
13
|
+
lambda do
|
14
|
+
ring = HashRing.new([HashRing.new('a'), HashRing.new('b')])
|
15
|
+
end.should_not raise_error
|
16
|
+
end
|
17
|
+
|
12
18
|
describe "bisection" do
|
13
19
|
before do
|
14
20
|
@ring = HashRing.new(['a'])
|
data/spec/spec_base.rb
CHANGED