RequestGroup.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "RequestGroup.h"
  36. #include "PostDownloadHandler.h"
  37. #include "DownloadEngine.h"
  38. #include "DefaultSegmentManFactory.h"
  39. #include "SegmentMan.h"
  40. #include "NullProgressInfoFile.h"
  41. #include "Dependency.h"
  42. #include "prefs.h"
  43. #include "InitiateConnectionCommandFactory.h"
  44. #include "CUIDCounter.h"
  45. #include "File.h"
  46. #include "message.h"
  47. #include "Util.h"
  48. #include "BtRegistry.h"
  49. #include "LogFactory.h"
  50. #include "Logger.h"
  51. #include "DiskAdaptor.h"
  52. #include "DiskWriterFactory.h"
  53. #include "RecoverableException.h"
  54. #include "StreamCheckIntegrityEntry.h"
  55. #include "CheckIntegrityCommand.h"
  56. #include "UnknownLengthPieceStorage.h"
  57. #include "BtContext.h"
  58. #include "SingleFileDownloadContext.h"
  59. #include "DlAbortEx.h"
  60. #include "DownloadFailureException.h"
  61. #include "RequestGroupMan.h"
  62. #include "DefaultBtProgressInfoFile.h"
  63. #include "DefaultPieceStorage.h"
  64. #include "DownloadResult.h"
  65. #include "DownloadHandlerFactory.h"
  66. #include "MemoryBufferPreDownloadHandler.h"
  67. #include "DownloadHandlerConstants.h"
  68. #include "ServerHost.h"
  69. #include "Option.h"
  70. #include "FileEntry.h"
  71. #include "Request.h"
  72. #include "FileAllocationIterator.h"
  73. #ifdef ENABLE_MESSAGE_DIGEST
  74. # include "CheckIntegrityCommand.h"
  75. #endif // ENABLE_MESSAGE_DIGEST
  76. #ifdef ENABLE_BITTORRENT
  77. # include "BtCheckIntegrityEntry.h"
  78. # include "DefaultPeerStorage.h"
  79. # include "DefaultBtAnnounce.h"
  80. # include "BtRuntime.h"
  81. # include "BtSetup.h"
  82. # include "BtFileAllocationEntry.h"
  83. # include "BtPostDownloadHandler.h"
  84. # include "DHTSetup.h"
  85. # include "DHTRegistry.h"
  86. # include "PeerObject.h"
  87. # include "BtMessageFactory.h"
  88. # include "BtRequestFactory.h"
  89. # include "BtMessageDispatcher.h"
  90. # include "BtMessageReceiver.h"
  91. # include "PeerConnection.h"
  92. # include "ExtensionMessageFactory.h"
  93. # include "DHTPeerAnnounceStorage.h"
  94. # include "DHTEntryPointNameResolveCommand.h"
  95. #endif // ENABLE_BITTORRENT
  96. #ifdef ENABLE_METALINK
  97. # include "MetalinkPostDownloadHandler.h"
  98. #endif // ENABLE_METALINK
  99. #include <cassert>
  100. #include <algorithm>
  101. namespace aria2 {
  102. int32_t RequestGroup::_gidCounter = 0;
  103. RequestGroup::RequestGroup(const Option* option,
  104. const std::deque<std::string>& uris):
  105. _gid(++_gidCounter),
  106. _uris(uris),
  107. _numConcurrentCommand(0),
  108. _numStreamConnection(0),
  109. _numCommand(0),
  110. _segmentManFactory(new DefaultSegmentManFactory(option)),
  111. _progressInfoFile(new NullProgressInfoFile()),
  112. _preLocalFileCheckEnabled(true),
  113. _haltRequested(false),
  114. _forceHaltRequested(false),
  115. _singleHostMultiConnectionEnabled(true),
  116. _option(option),
  117. _logger(LogFactory::getInstance())
  118. {
  119. if(_option->get(PREF_FILE_ALLOCATION) == V_PREALLOC) {
  120. _fileAllocationEnabled = true;
  121. } else {
  122. _fileAllocationEnabled = false;
  123. }
  124. initializePreDownloadHandler();
  125. initializePostDownloadHandler();
  126. }
  127. RequestGroup::~RequestGroup() {}
  128. SegmentManHandle RequestGroup::initSegmentMan()
  129. {
  130. _segmentMan = _segmentManFactory->createNewInstance(_downloadContext,
  131. _pieceStorage);
  132. return _segmentMan;
  133. }
  134. bool RequestGroup::downloadFinished() const
  135. {
  136. if(_pieceStorage.isNull()) {
  137. return false;
  138. } else {
  139. return _pieceStorage->downloadFinished();
  140. }
  141. }
  142. bool RequestGroup::allDownloadFinished() const
  143. {
  144. if(_pieceStorage.isNull()) {
  145. return false;
  146. } else {
  147. return _pieceStorage->allDownloadFinished();
  148. }
  149. }
  150. void RequestGroup::closeFile()
  151. {
  152. if(!_pieceStorage.isNull()) {
  153. _pieceStorage->getDiskAdaptor()->closeFile();
  154. }
  155. }
  156. Commands RequestGroup::createInitialCommand(DownloadEngine* e)
  157. {
  158. #ifdef ENABLE_BITTORRENT
  159. {
  160. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  161. if(!btContext.isNull()) {
  162. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  163. throw new DownloadFailureException(EX_DUPLICATE_FILE_DOWNLOAD,
  164. getFilePath().c_str());
  165. }
  166. initPieceStorage();
  167. if(btContext->getFileEntries().size() > 1) {
  168. // this is really multi file torrent.
  169. // clear http/ftp uris because the current implementation does not
  170. // allow integrating multi-file torrent and http/ftp.
  171. _logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp.");
  172. _uris.clear();
  173. _pieceStorage->setFileFilter(Util::parseIntRange(_option->get(PREF_SELECT_FILE)));
  174. }
  175. BtProgressInfoFileHandle
  176. progressInfoFile(new DefaultBtProgressInfoFile(_downloadContext,
  177. _pieceStorage,
  178. _option));
  179. BtRegistry::registerBtContext(btContext->getInfoHashAsString(), btContext);
  180. BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(),
  181. _pieceStorage);
  182. BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(),
  183. progressInfoFile);
  184. BtRuntimeHandle btRuntime(new BtRuntime());
  185. btRuntime->setListenPort(_option->getAsInt(PREF_LISTEN_PORT));
  186. BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime);
  187. PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, _option));
  188. BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage);
  189. BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, _option));
  190. BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce);
  191. btAnnounce->shuffleAnnounce();
  192. {
  193. SharedHandle<PeerObjectCluster> po(new PeerObjectCluster());
  194. BtRegistry::registerPeerObjectCluster(btContext->getInfoHashAsString(),
  195. po);
  196. }
  197. // Remove the control file if download file doesn't exist
  198. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  199. progressInfoFile->removeFile();
  200. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  201. progressInfoFile->getFilename().c_str(),
  202. _pieceStorage->getDiskAdaptor()->getFilePath().c_str());
  203. }
  204. // Call Load, Save and file allocation command here
  205. if(progressInfoFile->exists()) {
  206. // load .aria2 file if it exists.
  207. progressInfoFile->load();
  208. _pieceStorage->getDiskAdaptor()->openFile();
  209. } else {
  210. if(_pieceStorage->getDiskAdaptor()->fileExists()) {
  211. if(_option->get(PREF_CHECK_INTEGRITY) != V_TRUE &&
  212. _option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) {
  213. // TODO we need this->haltRequested = true?
  214. throw new DownloadFailureException(MSG_FILE_ALREADY_EXISTS,
  215. _pieceStorage->getDiskAdaptor()->getFilePath().c_str());
  216. } else {
  217. _pieceStorage->getDiskAdaptor()->openFile();
  218. }
  219. } else {
  220. _pieceStorage->getDiskAdaptor()->openFile();
  221. }
  222. }
  223. _progressInfoFile = progressInfoFile;
  224. if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) {
  225. e->addCommand(DHTSetup().setup(e, _option));
  226. if(btContext->getNodes().size() && DHTSetup::initialized()) {
  227. DHTEntryPointNameResolveCommand* command =
  228. new DHTEntryPointNameResolveCommand(CUIDCounterSingletonHolder::instance()->newID(), e, btContext->getNodes());
  229. command->setTaskQueue(DHTRegistry::_taskQueue);
  230. command->setTaskFactory(DHTRegistry::_taskFactory);
  231. command->setRoutingTable(DHTRegistry::_routingTable);
  232. command->setLocalNode(DHTRegistry::_localNode);
  233. e->commands.push_back(command);
  234. }
  235. }
  236. CheckIntegrityEntryHandle entry(new BtCheckIntegrityEntry(this));
  237. return processCheckIntegrityEntry(entry, e);
  238. }
  239. }
  240. #endif // ENABLE_BITTORRENT
  241. // TODO I assume here when totallength is set to DownloadContext and it is
  242. // not 0, then filepath is also set DownloadContext correctly....
  243. if(_downloadContext->getTotalLength() == 0) {
  244. return createNextCommand(e, 1);
  245. }else {
  246. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  247. throw new DownloadFailureException(EX_DUPLICATE_FILE_DOWNLOAD,
  248. getFilePath().c_str());
  249. }
  250. initPieceStorage();
  251. BtProgressInfoFileHandle
  252. infoFile(new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage, _option));
  253. if(!infoFile->exists() && downloadFinishedByFileLength()) {
  254. return Commands();
  255. }
  256. loadAndOpenFile(infoFile);
  257. SharedHandle<CheckIntegrityEntry>
  258. checkIntegrityEntry(new StreamCheckIntegrityEntry(SharedHandle<Request>(), this));
  259. return processCheckIntegrityEntry(checkIntegrityEntry, e);
  260. }
  261. }
  262. Commands RequestGroup::processCheckIntegrityEntry(const CheckIntegrityEntryHandle& entry, DownloadEngine* e)
  263. {
  264. #ifdef ENABLE_MESSAGE_DIGEST
  265. if(e->option->get(PREF_CHECK_INTEGRITY) == V_TRUE &&
  266. entry->isValidationReady()) {
  267. entry->initValidator();
  268. CheckIntegrityCommand* command =
  269. new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), this, e, entry);
  270. Commands commands;
  271. commands.push_back(command);
  272. return commands;
  273. } else
  274. #endif // ENABLE_MESSAGE_DIGEST
  275. {
  276. return entry->onDownloadIncomplete(e);
  277. }
  278. }
  279. void RequestGroup::initPieceStorage()
  280. {
  281. if(_downloadContext->getTotalLength() == 0) {
  282. UnknownLengthPieceStorageHandle ps(new UnknownLengthPieceStorage(_downloadContext, _option));
  283. if(!_diskWriterFactory.isNull()) {
  284. ps->setDiskWriterFactory(_diskWriterFactory);
  285. }
  286. _pieceStorage = ps;
  287. } else {
  288. DefaultPieceStorageHandle ps(new DefaultPieceStorage(_downloadContext, _option));
  289. if(!_diskWriterFactory.isNull()) {
  290. ps->setDiskWriterFactory(_diskWriterFactory);
  291. }
  292. _pieceStorage = ps;
  293. }
  294. _pieceStorage->initStorage();
  295. initSegmentMan();
  296. }
  297. bool RequestGroup::downloadFinishedByFileLength()
  298. {
  299. // assuming that a control file doesn't exist.
  300. if(!isPreLocalFileCheckEnabled() ||
  301. (_option->get(PREF_ALLOW_OVERWRITE) == V_TRUE) ||
  302. ((_option->get(PREF_CHECK_INTEGRITY) == V_TRUE) &&
  303. !_downloadContext->getPieceHashes().empty())) {
  304. return false;
  305. }
  306. // TODO consider the case when the getFilePath() returns dir path.
  307. File outfile(getFilePath());
  308. if(outfile.exists() && getTotalLength() == outfile.size()) {
  309. _pieceStorage->markAllPiecesDone();
  310. _logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _gid, getFilePath().c_str());
  311. return true;
  312. } else {
  313. return false;
  314. }
  315. }
  316. void RequestGroup::loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoFile)
  317. {
  318. try {
  319. if(!isPreLocalFileCheckEnabled()) {
  320. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  321. return;
  322. }
  323. // Remove the control file if download file doesn't exist
  324. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  325. progressInfoFile->removeFile();
  326. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  327. progressInfoFile->getFilename().c_str(),
  328. _pieceStorage->getDiskAdaptor()->getFilePath().c_str());
  329. }
  330. if(progressInfoFile->exists()) {
  331. progressInfoFile->load();
  332. _pieceStorage->getDiskAdaptor()->openExistingFile();
  333. } else {
  334. File outfile(getFilePath());
  335. if(outfile.exists() && _option->get(PREF_CONTINUE) == V_TRUE) {
  336. if(getTotalLength() < outfile.size()) {
  337. throw new DlAbortEx(EX_FILE_LENGTH_MISMATCH_BETWEEN_LOCAL_AND_REMOTE,
  338. getFilePath().c_str(),
  339. Util::itos(outfile.size()).c_str(),
  340. Util::itos(getTotalLength()).c_str());
  341. }
  342. _pieceStorage->getDiskAdaptor()->openExistingFile();
  343. _pieceStorage->markPiecesDone(outfile.size());
  344. } else {
  345. #ifdef ENABLE_MESSAGE_DIGEST
  346. if(outfile.exists() && _option->get(PREF_CHECK_INTEGRITY) == V_TRUE) {
  347. _pieceStorage->getDiskAdaptor()->openExistingFile();
  348. } else {
  349. shouldCancelDownloadForSafety();
  350. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  351. }
  352. #else // ENABLE_MESSAGE_DIGEST
  353. shouldCancelDownloadForSafety();
  354. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  355. #endif // ENABLE_MESSAGE_DIGEST
  356. }
  357. }
  358. setProgressInfoFile(progressInfoFile);
  359. } catch(RecoverableException* e) {
  360. throw new DownloadFailureException(e, EX_DOWNLOAD_ABORTED);
  361. }
  362. }
  363. // assuming that a control file does not exist
  364. void RequestGroup::shouldCancelDownloadForSafety()
  365. {
  366. if(_option->get(PREF_ALLOW_OVERWRITE) == V_TRUE) {
  367. return;
  368. }
  369. File outfile(getFilePath());
  370. if(outfile.exists()) {
  371. if(_option->get(PREF_AUTO_FILE_RENAMING) == V_TRUE) {
  372. if(tryAutoFileRenaming()) {
  373. _logger->notice(MSG_FILE_RENAMED, getFilePath().c_str());
  374. } else {
  375. throw new DownloadFailureException("File renaming failed: %s",
  376. getFilePath().c_str());
  377. }
  378. } else {
  379. throw new DownloadFailureException(MSG_FILE_ALREADY_EXISTS,
  380. getFilePath().c_str());
  381. }
  382. }
  383. }
  384. bool RequestGroup::tryAutoFileRenaming()
  385. {
  386. std::string filepath = getFilePath();
  387. if(filepath.empty()) {
  388. return false;
  389. }
  390. for(unsigned int i = 1; i < 10000; ++i) {
  391. File newfile(filepath+"."+Util::uitos(i));
  392. if(!newfile.exists()) {
  393. SingleFileDownloadContextHandle ctx =
  394. dynamic_pointer_cast<SingleFileDownloadContext>(_downloadContext);
  395. ctx->setUFilename(newfile.getBasename());
  396. return true;
  397. }
  398. }
  399. return false;
  400. }
  401. Commands RequestGroup::createNextCommandWithAdj(DownloadEngine* e, int numAdj)
  402. {
  403. unsigned int numCommand;
  404. if(_numConcurrentCommand == 0) {
  405. numCommand = _uris.size();
  406. } else {
  407. int n = _numConcurrentCommand+numAdj;
  408. if(n <= 0) {
  409. return Commands();
  410. } else {
  411. numCommand = n;
  412. }
  413. }
  414. return createNextCommand(e, numCommand, "GET");
  415. }
  416. Commands RequestGroup::createNextCommand(DownloadEngine* e, unsigned int numCommand, const std::string& method)
  417. {
  418. Commands commands;
  419. std::deque<std::string> pendingURIs;
  420. for(;!_uris.empty() && numCommand--; _uris.pop_front()) {
  421. std::string uri = _uris.front();
  422. RequestHandle req(new Request());
  423. if(req->setUrl(uri)) {
  424. ServerHostHandle sv;
  425. if(!_singleHostMultiConnectionEnabled){
  426. sv = searchServerHost(req->getHost());
  427. }
  428. if(sv.isNull()) {
  429. _spentUris.push_back(uri);
  430. req->setReferer(_option->get(PREF_REFERER));
  431. req->setMethod(method);
  432. if(_option->getAsBool(PREF_ENABLE_HTTP_KEEP_ALIVE)) {
  433. req->setKeepAliveHint(true);
  434. }
  435. if(_option->getAsBool(PREF_ENABLE_HTTP_PIPELINING)) {
  436. req->setPipeliningHint(true);
  437. }
  438. if(req->getProtocol() == "http" || req->getProtocol() == "https") {
  439. req->supportsPersistentConnection(true);
  440. }
  441. Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(CUIDCounterSingletonHolder::instance()->newID(), req, this, e);
  442. ServerHostHandle sv(new ServerHost(command->getCuid(), req->getHost()));
  443. registerServerHost(sv);
  444. // give a chance to be executed in the next loop in DownloadEngine
  445. command->setStatus(Command::STATUS_ONESHOT_REALTIME);
  446. commands.push_back(command);
  447. } else {
  448. pendingURIs.push_front(uri);
  449. }
  450. } else {
  451. _logger->error(MSG_UNRECOGNIZED_URI, req->getUrl().c_str());
  452. }
  453. }
  454. std::copy(pendingURIs.begin(), pendingURIs.end(), std::front_inserter(_uris));
  455. return commands;
  456. }
  457. std::string RequestGroup::getFilePath() const
  458. {
  459. assert(!_downloadContext.isNull());
  460. if(_downloadContext.isNull()) {
  461. return "";
  462. } else {
  463. return _downloadContext->getActualBasePath();
  464. }
  465. }
  466. uint64_t RequestGroup::getTotalLength() const
  467. {
  468. if(_pieceStorage.isNull()) {
  469. return 0;
  470. } else {
  471. if(_pieceStorage->isSelectiveDownloadingMode()) {
  472. return _pieceStorage->getFilteredTotalLength();
  473. } else {
  474. return _pieceStorage->getTotalLength();
  475. }
  476. }
  477. }
  478. uint64_t RequestGroup::getCompletedLength() const
  479. {
  480. if(_pieceStorage.isNull()) {
  481. return 0;
  482. } else {
  483. if(_pieceStorage->isSelectiveDownloadingMode()) {
  484. return _pieceStorage->getFilteredCompletedLength();
  485. } else {
  486. return _pieceStorage->getCompletedLength();
  487. }
  488. }
  489. }
  490. void RequestGroup::validateFilename(const std::string& expectedFilename,
  491. const std::string& actualFilename) const
  492. {
  493. if(expectedFilename.empty()) {
  494. return;
  495. }
  496. if(expectedFilename != actualFilename) {
  497. throw new DlAbortEx(EX_FILENAME_MISMATCH,
  498. expectedFilename.c_str(),
  499. actualFilename.c_str());
  500. }
  501. }
  502. void RequestGroup::validateTotalLength(uint64_t expectedTotalLength,
  503. uint64_t actualTotalLength) const
  504. {
  505. if(expectedTotalLength <= 0) {
  506. return;
  507. }
  508. if(expectedTotalLength != actualTotalLength) {
  509. throw new DlAbortEx(EX_SIZE_MISMATCH,
  510. Util::itos(expectedTotalLength, true).c_str(),
  511. Util::itos(actualTotalLength, true).c_str());
  512. }
  513. }
  514. void RequestGroup::validateFilename(const std::string& actualFilename) const
  515. {
  516. validateFilename(_downloadContext->getFileEntries().front()->getBasename(), actualFilename);
  517. }
  518. void RequestGroup::validateTotalLength(uint64_t actualTotalLength) const
  519. {
  520. validateTotalLength(getTotalLength(), actualTotalLength);
  521. }
  522. void RequestGroup::increaseStreamConnection()
  523. {
  524. ++_numStreamConnection;
  525. }
  526. void RequestGroup::decreaseStreamConnection()
  527. {
  528. --_numStreamConnection;
  529. }
  530. unsigned int RequestGroup::getNumConnection() const
  531. {
  532. unsigned int numConnection = _numStreamConnection;
  533. #ifdef ENABLE_BITTORRENT
  534. {
  535. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  536. if(!btContext.isNull()) {
  537. BtRuntimeHandle btRuntime = BT_RUNTIME(btContext);
  538. if(!btRuntime.isNull()) {
  539. numConnection += btRuntime->getConnections();
  540. }
  541. }
  542. }
  543. #endif // ENABLE_BITTORRENT
  544. return numConnection;
  545. }
  546. void RequestGroup::increaseNumCommand()
  547. {
  548. ++_numCommand;
  549. }
  550. void RequestGroup::decreaseNumCommand()
  551. {
  552. --_numCommand;
  553. }
  554. TransferStat RequestGroup::calculateStat()
  555. {
  556. TransferStat stat;
  557. #ifdef ENABLE_BITTORRENT
  558. {
  559. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  560. if(!btContext.isNull()) {
  561. PeerStorageHandle peerStorage = PEER_STORAGE(btContext);
  562. if(!peerStorage.isNull()) {
  563. stat = peerStorage->calculateStat();
  564. }
  565. }
  566. }
  567. #endif // ENABLE_BITTORRENT
  568. if(!_segmentMan.isNull()) {
  569. stat.setDownloadSpeed(stat.getDownloadSpeed()+_segmentMan->calculateDownloadSpeed());
  570. }
  571. return stat;
  572. }
  573. void RequestGroup::setHaltRequested(bool f)
  574. {
  575. _haltRequested = f;
  576. #ifdef ENABLE_BITTORRENT
  577. {
  578. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  579. if(!btContext.isNull()) {
  580. BtRuntimeHandle btRuntime = BT_RUNTIME(btContext);
  581. if(!btRuntime.isNull()) {
  582. btRuntime->setHalt(f);
  583. }
  584. }
  585. }
  586. #endif // ENABLE_BITTORRENT
  587. }
  588. void RequestGroup::setForceHaltRequested(bool f)
  589. {
  590. setHaltRequested(f);
  591. _forceHaltRequested = f;
  592. }
  593. void RequestGroup::releaseRuntimeResource()
  594. {
  595. #ifdef ENABLE_BITTORRENT
  596. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  597. if(!btContext.isNull()) {
  598. BtContextHandle btContextInReg = BtRegistry::getBtContext(btContext->getInfoHashAsString());
  599. if(!btContextInReg.isNull() &&
  600. btContextInReg->getOwnerRequestGroup()->getGID() ==
  601. btContext->getOwnerRequestGroup()->getGID()) {
  602. BtRegistry::unregister(btContext->getInfoHashAsString());
  603. if(!DHTRegistry::_peerAnnounceStorage.isNull()) {
  604. DHTRegistry::_peerAnnounceStorage->removePeerAnnounce(btContext);
  605. }
  606. }
  607. }
  608. #endif // ENABLE_BITTORRENT
  609. if(!_pieceStorage.isNull()) {
  610. _pieceStorage->removeAdvertisedPiece(0);
  611. }
  612. }
  613. void RequestGroup::preDownloadProcessing()
  614. {
  615. _logger->debug("Finding PreDownloadHandler for path %s.", getFilePath().c_str());
  616. try {
  617. for(PreDownloadHandlers::const_iterator itr = _preDownloadHandlers.begin();
  618. itr != _preDownloadHandlers.end(); ++itr) {
  619. if((*itr)->canHandle(this)) {
  620. (*itr)->execute(this);
  621. return;
  622. }
  623. }
  624. } catch(RecoverableException* ex) {
  625. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  626. delete ex;
  627. return;
  628. }
  629. _logger->debug("No PreDownloadHandler found.");
  630. return;
  631. }
  632. RequestGroups RequestGroup::postDownloadProcessing()
  633. {
  634. _logger->debug("Finding PostDownloadHandler for path %s.", getFilePath().c_str());
  635. try {
  636. for(PostDownloadHandlers::const_iterator itr = _postDownloadHandlers.begin();
  637. itr != _postDownloadHandlers.end(); ++itr) {
  638. if((*itr)->canHandle(this)) {
  639. return (*itr)->getNextRequestGroups(this);
  640. }
  641. }
  642. } catch(RecoverableException* ex) {
  643. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  644. delete ex;
  645. return RequestGroups();
  646. }
  647. _logger->debug("No PostDownloadHandler found.");
  648. return RequestGroups();
  649. }
  650. void RequestGroup::initializePreDownloadHandler()
  651. {
  652. #ifdef ENABLE_BITTORRENT
  653. if(_option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  654. _preDownloadHandlers.push_back(DownloadHandlerFactory::getBtPreDownloadHandler());
  655. }
  656. #endif // ENABLE_BITTORRENT
  657. #ifdef ENABLE_METALINK
  658. if(_option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  659. _preDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPreDownloadHandler());
  660. }
  661. #endif // ENABLE_METALINK
  662. }
  663. void RequestGroup::initializePostDownloadHandler()
  664. {
  665. #ifdef ENABLE_BITTORRENT
  666. if(_option->get(PREF_FOLLOW_TORRENT) == V_TRUE ||
  667. _option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  668. _postDownloadHandlers.push_back(DownloadHandlerFactory::getBtPostDownloadHandler());
  669. }
  670. #endif // ENABLE_BITTORRENT
  671. #ifdef ENABLE_METALINK
  672. if(_option->get(PREF_FOLLOW_METALINK) == V_TRUE ||
  673. _option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  674. _postDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPostDownloadHandler());
  675. }
  676. #endif // ENABLE_METALINK
  677. }
  678. std::deque<std::string> RequestGroup::getUris() const
  679. {
  680. std::deque<std::string> temp(_spentUris.begin(), _spentUris.end());
  681. temp.insert(temp.end(), _uris.begin(), _uris.end());
  682. return temp;
  683. }
  684. bool RequestGroup::isDependencyResolved()
  685. {
  686. if(_dependency.isNull()) {
  687. return true;
  688. }
  689. return _dependency->resolve();
  690. }
  691. void RequestGroup::setSegmentManFactory(const SegmentManFactoryHandle& segmentManFactory)
  692. {
  693. _segmentManFactory = segmentManFactory;
  694. }
  695. void RequestGroup::dependsOn(const DependencyHandle& dep)
  696. {
  697. _dependency = dep;
  698. }
  699. void RequestGroup::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
  700. {
  701. _diskWriterFactory = diskWriterFactory;
  702. }
  703. DiskWriterFactoryHandle RequestGroup::getDiskWriterFactory() const
  704. {
  705. return _diskWriterFactory;
  706. }
  707. void RequestGroup::addPostDownloadHandler(const PostDownloadHandlerHandle& handler)
  708. {
  709. _postDownloadHandlers.push_back(handler);
  710. }
  711. void RequestGroup::addPreDownloadHandler(const PreDownloadHandlerHandle& handler)
  712. {
  713. _preDownloadHandlers.push_back(handler);
  714. }
  715. void RequestGroup::clearPostDowloadHandler()
  716. {
  717. _postDownloadHandlers.clear();
  718. }
  719. void RequestGroup::clearPreDowloadHandler()
  720. {
  721. _preDownloadHandlers.clear();
  722. }
  723. SegmentManHandle RequestGroup::getSegmentMan() const
  724. {
  725. return _segmentMan;
  726. }
  727. DownloadContextHandle RequestGroup::getDownloadContext() const
  728. {
  729. return _downloadContext;
  730. }
  731. void RequestGroup::setDownloadContext(const DownloadContextHandle& downloadContext)
  732. {
  733. _downloadContext = downloadContext;
  734. }
  735. PieceStorageHandle RequestGroup::getPieceStorage() const
  736. {
  737. return _pieceStorage;
  738. }
  739. void RequestGroup::setPieceStorage(const PieceStorageHandle& pieceStorage)
  740. {
  741. _pieceStorage = pieceStorage;
  742. }
  743. BtProgressInfoFileHandle RequestGroup::getProgressInfoFile() const
  744. {
  745. return _progressInfoFile;
  746. }
  747. void RequestGroup::setProgressInfoFile(const BtProgressInfoFileHandle& progressInfoFile)
  748. {
  749. _progressInfoFile = progressInfoFile;
  750. }
  751. bool RequestGroup::needsFileAllocation() const
  752. {
  753. return isFileAllocationEnabled() &&
  754. (uint64_t)_option->getAsLLInt(PREF_NO_FILE_ALLOCATION_LIMIT) <= getTotalLength() &&
  755. !_pieceStorage->getDiskAdaptor()->fileAllocationIterator()->finished();
  756. }
  757. DownloadResultHandle RequestGroup::createDownloadResult() const
  758. {
  759. std::deque<std::string> uris = getUris();
  760. return
  761. SharedHandle<DownloadResult>(new DownloadResult(_gid,
  762. getFilePath(),
  763. getTotalLength(),
  764. uris.empty() ? "":uris.front(),
  765. uris.size(),
  766. downloadFinished()?
  767. DownloadResult::FINISHED :
  768. DownloadResult::NOT_YET));
  769. }
  770. void RequestGroup::registerServerHost(const ServerHostHandle& serverHost)
  771. {
  772. _serverHosts.push_back(serverHost);
  773. }
  774. class FindServerHostByCUID
  775. {
  776. private:
  777. int32_t _cuid;
  778. public:
  779. FindServerHostByCUID(int32_t cuid):_cuid(cuid) {}
  780. bool operator()(const ServerHostHandle& sv) const
  781. {
  782. return sv->getCuid() == _cuid;
  783. }
  784. };
  785. ServerHostHandle RequestGroup::searchServerHost(int32_t cuid) const
  786. {
  787. std::deque<SharedHandle<ServerHost> >::const_iterator itr =
  788. std::find_if(_serverHosts.begin(), _serverHosts.end(), FindServerHostByCUID(cuid));
  789. if(itr == _serverHosts.end()) {
  790. return SharedHandle<ServerHost>();
  791. } else {
  792. return *itr;
  793. }
  794. }
  795. class FindServerHostByHostname
  796. {
  797. private:
  798. const std::string& _hostname;
  799. public:
  800. FindServerHostByHostname(const std::string& hostname):_hostname(hostname) {}
  801. bool operator()(const ServerHostHandle& sv) const
  802. {
  803. return sv->getHostname() == _hostname;
  804. }
  805. };
  806. ServerHostHandle RequestGroup::searchServerHost(const std::string& hostname) const
  807. {
  808. std::deque<SharedHandle<ServerHost> >::const_iterator itr =
  809. std::find_if(_serverHosts.begin(), _serverHosts.end(), FindServerHostByHostname(hostname));
  810. if(itr == _serverHosts.end()) {
  811. return SharedHandle<ServerHost>();
  812. } else {
  813. return *itr;
  814. }
  815. }
  816. void RequestGroup::removeServerHost(int32_t cuid)
  817. {
  818. _serverHosts.erase(std::remove_if(_serverHosts.begin(), _serverHosts.end(), FindServerHostByCUID(cuid)), _serverHosts.end());
  819. }
  820. void RequestGroup::removeURIWhoseHostnameIs(const std::string& hostname)
  821. {
  822. std::deque<std::string> newURIs;
  823. Request req;
  824. for(std::deque<std::string>::const_iterator itr = _uris.begin(); itr != _uris.end(); ++itr) {
  825. if(((*itr).find(hostname) == std::string::npos) ||
  826. (req.setUrl(*itr) && (req.getHost() != hostname))) {
  827. newURIs.push_back(*itr);
  828. }
  829. }
  830. _logger->debug("GUID#%d - Removed %d duplicate hostname URIs",
  831. _gid, _uris.size()-newURIs.size());
  832. _uris = newURIs;
  833. }
  834. void RequestGroup::reportDownloadFinished()
  835. {
  836. _logger->notice(MSG_FILE_DOWNLOAD_COMPLETED,
  837. getFilePath().c_str());
  838. #ifdef ENABLE_BITTORRENT
  839. TransferStat stat = calculateStat();
  840. SharedHandle<BtContext> ctx = dynamic_pointer_cast<BtContext>(_downloadContext);
  841. if(!ctx.isNull()) {
  842. double shareRatio = ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0;
  843. _logger->notice(MSG_SHARE_RATIO_REPORT,
  844. shareRatio,
  845. Util::abbrevSize(stat.getAllTimeUploadLength()).c_str(),
  846. Util::abbrevSize(getCompletedLength()).c_str());
  847. }
  848. #endif // ENABLE_BITTORRENT
  849. }
  850. } // namespace aria2