Statistics
| Branch: | Revision:

mobicen / varie / util / oldNode.py @ 9110387b

History | View | Annotate | Download (8.04 KB)

1
from prettytable import PrettyTable
2
import os
3
import EventScheduler, MyUtil
4
import code
5

    
6
class Node(object):
7

    
8
    def __init__(self, name, outFolder):
9
        self.name = name
10
        self.RT={} #RoutingTable {destName:{'distance':float, 'NHs':[lista dei next-hop equivalenti]}}
11
        self.RT[name] = {'distance': 0.0, 'NHs': [name]}
12
        self.neighs={} #key: neigh_name, linkCost: attributes of neigh eg{'weight':float}
13
        self.bufferedDV={}
14

    
15
    def set_Neighbours(self,neighs):
16
        self.neighs.update(neighs)
17

    
18
    def getLinkCost(self, v):
19
        if (v in self.neighs):
20
            try:
21
                return float(self.neighs[v]['weight'])
22
            except KeyError:
23
                return 1.0
24
        return 1000.0
25

    
26

    
27

    
28
class LegacyNode(Node):
29

    
30
    def printNode(self):
31
        print "LegacyNode: "+self.name
32
        t = PrettyTable(['DEST', 'NHs'])
33
        for d in self.RT:
34
            t.add_row([str(d), self.RT[d]['NHs']])
35
        print t
36

    
37

    
38
    def sendDV(self):
39
        toSend = {}     #prepare standard DV (plus dummy-propagation of buffered info) 
40
        
41
        for dest in self.RT:    #Plain DV protocol
42
            dist = self.RT[dest]['distance']
43

    
44
            if (dest in self.bufferedDV and len(self.bufferedDV[dest]) > 1): #dummy propagation
45

    
46
                CentrInfo = self.bufferedDV[dest][1] #a tuple (creator,rdist,splitcontr,load)
47
                toSend[dest] = (dist, CentrInfo)
48
            else:
49
                toSend[dest] = (dist,)           
50

    
51
        return toSend
52

    
53

    
54
    def processRecInfo(self, time, senderName, DV):
55
        self.bufferedDV = DV    #store last received DV in RX_buffer
56
        lc = self.getLinkCost(senderName)
57

    
58
        for dest in DV:
59
            adv_dist = DV[dest][0]
60
            #Bellman-Ford (multi  NHs)
61
            if dest not in self.RT:
62
                self.RT[dest] = {'distance': adv_dist + lc, 'NHs': [senderName]}
63
            else:
64
                cdist = self.RT[dest]['distance']
65
                if (adv_dist + lc <= cdist):
66
                    if (adv_dist + lc < cdist):
67
                        self.RT[dest]['distance'] = adv_dist + lc
68
                        self.RT[dest]['NHs'] = [senderName]
69
                    elif (adv_dist + lc == cdist):
70
                        if (senderName not in self.RT[dest]['NHs']):
71
                            self.RT[dest]['NHs'].append(senderName)
72

    
73

    
74
class PopNode(Node):
75

    
76
    def __init__(self, name, outFolder):
77
        Node.__init__(self, name, outFolder)
78
        self.DT = {name: {'contribs': {}, 'Load': 0.0}} #DestinationTable {destName: {'contribs':{neigh: contrib}, 'Load':load of dest}}
79
        
80
            
81
    def printNode(self):
82
        print "PopNode: "+self.name+ " - Load: "+str(self.computeCentrality())
83
        t = PrettyTable(['DEST', 'NHs','CONTRs','Load'])
84
        for d in self.RT:
85
            contr_string = ""
86
            try:
87
                contributors = self.DT[d]['contribs']
88
                contr_string = str(contributors)
89
            except:
90
                contr_string="[//]"
91
                pass
92
            t.add_row([str(d), self.RT[d]['NHs'], contr_string, str(self.DT[d]['Load'])])
93
        print t
94

    
95

    
96
    #send DV to all neighbours and schedule next sending
97
    def sendDV(self):
98
        #update centrality
99
        myCentr = self.computeCentrality()
100
        toSend = {}     #prepare DV as dict {dest_name:(distance,CentrInfo=(NHs,contribute,Load))}
101
        
102
        for dest in self.RT:
103
            dist = self.RT[dest]['distance']
104
            NHs = self.RT[dest]['NHs']
105
            Load = -1.0
106
            try:
107
                Load = self.DT[dest]['Load']
108
            except:
109
                pass
110
            mycontr = 1.0 #my contributes for any dest is at least 1, counting for me
111
            try:
112
                contributors = self.DT[dest]['contribs']
