📄 btalgorithmrechoke.cpp
字号:
#include <algorithm>
#include "BTAlgorithmRechoke.h"
#include "BTEvent.h"
#include "BTSocket.h"
#include "SimEventScheduler.h"
#include "BTPeer.h"
#include "BTEvent.h"
#include "BTSession.h"
#include "Sysparameter.h"
#include "Debug.h"
#include "BT.h"
#include "BTTracker.h"
#include "Topology.h"
BTAlgorithmRechoke::BTAlgorithmRechoke( BTSession* session){
mSession = session;
mRechokeInterval = RECHOKE_INTERVAL;
mOptimisticInterval = OPTIMISTIC_INTERVAL;
mSnubDetectInterval = SNUB_CHECK_INTERVAL;
mSnubUnchokeNum = SNUB_UNCHOKE_NUM;
mUnchokeNum = MAX_UNCHOKE_NUM;
mOptimisticLastRunningTime = 0;
mSnubDetectLastRunningTime = 0;
};
bool InCompare::operator()(BTSocket* const & peer1, BTSocket* const & peer2) const{
double timestamp = Scheduler.getCurrent() - 2*RECHOKE_INTERVAL;
double num1 = peer1->calcInAverageBandwidthSince( timestamp);
double num2 = peer2->calcInAverageBandwidthSince(timestamp);
if( num1 > num2)
return true;
else
return false;
};
bool OutCompare::operator()(BTSocket* const & peer1, BTSocket* const & peer2) const{
double timestamp = Scheduler.getCurrent() - 2*RECHOKE_INTERVAL;
double num1 = peer1->calcOutAverageBandwidthSince( timestamp);
double num2 = peer2->calcOutAverageBandwidthSince(timestamp);
if( num1 > num2)
return true;
else
return false;
};
void BTAlgorithmRechoke::handler(SimEvent* event){
if( mSession->mState == stopped || !mSession->mActive){
delete event;
return;
}
//check if seed should retire
if( mSession->mAgent->mType == superseed )
if( mSession->checkRetire())
return;
//session check timout
mSession->checkTimeout();
//if peer is superseed should compute the unchoke number first
unsigned int avlConNum = mUnchokeNum;
if( mSession->mAgent->mType == superseed)
avlConNum = mSession->mAgent->getAvalConNum();
vector< BTSocket*>* connections = mSession->getConnections();
if( connections->size() == 0){
delete connections;
if( mRechoke != NULL ){
delete event;
mRechoke = NULL;
}
return;
}
set<BTPeer*>* unchokepeerlist = mSession->getUnchoklist();
unchokepeerlist->clear();
if( mSession->getDocument()->isWhole())
sort( connections->begin(), connections->end(), OutCompare());
else
sort(connections->begin(), connections->end(), InCompare());
//for debug
DEBUG(RECHOKEDEBUGLEVEL){
printf("in peer %d rechoke before algorithm sessionnum %d\n", mSession->getAgent()->getID(), mSession->mAgent->getActiveSessionNum());
print();
printCon(connections);
}
BTSocket* con = NULL;
BTPeer* peer = NULL;
unsigned int unchokeNum =0;
unsigned int i = 0;
for( ; i< (connections->size()) && unchokeNum < avlConNum; i++){
con = (*connections)[i];
peer = con->mCounterPart->mSession->getAgent();
if( mSession->getDocument()->isWhole() ||(!mSession->getDocument()->isWhole()&&con->mPeerInsterested ) ){
mSession->sendChoke(false, con);
mSession->removePeerFromCandidates(peer);
unchokepeerlist->insert(peer);
unchokeNum++;
}
}
if( connections->size() > i){
for(unsigned int j = i+1; j< connections->size(); j++){
con = (*connections)[j];
peer = con->mCounterPart->mSession->getAgent();
if( con->mPeerInsterested){
mSession->sendChoke(true, con);
if( !mSession->inCandidate( peer))
mSession->addPeerCandidates(peer);
}
}
}
//for debug
DEBUG(RECHOKEDEBUGLEVEL) {
printf("in peer %d rechoke after rechoke algorithm\n", mSession->getAgent()->getID());
print();
}
//for debug
optimisticUnchoke();
snubDetect();
nextSchedule();
delete connections;
delete event;
};
void BTAlgorithmRechoke::nextSchedule(void){
BTEvent* bte = new BTEvent( RECHOCK, Scheduler.getCurrent() + mRechokeInterval, this, NULL);
Scheduler.enqueue(bte);
mRechoke = bte;
};
void BTAlgorithmRechoke::optimisticUnchoke(void){
if( mSession->mDocument->isWhole() )
return;
//first running
if( mOptimisticLastRunningTime == 0){
vector<BTPeer*>* peerCandidates = mSession->getPeerCandidates();
mOptimisticLastRunningTime = Scheduler.getCurrent();
if( peerCandidates->size() > 0){
BTPeer* peer = *(peerCandidates->begin());
mSession->connectTo( peer, false );
return;
}
return;
}
//interval time not enough do nothing
if( Scheduler.getCurrent() - mOptimisticLastRunningTime < mOptimisticInterval)
return;
//interval time pass chose one peer to unchoke
vector<BTPeer*>* peerCandidates = mSession->getPeerCandidates();
mOptimisticLastRunningTime = Scheduler.getCurrent();
if( peerCandidates->size() > 0){
BTPeer* peer = *(peerCandidates->begin());
mSession->connectTo( peer, false );
}
mOptimisticLastRunningTime = Scheduler.getCurrent();
};
void BTAlgorithmRechoke::snubDetect(void){
if( Scheduler.getCurrent() - mSnubDetectLastRunningTime < mSnubDetectInterval)
return;
if( mSession->getDocument()->isWhole())
return;
if( mSession->getAmountBetweenSnubDect() == 0){
if( mSession->ifNoAvailablePeer()){
bt.mTracker->sendEspRecover( mSession->mDocument->mkey );
mSession->requestEsp();
return;
}
vector<BTSocket*>* connectionlist = mSession->getConnections();
random_shuffle(connectionlist->begin(), connectionlist->end());
BTPeer* peer = NULL;
unsigned int i = 0;
for(; i< mSnubUnchokeNum && i < connectionlist->size() ; i++ ){
peer = (*connectionlist)[i]->mSession->getAgent();
if( !mSession->inUnchokeList( peer))
mSession->connectTo( peer, false);
};
mSession->setAmountBetweenSnubDect( 0 );
delete connectionlist;
}
mSession->setAmountBetweenSnubDect( 0 );
mSnubDetectLastRunningTime = Scheduler.getCurrent();
};
void BTAlgorithmRechoke::print(void){
BTPeer* peer = NULL;
set<BTPeer*>::iterator aIt = mSession->getUnchoklist()->begin();
printf(" unchokepeerlist: \n");
while( aIt != mSession->getUnchoklist()->end()){
peer = *(aIt++);
printf("peer %d", peer->getID());
}
printf("\n");
printf(" peercandidates: \n");
vector<BTPeer*>::iterator pIt = mSession->getPeerCandidates()->begin();
while( pIt != mSession->getPeerCandidates()->end()){
peer = *(pIt ++);
printf("peer %d", peer->getID());
}
printf("\n");
}
void BTAlgorithmRechoke::printCon( vector<BTSocket*>* conlist){
BTSocket* peer;
for( unsigned int i = 0; i< conlist->size(); i++){
peer = (*conlist)[i];
printf("con to peer %d inbandwidth %f outbandwidth%f\n", peer->mCounterPart->mSession->getAgent()->getID(), peer->calcInAverageBandwidthSince( Scheduler.getCurrent()- 2*RECHOKE_INTERVAL), peer->calcOutAverageBandwidthSince(Scheduler.getCurrent()- 2*RECHOKE_INTERVAL));
}
}
void BTAlgorithmRechoke::cancelRechoke(void){
if( mRechoke == NULL)
return;
Scheduler.cancel( mRechoke);
delete mRechoke;
mRechoke = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -