TorrentStats.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # The contents of this file are subject to the BitTorrent Open Source License
  2. # Version 1.1 (the License). You may not copy or use this file, in either
  3. # source code or executable form, except in compliance with the License. You
  4. # may obtain a copy of the License at http://www.bittorrent.com/license/.
  5. #
  6. # Software distributed under the License is distributed on an AS IS basis,
  7. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  8. # for the specific language governing rights and limitations under the
  9. # License.
  10. # Written by Bram Cohen, Uoti Urpala
  11. from __future__ import division
  12. class TorrentStats(object):
  13. def __init__(self, logger, choker, upfunc, downfunc, uptotal, downtotal,
  14. remainingfunc, pcfunc, piece_states, finflag,
  15. connection_manager, multidownload, file_priorities,
  16. files, ever_got_incoming, rerequester):
  17. self.logger = logger
  18. self.multidownload = multidownload
  19. self.connection_manager = connection_manager
  20. self.file_priorities = file_priorities
  21. self.picker = multidownload.picker
  22. self.storage = multidownload.storage
  23. self.choker = choker
  24. self.connection_manager = connection_manager
  25. self.upfunc = upfunc
  26. self.downfunc = downfunc
  27. self.uptotal = uptotal
  28. self.downtotal = downtotal
  29. self.remainingfunc = remainingfunc
  30. self.pcfunc = pcfunc
  31. self.piece_states = piece_states
  32. self.finflag = finflag
  33. self.files = files
  34. self.ever_got_incoming = ever_got_incoming
  35. self.rerequester = rerequester
  36. def collect_spew(self, numpieces):
  37. l = []
  38. for c in self.connection_manager.complete_connectors:
  39. rec = {}
  40. rec['id'] = c.id
  41. rec['hostname'] = c.hostname
  42. rec["ip"] = c.ip
  43. rec["is_optimistic_unchoke"] = (c is self.choker.connections[0])
  44. if c.locally_initiated:
  45. rec["initiation"] = "L"
  46. else:
  47. rec["initiation"] = "R"
  48. if c._decrypt:
  49. rec["initiation"] += '+'
  50. u = c.upload
  51. rec['upload'] = (u.measure.get_total(), int(u.measure.get_rate()),
  52. u.interested, u.choked)
  53. d = c.download
  54. rec['download'] = (d.measure.get_total(), int(d.measure.get_rate()),
  55. d.interested, d.choked, d.is_snubbed())
  56. rec['max_backlog'] = d._backlog()
  57. rec['current_backlog'] = len(d.active_requests)
  58. rec['client_backlog'] = len(u.buffer)
  59. rec['client_buffer'] = sum([ i[0][2] for i in u.buffer ])
  60. rec['total_downloaded'] = d.total_bytes
  61. rec['completed'] = 1 - d.have.numfalse / numpieces
  62. rec['speed'] = d.connector.download.peermeasure.get_rate()
  63. if d.have.numfalse > 0:
  64. rec['total_eta'] = self.storage.total_length / max(1, d.connector.download.peermeasure.get_rate())
  65. l.append(rec)
  66. return l
  67. def get_swarm_speed(self):
  68. speed = 0
  69. for c in self.connection_manager.complete_connectors:
  70. speed += c.download.connector.download.peermeasure.get_rate()
  71. return speed
  72. def get_statistics(self, spewflag=False, fileflag=False):
  73. status = {}
  74. numSeeds = 0
  75. numPeers = 0
  76. for d in self.multidownload.downloads:
  77. numPeers += 1
  78. if d.have.numfalse == 0:
  79. numSeeds += 1
  80. status['numSeeds'] = numSeeds
  81. status['numPeers'] = numPeers
  82. if self.rerequester:
  83. status['trackerSeeds'] = self.rerequester.tracker_num_seeds
  84. status['trackerPeers'] = self.rerequester.tracker_num_peers
  85. if status['trackerSeeds'] is not None:
  86. if status['trackerPeers'] is not None:
  87. status['trackerPeers'] += status['trackerSeeds']
  88. else:
  89. status['trackerPeers'] = status['trackerSeeds']
  90. status['announceTime'] = self.rerequester.get_next_announce_time_est()
  91. else:
  92. status['trackerSeeds'] = None
  93. status['trackerPeers'] = None
  94. status['announceTime'] = None
  95. status['upRate'] = self.upfunc()
  96. status['upTotal'] = self.uptotal()
  97. status['ever_got_incoming'] = self.ever_got_incoming()
  98. status['distributed_copies'] = self.multidownload.get_adjusted_distributed_copies()
  99. status['discarded'] = self.multidownload.discarded_bytes
  100. status['swarm_speed'] = self.get_swarm_speed()
  101. status['pieceStates'] = self.piece_states()
  102. if spewflag:
  103. status['spew'] = self.collect_spew(self.multidownload.numpieces)
  104. status['bad_peers'] = self.multidownload.bad_peers
  105. if fileflag:
  106. undl = self.storage.storage.undownloaded
  107. status['files_left'] = [undl[fname] for fname in self.files]
  108. status['file_priorities'] = dict(self.file_priorities())
  109. if self.finflag.isSet():
  110. status['downRate'] = 0
  111. status['downTotal'] = self.downtotal()
  112. status['fractionDone'] = 1
  113. return status
  114. timeEst = self.remainingfunc()
  115. status['timeEst'] = timeEst
  116. fractionDone = self.pcfunc()
  117. status.update({
  118. "fractionDone" : fractionDone,
  119. "downRate" : self.downfunc(),
  120. "downTotal" : self.downtotal()
  121. })
  122. return status