summaryrefslogtreecommitdiff
path: root/ironic/common/hash_ring.py
diff options
context:
space:
mode:
authorDavid Shrewsbury <shrewsbury.dave@gmail.com>2014-10-16 15:34:32 -0400
committerDavid Shrewsbury <shrewsbury.dave@gmail.com>2014-10-20 11:53:33 -0400
commite2c1ebcb7f8dc4d76b3e413d060edde96b52e8b3 (patch)
tree1d90686cb875bc0ca2644deaf1d17ed093ad7390 /ironic/common/hash_ring.py
parente6ac648e41f6316b81bdc3d7aec8fd86f7857efa (diff)
downloadironic-e2c1ebcb7f8dc4d76b3e413d060edde96b52e8b3.tar.gz
Improve hash ring value conversion
The current method for computing the point on the hash ring converts the MD5 digest into a 4-byte integer (and assumes big-endian). The digest is actually a 16-byte value, so we are eliminating much of the value, thus increasing the possibility of hash collisions. This patch does two things: * Removes the endianness assumption * Uses the full value of the digest to create a long integer, which has unlimited precision in Python. Change-Id: I554ec46f506cb8cdfd5878c11a905a3acfe92db0
Diffstat (limited to 'ironic/common/hash_ring.py')
-rw-r--r--ironic/common/hash_ring.py14
1 files changed, 10 insertions, 4 deletions
diff --git a/ironic/common/hash_ring.py b/ironic/common/hash_ring.py
index a79ff344d..51ab38aa1 100644
--- a/ironic/common/hash_ring.py
+++ b/ironic/common/hash_ring.py
@@ -15,7 +15,6 @@
import bisect
import hashlib
-import struct
import threading
from oslo.config import cfg
@@ -91,16 +90,23 @@ class HashRing(object):
key_hash = hashlib.md5(key)
for p in range(2 ** CONF.hash_partition_exponent):
key_hash.update(key)
- hashed_key = struct.unpack_from('>I', key_hash.digest())[0]
+ hashed_key = self._hash2int(key_hash)
self._host_hashes[hashed_key] = host
# Gather the (possibly colliding) resulting hashes into a bisectable
# list.
self._partitions = sorted(self._host_hashes.keys())
+ def _hash2int(self, key_hash):
+ """Convert the given hash's digest to a numerical value for the ring.
+
+ :returns: An integer equivalent value of the digest.
+ """
+ return int(key_hash.hexdigest(), 16)
+
def _get_partition(self, data):
try:
- hashed_key = struct.unpack_from(
- '>I', hashlib.md5(data).digest())[0]
+ key_hash = hashlib.md5(data)
+ hashed_key = self._hash2int(key_hash)
position = bisect.bisect(self._partitions, hashed_key)
return position if position < len(self._partitions) else 0
except TypeError: