instrumentation: add next-share/
[cs-p2p-next.git] / instrumentation / next-share / BaseLib / Core / BitTornado / BT1 / Statistics.py
1 # Written by Edward Keyes
2 # see LICENSE.txt for license information
3
4 from threading import Event
5 try:
6     True
7 except:
8     True = 1
9     False = 0
10
11 class Statistics_Response:
12     pass    # empty class
13
14
15 class Statistics:
16     def __init__(self, upmeasure, downmeasure, connecter, ghttpdl, hhttpdl,
17                  ratelimiter, rerequest_lastfailed, fdatflag):
18         self.upmeasure = upmeasure
19         self.downmeasure = downmeasure
20         self.connecter = connecter
21         self.ghttpdl = ghttpdl
22         self.hhttpdl = hhttpdl
23         self.ratelimiter = ratelimiter
24         self.downloader = connecter.downloader
25         self.picker = connecter.downloader.picker
26         self.storage = connecter.downloader.storage
27         self.torrentmeasure = connecter.downloader.totalmeasure
28         self.rerequest_lastfailed = rerequest_lastfailed
29         self.fdatflag = fdatflag
30         self.fdatactive = False
31         self.piecescomplete = None
32         self.placesopen = None
33         self.storage_totalpieces = len(self.storage.hashes)
34
35
36     def set_dirstats(self, files, piece_length):
37         self.piecescomplete = 0
38         self.placesopen = 0
39         self.filelistupdated = Event()
40         self.filelistupdated.set()
41         frange = xrange(len(files))
42         self.filepieces = [[] for x in frange]
43         self.filepieces2 = [[] for x in frange]
44         self.fileamtdone = [0.0 for x in frange]
45         self.filecomplete = [False for x in frange]
46         self.fileinplace = [False for x in frange]
47         start = 0L
48         for i in frange:
49             l = files[i][1]
50             if l == 0:
51                 self.fileamtdone[i] = 1.0
52                 self.filecomplete[i] = True
53                 self.fileinplace[i] = True
54             else:
55                 fp = self.filepieces[i]
56                 fp2 = self.filepieces2[i]
57                 for piece in range(int(start/piece_length), 
58                                    int((start+l-1)/piece_length)+1):
59                     fp.append(piece)
60                     fp2.append(piece)
61                 start += l
62
63
64     def update(self):
65         s = Statistics_Response()
66         s.upTotal = self.upmeasure.get_total()
67         s.downTotal = self.downmeasure.get_total()
68         s.last_failed = self.rerequest_lastfailed()
69         s.external_connection_made = self.connecter.external_connection_made
70         if s.downTotal > 0:
71             s.shareRating = float(s.upTotal)/s.downTotal
72         elif s.upTotal == 0:
73             s.shareRating = 0.0
74         else:
75             s.shareRating = -1.0
76         s.torrentRate = self.torrentmeasure.get_rate()
77         s.torrentTotal = self.torrentmeasure.get_total()
78         s.numSeeds = self.picker.seeds_connected
79         s.numOldSeeds = self.downloader.num_disconnected_seeds()
80         s.numPeers = len(self.downloader.downloads)-s.numSeeds
81         s.numCopies = 0.0
82         for i in self.picker.crosscount:
83             if i==0:
84                 s.numCopies+=1
85             else:
86                 s.numCopies+=1-float(i)/self.picker.numpieces
87                 break
88         if self.picker.done:
89             s.numCopies2 = s.numCopies + 1
90         else:
91             s.numCopies2 = 0.0
92             for i in self.picker.crosscount2:
93                 if i==0:
94                     s.numCopies2+=1
95                 else:
96                     s.numCopies2+=1-float(i)/self.picker.numpieces
97                     break
98         s.discarded = self.downloader.discarded
99         s.numSeeds += self.ghttpdl.seedsfound
100         s.numSeeds += self.hhttpdl.seedsfound
101         s.numOldSeeds += self.ghttpdl.seedsfound
102         s.numOldSeeds += self.hhttpdl.seedsfound
103         if s.numPeers == 0 or self.picker.numpieces == 0:
104             s.percentDone = 0.0
105         else:
106             s.percentDone = 100.0*(float(self.picker.totalcount)/self.picker.numpieces)/s.numPeers
107
108         s.backgroundallocating = self.storage.bgalloc_active
109         s.storage_totalpieces = len(self.storage.hashes)
110         s.storage_active = len(self.storage.stat_active)
111         s.storage_new = len(self.storage.stat_new)
112         s.storage_dirty = len(self.storage.dirty)
113         numdownloaded = self.storage.stat_numdownloaded
114         s.storage_justdownloaded = numdownloaded
115         s.storage_numcomplete = self.storage.stat_numfound + numdownloaded
116         s.storage_numflunked = self.storage.stat_numflunked
117         s.storage_isendgame = self.downloader.endgamemode
118
119         s.peers_kicked = self.downloader.kicked.items()
120         s.peers_banned = self.downloader.banned.items()
121
122         try:
123             s.upRate = int(self.ratelimiter.upload_rate/1000)
124             assert s.upRate < 5000
125         except:
126             s.upRate = 0
127         s.upSlots = self.ratelimiter.slots
128
129         s.have = self.storage.get_have_copy()
130
131         if self.piecescomplete is None:     # not a multi-file torrent
132             return s
133         
134         if self.fdatflag.isSet():
135             if not self.fdatactive:
136                 self.fdatactive = True
137         else:
138             self.fdatactive = False
139
140         if self.piecescomplete != self.picker.numgot:
141             for i in xrange(len(self.filecomplete)):
142                 if self.filecomplete[i]:
143                     continue
144                 oldlist = self.filepieces[i]
145                 newlist = [ piece
146                             for piece in oldlist
147                             if not self.storage.have[piece] ]
148                 if len(newlist) != len(oldlist):
149                     self.filepieces[i] = newlist
150                     self.fileamtdone[i] = (
151                         (len(self.filepieces2[i])-len(newlist))
152                          /float(len(self.filepieces2[i])) )
153                     if not newlist:
154                         self.filecomplete[i] = True
155                     self.filelistupdated.set()
156
157             self.piecescomplete = self.picker.numgot
158
159         if ( self.filelistupdated.isSet()
160                  or self.placesopen != len(self.storage.places) ):
161             for i in xrange(len(self.filecomplete)):
162                 if not self.filecomplete[i] or self.fileinplace[i]:
163                     continue
164                 while self.filepieces2[i]:
165                     piece = self.filepieces2[i][-1]
166                     if self.storage.places[piece] != piece:
167                         break
168                     del self.filepieces2[i][-1]
169                 if not self.filepieces2[i]:
170                     self.fileinplace[i] = True
171                     self.storage.set_file_readonly(i)
172                     self.filelistupdated.set()
173
174             self.placesopen = len(self.storage.places)
175
176         s.fileamtdone = self.fileamtdone
177         s.filecomplete = self.filecomplete
178         s.fileinplace = self.fileinplace
179         s.filelistupdated = self.filelistupdated
180
181         return s
182