RequestGroup.cc 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  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 <cassert>
  37. #include <algorithm>
  38. #include "PostDownloadHandler.h"
  39. #include "DownloadEngine.h"
  40. #include "SegmentMan.h"
  41. #include "NullProgressInfoFile.h"
  42. #include "Dependency.h"
  43. #include "prefs.h"
  44. #include "CreateRequestCommand.h"
  45. #include "File.h"
  46. #include "message.h"
  47. #include "util.h"
  48. #include "LogFactory.h"
  49. #include "Logger.h"
  50. #include "DiskAdaptor.h"
  51. #include "DiskWriterFactory.h"
  52. #include "RecoverableException.h"
  53. #include "StreamCheckIntegrityEntry.h"
  54. #include "CheckIntegrityCommand.h"
  55. #include "UnknownLengthPieceStorage.h"
  56. #include "DownloadContext.h"
  57. #include "DlAbortEx.h"
  58. #include "DownloadFailureException.h"
  59. #include "RequestGroupMan.h"
  60. #include "DefaultBtProgressInfoFile.h"
  61. #include "DefaultPieceStorage.h"
  62. #include "DownloadHandlerFactory.h"
  63. #include "MemoryBufferPreDownloadHandler.h"
  64. #include "DownloadHandlerConstants.h"
  65. #include "Option.h"
  66. #include "FileEntry.h"
  67. #include "Request.h"
  68. #include "FileAllocationIterator.h"
  69. #include "StringFormat.h"
  70. #include "A2STR.h"
  71. #include "URISelector.h"
  72. #include "InOrderURISelector.h"
  73. #include "PieceSelector.h"
  74. #include "a2functional.h"
  75. #include "SocketCore.h"
  76. #include "SimpleRandomizer.h"
  77. #ifdef ENABLE_MESSAGE_DIGEST
  78. # include "CheckIntegrityCommand.h"
  79. #endif // ENABLE_MESSAGE_DIGEST
  80. #ifdef ENABLE_BITTORRENT
  81. # include "bittorrent_helper.h"
  82. # include "BtRegistry.h"
  83. # include "BtCheckIntegrityEntry.h"
  84. # include "DefaultPeerStorage.h"
  85. # include "DefaultBtAnnounce.h"
  86. # include "BtRuntime.h"
  87. # include "BtSetup.h"
  88. # include "BtFileAllocationEntry.h"
  89. # include "BtPostDownloadHandler.h"
  90. # include "DHTSetup.h"
  91. # include "DHTRegistry.h"
  92. # include "BtMessageFactory.h"
  93. # include "BtRequestFactory.h"
  94. # include "BtMessageDispatcher.h"
  95. # include "BtMessageReceiver.h"
  96. # include "PeerConnection.h"
  97. # include "ExtensionMessageFactory.h"
  98. # include "DHTPeerAnnounceStorage.h"
  99. # include "DHTEntryPointNameResolveCommand.h"
  100. # include "LongestSequencePieceSelector.h"
  101. # include "PriorityPieceSelector.h"
  102. #endif // ENABLE_BITTORRENT
  103. #ifdef ENABLE_METALINK
  104. # include "MetalinkPostDownloadHandler.h"
  105. #endif // ENABLE_METALINK
  106. namespace aria2 {
  107. int32_t RequestGroup::_gidCounter = 0;
  108. RequestGroup::RequestGroup(const SharedHandle<Option>& option):
  109. _gid(newGID()),
  110. _option(new Option(*option.get())),
  111. _numConcurrentCommand(option->getAsInt(PREF_SPLIT)),
  112. _numStreamConnection(0),
  113. _numCommand(0),
  114. _saveControlFile(true),
  115. _progressInfoFile(new NullProgressInfoFile()),
  116. _preLocalFileCheckEnabled(true),
  117. _haltRequested(false),
  118. _forceHaltRequested(false),
  119. _haltReason(RequestGroup::NONE),
  120. _uriSelector(new InOrderURISelector()),
  121. _lastModifiedTime(Time::null()),
  122. _fileNotFoundCount(0),
  123. _timeout(option->getAsInt(PREF_TIMEOUT)),
  124. _inMemoryDownload(false),
  125. _maxDownloadSpeedLimit(option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT)),
  126. _maxUploadSpeedLimit(option->getAsInt(PREF_MAX_UPLOAD_LIMIT)),
  127. _belongsToGID(0),
  128. _logger(LogFactory::getInstance())
  129. {
  130. _fileAllocationEnabled = _option->get(PREF_FILE_ALLOCATION) != V_NONE;
  131. // Add types to be sent as a Accept header value here.
  132. // It would be good to put this value in Option so that user can tweak
  133. // and add this list.
  134. // The mime types of Metalink is used for `transparent metalink'.
  135. addAcceptType(DownloadHandlerConstants::getMetalinkContentTypes().begin(),
  136. DownloadHandlerConstants::getMetalinkContentTypes().end());
  137. if(!_option->getAsBool(PREF_DRY_RUN)) {
  138. initializePreDownloadHandler();
  139. initializePostDownloadHandler();
  140. }
  141. }
  142. RequestGroup::~RequestGroup() {}
  143. bool RequestGroup::downloadFinished() const
  144. {
  145. if(_pieceStorage.isNull()) {
  146. return false;
  147. } else {
  148. return _pieceStorage->downloadFinished();
  149. }
  150. }
  151. bool RequestGroup::allDownloadFinished() const
  152. {
  153. if(_pieceStorage.isNull()) {
  154. return false;
  155. } else {
  156. return _pieceStorage->allDownloadFinished();
  157. }
  158. }
  159. downloadresultcode::RESULT RequestGroup::downloadResult() const
  160. {
  161. if (downloadFinished())
  162. return downloadresultcode::FINISHED;
  163. else {
  164. if (_lastUriResult.isNull()) {
  165. if(_haltReason == RequestGroup::USER_REQUEST) {
  166. return downloadresultcode::IN_PROGRESS;
  167. } else {
  168. return downloadresultcode::UNKNOWN_ERROR;
  169. }
  170. } else {
  171. return _lastUriResult->getResult();
  172. }
  173. }
  174. }
  175. void RequestGroup::closeFile()
  176. {
  177. if(!_pieceStorage.isNull()) {
  178. _pieceStorage->getDiskAdaptor()->closeFile();
  179. }
  180. }
  181. void RequestGroup::createInitialCommand
  182. (std::deque<Command*>& commands, DownloadEngine* e)
  183. {
  184. #ifdef ENABLE_BITTORRENT
  185. {
  186. if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
  187. const BDE& torrentAttrs =
  188. _downloadContext->getAttribute(bittorrent::BITTORRENT);
  189. bool metadataGetMode = !torrentAttrs.containsKey(bittorrent::METADATA);
  190. if(_option->getAsBool(PREF_DRY_RUN)) {
  191. throw DOWNLOAD_FAILURE_EXCEPTION
  192. ("Cancel BitTorrent download in dry-run context.");
  193. }
  194. SharedHandle<BtRegistry> btRegistry = e->getBtRegistry();
  195. if(!btRegistry->getDownloadContext
  196. (torrentAttrs[bittorrent::INFO_HASH].s()).isNull()) {
  197. throw DOWNLOAD_FAILURE_EXCEPTION
  198. (StringFormat
  199. ("InfoHash %s is already registered.",
  200. bittorrent::getInfoHashString(_downloadContext).c_str()).str());
  201. }
  202. if(metadataGetMode) {
  203. // Use UnknownLengthPieceStorage.
  204. initPieceStorage();
  205. } else {
  206. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  207. throw DOWNLOAD_FAILURE_EXCEPTION
  208. (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
  209. _downloadContext->getBasePath().c_str()).str());
  210. }
  211. initPieceStorage();
  212. if(_downloadContext->getFileEntries().size() > 1) {
  213. _pieceStorage->setupFileFilter();
  214. }
  215. }
  216. SharedHandle<DefaultBtProgressInfoFile> progressInfoFile;
  217. if(!metadataGetMode) {
  218. progressInfoFile.reset(new DefaultBtProgressInfoFile(_downloadContext,
  219. _pieceStorage,
  220. _option.get()));
  221. }
  222. BtRuntimeHandle btRuntime(new BtRuntime());
  223. btRuntime->setMaxPeers(_option->getAsInt(PREF_BT_MAX_PEERS));
  224. _btRuntime = btRuntime;
  225. if(!progressInfoFile.isNull()) {
  226. progressInfoFile->setBtRuntime(btRuntime);
  227. }
  228. SharedHandle<DefaultPeerStorage> peerStorage
  229. (new DefaultPeerStorage(_option.get()));
  230. peerStorage->setBtRuntime(btRuntime);
  231. peerStorage->setPieceStorage(_pieceStorage);
  232. _peerStorage = peerStorage;
  233. if(!progressInfoFile.isNull()) {
  234. progressInfoFile->setPeerStorage(peerStorage);
  235. }
  236. SharedHandle<DefaultBtAnnounce> btAnnounce
  237. (new DefaultBtAnnounce(_downloadContext, _option.get()));
  238. btAnnounce->setBtRuntime(btRuntime);
  239. btAnnounce->setPieceStorage(_pieceStorage);
  240. btAnnounce->setPeerStorage(peerStorage);
  241. btAnnounce->setUserDefinedInterval
  242. (_option->getAsInt(PREF_BT_TRACKER_INTERVAL));
  243. btAnnounce->shuffleAnnounce();
  244. assert(btRegistry->get(_gid).isNull());
  245. btRegistry->put(_gid,
  246. BtObject(_downloadContext,
  247. _pieceStorage,
  248. peerStorage,
  249. btAnnounce,
  250. btRuntime,
  251. (progressInfoFile.isNull()?
  252. _progressInfoFile:
  253. SharedHandle<BtProgressInfoFile>
  254. (progressInfoFile))));
  255. if(metadataGetMode) {
  256. if(_option->getAsBool(PREF_ENABLE_DHT)) {
  257. std::deque<Command*> dhtCommands;
  258. DHTSetup().setup(dhtCommands, e, _option.get());
  259. e->addCommand(dhtCommands);
  260. } else {
  261. _logger->notice("For BitTorrent Magnet URI, enabling DHT is strongly"
  262. " recommended. See --enable-dht option.");
  263. }
  264. SharedHandle<CheckIntegrityEntry> entry
  265. (new BtCheckIntegrityEntry(this));
  266. entry->onDownloadIncomplete(commands, e);
  267. return;
  268. }
  269. // Remove the control file if download file doesn't exist
  270. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  271. progressInfoFile->removeFile();
  272. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  273. progressInfoFile->getFilename().c_str(),
  274. _downloadContext->getBasePath().c_str());
  275. }
  276. {
  277. uint64_t actualFileSize = _pieceStorage->getDiskAdaptor()->size();
  278. if(actualFileSize == _downloadContext->getTotalLength()) {
  279. // First, make DiskAdaptor read-only mode to allow the
  280. // program to seed file in read-only media.
  281. _pieceStorage->getDiskAdaptor()->enableReadOnly();
  282. } else {
  283. // Open file in writable mode to allow the program
  284. // truncate the file to _downloadContext->getTotalLength()
  285. if(_logger->debug()) {
  286. _logger->debug("File size not match. File is opened in writable"
  287. " mode. Expected:%s Actual:%s",
  288. util::uitos(_downloadContext->getTotalLength()).c_str(),
  289. util::uitos(actualFileSize).c_str());
  290. }
  291. }
  292. }
  293. // Call Load, Save and file allocation command here
  294. if(progressInfoFile->exists()) {
  295. // load .aria2 file if it exists.
  296. progressInfoFile->load();
  297. _pieceStorage->getDiskAdaptor()->openFile();
  298. } else {
  299. if(_pieceStorage->getDiskAdaptor()->fileExists()) {
  300. if(!_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  301. !_option->getAsBool(PREF_ALLOW_OVERWRITE) &&
  302. !_option->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  303. // TODO we need this->haltRequested = true?
  304. throw DOWNLOAD_FAILURE_EXCEPTION
  305. (StringFormat
  306. (MSG_FILE_ALREADY_EXISTS,
  307. _downloadContext->getBasePath().c_str()).str());
  308. } else {
  309. _pieceStorage->getDiskAdaptor()->openFile();
  310. }
  311. if(_option->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  312. _pieceStorage->markAllPiecesDone();
  313. }
  314. } else {
  315. _pieceStorage->getDiskAdaptor()->openFile();
  316. }
  317. }
  318. _progressInfoFile = progressInfoFile;
  319. if(torrentAttrs[bittorrent::PRIVATE].i() == 0 &&
  320. _option->getAsBool(PREF_ENABLE_DHT)) {
  321. std::deque<Command*> dhtCommands;
  322. DHTSetup().setup(dhtCommands, e, _option.get());
  323. e->addCommand(dhtCommands);
  324. if(!torrentAttrs[bittorrent::NODES].empty() && DHTSetup::initialized()) {
  325. std::deque<std::pair<std::string, uint16_t> > entryPoints;
  326. const BDE& nodes = torrentAttrs[bittorrent::NODES];
  327. for(BDE::List::const_iterator i = nodes.listBegin();
  328. i != nodes.listEnd(); ++i) {
  329. std::pair<std::string, uint16_t> addr
  330. ((*i)[bittorrent::HOSTNAME].s(), (*i)[bittorrent::PORT].i());
  331. entryPoints.push_back(addr);
  332. }
  333. DHTEntryPointNameResolveCommand* command =
  334. new DHTEntryPointNameResolveCommand(e->newCUID(), e, entryPoints);
  335. command->setTaskQueue(DHTRegistry::_taskQueue);
  336. command->setTaskFactory(DHTRegistry::_taskFactory);
  337. command->setRoutingTable(DHTRegistry::_routingTable);
  338. command->setLocalNode(DHTRegistry::_localNode);
  339. e->commands.push_back(command);
  340. }
  341. }
  342. CheckIntegrityEntryHandle entry(new BtCheckIntegrityEntry(this));
  343. // --bt-seed-unverified=true is given and download has completed, skip
  344. // validation for piece hashes.
  345. if(_option->getAsBool(PREF_BT_SEED_UNVERIFIED) &&
  346. _pieceStorage->downloadFinished()) {
  347. entry->onDownloadFinished(commands, e);
  348. } else {
  349. processCheckIntegrityEntry(commands, entry, e);
  350. }
  351. return;
  352. }
  353. }
  354. #endif // ENABLE_BITTORRENT
  355. // TODO Currently, BitTorrent+WEB-Seeding is only way to download
  356. // multiple files in one RequestGroup. In this context, we don't
  357. // have BitTorrent, so add assertion here. This situation will be
  358. // changed if Metalink spec is formalized to support multi-file
  359. // torrent.
  360. assert(_downloadContext->getFileEntries().size() == 1);
  361. // TODO I assume here when totallength is set to DownloadContext and it is
  362. // not 0, then filepath is also set DownloadContext correctly....
  363. if(_option->getAsBool(PREF_DRY_RUN) ||
  364. _downloadContext->getTotalLength() == 0) {
  365. createNextCommand(commands, e, 1);
  366. }else {
  367. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  368. throw DOWNLOAD_FAILURE_EXCEPTION
  369. (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
  370. _downloadContext->getBasePath().c_str()).str());
  371. }
  372. adjustFilename
  373. (SharedHandle<BtProgressInfoFile>(new DefaultBtProgressInfoFile
  374. (_downloadContext,
  375. SharedHandle<PieceStorage>(),
  376. _option.get())));
  377. initPieceStorage();
  378. BtProgressInfoFileHandle infoFile
  379. (new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage,
  380. _option.get()));
  381. if(!infoFile->exists() && downloadFinishedByFileLength()) {
  382. _pieceStorage->markAllPiecesDone();
  383. _logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED,
  384. _gid, _downloadContext->getBasePath().c_str());
  385. } else {
  386. loadAndOpenFile(infoFile);
  387. SharedHandle<CheckIntegrityEntry> checkIntegrityEntry
  388. (new StreamCheckIntegrityEntry(this));
  389. processCheckIntegrityEntry(commands, checkIntegrityEntry, e);
  390. }
  391. }
  392. }
  393. void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
  394. const CheckIntegrityEntryHandle& entry,
  395. DownloadEngine* e)
  396. {
  397. #ifdef ENABLE_MESSAGE_DIGEST
  398. if(_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  399. entry->isValidationReady()) {
  400. entry->initValidator();
  401. entry->cutTrailingGarbage();
  402. // Don't save control file(.aria2 file) when user presses
  403. // control-c key while aria2 is checking hashes. If control file
  404. // doesn't exist when aria2 launched, the completed length in
  405. // saved control file will be 0 byte and this confuses user.
  406. // enableSaveControlFile() will be called after hash checking is
  407. // done. See CheckIntegrityCommand.
  408. disableSaveControlFile();
  409. e->_checkIntegrityMan->pushEntry(entry);
  410. } else
  411. #endif // ENABLE_MESSAGE_DIGEST
  412. {
  413. entry->onDownloadIncomplete(commands, e);
  414. }
  415. }
  416. void RequestGroup::initPieceStorage()
  417. {
  418. SharedHandle<PieceStorage> tempPieceStorage;
  419. if(_downloadContext->knowsTotalLength()) {
  420. #ifdef ENABLE_BITTORRENT
  421. SharedHandle<DefaultPieceStorage> ps
  422. (new DefaultPieceStorage(_downloadContext, _option.get()));
  423. if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
  424. if(isUriSuppliedForRequsetFileEntry
  425. (_downloadContext->getFileEntries().begin(),
  426. _downloadContext->getFileEntries().end())) {
  427. // Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent
  428. // integrated downloads. Currently multi-file integrated
  429. // download is not supported.
  430. if(_logger->debug()) {
  431. _logger->debug("Using LongestSequencePieceSelector");
  432. }
  433. ps->setPieceSelector
  434. (SharedHandle<PieceSelector>(new LongestSequencePieceSelector()));
  435. }
  436. if(_option->defined(PREF_BT_PRIORITIZE_PIECE)) {
  437. std::vector<size_t> result;
  438. util::parsePrioritizePieceRange
  439. (result, _option->get(PREF_BT_PRIORITIZE_PIECE),
  440. _downloadContext->getFileEntries(),
  441. _downloadContext->getPieceLength());
  442. if(!result.empty()) {
  443. std::random_shuffle(result.begin(), result.end(),
  444. *(SimpleRandomizer::getInstance().get()));
  445. SharedHandle<PriorityPieceSelector> priSelector
  446. (new PriorityPieceSelector(ps->getPieceSelector()));
  447. priSelector->setPriorityPiece(result.begin(), result.end());
  448. ps->setPieceSelector(priSelector);
  449. }
  450. }
  451. }
  452. #else // !ENABLE_BITTORRENT
  453. SharedHandle<DefaultPieceStorage> ps
  454. (new DefaultPieceStorage(_downloadContext, _option.get()));
  455. #endif // !ENABLE_BITTORRENT
  456. if(!_diskWriterFactory.isNull()) {
  457. ps->setDiskWriterFactory(_diskWriterFactory);
  458. }
  459. tempPieceStorage = ps;
  460. } else {
  461. UnknownLengthPieceStorageHandle ps
  462. (new UnknownLengthPieceStorage(_downloadContext, _option.get()));
  463. if(!_diskWriterFactory.isNull()) {
  464. ps->setDiskWriterFactory(_diskWriterFactory);
  465. }
  466. tempPieceStorage = ps;
  467. }
  468. tempPieceStorage->initStorage();
  469. SharedHandle<SegmentMan> tempSegmentMan
  470. (new SegmentMan(_option.get(), _downloadContext, tempPieceStorage));
  471. _pieceStorage = tempPieceStorage;
  472. _segmentMan = tempSegmentMan;
  473. }
  474. bool RequestGroup::downloadFinishedByFileLength()
  475. {
  476. // assuming that a control file doesn't exist.
  477. if(!isPreLocalFileCheckEnabled() ||
  478. _option->getAsBool(PREF_ALLOW_OVERWRITE) ||
  479. (_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  480. !_downloadContext->getPieceHashes().empty())) {
  481. return false;
  482. }
  483. if(!_downloadContext->knowsTotalLength()) {
  484. return false;
  485. }
  486. File outfile(getFirstFilePath());
  487. if(outfile.exists() && _downloadContext->getTotalLength() == outfile.size()) {
  488. return true;
  489. } else {
  490. return false;
  491. }
  492. }
  493. void RequestGroup::adjustFilename
  494. (const SharedHandle<BtProgressInfoFile>& infoFile)
  495. {
  496. if(!isPreLocalFileCheckEnabled()) {
  497. // OK, no need to care about filename.
  498. } else if(infoFile->exists()) {
  499. // Use current filename
  500. } else if(downloadFinishedByFileLength()) {
  501. // File was downloaded already, no need to change file name.
  502. } else {
  503. File outfile(getFirstFilePath());
  504. if(outfile.exists() && _option->getAsBool(PREF_CONTINUE) &&
  505. outfile.size() <= _downloadContext->getTotalLength()) {
  506. // File exists but user decided to resume it.
  507. } else {
  508. #ifdef ENABLE_MESSAGE_DIGEST
  509. if(outfile.exists() && _option->getAsBool(PREF_CHECK_INTEGRITY)) {
  510. // check-integrity existing file
  511. } else {
  512. #endif // ENABLE_MESSAGE_DIGEST
  513. shouldCancelDownloadForSafety();
  514. #ifdef ENABLE_MESSAGE_DIGEST
  515. }
  516. #endif // ENABLE_MESSAGE_DIGEST
  517. }
  518. }
  519. }
  520. void RequestGroup::loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoFile)
  521. {
  522. try {
  523. if(!isPreLocalFileCheckEnabled()) {
  524. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  525. return;
  526. }
  527. // Remove the control file if download file doesn't exist
  528. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  529. progressInfoFile->removeFile();
  530. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  531. progressInfoFile->getFilename().c_str(),
  532. _downloadContext->getBasePath().c_str());
  533. }
  534. if(progressInfoFile->exists()) {
  535. progressInfoFile->load();
  536. _pieceStorage->getDiskAdaptor()->openExistingFile();
  537. } else {
  538. File outfile(getFirstFilePath());
  539. if(outfile.exists() && _option->getAsBool(PREF_CONTINUE) &&
  540. outfile.size() <= getTotalLength()) {
  541. _pieceStorage->getDiskAdaptor()->openExistingFile();
  542. _pieceStorage->markPiecesDone(outfile.size());
  543. } else {
  544. #ifdef ENABLE_MESSAGE_DIGEST
  545. if(outfile.exists() && _option->getAsBool(PREF_CHECK_INTEGRITY)) {
  546. _pieceStorage->getDiskAdaptor()->openExistingFile();
  547. } else {
  548. #endif // ENABLE_MESSAGE_DIGEST
  549. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  550. #ifdef ENABLE_MESSAGE_DIGEST
  551. }
  552. #endif // ENABLE_MESSAGE_DIGEST
  553. }
  554. }
  555. setProgressInfoFile(progressInfoFile);
  556. } catch(RecoverableException& e) {
  557. throw DOWNLOAD_FAILURE_EXCEPTION2
  558. (StringFormat(EX_DOWNLOAD_ABORTED).str(), e);
  559. }
  560. }
  561. // assuming that a control file does not exist
  562. void RequestGroup::shouldCancelDownloadForSafety()
  563. {
  564. if(_option->getAsBool(PREF_ALLOW_OVERWRITE)) {
  565. return;
  566. }
  567. File outfile(getFirstFilePath());
  568. if(outfile.exists()) {
  569. if(_option->getAsBool(PREF_AUTO_FILE_RENAMING)) {
  570. if(tryAutoFileRenaming()) {
  571. _logger->notice(MSG_FILE_RENAMED, getFirstFilePath().c_str());
  572. } else {
  573. throw DOWNLOAD_FAILURE_EXCEPTION
  574. (StringFormat("File renaming failed: %s",
  575. getFirstFilePath().c_str()).str());
  576. }
  577. } else {
  578. throw DOWNLOAD_FAILURE_EXCEPTION
  579. (StringFormat(MSG_FILE_ALREADY_EXISTS,
  580. getFirstFilePath().c_str()).str());
  581. }
  582. }
  583. }
  584. bool RequestGroup::tryAutoFileRenaming()
  585. {
  586. std::string filepath = getFirstFilePath();
  587. if(filepath.empty()) {
  588. return false;
  589. }
  590. for(unsigned int i = 1; i < 10000; ++i) {
  591. File newfile(strconcat(filepath, A2STR::DOT_C, util::uitos(i)));
  592. File ctrlfile(newfile.getPath()+DefaultBtProgressInfoFile::getSuffix());
  593. if(!newfile.exists() || (newfile.exists() && ctrlfile.exists())) {
  594. _downloadContext->getFirstFileEntry()->setPath(newfile.getPath());
  595. return true;
  596. }
  597. }
  598. return false;
  599. }
  600. void RequestGroup::createNextCommandWithAdj(std::deque<Command*>& commands,
  601. DownloadEngine* e, int numAdj)
  602. {
  603. int numCommand;
  604. if(getTotalLength() == 0) {
  605. numCommand = 1+numAdj;
  606. } else {
  607. numCommand = std::min(_downloadContext->getNumPieces(),
  608. _numConcurrentCommand);
  609. numCommand += numAdj;
  610. }
  611. if(numCommand > 0) {
  612. createNextCommand(commands, e, numCommand);
  613. }
  614. }
  615. void RequestGroup::createNextCommand(std::deque<Command*>& commands,
  616. DownloadEngine* e,
  617. unsigned int numCommand)
  618. {
  619. for(; numCommand--; ) {
  620. Command* command = new CreateRequestCommand(e->newCUID(), this, e);
  621. commands.push_back(command);
  622. }
  623. if(!commands.empty()) {
  624. e->setNoWait(true);
  625. }
  626. }
  627. std::string RequestGroup::getFirstFilePath() const
  628. {
  629. assert(!_downloadContext.isNull());
  630. if(inMemoryDownload()) {
  631. static const std::string DIR_MEMORY("[MEMORY]");
  632. return DIR_MEMORY+File(_downloadContext->getFirstFileEntry()->getPath()).getBasename();
  633. } else {
  634. return _downloadContext->getFirstFileEntry()->getPath();
  635. }
  636. }
  637. uint64_t RequestGroup::getTotalLength() const
  638. {
  639. if(_pieceStorage.isNull()) {
  640. return 0;
  641. } else {
  642. if(_pieceStorage->isSelectiveDownloadingMode()) {
  643. return _pieceStorage->getFilteredTotalLength();
  644. } else {
  645. return _pieceStorage->getTotalLength();
  646. }
  647. }
  648. }
  649. uint64_t RequestGroup::getCompletedLength() const
  650. {
  651. if(_pieceStorage.isNull()) {
  652. return 0;
  653. } else {
  654. if(_pieceStorage->isSelectiveDownloadingMode()) {
  655. return _pieceStorage->getFilteredCompletedLength();
  656. } else {
  657. return _pieceStorage->getCompletedLength();
  658. }
  659. }
  660. }
  661. void RequestGroup::validateFilename(const std::string& expectedFilename,
  662. const std::string& actualFilename) const
  663. {
  664. if(expectedFilename.empty()) {
  665. return;
  666. }
  667. if(expectedFilename != actualFilename) {
  668. throw DL_ABORT_EX(StringFormat(EX_FILENAME_MISMATCH,
  669. expectedFilename.c_str(),
  670. actualFilename.c_str()).str());
  671. }
  672. }
  673. void RequestGroup::validateTotalLength(uint64_t expectedTotalLength,
  674. uint64_t actualTotalLength) const
  675. {
  676. if(expectedTotalLength <= 0) {
  677. return;
  678. }
  679. if(expectedTotalLength != actualTotalLength) {
  680. throw DL_ABORT_EX
  681. (StringFormat(EX_SIZE_MISMATCH,
  682. util::itos(expectedTotalLength, true).c_str(),
  683. util::itos(actualTotalLength, true).c_str()).str());
  684. }
  685. }
  686. void RequestGroup::validateFilename(const std::string& actualFilename) const
  687. {
  688. validateFilename(_downloadContext->getFileEntries().front()->getBasename(), actualFilename);
  689. }
  690. void RequestGroup::validateTotalLength(uint64_t actualTotalLength) const
  691. {
  692. validateTotalLength(getTotalLength(), actualTotalLength);
  693. }
  694. void RequestGroup::increaseStreamConnection()
  695. {
  696. ++_numStreamConnection;
  697. }
  698. void RequestGroup::decreaseStreamConnection()
  699. {
  700. --_numStreamConnection;
  701. }
  702. unsigned int RequestGroup::getNumConnection() const
  703. {
  704. unsigned int numConnection = _numStreamConnection;
  705. #ifdef ENABLE_BITTORRENT
  706. if(!_btRuntime.isNull()) {
  707. numConnection += _btRuntime->getConnections();
  708. }
  709. #endif // ENABLE_BITTORRENT
  710. return numConnection;
  711. }
  712. void RequestGroup::increaseNumCommand()
  713. {
  714. ++_numCommand;
  715. }
  716. void RequestGroup::decreaseNumCommand()
  717. {
  718. --_numCommand;
  719. }
  720. TransferStat RequestGroup::calculateStat()
  721. {
  722. TransferStat stat;
  723. #ifdef ENABLE_BITTORRENT
  724. if(!_peerStorage.isNull()) {
  725. stat = _peerStorage->calculateStat();
  726. }
  727. #endif // ENABLE_BITTORRENT
  728. if(!_segmentMan.isNull()) {
  729. stat.setDownloadSpeed(stat.getDownloadSpeed()+_segmentMan->calculateDownloadSpeed());
  730. }
  731. return stat;
  732. }
  733. void RequestGroup::setHaltRequested(bool f, HaltReason haltReason)
  734. {
  735. _haltRequested = f;
  736. if(_haltRequested) {
  737. _haltReason = haltReason;
  738. }
  739. #ifdef ENABLE_BITTORRENT
  740. if(!_btRuntime.isNull()) {
  741. _btRuntime->setHalt(f);
  742. }
  743. #endif // ENABLE_BITTORRENT
  744. }
  745. void RequestGroup::setForceHaltRequested(bool f, HaltReason haltReason)
  746. {
  747. setHaltRequested(f, haltReason);
  748. _forceHaltRequested = f;
  749. }
  750. void RequestGroup::releaseRuntimeResource(DownloadEngine* e)
  751. {
  752. #ifdef ENABLE_BITTORRENT
  753. e->getBtRegistry()->remove(_gid);
  754. #endif // ENABLE_BITTORRENT
  755. if(!_pieceStorage.isNull()) {
  756. _pieceStorage->removeAdvertisedPiece(0);
  757. }
  758. _downloadContext->releaseRuntimeResource();
  759. }
  760. void RequestGroup::preDownloadProcessing()
  761. {
  762. if(_logger->debug()) {
  763. _logger->debug("Finding PreDownloadHandler for path %s.",
  764. getFirstFilePath().c_str());
  765. }
  766. try {
  767. for(PreDownloadHandlers::const_iterator itr = _preDownloadHandlers.begin();
  768. itr != _preDownloadHandlers.end(); ++itr) {
  769. if((*itr)->canHandle(this)) {
  770. (*itr)->execute(this);
  771. return;
  772. }
  773. }
  774. } catch(RecoverableException& ex) {
  775. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  776. return;
  777. }
  778. if(_logger->debug()) {
  779. _logger->debug("No PreDownloadHandler found.");
  780. }
  781. return;
  782. }
  783. void RequestGroup::postDownloadProcessing
  784. (std::deque<SharedHandle<RequestGroup> >& groups)
  785. {
  786. if(_logger->debug()) {
  787. _logger->debug("Finding PostDownloadHandler for path %s.",
  788. getFirstFilePath().c_str());
  789. }
  790. try {
  791. for(PostDownloadHandlers::const_iterator itr = _postDownloadHandlers.begin();
  792. itr != _postDownloadHandlers.end(); ++itr) {
  793. if((*itr)->canHandle(this)) {
  794. (*itr)->getNextRequestGroups(groups, this);
  795. return;
  796. }
  797. }
  798. } catch(RecoverableException& ex) {
  799. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  800. }
  801. if(_logger->debug()) {
  802. _logger->debug("No PostDownloadHandler found.");
  803. }
  804. }
  805. void RequestGroup::initializePreDownloadHandler()
  806. {
  807. #ifdef ENABLE_BITTORRENT
  808. if(_option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  809. _preDownloadHandlers.push_back(DownloadHandlerFactory::getBtPreDownloadHandler());
  810. }
  811. #endif // ENABLE_BITTORRENT
  812. #ifdef ENABLE_METALINK
  813. if(_option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  814. _preDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPreDownloadHandler());
  815. }
  816. #endif // ENABLE_METALINK
  817. }
  818. void RequestGroup::initializePostDownloadHandler()
  819. {
  820. #ifdef ENABLE_BITTORRENT
  821. if(_option->getAsBool(PREF_FOLLOW_TORRENT) ||
  822. _option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  823. _postDownloadHandlers.push_back(DownloadHandlerFactory::getBtPostDownloadHandler());
  824. }
  825. #endif // ENABLE_BITTORRENT
  826. #ifdef ENABLE_METALINK
  827. if(_option->getAsBool(PREF_FOLLOW_METALINK) ||
  828. _option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  829. _postDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPostDownloadHandler());
  830. }
  831. #endif // ENABLE_METALINK
  832. }
  833. bool RequestGroup::isDependencyResolved()
  834. {
  835. if(_dependency.isNull()) {
  836. return true;
  837. }
  838. return _dependency->resolve();
  839. }
  840. void RequestGroup::dependsOn(const DependencyHandle& dep)
  841. {
  842. _dependency = dep;
  843. }
  844. void RequestGroup::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
  845. {
  846. _diskWriterFactory = diskWriterFactory;
  847. }
  848. void RequestGroup::addPostDownloadHandler(const PostDownloadHandlerHandle& handler)
  849. {
  850. _postDownloadHandlers.push_back(handler);
  851. }
  852. void RequestGroup::addPreDownloadHandler(const PreDownloadHandlerHandle& handler)
  853. {
  854. _preDownloadHandlers.push_back(handler);
  855. }
  856. void RequestGroup::clearPostDownloadHandler()
  857. {
  858. _postDownloadHandlers.clear();
  859. }
  860. void RequestGroup::clearPreDownloadHandler()
  861. {
  862. _preDownloadHandlers.clear();
  863. }
  864. void RequestGroup::setPieceStorage(const PieceStorageHandle& pieceStorage)
  865. {
  866. _pieceStorage = pieceStorage;
  867. }
  868. void RequestGroup::setProgressInfoFile(const BtProgressInfoFileHandle& progressInfoFile)
  869. {
  870. _progressInfoFile = progressInfoFile;
  871. }
  872. bool RequestGroup::needsFileAllocation() const
  873. {
  874. return isFileAllocationEnabled() &&
  875. (uint64_t)_option->getAsLLInt(PREF_NO_FILE_ALLOCATION_LIMIT) <= getTotalLength() &&
  876. !_pieceStorage->getDiskAdaptor()->fileAllocationIterator()->finished();
  877. }
  878. DownloadResultHandle RequestGroup::createDownloadResult() const
  879. {
  880. uint64_t sessionDownloadLength = 0;
  881. #ifdef ENABLE_BITTORRENT
  882. if(!_peerStorage.isNull()) {
  883. sessionDownloadLength +=
  884. _peerStorage->calculateStat().getSessionDownloadLength();
  885. }
  886. #endif // ENABLE_BITTORRENT
  887. if(!_segmentMan.isNull()) {
  888. sessionDownloadLength +=
  889. _segmentMan->calculateSessionDownloadLength();
  890. }
  891. return
  892. SharedHandle<DownloadResult>
  893. (new DownloadResult(_gid,
  894. _downloadContext->getFileEntries(),
  895. _inMemoryDownload,
  896. sessionDownloadLength,
  897. _downloadContext->calculateSessionTime(),
  898. downloadResult(),
  899. _followedByGIDs,
  900. _belongsToGID));
  901. }
  902. void RequestGroup::reportDownloadFinished()
  903. {
  904. _logger->notice(MSG_FILE_DOWNLOAD_COMPLETED,
  905. _downloadContext->getBasePath().c_str());
  906. _uriSelector->resetCounters();
  907. #ifdef ENABLE_BITTORRENT
  908. if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
  909. TransferStat stat = calculateStat();
  910. double shareRatio =
  911. ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0;
  912. const BDE& attrs = _downloadContext->getAttribute(bittorrent::BITTORRENT);
  913. if(attrs.containsKey(bittorrent::METADATA)) {
  914. _logger->notice(MSG_SHARE_RATIO_REPORT,
  915. shareRatio,
  916. util::abbrevSize(stat.getAllTimeUploadLength()).c_str(),
  917. util::abbrevSize(getCompletedLength()).c_str());
  918. }
  919. }
  920. #endif // ENABLE_BITTORRENT
  921. }
  922. void RequestGroup::addAcceptType(const std::string& type)
  923. {
  924. if(std::find(_acceptTypes.begin(), _acceptTypes.end(), type) == _acceptTypes.end()) {
  925. _acceptTypes.push_back(type);
  926. }
  927. }
  928. void RequestGroup::removeAcceptType(const std::string& type)
  929. {
  930. _acceptTypes.erase(std::remove(_acceptTypes.begin(), _acceptTypes.end(), type),
  931. _acceptTypes.end());
  932. }
  933. void RequestGroup::setURISelector(const SharedHandle<URISelector>& uriSelector)
  934. {
  935. _uriSelector = uriSelector;
  936. }
  937. void RequestGroup::applyLastModifiedTimeToLocalFiles()
  938. {
  939. if(!_pieceStorage.isNull() && _lastModifiedTime.good()) {
  940. time_t t = _lastModifiedTime.getTime();
  941. _logger->info("Applying Last-Modified time: %s in local time zone",
  942. ctime(&t));
  943. size_t n =
  944. _pieceStorage->getDiskAdaptor()->utime(Time(), _lastModifiedTime);
  945. _logger->info("Last-Modified attrs of %lu files were updated.",
  946. static_cast<unsigned long>(n));
  947. }
  948. }
  949. void RequestGroup::updateLastModifiedTime(const Time& time)
  950. {
  951. if(time.good() && _lastModifiedTime < time) {
  952. _lastModifiedTime = time;
  953. }
  954. }
  955. void RequestGroup::increaseAndValidateFileNotFoundCount()
  956. {
  957. ++_fileNotFoundCount;
  958. const unsigned int maxCount = _option->getAsInt(PREF_MAX_FILE_NOT_FOUND);
  959. if(maxCount > 0 && _fileNotFoundCount >= maxCount &&
  960. (_segmentMan.isNull() ||
  961. _segmentMan->calculateSessionDownloadLength() == 0)) {
  962. throw DOWNLOAD_FAILURE_EXCEPTION2
  963. (StringFormat("Reached max-file-not-found count=%u", maxCount).str(),
  964. downloadresultcode::MAX_FILE_NOT_FOUND);
  965. }
  966. }
  967. void RequestGroup::markInMemoryDownload()
  968. {
  969. _inMemoryDownload = true;
  970. }
  971. void RequestGroup::setTimeout(time_t timeout)
  972. {
  973. _timeout = timeout;
  974. }
  975. bool RequestGroup::doesDownloadSpeedExceed()
  976. {
  977. return _maxDownloadSpeedLimit > 0 &&
  978. _maxDownloadSpeedLimit < calculateStat().getDownloadSpeed();
  979. }
  980. bool RequestGroup::doesUploadSpeedExceed()
  981. {
  982. return _maxUploadSpeedLimit > 0 &&
  983. _maxUploadSpeedLimit < calculateStat().getUploadSpeed();
  984. }
  985. void RequestGroup::setLastUriResult
  986. (const std::string uri, downloadresultcode::RESULT result)
  987. {
  988. _lastUriResult.reset(new URIResult(uri, result));
  989. }
  990. void RequestGroup::saveControlFile() const
  991. {
  992. if(_saveControlFile) {
  993. _progressInfoFile->save();
  994. }
  995. }
  996. void RequestGroup::removeControlFile() const
  997. {
  998. _progressInfoFile->removeFile();
  999. }
  1000. void RequestGroup::setDownloadContext
  1001. (const SharedHandle<DownloadContext>& downloadContext)
  1002. {
  1003. _downloadContext = downloadContext;
  1004. if(!_downloadContext.isNull()) {
  1005. _downloadContext->setOwnerRequestGroup(this);
  1006. }
  1007. }
  1008. int32_t RequestGroup::newGID()
  1009. {
  1010. if(_gidCounter == INT32_MAX) {
  1011. _gidCounter = 0;
  1012. }
  1013. return ++_gidCounter;
  1014. }
  1015. } // namespace aria2