/* */ #include "TrackerWatcherCommand.h" #include #include "DownloadEngine.h" #include "BtContext.h" #include "BtAnnounce.h" #include "BtRuntime.h" #include "PieceStorage.h" #include "PeerStorage.h" #include "Peer.h" #include "prefs.h" #include "message.h" #include "SingleFileDownloadContext.h" #include "ByteArrayDiskWriterFactory.h" #include "RecoverableException.h" #include "PeerInitiateConnectionCommand.h" #include "DiskAdaptor.h" #include "FileEntry.h" #include "RequestGroup.h" #include "Option.h" #include "DlAbortEx.h" #include "Logger.h" #include "A2STR.h" #include "SocketCore.h" namespace aria2 { TrackerWatcherCommand::TrackerWatcherCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const BtContextHandle& btContext): Command(cuid), RequestGroupAware(requestGroup), e(e), _btContext(btContext) {} TrackerWatcherCommand::~TrackerWatcherCommand() {} bool TrackerWatcherCommand::execute() { if(_requestGroup->isForceHaltRequested()) { if(_trackerRequestGroup.isNull()) { return true; } else if(_trackerRequestGroup->getNumCommand() == 0 || _trackerRequestGroup->downloadFinished()) { return true; } else { _trackerRequestGroup->setForceHaltRequested(true); return false; } } if(_btAnnounce->noMoreAnnounce()) { logger->debug("no more announce"); return true; } if(_trackerRequestGroup.isNull()) { _trackerRequestGroup = createAnnounce(); if(!_trackerRequestGroup.isNull()) { std::deque commands; _trackerRequestGroup->createInitialCommand(commands, e); e->addCommand(commands); logger->debug("added tracker request command"); } } else if(_trackerRequestGroup->downloadFinished()){ try { std::string trackerResponse = getTrackerResponse(_trackerRequestGroup); processTrackerResponse(trackerResponse); _btAnnounce->announceSuccess(); _btAnnounce->resetAnnounce(); } catch(RecoverableException& ex) { logger->error(EX_EXCEPTION_CAUGHT, ex); _btAnnounce->announceFailure(); if(_btAnnounce->isAllAnnounceFailed()) { _btAnnounce->resetAnnounce(); } } _trackerRequestGroup.reset(); } else if(_trackerRequestGroup->getNumCommand() == 0){ // handle errors here _btAnnounce->announceFailure(); // inside it, trackers = 0. _trackerRequestGroup.reset(); if(_btAnnounce->isAllAnnounceFailed()) { _btAnnounce->resetAnnounce(); } } e->commands.push_back(this); return false; } std::string TrackerWatcherCommand::getTrackerResponse (const RequestGroupHandle& requestGroup) { std::stringstream strm; unsigned char data[2048]; requestGroup->getPieceStorage()->getDiskAdaptor()->openFile(); while(1) { ssize_t dataLength = requestGroup->getPieceStorage()-> getDiskAdaptor()->readData(data, sizeof(data), strm.tellp()); if(dataLength == 0) { break; } strm.write(reinterpret_cast(data), dataLength); } return strm.str(); } // TODO we have to deal with the exception thrown By BtAnnounce void TrackerWatcherCommand::processTrackerResponse (const std::string& trackerResponse) { _btAnnounce->processAnnounceResponse (reinterpret_cast(trackerResponse.c_str()), trackerResponse.size()); while(!_btRuntime->isHalt() && _btRuntime->lessThanMinPeers()) { PeerHandle peer = _peerStorage->getUnusedPeer(); if(peer.isNull()) { break; } peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e, _btContext, _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); logger->debug("CUID#%d - Adding new command CUID#%d", cuid, peer->usedBy()); } } RequestGroupHandle TrackerWatcherCommand::createAnnounce() { RequestGroupHandle rg; if(_btAnnounce->isAnnounceReady()) { rg = createRequestGroup(_btAnnounce->getAnnounceUrl()); _btAnnounce->announceStart(); // inside it, trackers++. } return rg; } RequestGroupHandle TrackerWatcherCommand::createRequestGroup(const std::string& uri) { std::deque uris; uris.push_back(uri); RequestGroupHandle rg(new RequestGroup(e->option, uris)); static const std::string TRACKER_ANNOUNCE_FILE("[tracker.announce]"); SingleFileDownloadContextHandle dctx (new SingleFileDownloadContext(e->option->getAsInt(PREF_SEGMENT_SIZE), 0, A2STR::NIL, TRACKER_ANNOUNCE_FILE)); dctx->setDir(A2STR::NIL); rg->setDownloadContext(dctx); SharedHandle dwf(new ByteArrayDiskWriterFactory()); rg->setDiskWriterFactory(dwf); rg->setFileAllocationEnabled(false); rg->setPreLocalFileCheckEnabled(false); logger->info("Creating tracker request group GID#%d", rg->getGID()); return rg; } void TrackerWatcherCommand::setBtRuntime (const SharedHandle& btRuntime) { _btRuntime = btRuntime; } void TrackerWatcherCommand::setPeerStorage (const SharedHandle& peerStorage) { _peerStorage = peerStorage; } void TrackerWatcherCommand::setPieceStorage (const SharedHandle& pieceStorage) { _pieceStorage = pieceStorage; } void TrackerWatcherCommand::setBtAnnounce (const SharedHandle& btAnnounce) { _btAnnounce = btAnnounce; } } // namespace aria2