113
                mycontr = 1.0 + sum(self.DT[dest]['contribs'].values())
114
            except KeyError:
115
                # if I know dest but I do not have any contributes for it
116
                pass        
117
            #Split contributes before sending them
118
            splitcontr = mycontr / len(NHs)
119
            # CentrInfo = (creator, creator_dist, splitcontr, load)
120
            toSend[dest] = (dist, (self.name, dist, splitcontr, Load)) 
121

    
122
        return toSend
123

    
124

    
125
    def processRecInfo(self, time, senderName, DV):
126
        
127
        myCentr = self.computeCentrality()
128
        lc = self.getLinkCost(senderName)
129

    
130
        for dest in DV:
131
            '''if (dest==self.name):
132
                continue'''
133
            adv_dist = DV[dest][0]
134
            #Bellman-Ford (multi  NHs)
135
            if dest not in self.RT:
136
                self.RT[dest] = {'distance': adv_dist + lc, 'NHs': [senderName]}
137
                self.DT[dest] = {'contribs': {}, 'Load': 0.0}
138
            else:
139
                cdist = self.RT[dest]['distance']
140
                if (adv_dist + lc <= cdist):
141
                    if (adv_dist + lc < cdist):
142
                        self.RT[dest]['distance'] = adv_dist + lc
143
                        self.RT[dest]['NHs'] = [senderName]
144
                    elif (adv_dist + lc == cdist):
145
                        if (senderName not in self.RT[dest]['NHs']):
146
                            self.RT[dest]['NHs'].append(senderName)
147

    
148
        # END Bellman-Ford, now RT is up-to-date
149
            
150
        # Guerrieri + contributions intercepting
151
        for dest in DV:
152
            try:
153
                CentrInfo = DV[dest][1]
154
            except IndexError as e:
155
                #No CentrInfo
156
                pass
157
            else:
158
                creator = CentrInfo[0]
159
                rdist = CentrInfo[1]
160
                splitcontr = CentrInfo[2]
161
                Load = CentrInfo[3]
162

    
163
                cdist = self.RT[dest]['distance']
164
                try:
165
                    rcost = self.RT[creator]['distance']
166
                except:
167
                    rcost = 1000000.0
168

    
169
                '''
170
                ### TUTOR OF LEGACY NEIGH ###
171
                tutor_addend = 0
172
                if (senderName != creator):
173
                    #il mio vicino e' legacy! genero un contributo da
174
                    #parte di senderName se sono suo NH per raggiungere dest
175
                    if (adv_dist >= lc + self.RT[dest]['distance'] and rcost < 1000000.0):
176
                        tutor_addend += (rcost * (rcost + 1) / 2) #si assume metrica hop
177
                        #tutor_addend += 1 #recupero
178
                '''
179

    
180
                #Intercetto se la mia cdist < rdist e, in particolare,
181
                # rdist >= cdist + rcost, perche' vuol dire che io giaccio
182
                # su un cammino minimo tra remote e dest
183
                # NB: i contributi pero' li taggo per vicino che me li consegna!!!
184
                # cammini minimi equivalenti possono infatti convergere in me e, 
185
                # pur provenendo dallo stesso remoteNode, arrivarmi gia' splittati.
186
                # Pertanto devo tenermi i contributi separati per vicino che me li manda
187
                if (cdist < rdist and (rdist >= cdist + rcost)):
188
                    #self.updateContributors(senderName, dest, splitcontr + tutor_addend) #con tutoring vicini Legacy
189
                    self.updateContributors(senderName, dest, splitcontr) #senza tutoring vicini Legacy
190
                else:
191
                    self.removeContr(senderName, dest)
192

    
193
                # La condizione di aggiornamento del Load puo' essere piu' blanda.
194
                # Se il remoteNode e' piu' vicino di me (punto e basta) allora mi fido.
195
                # Poiche' ogni link costa almeno 1 posso mettere < e non <=
196
                if (rdist < cdist):
197
                    self.DT[dest]['Load'] = Load
198
                    
199

    
200
    def computeCentrality(self):
201
        tot=0.0
202
        for d in self.DT:    
203
            if (d != self.name):
204
                part = sum(self.DT[d]['contribs'].values())
205
                tot += part
206
        self.DT[self.name]['Load'] = float(tot)
207
        return float(tot)
208

    
209

    
210
    def updateContributors(self, neighName, dest, contr):
211
        self.DT[dest]['contribs'][neighName] = contr
212

    
213

    
214
    def removeContr(self, neighName, dest):
215
        if neighName in self.DT[dest]['contribs']:
216
            self.DT[dest]['contribs'].pop(neighName)