www.pudn.com > GGBT.rar > Choker.cpp


// Choker.cpp: implementation of the CChoker class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "testbt.h" 
#include "Choker.h" 
 
 
#include "Connection.h" 
#include "Upload.h" 
#include "SingleDownload.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
#define TIME_ROUND_ROBIN 10 //number of seconds to pause between round_robin. 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CChoker::CChoker(long lMaxUploads, HANDLE hevDone) 
{ 
	m_lMaxUploads = lMaxUploads; 
	m_hevDone = hevDone; 
 
	m_lCount = 0; 
	time(&m_tRoundRobin); 
 
	_test(); 
} 
 
CChoker::~CChoker() 
{ 
 
} 
 
void CChoker::connection_made(CConnection *pConnection) 
{ 
	m_connections.push_back(pConnection); 
	_rechoke(); 
} 
 
void CChoker::connection_lost(CConnection *pConnection) 
{ 
	vector::iterator it = find(m_connections.begin(), m_connections.end(), pConnection); 
	assert(it != m_connections.end()); 
	m_connections.erase(it); 
	if ((*it)->m_pUpload->is_interested() && !(*it)->m_pUpload->is_choked()) 
		_rechoke(); 
} 
 
void CChoker::interested(CConnection *pConnection) 
{ 
	vector::iterator it = find(m_connections.begin(), m_connections.end(), pConnection); 
	assert(it != m_connections.end()); 
	if (!(*it)->m_pUpload->is_choked()) 
		_rechoke(); 
 
} 
 
void CChoker::not_interested(CConnection *pConnection) 
{ 
	vector::iterator it = find(m_connections.begin(), m_connections.end(), pConnection); 
	assert(it != m_connections.end()); 
	if (!(*it)->m_pUpload->is_choked()) 
		_rechoke(); 
} 
 
 
bool CChoker::_snubbed(CConnection *pConnection) 
{ 
	if (IsEventSet(m_hevDone)) 
		return false; 
	return pConnection->m_pDownload->is_snubbed(); 
} 
 
long CChoker::_rate(CConnection *pConnection) 
{ 
	if (IsEventSet(m_hevDone)) 
		return pConnection->m_pUpload->get_rate(); 
	else 
		return pConnection->m_pDownload->get_rate(); 
} 
 
void CChoker::printitem(CPreferItem& item) 
{ 
	TRACE("(%d,%d)", item.m_lrate, item.m_pConnection); 
} 
 
void CChoker::_rechoke() 
{ 
	vector vPreferred; 
 
	for (int i=0; im_pUpload->is_interested()) 
		{ 
			vPreferred.push_back(CPreferItem(_rate(m_connections[i]), m_connections[i])); 
		} 
 
	sort(vPreferred.begin(), vPreferred.end(), greater()); 
	if (vPreferred.size() > m_lMaxUploads) 
		vPreferred.erase(vPreferred.begin() + m_lMaxUploads, vPreferred.end()); 
	long lCount = vPreferred.size(); 
 
	/* 
	TRACE("\r\n_rechoke() {"); 
	for_each(vPreferred.begin(), vPreferred.end(), printitem); 
	TRACE("}\r\n"); 
	//*/ 
 
	for (i=0; im_pUpload; 
 
		bool bfind = false; 
		for (int j=0; junchoke(); 
		else 
		{ 
			if (lCount < m_lMaxUploads) 
			{ 
				pu->unchoke(); 
				if (pu->is_interested()) 
					lCount ++; 
			} 
			else 
				pu->choke(); 
		} 
 
	} 
} 
 
time_t CChoker::round_robin() 
{ 
	time_t t; 
	time(&t); 
	time_t tspan = t - m_tRoundRobin; 
	assert(tspan >= 0); 
	if (tspan < 0) 
		m_tRoundRobin = t; 
	if (tspan < TIME_ROUND_ROBIN) 
		return TIME_ROUND_ROBIN - tspan; 
 
	// TRACE("round_robin() "); 
	_round_robin(); 
 
	time(&m_tRoundRobin); 
	return TIME_ROUND_ROBIN; 
} 
 
void CChoker::_round_robin() 
{ 
	m_lCount++; 
	if (m_lCount%3 == 0) 
	{ 
		for (int i=0; im_pUpload; 
			if (pu->is_choked() && pu->is_interested()) 
			{ 
				rotate(m_connections.begin(), m_connections.begin() + i, m_connections.end()); 
				break; 
			} 
		} 
	} 
 
	_rechoke(); 
} 
 
void CChoker::SetMaxUploads(long lMaxUploads) 
{ 
	if (lMaxUploads <= 0) 
	{ 
		assert(false); 
		return; 
	} 
	m_lMaxUploads = lMaxUploads; 
} 
 
void printl(CConnection* l) 
{ 
	TRACE("%d, ", l); 
} 
 
void CChoker::_test() 
{	 
	/* 
	for (int i=0; i<5; i++) 
	{ 
		m_connections.push_back((CConnection*)i); 
	} 
	 
	TRACE("\r\n{"); 
	for_each(m_connections.begin(), m_connections.end(), printl); 
	TRACE("}\r\n"); 
 
	rotate(m_connections.begin(), m_connections.begin() + 2, m_connections.end()); 
	// iter_swap(m_connections.begin() + 4, m_connections.begin() + 2); 
	/* 
	CConnection* pold = m_connections[4]; 
	m_connections[4] = m_connections[2]; 
	m_connections[2] = pold; 
	 
	 
	 
	TRACE("\r\n{"); 
	for_each(m_connections.begin(), m_connections.end(), printl); 
	TRACE("}\r\n");//*/ 
 
	/* 
	for (int i=0; i<100; i++) 
	{ 
		Sleep(3000); 
		time_t td = round_robin(); 
		TRACE("time delay %d\r\n", td); 
	} 
	int ii = 0; 
	//*/ 
	// _rechoke(); 
}