DownloaderFeedback.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # Written by Bram Cohen
  2. # see LICENSE.txt for license information
  3. from cStringIO import StringIO
  4. from urllib import quote
  5. from threading import Event
  6. try:
  7. True
  8. except:
  9. True = 1
  10. False = 0
  11. INIT_STATE = (('R','R+'),('L','L+'))
  12. class DownloaderFeedback:
  13. def __init__(self, choker, httpdl, add_task, upfunc, downfunc,
  14. ratemeasure, leftfunc, file_length, finflag, sp, statistics,
  15. statusfunc = None, interval = None):
  16. self.choker = choker
  17. self.httpdl = httpdl
  18. self.add_task = add_task
  19. self.upfunc = upfunc
  20. self.downfunc = downfunc
  21. self.ratemeasure = ratemeasure
  22. self.leftfunc = leftfunc
  23. self.file_length = file_length
  24. self.finflag = finflag
  25. self.sp = sp
  26. self.statistics = statistics
  27. self.lastids = []
  28. self.spewdata = None
  29. self.doneprocessing = Event()
  30. self.doneprocessing.set()
  31. if statusfunc:
  32. self.autodisplay(statusfunc, interval)
  33. def _rotate(self):
  34. cs = self.choker.connections
  35. for id in self.lastids:
  36. for i in xrange(len(cs)):
  37. if cs[i].get_id() == id:
  38. return cs[i:] + cs[:i]
  39. return cs
  40. def spews(self):
  41. l = []
  42. cs = self._rotate()
  43. self.lastids = [c.get_id() for c in cs]
  44. for c in cs:
  45. a = {}
  46. a['id'] = c.get_readable_id()
  47. a['ip'] = c.get_ip()
  48. a['optimistic'] = (c is self.choker.connections[0])
  49. a['direction'] = INIT_STATE[c.is_locally_initiated()][c.is_encrypted()]
  50. u = c.get_upload()
  51. a['uprate'] = int(u.measure.get_rate())
  52. a['uinterested'] = u.is_interested()
  53. a['uchoked'] = u.is_choked()
  54. d = c.get_download()
  55. a['downrate'] = int(d.measure.get_rate())
  56. a['dinterested'] = d.is_interested()
  57. a['dchoked'] = d.is_choked()
  58. a['snubbed'] = d.is_snubbed()
  59. a['utotal'] = d.connection.upload.measure.get_total()
  60. a['dtotal'] = d.connection.download.measure.get_total()
  61. if len(d.connection.download.have) > 0:
  62. a['completed'] = float(len(d.connection.download.have)-d.connection.download.have.numfalse)/float(len(d.connection.download.have))
  63. else:
  64. a['completed'] = 1.0
  65. a['speed'] = d.connection.download.peermeasure.get_rate()
  66. l.append(a)
  67. for dl in self.httpdl.get_downloads():
  68. if dl.goodseed:
  69. a = {}
  70. a['id'] = 'http seed'
  71. a['ip'] = dl.baseurl
  72. a['optimistic'] = False
  73. a['direction'] = 'L'
  74. a['uprate'] = 0
  75. a['uinterested'] = False
  76. a['uchoked'] = False
  77. a['downrate'] = int(dl.measure.get_rate())
  78. a['dinterested'] = True
  79. a['dchoked'] = not dl.active
  80. a['snubbed'] = not dl.active
  81. a['utotal'] = None
  82. a['dtotal'] = dl.measure.get_total()
  83. a['completed'] = 1.0
  84. a['speed'] = None
  85. l.append(a)
  86. return l
  87. def gather(self, displayfunc = None):
  88. s = {'stats': self.statistics.update()}
  89. if self.sp.isSet():
  90. s['spew'] = self.spews()
  91. else:
  92. s['spew'] = None
  93. s['up'] = self.upfunc()
  94. if self.finflag.isSet():
  95. s['done'] = self.file_length
  96. return s
  97. s['down'] = self.downfunc()
  98. obtained, desired = self.leftfunc()
  99. s['done'] = obtained
  100. s['wanted'] = desired
  101. if desired > 0:
  102. s['frac'] = float(obtained)/desired
  103. else:
  104. s['frac'] = 1.0
  105. if desired == obtained:
  106. s['time'] = 0
  107. else:
  108. s['time'] = self.ratemeasure.get_time_left(desired-obtained)
  109. return s
  110. def display(self, displayfunc):
  111. if not self.doneprocessing.isSet():
  112. return
  113. self.doneprocessing.clear()
  114. stats = self.gather()
  115. if self.finflag.isSet():
  116. displayfunc(dpflag = self.doneprocessing,
  117. upRate = stats['up'],
  118. statistics = stats['stats'], spew = stats['spew'])
  119. elif stats['time'] is not None:
  120. displayfunc(dpflag = self.doneprocessing,
  121. fractionDone = stats['frac'], sizeDone = stats['done'],
  122. downRate = stats['down'], upRate = stats['up'],
  123. statistics = stats['stats'], spew = stats['spew'],
  124. timeEst = stats['time'])
  125. else:
  126. displayfunc(dpflag = self.doneprocessing,
  127. fractionDone = stats['frac'], sizeDone = stats['done'],
  128. downRate = stats['down'], upRate = stats['up'],
  129. statistics = stats['stats'], spew = stats['spew'])
  130. def autodisplay(self, displayfunc, interval):
  131. self.displayfunc = displayfunc
  132. self.interval = interval
  133. self._autodisplay()
  134. def _autodisplay(self):
  135. self.add_task(self._autodisplay, self.interval)
  136. self.display(self.displayfunc)