RequestGroup.cc 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  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 "DefaultSegmentManFactory.h"
  41. #include "SegmentMan.h"
  42. #include "NullProgressInfoFile.h"
  43. #include "Dependency.h"
  44. #include "prefs.h"
  45. #include "CreateRequestCommand.h"
  46. #include "File.h"
  47. #include "message.h"
  48. #include "util.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 "DownloadContext.h"
  58. #include "DlAbortEx.h"
  59. #include "DownloadFailureException.h"
  60. #include "RequestGroupMan.h"
  61. #include "DefaultBtProgressInfoFile.h"
  62. #include "DefaultPieceStorage.h"
  63. #include "DownloadHandlerFactory.h"
  64. #include "MemoryBufferPreDownloadHandler.h"
  65. #include "DownloadHandlerConstants.h"
  66. #include "Option.h"
  67. #include "FileEntry.h"
  68. #include "Request.h"
  69. #include "FileAllocationIterator.h"
  70. #include "StringFormat.h"
  71. #include "A2STR.h"
  72. #include "URISelector.h"
  73. #include "InOrderURISelector.h"
  74. #include "PieceSelector.h"
  75. #include "a2functional.h"
  76. #include "SocketCore.h"
  77. #include "SimpleRandomizer.h"
  78. #ifdef ENABLE_MESSAGE_DIGEST
  79. # include "CheckIntegrityCommand.h"
  80. #endif // ENABLE_MESSAGE_DIGEST
  81. #ifdef ENABLE_BITTORRENT
  82. # include "bittorrent_helper.h"
  83. # include "BtRegistry.h"
  84. # include "BtCheckIntegrityEntry.h"
  85. # include "DefaultPeerStorage.h"
  86. # include "DefaultBtAnnounce.h"
  87. # include "BtRuntime.h"
  88. # include "BtSetup.h"
  89. # include "BtFileAllocationEntry.h"
  90. # include "BtPostDownloadHandler.h"
  91. # include "DHTSetup.h"
  92. # include "DHTRegistry.h"
  93. # include "BtMessageFactory.h"
  94. # include "BtRequestFactory.h"
  95. # include "BtMessageDispatcher.h"
  96. # include "BtMessageReceiver.h"
  97. # include "PeerConnection.h"
  98. # include "ExtensionMessageFactory.h"
  99. # include "DHTPeerAnnounceStorage.h"
  100. # include "DHTEntryPointNameResolveCommand.h"
  101. # include "LongestSequencePieceSelector.h"
  102. # include "PriorityPieceSelector.h"
  103. #endif // ENABLE_BITTORRENT
  104. #ifdef ENABLE_METALINK
  105. # include "MetalinkPostDownloadHandler.h"
  106. #endif // ENABLE_METALINK
  107. namespace aria2 {
  108. int32_t RequestGroup::_gidCounter = 0;
  109. const std::string RequestGroup::ACCEPT_METALINK = "application/metalink+xml";
  110. RequestGroup::RequestGroup(const SharedHandle<Option>& option):
  111. _gid(newGID()),
  112. _option(new Option(*option.get())),
  113. _numConcurrentCommand(option->getAsInt(PREF_SPLIT)),
  114. _numStreamConnection(0),
  115. _numCommand(0),
  116. _segmentManFactory(new DefaultSegmentManFactory(_option.get())),
  117. _saveControlFile(true),
  118. _progressInfoFile(new NullProgressInfoFile()),
  119. _preLocalFileCheckEnabled(true),
  120. _haltRequested(false),
  121. _forceHaltRequested(false),
  122. _haltReason(RequestGroup::NONE),
  123. _uriSelector(new InOrderURISelector()),
  124. _lastModifiedTime(Time::null()),
  125. _fileNotFoundCount(0),
  126. _timeout(option->getAsInt(PREF_TIMEOUT)),
  127. _inMemoryDownload(false),
  128. _maxDownloadSpeedLimit(option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT)),
  129. _maxUploadSpeedLimit(option->getAsInt(PREF_MAX_UPLOAD_LIMIT)),
  130. _belongsToGID(0),
  131. _logger(LogFactory::getInstance())
  132. {
  133. _fileAllocationEnabled = _option->get(PREF_FILE_ALLOCATION) != V_NONE;
  134. // Add types to be sent as a Accept header value here.
  135. // It would be good to put this value in Option so that user can tweak
  136. // and add this list.
  137. // ACCEPT_METALINK is used for `transparent metalink'.
  138. addAcceptType(ACCEPT_METALINK);
  139. if(!_option->getAsBool(PREF_DRY_RUN)) {
  140. initializePreDownloadHandler();
  141. initializePostDownloadHandler();
  142. }
  143. }
  144. RequestGroup::~RequestGroup() {}
  145. const SegmentManHandle& RequestGroup::initSegmentMan()
  146. {
  147. _segmentMan = _segmentManFactory->createNewInstance(_downloadContext,
  148. _pieceStorage);
  149. return _segmentMan;
  150. }
  151. bool RequestGroup::downloadFinished() const
  152. {
  153. if(_pieceStorage.isNull()) {
  154. return false;
  155. } else {
  156. return _pieceStorage->downloadFinished();
  157. }
  158. }
  159. bool RequestGroup::allDownloadFinished() const
  160. {
  161. if(_pieceStorage.isNull()) {
  162. return false;
  163. } else {
  164. return _pieceStorage->allDownloadFinished();
  165. }
  166. }
  167. downloadresultcode::RESULT RequestGroup::downloadResult() const
  168. {
  169. if (downloadFinished())
  170. return downloadresultcode::FINISHED;
  171. else {
  172. if (_lastUriResult.isNull()) {
  173. if(_haltReason == RequestGroup::USER_REQUEST) {
  174. return downloadresultcode::IN_PROGRESS;
  175. } else {
  176. return downloadresultcode::UNKNOWN_ERROR;
  177. }
  178. } else {
  179. return _lastUriResult->getResult();
  180. }
  181. }
  182. }
  183. void RequestGroup::closeFile()
  184. {
  185. if(!_pieceStorage.isNull()) {
  186. _pieceStorage->getDiskAdaptor()->closeFile();
  187. }
  188. }
  189. void RequestGroup::createInitialCommand
  190. (std::deque<Command*>& commands, DownloadEngine* e)
  191. {
  192. #ifdef ENABLE_BITTORRENT
  193. {
  194. if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
  195. const BDE& torrentAttrs =
  196. _downloadContext->getAttribute(bittorrent::BITTORRENT);
  197. bool metadataGetMode = !torrentAttrs.containsKey(bittorrent::METADATA);
  198. if(_option->getAsBool(PREF_DRY_RUN)) {
  199. throw DOWNLOAD_FAILURE_EXCEPTION
  200. ("Cancel BitTorrent download in dry-run context.");
  201. }
  202. SharedHandle<BtRegistry> btRegistry = e->getBtRegistry();
  203. if(!btRegistry->getDownloadContext
  204. (torrentAttrs[bittorrent::INFO_HASH].s()).isNull()) {
  205. throw DOWNLOAD_FAILURE_EXCEPTION
  206. (StringFormat
  207. ("InfoHash %s is already registered.",
  208. bittorrent::getInfoHashString(_downloadContext).c_str()).str());
  209. }
  210. if(metadataGetMode) {
  211. // Use UnknownLengthPieceStorage.
  212. initPieceStorage();
  213. } else {
  214. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  215. throw DOWNLOAD_FAILURE_EXCEPTION
  216. (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
  217. _downloadContext->getBasePath().c_str()).str());
  218. }
  219. initPieceStorage();
  220. if(_downloadContext->getFileEntries().size() > 1) {
  221. _pieceStorage->setupFileFilter();
  222. }
  223. }
  224. SharedHandle<DefaultBtProgressInfoFile> progressInfoFile;
  225. if(!metadataGetMode) {
  226. progressInfoFile.reset(new DefaultBtProgressInfoFile(_downloadContext,
  227. _pieceStorage,
  228. _option.get()));
  229. }
  230. BtRuntimeHandle btRuntime(new BtRuntime());
  231. btRuntime->setMaxPeers(_option->getAsInt(PREF_BT_MAX_PEERS));
  232. _btRuntime = btRuntime;
  233. if(!progressInfoFile.isNull()) {
  234. progressInfoFile->setBtRuntime(btRuntime);
  235. }
  236. SharedHandle<DefaultPeerStorage> peerStorage
  237. (new DefaultPeerStorage(_option.get()));
  238. peerStorage->setBtRuntime(btRuntime);
  239. peerStorage->setPieceStorage(_pieceStorage);
  240. _peerStorage = peerStorage;
  241. if(!progressInfoFile.isNull()) {
  242. progressInfoFile->setPeerStorage(peerStorage);
  243. }
  244. SharedHandle<DefaultBtAnnounce> btAnnounce
  245. (new DefaultBtAnnounce(_downloadContext, _option.get()));
  246. btAnnounce->setBtRuntime(btRuntime);
  247. btAnnounce->setPieceStorage(_pieceStorage);
  248. btAnnounce->setPeerStorage(peerStorage);
  249. btAnnounce->setUserDefinedInterval
  250. (_option->getAsInt(PREF_BT_TRACKER_INTERVAL));
  251. btAnnounce->shuffleAnnounce();
  252. assert(btRegistry->get(_gid).isNull());
  253. btRegistry->put(_gid,
  254. BtObject(_downloadContext,
  255. _pieceStorage,
  256. peerStorage,
  257. btAnnounce,
  258. btRuntime,
  259. (progressInfoFile.isNull()?
  260. _progressInfoFile:
  261. SharedHandle<BtProgressInfoFile>
  262. (progressInfoFile))));
  263. if(metadataGetMode) {
  264. if(_option->getAsBool(PREF_ENABLE_DHT)) {
  265. std::deque<Command*> dhtCommands;
  266. DHTSetup().setup(dhtCommands, e, _option.get());
  267. e->addCommand(dhtCommands);
  268. } else {
  269. _logger->notice("For BitTorrent Magnet URI, enabling DHT is strongly"
  270. " recommended. See --enable-dht option.");
  271. }
  272. SharedHandle<CheckIntegrityEntry> entry
  273. (new BtCheckIntegrityEntry(this));
  274. entry->onDownloadIncomplete(commands, e);
  275. return;
  276. }
  277. // Remove the control file if download file doesn't exist
  278. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  279. progressInfoFile->removeFile();
  280. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  281. progressInfoFile->getFilename().c_str(),
  282. _downloadContext->getBasePath().c_str());
  283. }
  284. {
  285. uint64_t actualFileSize = _pieceStorage->getDiskAdaptor()->size();
  286. if(actualFileSize == _downloadContext->getTotalLength()) {
  287. // First, make DiskAdaptor read-only mode to allow the
  288. // program to seed file in read-only media.
  289. _pieceStorage->getDiskAdaptor()->enableReadOnly();
  290. } else {
  291. // Open file in writable mode to allow the program
  292. // truncate the file to _downloadContext->getTotalLength()
  293. _logger->debug("File size not match. File is opened in writable mode."
  294. " Expected:%s Actual:%s",
  295. util::uitos(_downloadContext->getTotalLength()).c_str(),
  296. util::uitos(actualFileSize).c_str());
  297. }
  298. }
  299. // Call Load, Save and file allocation command here
  300. if(progressInfoFile->exists()) {
  301. // load .aria2 file if it exists.
  302. progressInfoFile->load();
  303. _pieceStorage->getDiskAdaptor()->openFile();
  304. } else {
  305. if(_pieceStorage->getDiskAdaptor()->fileExists()) {
  306. if(!_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  307. !_option->getAsBool(PREF_ALLOW_OVERWRITE) &&
  308. !_option->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  309. // TODO we need this->haltRequested = true?
  310. throw DOWNLOAD_FAILURE_EXCEPTION
  311. (StringFormat
  312. (MSG_FILE_ALREADY_EXISTS,
  313. _downloadContext->getBasePath().c_str()).str());
  314. } else {
  315. _pieceStorage->getDiskAdaptor()->openFile();
  316. }
  317. if(_option->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  318. _pieceStorage->markAllPiecesDone();
  319. }
  320. } else {
  321. _pieceStorage->getDiskAdaptor()->openFile();
  322. }
  323. }
  324. _progressInfoFile = progressInfoFile;
  325. if(torrentAttrs[bittorrent::PRIVATE].i() == 0 &&
  326. _option->getAsBool(PREF_ENABLE_DHT)) {
  327. std::deque<Command*> dhtCommands;
  328. DHTSetup().setup(dhtCommands, e, _option.get());
  329. e->addCommand(dhtCommands);
  330. if(!torrentAttrs[bittorrent::NODES].empty() && DHTSetup::initialized()) {
  331. std::deque<std::pair<std::string, uint16_t> > entryPoints;
  332. const BDE& nodes = torrentAttrs[bittorrent::NODES];
  333. for(BDE::List::const_iterator i = nodes.listBegin();
  334. i != nodes.listEnd(); ++i) {
  335. std::pair<std::string, uint16_t> addr
  336. ((*i)[bittorrent::HOSTNAME].s(), (*i)[bittorrent::PORT].i());
  337. entryPoints.push_back(addr);
  338. }
  339. DHTEntryPointNameResolveCommand* command =
  340. new DHTEntryPointNameResolveCommand(e->newCUID(), e, entryPoints);
  341. command->setTaskQueue(DHTRegistry::_taskQueue);
  342. command->setTaskFactory(DHTRegistry::_taskFactory);
  343. command->setRoutingTable(DHTRegistry::_routingTable);
  344. command->setLocalNode(DHTRegistry::_localNode);
  345. e->commands.push_back(command);
  346. }
  347. }
  348. CheckIntegrityEntryHandle entry(new BtCheckIntegrityEntry(this));
  349. // --bt-seed-unverified=true is given and download has completed, skip
  350. // validation for piece hashes.
  351. if(_option->getAsBool(PREF_BT_SEED_UNVERIFIED) &&
  352. _pieceStorage->downloadFinished()) {
  353. entry->onDownloadFinished(commands, e);
  354. } else {
  355. processCheckIntegrityEntry(commands, entry, e);
  356. }
  357. return;
  358. }
  359. }
  360. #endif // ENABLE_BITTORRENT
  361. // TODO Currently, BitTorrent+WEB-Seeding is only way to download
  362. // multiple files in one RequestGroup. In this context, we don't
  363. // have BitTorrent, so add assertion here. This situation will be
  364. // changed if Metalink spec is formalized to support multi-file
  365. // torrent.
  366. assert(_downloadContext->getFileEntries().size() == 1);
  367. // TODO I assume here when totallength is set to DownloadContext and it is
  368. // not 0, then filepath is also set DownloadContext correctly....
  369. if(_option->getAsBool(PREF_DRY_RUN) ||
  370. _downloadContext->getTotalLength() == 0) {
  371. createNextCommand(commands, e, 1);
  372. }else {
  373. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  374. throw DOWNLOAD_FAILURE_EXCEPTION
  375. (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
  376. _downloadContext->getBasePath().c_str()).str());
  377. }
  378. adjustFilename
  379. (SharedHandle<BtProgressInfoFile>(new DefaultBtProgressInfoFile
  380. (_downloadContext,
  381. SharedHandle<PieceStorage>(),
  382. _option.get())));
  383. initPieceStorage();
  384. BtProgressInfoFileHandle infoFile
  385. (new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage,
  386. _option.get()));
  387. if(!infoFile->exists() && downloadFinishedByFileLength()) {
  388. _pieceStorage->markAllPiecesDone();
  389. _logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED,
  390. _gid, _downloadContext->getBasePath().c_str());
  391. } else {
  392. loadAndOpenFile(infoFile);
  393. SharedHandle<CheckIntegrityEntry> checkIntegrityEntry
  394. (new StreamCheckIntegrityEntry(this));
  395. processCheckIntegrityEntry(commands, checkIntegrityEntry, e);
  396. }
  397. }
  398. }
  399. void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
  400. const CheckIntegrityEntryHandle& entry,
  401. DownloadEngine* e)
  402. {
  403. #ifdef ENABLE_MESSAGE_DIGEST
  404. if(_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  405. entry->isValidationReady()) {
  406. entry->initValidator();
  407. entry->cutTrailingGarbage();
  408. // Don't save control file(.aria2 file) when user presses
  409. // control-c key while aria2 is checking hashes. If control file
  410. // doesn't exist when aria2 launched, the completed length in
  411. // saved control file will be 0 byte and this confuses user.
  412. // enableSaveControlFile() will be called after hash checking is
  413. // done. See CheckIntegrityCommand.
  414. disableSaveControlFile();
  415. e->_checkIntegrityMan->pushEntry(entry);
  416. } else
  417. #endif // ENABLE_MESSAGE_DIGEST
  418. {
  419. entry->onDownloadIncomplete(commands, e);
  420. }
  421. }
  422. void RequestGroup::initPieceStorage()
  423. {
  424. if(_downloadContext->knowsTotalLength()) {
  425. #ifdef ENABLE_BITTORRENT
  426. SharedHandle<DefaultPieceStorage> ps
  427. (new DefaultPieceStorage(_downloadContext, _option.get()));
  428. if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
  429. if(isUriSuppliedForRequsetFileEntry
  430. (_downloadContext->getFileEntries().begin(),
  431. _downloadContext->getFileEntries().end())) {
  432. // Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent
  433. // integrated downloads. Currently multi-file integrated
  434. // download is not supported.
  435. _logger->debug("Using LongestSequencePieceSelector");
  436. ps->setPieceSelector
  437. (SharedHandle<PieceSelector>(new LongestSequencePieceSelector()));
  438. }
  439. if(_option->defined(PREF_BT_PRIORITIZE_PIECE)) {
  440. std::vector<size_t> result;
  441. util::parsePrioritizePieceRange
  442. (result, _option->get(PREF_BT_PRIORITIZE_PIECE),
  443. _downloadContext->getFileEntries(),
  444. _downloadContext->getPieceLength());
  445. if(!result.empty()) {
  446. std::random_shuffle(result.begin(), result.end(),
  447. *(SimpleRandomizer::getInstance().get()));
  448. SharedHandle<PriorityPieceSelector> priSelector
  449. (new PriorityPieceSelector(ps->getPieceSelector()));
  450. priSelector->setPriorityPiece(result.begin(), result.end());
  451. ps->setPieceSelector(priSelector);
  452. }
  453. }
  454. }
  455. #else // !ENABLE_BITTORRENT
  456. SharedHandle<DefaultPieceStorage> ps
  457. (new DefaultPieceStorage(_downloadContext, _option.get()));
  458. #endif // !ENABLE_BITTORRENT
  459. if(!_diskWriterFactory.isNull()) {
  460. ps->setDiskWriterFactory(_diskWriterFactory);
  461. }
  462. _pieceStorage = ps;
  463. } else {
  464. UnknownLengthPieceStorageHandle ps
  465. (new UnknownLengthPieceStorage(_downloadContext, _option.get()));
  466. if(!_diskWriterFactory.isNull()) {
  467. ps->setDiskWriterFactory(_diskWriterFactory);
  468. }
  469. _pieceStorage = ps;
  470. }
  471. _pieceStorage->initStorage();
  472. initSegmentMan();
  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, ".", 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. _logger->debug("Finding PreDownloadHandler for path %s.",
  763. getFirstFilePath().c_str());
  764. try {
  765. for(PreDownloadHandlers::const_iterator itr = _preDownloadHandlers.begin();
  766. itr != _preDownloadHandlers.end(); ++itr) {
  767. if((*itr)->canHandle(this)) {
  768. (*itr)->execute(this);
  769. return;
  770. }
  771. }
  772. } catch(RecoverableException& ex) {
  773. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  774. return;
  775. }
  776. _logger->debug("No PreDownloadHandler found.");
  777. return;
  778. }
  779. void RequestGroup::postDownloadProcessing
  780. (std::deque<SharedHandle<RequestGroup> >& groups)
  781. {
  782. _logger->debug("Finding PostDownloadHandler for path %s.",
  783. getFirstFilePath().c_str());
  784. try {
  785. for(PostDownloadHandlers::const_iterator itr = _postDownloadHandlers.begin();
  786. itr != _postDownloadHandlers.end(); ++itr) {
  787. if((*itr)->canHandle(this)) {
  788. (*itr)->getNextRequestGroups(groups, this);
  789. return;
  790. }
  791. }
  792. } catch(RecoverableException& ex) {
  793. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  794. }
  795. _logger->debug("No PostDownloadHandler found.");
  796. }
  797. void RequestGroup::initializePreDownloadHandler()
  798. {
  799. #ifdef ENABLE_BITTORRENT
  800. if(_option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  801. _preDownloadHandlers.push_back(DownloadHandlerFactory::getBtPreDownloadHandler());
  802. }
  803. #endif // ENABLE_BITTORRENT
  804. #ifdef ENABLE_METALINK
  805. if(_option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  806. _preDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPreDownloadHandler());
  807. }
  808. #endif // ENABLE_METALINK
  809. }
  810. void RequestGroup::initializePostDownloadHandler()
  811. {
  812. #ifdef ENABLE_BITTORRENT
  813. if(_option->getAsBool(PREF_FOLLOW_TORRENT) ||
  814. _option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  815. _postDownloadHandlers.push_back(DownloadHandlerFactory::getBtPostDownloadHandler());
  816. }
  817. #endif // ENABLE_BITTORRENT
  818. #ifdef ENABLE_METALINK
  819. if(_option->getAsBool(PREF_FOLLOW_METALINK) ||
  820. _option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  821. _postDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPostDownloadHandler());
  822. }
  823. #endif // ENABLE_METALINK
  824. }
  825. bool RequestGroup::isDependencyResolved()
  826. {
  827. if(_dependency.isNull()) {
  828. return true;
  829. }
  830. return _dependency->resolve();
  831. }
  832. void RequestGroup::setSegmentManFactory(const SegmentManFactoryHandle& segmentManFactory)
  833. {
  834. _segmentManFactory = segmentManFactory;
  835. }
  836. void RequestGroup::dependsOn(const DependencyHandle& dep)
  837. {
  838. _dependency = dep;
  839. }
  840. void RequestGroup::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
  841. {
  842. _diskWriterFactory = diskWriterFactory;
  843. }
  844. void RequestGroup::addPostDownloadHandler(const PostDownloadHandlerHandle& handler)
  845. {
  846. _postDownloadHandlers.push_back(handler);
  847. }
  848. void RequestGroup::addPreDownloadHandler(const PreDownloadHandlerHandle& handler)
  849. {
  850. _preDownloadHandlers.push_back(handler);
  851. }
  852. void RequestGroup::clearPostDownloadHandler()
  853. {
  854. _postDownloadHandlers.clear();
  855. }
  856. void RequestGroup::clearPreDownloadHandler()
  857. {
  858. _preDownloadHandlers.clear();
  859. }
  860. void RequestGroup::setPieceStorage(const PieceStorageHandle& pieceStorage)
  861. {
  862. _pieceStorage = pieceStorage;
  863. }
  864. void RequestGroup::setProgressInfoFile(const BtProgressInfoFileHandle& progressInfoFile)
  865. {
  866. _progressInfoFile = progressInfoFile;
  867. }
  868. bool RequestGroup::needsFileAllocation() const
  869. {
  870. return isFileAllocationEnabled() &&
  871. (uint64_t)_option->getAsLLInt(PREF_NO_FILE_ALLOCATION_LIMIT) <= getTotalLength() &&
  872. !_pieceStorage->getDiskAdaptor()->fileAllocationIterator()->finished();
  873. }
  874. DownloadResultHandle RequestGroup::createDownloadResult() const
  875. {
  876. uint64_t sessionDownloadLength = 0;
  877. #ifdef ENABLE_BITTORRENT
  878. if(!_peerStorage.isNull()) {
  879. sessionDownloadLength +=
  880. _peerStorage->calculateStat().getSessionDownloadLength();
  881. }
  882. #endif // ENABLE_BITTORRENT
  883. if(!_segmentMan.isNull()) {
  884. sessionDownloadLength +=
  885. _segmentMan->calculateSessionDownloadLength();
  886. }
  887. return
  888. SharedHandle<DownloadResult>
  889. (new DownloadResult(_gid,
  890. _downloadContext->getFileEntries(),
  891. _inMemoryDownload,
  892. sessionDownloadLength,
  893. _downloadContext->calculateSessionTime(),
  894. downloadResult(),
  895. _followedByGIDs,
  896. _belongsToGID));
  897. }
  898. void RequestGroup::reportDownloadFinished()
  899. {
  900. _logger->notice(MSG_FILE_DOWNLOAD_COMPLETED,
  901. _downloadContext->getBasePath().c_str());
  902. _uriSelector->resetCounters();
  903. #ifdef ENABLE_BITTORRENT
  904. if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
  905. TransferStat stat = calculateStat();
  906. double shareRatio =
  907. ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0;
  908. const BDE& attrs = _downloadContext->getAttribute(bittorrent::BITTORRENT);
  909. if(attrs.containsKey(bittorrent::METADATA)) {
  910. _logger->notice(MSG_SHARE_RATIO_REPORT,
  911. shareRatio,
  912. util::abbrevSize(stat.getAllTimeUploadLength()).c_str(),
  913. util::abbrevSize(getCompletedLength()).c_str());
  914. }
  915. }
  916. #endif // ENABLE_BITTORRENT
  917. }
  918. void RequestGroup::addAcceptType(const std::string& type)
  919. {
  920. if(std::find(_acceptTypes.begin(), _acceptTypes.end(), type) == _acceptTypes.end()) {
  921. _acceptTypes.push_back(type);
  922. }
  923. }
  924. void RequestGroup::removeAcceptType(const std::string& type)
  925. {
  926. _acceptTypes.erase(std::remove(_acceptTypes.begin(), _acceptTypes.end(), type),
  927. _acceptTypes.end());
  928. }
  929. void RequestGroup::setURISelector(const SharedHandle<URISelector>& uriSelector)
  930. {
  931. _uriSelector = uriSelector;
  932. }
  933. void RequestGroup::applyLastModifiedTimeToLocalFiles()
  934. {
  935. if(!_pieceStorage.isNull() && _lastModifiedTime.good()) {
  936. time_t t = _lastModifiedTime.getTime();
  937. _logger->info("Applying Last-Modified time: %s in local time zone",
  938. ctime(&t));
  939. size_t n =
  940. _pieceStorage->getDiskAdaptor()->utime(Time(), _lastModifiedTime);
  941. _logger->info("Last-Modified attrs of %lu files were updated.",
  942. static_cast<unsigned long>(n));
  943. }
  944. }
  945. void RequestGroup::updateLastModifiedTime(const Time& time)
  946. {
  947. if(time.good() && _lastModifiedTime < time) {
  948. _lastModifiedTime = time;
  949. }
  950. }
  951. void RequestGroup::increaseAndValidateFileNotFoundCount()
  952. {
  953. ++_fileNotFoundCount;
  954. const unsigned int maxCount = _option->getAsInt(PREF_MAX_FILE_NOT_FOUND);
  955. if(maxCount > 0 && _fileNotFoundCount >= maxCount &&
  956. _segmentMan->calculateSessionDownloadLength() == 0) {
  957. throw DOWNLOAD_FAILURE_EXCEPTION2
  958. (StringFormat("Reached max-file-not-found count=%u", maxCount).str(),
  959. downloadresultcode::MAX_FILE_NOT_FOUND);
  960. }
  961. }
  962. void RequestGroup::markInMemoryDownload()
  963. {
  964. _inMemoryDownload = true;
  965. }
  966. void RequestGroup::setTimeout(time_t timeout)
  967. {
  968. _timeout = timeout;
  969. }
  970. bool RequestGroup::doesDownloadSpeedExceed()
  971. {
  972. return _maxDownloadSpeedLimit > 0 &&
  973. _maxDownloadSpeedLimit < calculateStat().getDownloadSpeed();
  974. }
  975. bool RequestGroup::doesUploadSpeedExceed()
  976. {
  977. return _maxUploadSpeedLimit > 0 &&
  978. _maxUploadSpeedLimit < calculateStat().getUploadSpeed();
  979. }
  980. void RequestGroup::setLastUriResult
  981. (const std::string uri, downloadresultcode::RESULT result)
  982. {
  983. _lastUriResult.reset(new URIResult(uri, result));
  984. }
  985. void RequestGroup::saveControlFile() const
  986. {
  987. if(_saveControlFile) {
  988. _progressInfoFile->save();
  989. }
  990. }
  991. void RequestGroup::removeControlFile() const
  992. {
  993. _progressInfoFile->removeFile();
  994. }
  995. void RequestGroup::setDownloadContext
  996. (const SharedHandle<DownloadContext>& downloadContext)
  997. {
  998. _downloadContext = downloadContext;
  999. if(!_downloadContext.isNull()) {
  1000. _downloadContext->setOwnerRequestGroup(this);
  1001. }
  1002. }
  1003. int32_t RequestGroup::newGID()
  1004. {
  1005. if(_gidCounter == INT32_MAX) {
  1006. _gidCounter = 0;
  1007. }
  1008. return ++_gidCounter;
  1009. }
  1010. } // namespace aria2