Choker.cpp
上传用户:lds876
上传日期:2013-05-25
资源大小:567k
文件大小:5k
源码类别:

P2P编程

开发平台:

Visual C++

  1. // Choker.cpp: implementation of the CChoker class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "testbt.h"
  6. #include "Choker.h"
  7. #include "Connection.h"
  8. #include "Upload.h"
  9. #include "SingleDownload.h"
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[]=__FILE__;
  13. #define new DEBUG_NEW
  14. #endif
  15. #define TIME_ROUND_ROBIN 10 //number of seconds to pause between round_robin.
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. CChoker::CChoker(long lMaxUploads, HANDLE hevDone)
  20. {
  21. m_lMaxUploads = lMaxUploads;
  22. m_hevDone = hevDone;
  23. m_lCount = 0;
  24. time(&m_tRoundRobin);
  25. _test();
  26. }
  27. CChoker::~CChoker()
  28. {
  29. }
  30. void CChoker::connection_made(CConnection *pConnection)
  31. {
  32. m_connections.push_back(pConnection);
  33. _rechoke();
  34. }
  35. void CChoker::connection_lost(CConnection *pConnection)
  36. {
  37. vector<CConnection*>::iterator it = find(m_connections.begin(), m_connections.end(), pConnection);
  38. assert(it != m_connections.end());
  39. m_connections.erase(it);
  40. if ((*it)->m_pUpload->is_interested() && !(*it)->m_pUpload->is_choked())
  41. _rechoke();
  42. }
  43. void CChoker::interested(CConnection *pConnection)
  44. {
  45. vector<CConnection*>::iterator it = find(m_connections.begin(), m_connections.end(), pConnection);
  46. assert(it != m_connections.end());
  47. if (!(*it)->m_pUpload->is_choked())
  48. _rechoke();
  49. }
  50. void CChoker::not_interested(CConnection *pConnection)
  51. {
  52. vector<CConnection*>::iterator it = find(m_connections.begin(), m_connections.end(), pConnection);
  53. assert(it != m_connections.end());
  54. if (!(*it)->m_pUpload->is_choked())
  55. _rechoke();
  56. }
  57. bool CChoker::_snubbed(CConnection *pConnection)
  58. {
  59. if (IsEventSet(m_hevDone))
  60. return false;
  61. return pConnection->m_pDownload->is_snubbed();
  62. }
  63. long CChoker::_rate(CConnection *pConnection)
  64. {
  65. if (IsEventSet(m_hevDone))
  66. return pConnection->m_pUpload->get_rate();
  67. else
  68. return pConnection->m_pDownload->get_rate();
  69. }
  70. void CChoker::printitem(CPreferItem& item)
  71. {
  72. TRACE("(%d,%d)", item.m_lrate, item.m_pConnection);
  73. }
  74. void CChoker::_rechoke()
  75. {
  76. vector<CPreferItem> vPreferred;
  77. for (int i=0; i<m_connections.size(); i++)
  78. if (!_snubbed(m_connections[i]) && m_connections[i]->m_pUpload->is_interested())
  79. {
  80. vPreferred.push_back(CPreferItem(_rate(m_connections[i]), m_connections[i]));
  81. }
  82. sort(vPreferred.begin(), vPreferred.end(), greater<CPreferItem&>());
  83. if (vPreferred.size() > m_lMaxUploads)
  84. vPreferred.erase(vPreferred.begin() + m_lMaxUploads, vPreferred.end());
  85. long lCount = vPreferred.size();
  86. /*
  87. TRACE("rn_rechoke() {");
  88. for_each(vPreferred.begin(), vPreferred.end(), printitem);
  89. TRACE("}rn");
  90. //*/
  91. for (i=0; i<m_connections.size(); i++)
  92. {
  93. CUpload* pu = m_connections[i]->m_pUpload;
  94. bool bfind = false;
  95. for (int j=0; j<vPreferred.size(); j++)
  96. if (m_connections[i] == vPreferred[j].m_pConnection)
  97. {
  98. bfind = true;
  99. break;
  100. }
  101. if (bfind)
  102. pu->unchoke();
  103. else
  104. {
  105. if (lCount < m_lMaxUploads)
  106. {
  107. pu->unchoke();
  108. if (pu->is_interested())
  109. lCount ++;
  110. }
  111. else
  112. pu->choke();
  113. }
  114. }
  115. }
  116. time_t CChoker::round_robin()
  117. {
  118. time_t t;
  119. time(&t);
  120. time_t tspan = t - m_tRoundRobin;
  121. assert(tspan >= 0);
  122. if (tspan < 0)
  123. m_tRoundRobin = t;
  124. if (tspan < TIME_ROUND_ROBIN)
  125. return TIME_ROUND_ROBIN - tspan;
  126. // TRACE("round_robin() ");
  127. _round_robin();
  128. time(&m_tRoundRobin);
  129. return TIME_ROUND_ROBIN;
  130. }
  131. void CChoker::_round_robin()
  132. {
  133. m_lCount++;
  134. if (m_lCount%3 == 0)
  135. {
  136. for (int i=0; i<m_connections.size(); i++)
  137. {
  138. CUpload* pu = m_connections[i]->m_pUpload;
  139. if (pu->is_choked() && pu->is_interested())
  140. {
  141. rotate(m_connections.begin(), m_connections.begin() + i, m_connections.end());
  142. break;
  143. }
  144. }
  145. }
  146. _rechoke();
  147. }
  148. void CChoker::SetMaxUploads(long lMaxUploads)
  149. {
  150. if (lMaxUploads <= 0)
  151. {
  152. assert(false);
  153. return;
  154. }
  155. m_lMaxUploads = lMaxUploads;
  156. }
  157. void printl(CConnection* l)
  158. {
  159. TRACE("%d, ", l);
  160. }
  161. void CChoker::_test()
  162. {
  163. /*
  164. for (int i=0; i<5; i++)
  165. {
  166. m_connections.push_back((CConnection*)i);
  167. }
  168. TRACE("rn{");
  169. for_each(m_connections.begin(), m_connections.end(), printl);
  170. TRACE("}rn");
  171. rotate(m_connections.begin(), m_connections.begin() + 2, m_connections.end());
  172. // iter_swap(m_connections.begin() + 4, m_connections.begin() + 2);
  173. /*
  174. CConnection* pold = m_connections[4];
  175. m_connections[4] = m_connections[2];
  176. m_connections[2] = pold;
  177. TRACE("rn{");
  178. for_each(m_connections.begin(), m_connections.end(), printl);
  179. TRACE("}rn");//*/
  180. /*
  181. for (int i=0; i<100; i++)
  182. {
  183. Sleep(3000);
  184. time_t td = round_robin();
  185. TRACE("time delay %drn", td);
  186. }
  187. int ii = 0;
  188. //*/
  189. // _rechoke();
  190. }