Skip to content

Instantly share code, notes, and snippets.

@sithu
Created May 27, 2017 07:34
Show Gist options
  • Save sithu/3073385c46401592dfea119caaff5a73 to your computer and use it in GitHub Desktop.
Save sithu/3073385c46401592dfea119caaff5a73 to your computer and use it in GitHub Desktop.
"""
You must use hashlib to hash the node ('0.0.0.0:3000') and key ('mykey') combination.
Example:
x = '0.0.0.0:3000' + 'my-key'
x = node + key
hash = hashlib.md5(x).hexdigest()
More@https://docs.python.org/2/library/hashlib.html
"""
# TODO: Add any required import
import hashlib
from client import DBClient
class RendezvousHash(object):
"""This class implements the Rendezvous (HRW) hashing logic."""
def __init__(self, nodes=None):
"""
Initialize the instance with node list and others.
A node means a server host name and its listening port. E.g. '0.0.0.0:3000'
:param nodes: a list of DB server nodes to register.
"""
# TODO
self.nodes = []
if nodes is not None:
self.nodes = nodes
self.hash_function = lambda x: hashlib.md5(x).hexdigest()
def get_node(self, key):
"""
Find the highest hash value via hash(node+key) and the node that generates the highest
value among all nodes.
:param key: a string key name.
:return the highest node.
"""
# TODO
highest_hash = -1
highest_node = None
for node in self.nodes:
hash = self.hash_function("%s-%s" % (str(node), str(key)))
if hash > highest_hash:
highest_node, highest_hash = (node, hash)
elif hash == highest_hash:
highest_node, highest_hash = (max(str(node), str(highest_node)), hash)
return highest_node
class RendezvousHashDBClient(RendezvousHash):
"""
This class extends from the above RendezvousHash class and
integrates DBClient ([email protected]) with RendezvousHash so that
client can PUT and GET to the DB servers while the rendezvous hash shards
the data across multiple DB servers.
"""
def __init__(self, db_servers=None):
"""
1. Initialize the super/parent RendezvousHash class.
Class inheritance@http://www.python-course.eu/python3_inheritance.php
2. Create DBClient instance for all servers and save them in a dictionary.
:param db_servers: a list of DB servers: ['0.0.0.0:3000', '0.0.0.0:3001', '0.0.0.0:3002']
"""
# TODO
RendezvousHash.__init__(self, nodes=db_servers)
self.clients = {}
for server in db_servers:
host_port = server.split(':')
self.clients[server] = DBClient(host_port[0], int(host_port[1]))
def put(self, key, value):
"""
1. Get the highest Rendezvous node for the given key.
2. Retrieve the DBClient instance reference by the node.
3. Save the value into DB via client's put().
:param key: a string key.
:param value: a string key-value pair dictionary to be stored in DB.
:return a PutResponse - [email protected]
NOTE: Both key and value must be the string type.
"""
# TODO
node = self.get_node(key)
client = self.clients[node]
return client.put(key, value)
def get(self, key):
"""
1. Get the highest Rendezvous node for the given key.
2. Retrieve the DBClient instance reference by the node.
3. Get the value by the key via client's get().
:param key: a string key.
:param value: a string key-value pair dictionary to be stored in DB.
:return a GetResposne - [email protected]
"""
# TODO
node = self.get_node(key)
client = self.clients[node]
return client.get(key)
def info(self):
"""
Return a list of InfoResponse from all servers.
1. Invoke DB client's info() to retrieve server info for all host.
"""
# TODO
server_info = []
for host in self.clients:
server_info.append(self.clients[host].info())
return server_info
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment