mitchellh-hash_ring 0.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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