Created
May 27, 2017 07:34
-
-
Save sithu/3073385c46401592dfea119caaff5a73 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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