-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDHT.py
More file actions
129 lines (111 loc) · 4.11 KB
/
DHT.py
File metadata and controls
129 lines (111 loc) · 4.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import socket
import threading
import os
import time
import hashlib
class Node:
def __init__(self, host, port):
self.stop = False
self.host = host
self.port = port
self.M = 16
self.N = 2**self.M
self.key = self.hasher(host+str(port))
# You will need to kill this thread when leaving, to do so just set self.stop = True
threading.Thread(target = self.listener).start()
self.files = []
self.backUpFiles = []
if not os.path.exists(host+"_"+str(port)):
os.mkdir(host+"_"+str(port))
'''
------------------------------------------------------------------------------------
DO NOT EDIT ANYTHING ABOVE THIS LINE
'''
# Set value of the following variables appropriately to pass Intialization test
self.successor = None
self.predecessor = None
# additional state variables
def hasher(self, key):
'''
DO NOT EDIT THIS FUNCTION.
You can use this function as follow:
For a node: self.hasher(node.host+str(node.port))
For a file: self.hasher(file)
'''
return int(hashlib.md5(key.encode()).hexdigest(), 16) % self.N
def handleConnection(self, client, addr):
'''
Function to handle each inbound connection, called as a thread from the listener.
'''
def listener(self):
'''
We have already created a listener for you, any connection made by other nodes will be accepted here.
For every inbound connection we spin a new thread in the form of handleConnection function. You do not need
to edit this function. If needed you can edit signature of handleConnection function, but nothing more.
'''
listener = socket.socket()
listener.bind((self.host, self.port))
listener.listen(10)
while not self.stop:
client, addr = listener.accept()
threading.Thread(target = self.handleConnection, args = (client, addr)).start()
print ("Shutting down node:", self.host, self.port)
try:
listener.shutdown(2)
listener.close()
except:
listener.close()
def join(self, joiningAddr):
'''
This function handles the logic of a node joining. This function should do a lot of things such as:
Update successor, predecessor, getting files, back up files. SEE MANUAL FOR DETAILS.
'''
def put(self, fileName):
'''
This function should first find node responsible for the file given by fileName, then send the file over the socket to that node
Responsible node should then replicate the file on appropriate node. SEE MANUAL FOR DETAILS. Responsible node should save the files
in directory given by host_port e.g. "localhost_20007/file.py".
'''
def get(self, fileName):
'''
This function finds node responsible for file given by fileName, gets the file from responsible node, saves it in current directory
i.e. "./file.py" and returns the name of file. If the file is not present on the network, return None.
'''
def leave(self):
'''
When called leave, a node should gracefully leave the network i.e. it should update its predecessor that it is leaving
it should send its share of file to the new responsible node, close all the threads and leave. You can close listener thread
by setting self.stop flag to True
'''
def sendFile(self, soc, fileName):
'''
Utility function to send a file over a socket
Arguments: soc => a socket object
fileName => file's name including its path e.g. NetCen/PA3/file.py
'''
fileSize = os.path.getsize(fileName)
soc.send(str(fileSize).encode('utf-8'))
soc.recv(1024).decode('utf-8')
with open(fileName, "rb") as file:
contentChunk = file.read(1024)
while contentChunk!="".encode('utf-8'):
soc.send(contentChunk)
contentChunk = file.read(1024)
def recieveFile(self, soc, fileName):
'''
Utility function to recieve a file over a socket
Arguments: soc => a socket object
fileName => file's name including its path e.g. NetCen/PA3/file.py
'''
fileSize = int(soc.recv(1024).decode('utf-8'))
soc.send("ok".encode('utf-8'))
contentRecieved = 0
file = open(fileName, "wb")
while contentRecieved < fileSize:
contentChunk = soc.recv(1024)
contentRecieved += len(contentChunk)
file.write(contentChunk)
file.close()
def kill(self):
# DO NOT EDIT THIS, used for code testing
self.stop = True