-
Notifications
You must be signed in to change notification settings - Fork 0
/
chord.py
executable file
·288 lines (230 loc) · 7.64 KB
/
chord.py
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
import random
import socket
import thread
from threading import Thread
import sys
import time
import sha
import hashlib
import traceback
import copy
from threading import Lock
k = 160
MAX = 2**k
DEFAULT_IP = "192.168.1.5"
DEFAULT_PORT = 4567
HASH_LENGTH = 160
finger = {}
fingerLock = Lock()
#if enter printnode in the command, all the nodes of the ring will print
def printNodes(node):
print ' Ring nodes:'
end = node
print end.key
while end.key != node.successor().key:
end.key = end.successor().key
print end.key
print "******************************"
def get_key(ip, port):
line = str(ip) + str(port)
key=long(sha.new(line).hexdigest(),16)
return key
class Node:
def __init__(self, ip, port):
global fingerLock
self.ip = ip
self.port = port
self.key = get_key(ip, port)
self.finger = {}
self.start = {}
fingerLock.acquire()
self.predecessor = self
for i in range(HASH_LENGTH):
self.start[i] = (self.key+(2**i)) % (2**HASH_LENGTH)
fingerLock.release()
def successor(self):
return self.finger[0]
def find_successor(self,key):
n1 = self
if key == self.key:
return n1
elif self.predecessor.key > self.key:
shift = MAX - init
self.key = (self.key + shift) % MAX
key = (key + shift) % MAX
if key < self.key:
return n1
else:
n1 = self.find_predecessor(key)
return n1.successor()
def find_predecessor(self,key):
if key == self.key:
return self.predecessor
n1 = self
while True:
if key == n1.successor().key or n1.successor().key == n1.key:
n1 = self
elif n1.key > n1.successor().key:
shift = MAX - n1.key
n1.successor().key = (n1.successor().key + shift) % MAX
key = (key + shift) % MAX
if key < n1.successor().key:
n1 = self
else:
n1 = n1.closest_preceding_finger(key)
return n1
def closest_preceding_finger(self,key):
global fingerLock
for i in range(HASH_LENGTH-1,-1,-1):
if self.key == key:
return self.finger[0]
elif self.key > key:
shift = MAX - self.key
init = 0
key = (key + shift) % MAX
fingerLock.acquire()
self.finger[i].key = (self.finger[i].key + shift) % MAX
fingerLock.release()
if self.key < self.finger[i].key and self.finger[i].key < key:
return self.finger[0]
return self
def join(self,n1):
global fingerLock
if self.key == n1.key:
fingerLock.acquire()
for i in range(HASH_LENGTH):
self.finger[i] = self
self.predecessor = self
fingerLock.release()
else:
send_message(n1.ip, n1.port)
fingerLock.acquire()
self.finger[0] = n1.find_successor(self.start[0])
self.predecessor = self.successor().predecessor
self.successor().predecessor = self
self.predecessor.finger[0] = self
for i in range(HASH_LENGTH-1):
if between(self.start[i+1],self.key,self.finger[i].key):
self.finger[i+1] = self.finger[i]
else :
self.finger[i+1] = n1.find_successor(self.start[i+1])
fingerLock.release()
for i in range(HASH_LENGTH):
if self.key >= 2**i:
prev = self.key - 2**i
else:
prev = MAX - (2**i - self.key)
p = self.find_predecessor(prev)
if prev == p.successor().key:
p = p.successor()
p.fix_fingers(self,i)
def fix_fingers(self,s,i):
global fingerLock
if s.key == self.finger[i].key or self.finger[i].key == self.key:
if self.key != s.key:
fingerLock.acquire()
self.finger[i] = s
fingerLock.release()
p = self.predecessor
p.fix_fingers(s,i)
elif self.key > self.finger[i].key:
shift = MAX - self.key
self.finger[i].key = (self.finger[i].key + shift) % MAX
s.key = (s.key + shift) % MAX
if self.key < self.finger[i].key:
if self.key != s.key:
fingerLock.acquire()
self.finger[i] = s
fingerLock.release()
p = self.predecessor
p.fix_fingers(s,i)
def update_others_leave(self):
for i in range(HASH_LENGTH):
if self.key >= 2**i:
prev = self.key - 2**i
else:
prev = MAX - (2**i - self.key)
p = self.find_predecessor(prev)
p.fix_fingers(self.successor(),i)
def leave(self):
self.successor().predecessor = self.predecessor
self.predecessor.setSuccessor(self.successor())
self.update_others_leave()
def setSuccessor(self,succ):
global fingerLock
fingerLock.acquire()
self.finger[0] = succ
fingerLock.release()
def print_finger_table(node):
print 'Finger Table of ' + str(node.key)
for i in range(HASH_LENGTH):
print str(node.start[i]) +' : ' +str(node.finger[i].key)
print "***************************************************"
def between(value,init,end):
if value == init or init == end:
return True
elif init > end :
shift = MAX - init
end = (end +shift)%MAX
value = (value + shift)%MAX
if value < end:
return True
else:
return False
def send_message(ip, port):
UDP_IP = ip
UDP_PORT = port
MESSAGE = "Hello, World!"
print "message:" + MESSAGE
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
#A new thread needed for this method, it's used for receive message
def reveive_message(ip, port):
UDP_IP = ip
UDP_PORT = port
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.bind((UDP_IP, UDP_PORT))
except:
traceback.print_exc()
print "no connect"
return None
while True:
data, addr = sock.recvfrom(1024)
print "received message:", data
return data
def set_chord(node):
recv = send_message(node.ip, node.port)
if __name__ == "__main__":
knowNode = Node(DEFAULT_IP, DEFAULT_PORT)
port = 0
MY_IP = ""
if (len(sys.argv) == 2):
port = int(sys.argv[-1])
MY_IP = socket.gethostbyname(socket.gethostname())
else:
port = DEFAULT_PORT
MY_IP = DEFAULT_IP
myNode = Node(MY_IP, port)
fingerLock.acquire()
for i in range(0, HASH_LENGTH):
finger[i] = copy.deepcopy(myNode.key)
fingerLock.release()
answerThread = Thread(target=reveive_message, args=(MY_IP, port))
answerThread.daemon = True
answerThread.start()
knowNode.join(knowNode)
myNode.join(knowNode)
while True:
command = raw_input("Command>> ")
command = command.lower()
if len(command) == 0:
pass
elif command in ("fingertable"):
print_finger_table(myNode)
elif command in ("printnode"):
printNodes(myNode)
elif command in ("leave"):
myNode.leave()
elif command in ("set"):
set_chord(myNode)