/* */ #include "DefaultBtRequestFactory.h" #include #include "LogFactory.h" #include "Logger.h" #include "Piece.h" #include "Peer.h" #include "PieceStorage.h" #include "BtMessageDispatcher.h" #include "BtMessageFactory.h" #include "BtMessage.h" #include "a2functional.h" #include "SimpleRandomizer.h" #include "array_fun.h" #include "fmt.h" namespace aria2 { DefaultBtRequestFactory::DefaultBtRequestFactory() : dispatcher_(0), messageFactory_(0) {} DefaultBtRequestFactory::~DefaultBtRequestFactory() {} void DefaultBtRequestFactory::addTargetPiece(const SharedHandle& piece) { pieces_.push_back(piece); } namespace { class AbortCompletedPieceRequest { private: BtMessageDispatcher* dispatcher_; public: AbortCompletedPieceRequest(BtMessageDispatcher* dispatcher): dispatcher_(dispatcher) {} void operator()(const SharedHandle& piece) { if(piece->pieceComplete()) { dispatcher_->doAbortOutstandingRequestAction(piece); } } }; } // namespace void DefaultBtRequestFactory::removeCompletedPiece() { std::for_each(pieces_.begin(), pieces_.end(), AbortCompletedPieceRequest(dispatcher_)); pieces_.erase(std::remove_if(pieces_.begin(), pieces_.end(), mem_fun_sh(&Piece::pieceComplete)), pieces_.end()); } void DefaultBtRequestFactory::removeTargetPiece (const SharedHandle& piece) { pieces_.erase(std::remove_if(pieces_.begin(), pieces_.end(), derefEqual(piece)), pieces_.end()); dispatcher_->doAbortOutstandingRequestAction(piece); pieceStorage_->cancelPiece(piece); } namespace { class ProcessChokedPiece { private: SharedHandle peer_; SharedHandle pieceStorage_; public: ProcessChokedPiece(const SharedHandle& peer, const SharedHandle& pieceStorage): peer_(peer), pieceStorage_(pieceStorage) {} void operator()(const SharedHandle& piece) { if(!peer_->isInPeerAllowedIndexSet(piece->getIndex())) { pieceStorage_->cancelPiece(piece); } } }; } // namespace namespace { class FindChokedPiece { private: SharedHandle peer_; public: FindChokedPiece(const SharedHandle& peer):peer_(peer) {} bool operator()(const SharedHandle& piece) { return !peer_->isInPeerAllowedIndexSet(piece->getIndex()); } }; } // namespace void DefaultBtRequestFactory::doChokedAction() { std::for_each(pieces_.begin(), pieces_.end(), ProcessChokedPiece(peer_, pieceStorage_)); pieces_.erase(std::remove_if(pieces_.begin(), pieces_.end(), FindChokedPiece(peer_)), pieces_.end()); } void DefaultBtRequestFactory::removeAllTargetPiece() { for(std::deque >::iterator itr = pieces_.begin(), eoi = pieces_.end(); itr != eoi; ++itr) { dispatcher_->doAbortOutstandingRequestAction(*itr); pieceStorage_->cancelPiece(*itr); } pieces_.clear(); } void DefaultBtRequestFactory::createRequestMessages (std::vector >& requests, size_t max) { if(requests.size() >= max) { return; } size_t getnum = max-requests.size(); std::vector blockIndexes; blockIndexes.reserve(getnum); for(std::deque >::iterator itr = pieces_.begin(), eoi = pieces_.end(); itr != eoi && getnum; ++itr) { SharedHandle& piece = *itr; if(piece->getMissingUnusedBlockIndex(blockIndexes, getnum)) { getnum -= blockIndexes.size(); for(std::vector::const_iterator i = blockIndexes.begin(), eoi2 = blockIndexes.end(); i != eoi2; ++i) { A2_LOG_DEBUG (fmt("Creating RequestMessage index=%lu, begin=%u," " blockIndex=%lu", static_cast(piece->getIndex()), static_cast((*i)*piece->getBlockLength()), static_cast(*i))); requests.push_back (messageFactory_->createRequestMessage(piece, *i)); } blockIndexes.clear(); } } } void DefaultBtRequestFactory::createRequestMessagesOnEndGame (std::vector >& requests, size_t max) { for(std::deque >::iterator itr = pieces_.begin(), eoi = pieces_.end(); itr != eoi && requests.size() < max; ++itr) { SharedHandle& piece = *itr; const size_t mislen = piece->getBitfieldLength(); array_ptr misbitfield(new unsigned char[mislen]); piece->getAllMissingBlockIndexes(misbitfield, mislen); std::vector missingBlockIndexes; size_t blockIndex = 0; for(size_t i = 0; i < mislen; ++i) { unsigned char bits = misbitfield[i]; unsigned char mask = 128; for(size_t bi = 0; bi < 8; ++bi, mask >>= 1, ++blockIndex) { if(bits & mask) { missingBlockIndexes.push_back(blockIndex); } } } std::random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end(), *(SimpleRandomizer::getInstance().get())); for(std::vector::const_iterator bitr = missingBlockIndexes.begin(), eoi2 = missingBlockIndexes.end(); bitr != eoi2 && requests.size() < max; ++bitr) { const size_t& blockIndex = *bitr; if(!dispatcher_->isOutstandingRequest(piece->getIndex(), blockIndex)) { A2_LOG_DEBUG (fmt("Creating RequestMessage index=%lu, begin=%u," " blockIndex=%lu", static_cast(piece->getIndex()), static_cast(blockIndex*piece->getBlockLength()), static_cast(blockIndex))); requests.push_back(messageFactory_->createRequestMessage (piece, blockIndex)); } } } } namespace { class CountMissingBlock { private: size_t numMissingBlock_; public: CountMissingBlock():numMissingBlock_(0) {} size_t getNumMissingBlock() { return numMissingBlock_; } void operator()(const SharedHandle& piece) { numMissingBlock_ += piece->countMissingBlock(); } }; } // namespace size_t DefaultBtRequestFactory::countMissingBlock() { return std::for_each(pieces_.begin(), pieces_.end(), CountMissingBlock()).getNumMissingBlock(); } void DefaultBtRequestFactory::getTargetPieceIndexes (std::vector& indexes) const { std::transform(pieces_.begin(), pieces_.end(), std::back_inserter(indexes), mem_fun_sh(&Piece::getIndex)); } void DefaultBtRequestFactory::setPieceStorage (const SharedHandle& pieceStorage) { pieceStorage_ = pieceStorage; } void DefaultBtRequestFactory::setPeer(const SharedHandle& peer) { peer_ = peer; } void DefaultBtRequestFactory::setBtMessageDispatcher (BtMessageDispatcher* dispatcher) { dispatcher_ = dispatcher; } void DefaultBtRequestFactory::setBtMessageFactory(BtMessageFactory* factory) { messageFactory_ = factory; } } // namespace aria2