-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode.py
More file actions
executable file
·812 lines (649 loc) · 26.1 KB
/
Copy pathnode.py
File metadata and controls
executable file
·812 lines (649 loc) · 26.1 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
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
import random
from globals import *
#Node States - not sure if this should be in the node class
#Node class to contain explicit copies of the bit field and peer lists
class Node:
def __init__(self, node_id, selection, altruism, leave, have, rate):
self.id = node_id
# Save the start time for the node.
self.start_time = wq.cur_time
# counter for log purposes
self.count = 0
self.starting = 1
# Specify the bounds on the number of allowed peers.
self.min_peers = MIN_PEERS
self.max_peers = MAX_PEERS
# Style of next piece selection
# Options: Random, Priority
self.piece_selection = selection
# Style of altruism
# Options: leave_on_complete, eternal_seed, leave_time_after_complete, leave_after_round
self.altruism = altruism
self.leave_time = leave
# Pick a random number of desired peers.
# Will always try to have at least this many peers (but may have more).
self.desired_peers = DESIRED_PEERS
# peers dictionary
# key: peers that are choked
# value: the time the peering was made
self.peers = {}
# unchoked dictionary
# key: peers that are unchoked
# value: the time the peering was made
# Note: AT NO TIME SHOULD SOMETHING BE IN BOTH PEERS AND UNCHOKED
self.unchoked = {} # Set of unchoked peers this list should never have more than 5 things in it
# interest dictionary
# key: peers that are interested in downloading from this node
# value: the highest priority piece that this peer wants that we have
self.interest = {}
# interest expressed
# ** What's in here is functionally the head of our priority queue, its what we will get next round **
# maintain this for measurement purposes
# key: peers that we are interested in downloading from
# value: the piece we asked for first from them
self.requested = {}
self.op_unchoke = -1 # ID of current optimistically unchoked peer
self.op_unchoke_count = 0 # number of times we've tried to unchoke this peer, try 3 times then switch
self.never_unchoked = []
if rate:
# If rate is not None, then use the given rate.
self.max_down = rate[0]
self.max_up = rate[1]
else:
# Otherwise, compute random rates.
# Default download capacity
#self.max_down = random.betavariate(1.5, 5)*1000
self.max_down = random.uniform(50,100)
# Default upload capacity
#self.max_up = self.max_down * random.uniform(0.5, 1.0)
self.max_up = 0.5 * self.max_down
self.remain_down = self.max_down # Download capacity not being used yet
self.curr_up = {} # Values to keep track of current upload resources being spent, indexed by node id
self.curr_down = {} # Values to keep track of current download resources being spent, indexed by node id
# List of the piece IDs we want in order of their rarity
self.priority_list = []
# Sorted list of the piece IDs we have seen in gossip messages
# ** Actually a list of objects, first entry is number of times we've seen it in different gossip messages
# second entry is the piece id
self.gossip_rare = []
# have_pieces dictionary
# key: the blocks that we have
# value: the time the block finished
self.have_pieces = {}
self.init_have(have)
# want_pieces dictionary
# key: the pieces we DO NOT have
# value: the number of subblocks left to download
self.want_pieces = {}
self.init_want(have)
# Define the gossip queue
self.gossip_queue = []
# Define the gossip sequence number dictionary
self.my_gossip_num = 0
self.peer_gossip_numbers = {}
# Store the important details about this node on its creation
# but only do this if we aren't loading in values
if LOAD_RATES == False:
sf = open(statefile, 'a')
sf.write(str(self.id)+'\n')
sf.write(str(self.start_time)+'\n')
sf.write(str(self.max_down)+'\n')
sf.write(str(self.max_up)+'\n')
sf.close()
# Initialize the have_pieces dictionary
def init_have(self, have):
#copy the have list into the have_pieces dictionary
for i in range(len(have)):
if have[i] == PIECE_SIZE:
self.have_pieces[i] = 0
# Initialize the want_pieces dictionary
def init_want(self, have):
for i in range(NUM_PIECES):
if i in self.have_pieces:
# Already have the piece, so skip it.
pass
elif len(have) > 0:
if have[i] > 0:
self.want_pieces[i] = have[i]
else:
self.want_pieces[i] = PIECE_SIZE
else:
self.want_pieces[i] = PIECE_SIZE
def add_peer(self, node_id, time):
self.peers[node_id] = time
self.never_unchoked.append(node_id)
def remove_peer(self, node_id):
if node_id in self.peers:
del self.peers[node_id]
if node_id in self.unchoked:
del self.unchoked[node_id]
if self.op_unchoke == node_id:
self.op_unchoke_count = 0
if node_id in self.never_unchoked:
self.never_unchoked.remove(node_id)
# also need to check the curr_up and curr_down dictionaries for this peer
if node_id in self.curr_up:
del self.curr_up[node_id]
if node_id in self.curr_down:
del self.curr_down[node_id]
if node_id in self.interest:
del self.interest[node_id]
self.sort_priority()
self.update_full_interest()
# Remove all gossip messages from node
del_list = []
for msg in self.gossip_queue:
if node_id == msg[0]:
del_list.append(msg)
[self.gossip_queue.remove(msg) for msg in del_list]
# Delete gossip sequence number
if node_id in self.peer_gossip_numbers:
del self.peer_gossip_numbers[node_id]
def num_peers(self):
return len(self.peers) + len(self.unchoked)
def get_peers(self, time):
# Check to see if more peers are needed.
if self.num_peers() >= self.desired_peers:
# If not, return because there is nothing to do.
pass
else:
# Get a list of all the nodes that we are not peers with.
available_nodes = nodes.keys()
available_nodes.remove(self.id)
[available_nodes.remove(i) for i in self.unchoked.keys()]
[available_nodes.remove(i) for i in self.peers.keys()]
del_list = []
for i in available_nodes:
if nodes[i].num_peers() >= nodes[i].max_peers:
del_list.append(i)
for i in range(len(del_list)):
available_nodes.remove(del_list[i])
# Otherwise, get more peers until we have desired_peers (or there are none left to get).
peers_needed = min([self.desired_peers-self.num_peers(), len(available_nodes)])
#outf = open('out_file', 'a')
#outf.write('node '+str(self.id)+' ( '+str(self.num_peers())+' peers ) has the available nodes '+str(available_nodes)+'\n')
#outf.write('node '+str(self.id)+' ( '+str(self.num_peers())+' peers ) thinks it needs '+str(peers_needed)+' peers \n')
#outf.write('\n')
#outf.close()
for i in range(peers_needed):
# Pick a random peer among those left
new_peer = random.choice(available_nodes)
# Remove it from the available nodes list and set the peer for both nodes.
available_nodes.remove(new_peer)
nodes[new_peer].add_peer(self.id, time)
self.add_peer(new_peer, time)
def choke(self, node_id):
if node_id not in self.unchoked:
raise Exception('Attempted to choke a node that is not in unchoked.')
else:
self.peers[node_id] = self.unchoked[node_id]
del self.unchoked[node_id]
def unchoke(self, node_id):
if node_id not in self.peers:
raise Exception('Attempted to unchoke a node that is not in peers.')
else:
self.unchoked[node_id] = self.peers[node_id]
del self.peers[node_id]
if node_id in self.never_unchoked:
self.never_unchoked.remove(node_id)
# unchoking process
# there might be a much simpler way to do this, I was really tired when I wrote it
def update_unchoke(self, time):
# Move all unchoked nodes back into the peers list.
for i in self.unchoked.keys():
self.choke(i)
# build the unchoke list for the peers we have
unchoke_list = []
if self.want_pieces.keys() == []:
for i in self.curr_up:
# only unchoke them if they want to download something from us
if i in self.interest.keys():
unchoke_list.append([self.curr_up[i], i])
else:
for i in self.curr_down:
# only unchoke them if they want to download something from us
if i in self.interest.keys():
unchoke_list.append([self.curr_down[i], i])
unchoke_list.sort();
unchoke_list.reverse();
# Pick the unchoked nodes
if len(unchoke_list) >= 4:
# find the top four uploaders among the unchoked peers
unchoke_list = unchoke_list[0:4]
# update unchoked set with the new top four peers or however many we have
for i in range(len(unchoke_list)):
id = unchoke_list[i][1]
self.unchoke(id)
# see if the op_unchoke got picked
for i in self.unchoked:
if i == self.op_unchoke:
# if it was picked, reset the op_unchoke
self.op_unchoke_count = 0
# if it wasn't picked, put it back into unchoked
if self.op_unchoke_count != 0:
self.unchoke(self.op_unchoke)
# take care of the optimistic unchoke
self.update_op_unchoke()
# Pick the node to be optimistically unchoked.
def update_op_unchoke(self):
# If there are any choked peers left
if len(self.peers) > 0:
if self.op_unchoke_count > 3:
# The current optimistic unchoke time has expired.
# Set the unchoke count to 0 to make a new op_unchoke get
# picked below.
self.op_unchoke_count = 0
# Move the op_unchoke back to the choked list.
# if he uploaded enough, he should get selected as
# one of the four unchoked peers this round
self.choke(self.op_unchoke)
self.op_unchoke = -1
# make sure the current optimistic unchoke is still interested
else:
if self.op_unchoke not in self.interest.keys():
if self.op_unchoke_count != 0:
self.op_unchoke_count = 0
# Move the op_unchoke back to the choked list
self.choke(self.op_unchoke)
self.op_unchoke = -1
if self.op_unchoke_count == 0: # first time we're here or old op_unchoke was removed
# Create a new list of the keys of the peers list
op_unchoke_list = []
# For each peer that we are interested in.
for i in self.peers:
if i in self.interest.keys():
# Add them to the op_unchoke list.
op_unchoke_list.append(i)
if i in self.never_unchoked:
# Add two more times if they have never been unchoked.
op_unchoke_list.append(i)
op_unchoke_list.append(i)
if len(op_unchoke_list) > 0:
temp = random.choice(op_unchoke_list)
self.op_unchoke = temp # should be a node_id
self.unchoke(self.op_unchoke)
self.op_unchoke_count = 1
# if we have no peers to make the op_unchoke just set the unchoke_count to 0 and
# check again next time
else:
self.op_unchoke_count = 0
else:
# Run this op_unchoke peer for another round.
self.op_unchoke_count = self.op_unchoke_count + 1
#if there are no peers left, check to make sure this peer should still be optimistically unchoked
else:
if self.op_unchoke not in self.interest.keys():
if self.op_unchoke_count != 0:
self.op_unchoke_count = 0
# Move the op_unchoke back to the choked list
self.choke(self.op_unchoke)
self.op_unchoke = -1
# Function to clean up the temp_peers dictionary
def clean_temp_peers(self, temp_peers):
del_list = []
for i in range(len(temp_peers)):
# if we're already interested in one of their pieces
if self.id in nodes[temp_peers[i]].interest.keys():
# get the piece index
piece_index = nodes[temp_peers[i]].interest[self.id]
# if we still want the piece
if piece_index in nodes[temp_peers[i]].want_pieces.keys():
if nodes[temp_peers[i]].want_pieces[piece_index] == PIECE_SIZE:
del nodes[temp_peers[i]].interest[self.id]
else:
del_list.append(temp_peers[i])
elif piece_index in nodes[temp_peers[i]].have_pieces.keys():
del nodes[temp_peers[i]].interest[self.id]
else:
del_list.append(temp_peers[i])
for i in range(len(del_list)):
temp_peers.remove(del_list[i])
# Function to scan through the priority list
def priority_scan(self, temp_peers):
temp_del2 = []
for i in range(len(self.priority_list)):
temp_del = NUM_NODES+1
for j in range(len(temp_peers)):
if self.priority_list[i] in nodes[temp_peers[j]].have_pieces:
nodes[temp_peers[j]].interest[self.id] = self.priority_list[i]
temp_del = temp_peers[j]
temp_del2.append(self.priority_list[i])
# break out of the loop cause we've found a peer for that piece
break
# remove the peer we found for this piece so we don't associate it with another piece
if temp_del != NUM_NODES+1:
temp_peers.remove(temp_del)
# remove this piece from the list so we don't try to get it again
if temp_del2 != []:
# we are removing something from the priority list
for i in range(len(temp_del2)):
self.priority_list.remove(temp_del2[i])
# Function to scan through the gossip list
def gossip_scan(self, temp_peers):
# go through the gossiped rare list and find out which peers (if any) have these pieces
temp_del2 = []
temp_del3 = []
for i in range(len(self.gossip_rare)):
temp_del = NUM_NODES+1
for j in range(len(temp_peers)):
if self.gossip_rare[i][1] in nodes[temp_peers[j]].have_pieces:
nodes[temp_peers[j]].interest[self.id] = self.gossip_rare[i][1]
self.requested[temp_peers[j]] = self.gossip_rare[i][1]
temp_del = temp_peers[j]
temp_del2.append(self.gossip_rare[i])
temp_del3.append(self.gossip_rare[i][1])
break
if temp_del != NUM_NODES+1:
temp_peers.remove(temp_del)
# remove this piece from the list so we don't try to get it again
if temp_del2 != []:
for i in range(len(temp_del2)):
self.gossip_rare.remove(temp_del2[i])
# also remove this from the priority list cause we're getting it
self.priority_list.remove(temp_del3[i])
# Update our entry in the interest dictionaries of our peers
# This should be called whenever a peer is added or an exchange round begins
def update_full_interest(self):
# create a temporary list of all of the peers
temp_peers = []
num_all_peers = self.num_peers()
for i in self.peers.keys():
temp_peers.append(i)
for i in self.unchoked.keys():
temp_peers.append(i)
# First time we're here so random choice of piece
if self.starting == 1:
# keey track of which pieces we're getting so we don't get the same piece from two peers
temp_del = []
for j in range(len(temp_peers)):
# Get all of the pieces that this peer has.
temp_pieces = {}
for k in nodes[temp_peers[j]].have_pieces.keys():
temp_pieces[k] = nodes[temp_peers[j]].have_pieces[k]
# Remove all fo the pieces that we have already scheduled to other peers.
if temp_del != []:
for k in range(len(temp_del)):
if temp_del[k] in temp_pieces.keys():
del temp_pieces[temp_del[k]]
# Pick a random piece that this peer has to download
if temp_pieces.keys() != []:
rand_piece = random.choice(temp_pieces.keys())
temp_del.append(rand_piece)
nodes[temp_peers[j]].interest[self.id] = rand_piece
self.requested[temp_peers[j]] = rand_piece
self.priority_list.remove(rand_piece)
if rand_piece in self.gossip_rare:
self.gossip_rare.remove(rand_piece)
self.starting = 0
else:
if GOSSIP == True and (GOSSIP_STYLE == 'priority' or GOSSIP_STYLE == 'all'):
# clear our entry in all of our peers interest dictionaries because it might be out of date
# however, if the entry is a partially downloaded piece, instead remove that peer from
# temp_peers cause we don't want to touch that dictionary entry
#test_out.write(str(temp_peers)+'\n')
print 'UPDATING INTEREST WITH GOSSIP'
# clean up the temp peeers dictionary
self.clean_temp_peers(temp_peers)
# scan through the gossiped priority list and see if we can get one of those pieces from this peer
self.gossip_scan(temp_peers)
# scan through our priority list and find the next thing that this peer has that we want
self.priority_scan(temp_peers)
else:
print 'NORMAL INTEREST UPDATE'
# clear our entry in all of our peers interest dictionaries because it might be out of date
# however, if the entry is a partially downloaded piece, instead remove that peer from
# temp_peers cause we don't want to touch that dictionary entry
#test_out.write(str(temp_peers)+'\n')
# clean up the temp peeers dictionary
self.clean_temp_peers(temp_peers)
# go through the priority list and find out which peers have these pieces
self.priority_scan(temp_peers)
# Update our entry in the interest dictionary of a specific peer
def update_interest(self, peer):
if GOSSIP == True and (GOSSIP_STYLE == 'priority' or GOSSIP_STYLE == 'all'):
temp_peers = [peer]
# scan through the gossiped priority list and see if we can get one of those pieces from this peer
self.gossip_scan(temp_peers)
# if we didn't find anything
if temp_peers != []:
# scan through our priority list and find the next thing that this peer has that we want
self.priority_scan(temp_peers)
# check to see if we actually updated the interest entry, if not delete it since they no longer have anything we want
if nodes[peer].interest[self.id] == NUM_PIECES+1:
del nodes[peer].interest[self.id]
else:
temp_peers = [peer]
# scan through our priority list and find the next thing that this peer has that we want
self.priority_scan(temp_peers)
# check to see if we actually updated the interest entry, if not delete it since they no longer have anything we want
if nodes[peer].interest[self.id] == NUM_PIECES+1:
del nodes[peer].interest[self.id]
# Sorts the priority list of the node based on rarity
def sort_priority(self):
self.priority_list = [] # clear the list cause the priority will change between rounds
count_dict = {}
count_list = []
# If global
if (KNOWLEDGE_MODE == 'global' or KNOWLEDGE_MODE == 'omni'):
all_peers = nodes.keys()
else:
all_peers = self.peers.keys() + self.unchoked.keys() + [self.id]
for i in self.want_pieces:
# don't want to add in flight pieces to the priority queue
if self.want_pieces[i] != 0:
# don't want to add pieces that are already in the interest dictionary
count_dict[i] = 0
for j in all_peers:
if KNOWLEDGE_MODE == 'omni':
if i in nodes[j].have_pieces:
if i in count_dict:
count_dict[i] += 1
else:
count_dict[i] = 1
elif i in nodes[j].requested:
if i in count_dict:
count_dict[i] += 1
else:
count_dict[i] = 1
else:
if i in nodes[j].have_pieces:
if i in count_dict:
count_dict[i] += 1
else:
count_dict[i] = 1
if i in count_dict:
count_list.append([count_dict[i], i])
count_list.sort() # Sort least to greatest so the head is now the most rare pieces
self.priority_list = [i[1] for i in count_list] # Put the piece numbers in order of rarity, into the priority_list
def add_gossip(self, msg):
# Add to end of queue (if it is not a message from this node).
if msg[0] == self.id:
return
# Delete old gossip messages from this node.
del_list = []
for i in self.gossip_queue:
if i[0] == msg[0]:
del_list.append(i)
[self.gossip_queue.remove(i) for i in del_list]
self.gossip_queue.append(msg)
def gossip(self):
# Step 1: Send my latest gossip message
# Find the three rarest pieces within my peer set
all_peers = self.peers.keys() + self.unchoked.keys()
piece_list = []
piece_dict = {}
for j in range(NUM_PIECES):
cnt = 0
for i in all_peers:
if j in nodes[i].have_pieces:
cnt += 1
if j in self.requested:
cnt += 1
piece_dict[j] = cnt
piece_list.append([cnt, j])
piece_list.sort()
rare_list = [i[1] for i in piece_list if i[1] not in self.have_pieces][0:3]
# If there is anything to send.
if len(rare_list) > 0:
# Form the gossip message
gossip_msg = [self.id, self.my_gossip_num, rare_list]
# Send it to all peers (call node[i].add_gossip()
for i in all_peers:
nodes[i].add_gossip(gossip_msg)
# Update my gossip sequence number
self.my_gossip_num += 1
# Step 2: Process my gossip queue and form the list of peer candidates
print wq.cur_time,': Processing gossip queue for node',self.id
print 'gossip_queue:',self.gossip_queue
print 'have list:',self.have_pieces.keys()
print
peer_candidates = []
for msg in self.gossip_queue:
make_peer = False
if GOSSIP_STYLE == 'peering':
# If the node is not already a peer
if msg[0] not in all_peers:
# See if I have the piece
ppiece = []
for j in msg[2]:
if j in self.have_pieces:
if msg[0] not in peer_candidates:
peer_candidates.append(msg[0])
# If so, then decide whether to peer with the source node
# I have a 2/P chance to peer with this node
upper_bound = 0.2
if piece_dict[j] == 0:
probability = upper_bound
else:
probability = upper_bound / piece_dict[j]
if random.random() < probability:
make_peer = True
ppiece.append(j)
# Add the peer if necessary
if make_peer and (self.num_peers() < self.max_peers) and (nodes[msg[0]].num_peers() < self.max_peers):
print wq.cur_time,': gossip resulted in new peering between',self.id,'and',msg[0],'for one of these pieces:',ppiece
self.add_peer(msg[0], wq.cur_time)
nodes[msg[0]].add_peer(self.id, wq.cur_time)
# Initialize the node's sequence number if necessary
if msg[0] not in self.peer_gossip_numbers:
self.peer_gossip_numbers[msg[0]] = 0
# Decide whether to forward message to peers
if msg[1] > self.peer_gossip_numbers[msg[0]]:
# Update the gossip sequence number for this node.
self.peer_gossip_numbers[msg[0]] = msg[1]
# Forward the message to my peers if I didn't peer this node
if not make_peer:
for i in all_peers:
nodes[i].add_gossip(msg)
elif GOSSIP_STYLE == 'priority':
#make sure this is a fresh message
if msg[0] in self.peer_gossip_numbers:
if msg[1] < self.peer_gossip_numbers[msg[0]]:
break
#temporary dictionary of gossiped pieces
temp_dict = {}
for i in self.gossip_rare:
if i[1] in self.priority_list:
temp_dict[i[1]] = i[0]
#clear the gossip_rare list, we're about to rebuild it
self.gossip_rare = []
#update gossip piece counts
#this is weighted by the place of the piece in rare message
#most rare = count + 1.3, second most rare = count + 1.2, etc
count = 1.3
for i in msg[2]:
# don't add it to the rarest list if we have already requested or gotten it from someone
# in which case it would no longer be in the priority queue
# ** In the all implementation of gossip the else of this if should be an attempt to peer **
if i in self.priority_list:
if i in temp_dict.keys():
temp_dict[i] = temp_dict[i] + count
else:
temp_dict[i] = count
count = count - 0.1
#rebuild the gossip_rare list
for i in temp_dict.keys():
self.gossip_rare.append([temp_dict[i], i])
#sort the gossip_rare list, this returns least to greatest, but we want least to greatest
self.gossip_rare.sort()
#reverse the list so we get greatest to least
self.gossip_rare.reverse()
# Initialize the node's sequence number if necessary
if msg[0] not in self.peer_gossip_numbers:
self.peer_gossip_numbers[msg[0]] = 0
# Update the gossip sequence number for this node.
self.peer_gossip_numbers[msg[0]] = msg[1]
# Forward the message to my peers
for i in all_peers:
nodes[i].add_gossip(msg)
elif GOSSIP_STYLE == 'all':
#make sure this is a fresh message
if msg[0] in self.peer_gossip_numbers:
if msg[1] < self.peer_gossip_numbers[msg[0]]:
break
#temporary dictionary of gossiped pieces
temp_dict = {}
for i in self.gossip_rare:
if i[1] in self.priority_list:
temp_dict[i[1]] = i[0]
#clear the gossip_rare list, we're about to rebuild it
self.gossip_rare = []
#update gossip piece counts
#this is weighted by the place of the piece in rare message
#most rare = count + 1.3, second most rare = count + 1.2, etc
count = 1.3
ppiece = []
for i in msg[2]:
# don't add it to the rarest list if we have already requested or gotten it from someone
# in which case it would no longer be in the priority queue
if i in self.priority_list:
if i in temp_dict.keys():
temp_dict[i] = temp_dict[i] + count
else:
temp_dict[i] = count
# we actually have the piece so try to peer
elif i in self.have_list:
# If the node is not already a peer
if msg[0] not in all_peers:
if msg[0] not in peer_candidates:
peer_candidates.append(msg[0])
# If so, then decide whether to peer with the source node
# I have a 2/P chance to peer with this node
upper_bound = 0.2
if piece_dict[i] == 0:
probability = upper_bound
else:
probability = upper_bound / piece_dict[i]
if random.random() < probability:
make_peer = True
ppiece.append(i)
count = count - 0.1
# Add the peer if necessary
if make_peer and (self.num_peers() < self.max_peers) and (nodes[msg[0]].num_peers() < self.max_peers):
print wq.cur_time,': gossip resulted in new peering between',self.id,'and',msg[0],'for one of these pieces:',ppiece
self.add_peer(msg[0], wq.cur_time)
nodes[msg[0]].add_peer(self.id, wq.cur_time)
cont = True
while (cont):
cmd = raw_input('>')
if cmd == '':
cont = False
else:
print eval(cmd)
#rebuild the gossip_rare list
for i in temp_dict.keys():
self.gossip_rare.append([temp_dict[i], i])
#sort the gossip_rare list, this returns least to greatest, but we want least to greatest
self.gossip_rare.sort()
#reverse the list so we get greatest to least
self.gossip_rare.reverse()
# Initialize the node's sequence number if necessary
if msg[0] not in self.peer_gossip_numbers:
self.peer_gossip_numbers[msg[0]] = 0
# Update the gossip sequence number for this node.
self.peer_gossip_numbers[msg[0]] = msg[1]
# Forward the message to my peers
for i in all_peers:
nodes[i].add_gossip(msg)
# Step 3: Clear the gossip queue
self.gossip_queue = []