RequestGroup.cc 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  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 "fmt.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. #include "Segment.h"
  78. #include "SocketRecvBuffer.h"
  79. #ifdef ENABLE_MESSAGE_DIGEST
  80. # include "CheckIntegrityCommand.h"
  81. # include "ChecksumCheckIntegrityEntry.h"
  82. #endif // ENABLE_MESSAGE_DIGEST
  83. #ifdef ENABLE_BITTORRENT
  84. # include "bittorrent_helper.h"
  85. # include "BtRegistry.h"
  86. # include "BtCheckIntegrityEntry.h"
  87. # include "DefaultPeerStorage.h"
  88. # include "DefaultBtAnnounce.h"
  89. # include "BtRuntime.h"
  90. # include "BtSetup.h"
  91. # include "BtPostDownloadHandler.h"
  92. # include "DHTSetup.h"
  93. # include "DHTRegistry.h"
  94. # include "DHTNode.h"
  95. # include "DHTRoutingTable.h"
  96. # include "DHTTaskQueue.h"
  97. # include "DHTTaskFactory.h"
  98. # include "DHTTokenTracker.h"
  99. # include "DHTMessageDispatcher.h"
  100. # include "DHTMessageReceiver.h"
  101. # include "DHTMessageFactory.h"
  102. # include "DHTMessageCallback.h"
  103. # include "BtMessageFactory.h"
  104. # include "BtRequestFactory.h"
  105. # include "BtMessageDispatcher.h"
  106. # include "BtMessageReceiver.h"
  107. # include "PeerConnection.h"
  108. # include "ExtensionMessageFactory.h"
  109. # include "DHTPeerAnnounceStorage.h"
  110. # include "DHTEntryPointNameResolveCommand.h"
  111. # include "LongestSequencePieceSelector.h"
  112. # include "PriorityPieceSelector.h"
  113. # include "bittorrent_helper.h"
  114. #endif // ENABLE_BITTORRENT
  115. #ifdef ENABLE_METALINK
  116. # include "MetalinkPostDownloadHandler.h"
  117. #endif // ENABLE_METALINK
  118. namespace aria2 {
  119. RequestGroup::RequestGroup(const SharedHandle<GroupId>& gid,
  120. const SharedHandle<Option>& option)
  121. : gid_(gid),
  122. state_(STATE_WAITING),
  123. option_(option),
  124. numConcurrentCommand_(option->getAsInt(PREF_SPLIT)),
  125. numStreamConnection_(0),
  126. numStreamCommand_(0),
  127. numCommand_(0),
  128. saveControlFile_(true),
  129. progressInfoFile_(new NullProgressInfoFile()),
  130. preLocalFileCheckEnabled_(true),
  131. haltRequested_(false),
  132. forceHaltRequested_(false),
  133. haltReason_(RequestGroup::NONE),
  134. pauseRequested_(false),
  135. uriSelector_(new InorderURISelector()),
  136. lastModifiedTime_(Time::null()),
  137. fileNotFoundCount_(0),
  138. timeout_(option->getAsInt(PREF_TIMEOUT)),
  139. #ifdef ENABLE_BITTORRENT
  140. btRuntime_(0),
  141. peerStorage_(0),
  142. #endif // ENABLE_BITTORRENT
  143. inMemoryDownload_(false),
  144. maxDownloadSpeedLimit_(option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT)),
  145. maxUploadSpeedLimit_(option->getAsInt(PREF_MAX_UPLOAD_LIMIT)),
  146. lastErrorCode_(error_code::UNDEFINED),
  147. belongsToGID_(0),
  148. requestGroupMan_(0),
  149. resumeFailureCount_(0)
  150. {
  151. fileAllocationEnabled_ = option_->get(PREF_FILE_ALLOCATION) != V_NONE;
  152. if(!option_->getAsBool(PREF_DRY_RUN)) {
  153. initializePreDownloadHandler();
  154. initializePostDownloadHandler();
  155. }
  156. }
  157. RequestGroup::~RequestGroup() {}
  158. bool RequestGroup::isCheckIntegrityReady()
  159. {
  160. return option_->getAsBool(PREF_CHECK_INTEGRITY) &&
  161. ((downloadContext_->isChecksumVerificationAvailable() &&
  162. downloadFinishedByFileLength()) ||
  163. downloadContext_->isPieceHashVerificationAvailable());
  164. }
  165. bool RequestGroup::downloadFinished() const
  166. {
  167. if(!pieceStorage_) {
  168. return false;
  169. } else {
  170. return pieceStorage_->downloadFinished();
  171. }
  172. }
  173. bool RequestGroup::allDownloadFinished() const
  174. {
  175. if(!pieceStorage_) {
  176. return false;
  177. } else {
  178. return pieceStorage_->allDownloadFinished();
  179. }
  180. }
  181. error_code::Value RequestGroup::downloadResult() const
  182. {
  183. if(downloadFinished() && !downloadContext_->isChecksumVerificationNeeded())
  184. return error_code::FINISHED;
  185. else {
  186. if(haltReason_ == RequestGroup::USER_REQUEST) {
  187. return error_code::REMOVED;
  188. } else if(lastErrorCode_ == error_code::UNDEFINED) {
  189. if(haltReason_ == RequestGroup::SHUTDOWN_SIGNAL) {
  190. return error_code::IN_PROGRESS;
  191. } else {
  192. return error_code::UNKNOWN_ERROR;
  193. }
  194. } else {
  195. return lastErrorCode_;
  196. }
  197. }
  198. }
  199. void RequestGroup::closeFile()
  200. {
  201. if(pieceStorage_) {
  202. pieceStorage_->flushWrDiskCacheEntry();
  203. pieceStorage_->getDiskAdaptor()->closeFile();
  204. }
  205. }
  206. // TODO The function name is not intuitive at all.. it does not convey
  207. // that this function open file.
  208. SharedHandle<CheckIntegrityEntry> RequestGroup::createCheckIntegrityEntry()
  209. {
  210. SharedHandle<BtProgressInfoFile> infoFile
  211. (new DefaultBtProgressInfoFile(downloadContext_, pieceStorage_,
  212. option_.get()));
  213. SharedHandle<CheckIntegrityEntry> checkEntry;
  214. if(option_->getAsBool(PREF_CHECK_INTEGRITY) &&
  215. downloadContext_->isPieceHashVerificationAvailable()) {
  216. // When checking piece hash, we don't care file is downloaded and
  217. // infoFile exists.
  218. loadAndOpenFile(infoFile);
  219. checkEntry.reset(new StreamCheckIntegrityEntry(this));
  220. } else if(isPreLocalFileCheckEnabled() && infoFile->exists()) {
  221. loadAndOpenFile(infoFile);
  222. if(downloadFinished()) {
  223. #ifdef ENABLE_MESSAGE_DIGEST
  224. if(downloadContext_->isChecksumVerificationNeeded()) {
  225. A2_LOG_INFO(MSG_HASH_CHECK_NOT_DONE);
  226. ChecksumCheckIntegrityEntry* tempEntry =
  227. new ChecksumCheckIntegrityEntry(this);
  228. tempEntry->setRedownload(true);
  229. checkEntry.reset(tempEntry);
  230. } else
  231. #endif // ENABLE_MESSAGE_DIGEST
  232. {
  233. downloadContext_->setChecksumVerified(true);
  234. A2_LOG_NOTICE(fmt(MSG_DOWNLOAD_ALREADY_COMPLETED,
  235. gid_->toHex().c_str(),
  236. downloadContext_->getBasePath().c_str()));
  237. }
  238. } else {
  239. checkEntry.reset(new StreamCheckIntegrityEntry(this));
  240. }
  241. } else
  242. #ifdef ENABLE_MESSAGE_DIGEST
  243. if(downloadFinishedByFileLength() &&
  244. downloadContext_->isChecksumVerificationAvailable()) {
  245. pieceStorage_->markAllPiecesDone();
  246. loadAndOpenFile(infoFile);
  247. ChecksumCheckIntegrityEntry* tempEntry =
  248. new ChecksumCheckIntegrityEntry(this);
  249. tempEntry->setRedownload(true);
  250. checkEntry.reset(tempEntry);
  251. } else
  252. #endif // ENABLE_MESSAGE_DIGEST
  253. {
  254. loadAndOpenFile(infoFile);
  255. checkEntry.reset(new StreamCheckIntegrityEntry(this));
  256. }
  257. return checkEntry;
  258. }
  259. void RequestGroup::createInitialCommand
  260. (std::vector<Command*>& commands, DownloadEngine* e)
  261. {
  262. // Start session timer here. When file size becomes known, it will
  263. // be reset again in *FileAllocationEntry, because hash check and
  264. // file allocation takes a time. For downloads in which file size
  265. // is unknown, session timer will not be reset.
  266. downloadContext_->resetDownloadStartTime();
  267. #ifdef ENABLE_BITTORRENT
  268. {
  269. if(downloadContext_->hasAttribute(CTX_ATTR_BT)) {
  270. SharedHandle<TorrentAttribute> torrentAttrs =
  271. bittorrent::getTorrentAttrs(downloadContext_);
  272. bool metadataGetMode = torrentAttrs->metadata.empty();
  273. if(option_->getAsBool(PREF_DRY_RUN)) {
  274. throw DOWNLOAD_FAILURE_EXCEPTION
  275. ("Cancel BitTorrent download in dry-run context.");
  276. }
  277. SharedHandle<BtRegistry> btRegistry = e->getBtRegistry();
  278. if(btRegistry->getDownloadContext(torrentAttrs->infoHash)) {
  279. // TODO If metadataGetMode == false and each FileEntry has
  280. // URI, then go without BT.
  281. throw DOWNLOAD_FAILURE_EXCEPTION2
  282. (fmt("InfoHash %s is already registered.",
  283. bittorrent::getInfoHashString(downloadContext_).c_str()),
  284. error_code::DUPLICATE_INFO_HASH);
  285. }
  286. if(metadataGetMode) {
  287. // Use UnknownLengthPieceStorage.
  288. initPieceStorage();
  289. } else {
  290. if(e->getRequestGroupMan()->isSameFileBeingDownloaded(this)) {
  291. throw DOWNLOAD_FAILURE_EXCEPTION2
  292. (fmt(EX_DUPLICATE_FILE_DOWNLOAD,
  293. downloadContext_->getBasePath().c_str()),
  294. error_code::DUPLICATE_DOWNLOAD);
  295. }
  296. initPieceStorage();
  297. if(downloadContext_->getFileEntries().size() > 1) {
  298. pieceStorage_->setupFileFilter();
  299. }
  300. }
  301. DefaultBtProgressInfoFile* progressInfoFilePtr = 0;
  302. SharedHandle<BtProgressInfoFile> progressInfoFile;
  303. if(!metadataGetMode) {
  304. progressInfoFilePtr = new DefaultBtProgressInfoFile(downloadContext_,
  305. pieceStorage_,
  306. option_.get());
  307. progressInfoFile.reset(progressInfoFilePtr);
  308. }
  309. SharedHandle<BtRuntime> btRuntime(new BtRuntime());
  310. btRuntime->setMaxPeers(option_->getAsInt(PREF_BT_MAX_PEERS));
  311. btRuntime_ = btRuntime.get();
  312. if(progressInfoFilePtr) {
  313. progressInfoFilePtr->setBtRuntime(btRuntime);
  314. }
  315. DefaultPeerStorage* peerStoragePtr(new DefaultPeerStorage());
  316. peerStoragePtr->setBtRuntime(btRuntime);
  317. peerStoragePtr->setPieceStorage(pieceStorage_);
  318. peerStorage_ = peerStoragePtr;
  319. SharedHandle<PeerStorage> peerStorage(peerStoragePtr);
  320. if(progressInfoFilePtr) {
  321. progressInfoFilePtr->setPeerStorage(peerStorage);
  322. }
  323. DefaultBtAnnounce* btAnnouncePtr
  324. (new DefaultBtAnnounce(downloadContext_, option_.get()));
  325. btAnnouncePtr->setBtRuntime(btRuntime);
  326. btAnnouncePtr->setPieceStorage(pieceStorage_);
  327. btAnnouncePtr->setPeerStorage(peerStorage);
  328. btAnnouncePtr->setUserDefinedInterval
  329. (option_->getAsInt(PREF_BT_TRACKER_INTERVAL));
  330. btAnnouncePtr->shuffleAnnounce();
  331. SharedHandle<BtAnnounce> btAnnounce(btAnnouncePtr);
  332. assert(!btRegistry->get(gid_->getNumericId()));
  333. btRegistry->put
  334. (gid_->getNumericId(), SharedHandle<BtObject>
  335. (new BtObject
  336. (downloadContext_,
  337. pieceStorage_,
  338. peerStorage,
  339. btAnnounce,
  340. btRuntime,
  341. (progressInfoFile ?
  342. progressInfoFile : progressInfoFile_))));
  343. if(metadataGetMode) {
  344. if(option_->getAsBool(PREF_ENABLE_DHT) ||
  345. (!e->getOption()->getAsBool(PREF_DISABLE_IPV6) &&
  346. option_->getAsBool(PREF_ENABLE_DHT6))) {
  347. if(option_->getAsBool(PREF_ENABLE_DHT)) {
  348. std::vector<Command*> dhtCommands;
  349. DHTSetup().setup(dhtCommands, e, AF_INET);
  350. e->addCommand(dhtCommands);
  351. }
  352. if(!e->getOption()->getAsBool(PREF_DISABLE_IPV6) &&
  353. option_->getAsBool(PREF_ENABLE_DHT6)) {
  354. std::vector<Command*> dhtCommands;
  355. DHTSetup().setup(dhtCommands, e, AF_INET6);
  356. e->addCommand(dhtCommands);
  357. }
  358. } else {
  359. A2_LOG_NOTICE(_("For BitTorrent Magnet URI, enabling DHT is strongly"
  360. " recommended. See --enable-dht option."));
  361. }
  362. SharedHandle<CheckIntegrityEntry> entry
  363. (new BtCheckIntegrityEntry(this));
  364. entry->onDownloadIncomplete(commands, e);
  365. return;
  366. }
  367. removeDefunctControlFile(progressInfoFile);
  368. {
  369. int64_t actualFileSize = pieceStorage_->getDiskAdaptor()->size();
  370. if(actualFileSize == downloadContext_->getTotalLength()) {
  371. // First, make DiskAdaptor read-only mode to allow the
  372. // program to seed file in read-only media.
  373. pieceStorage_->getDiskAdaptor()->enableReadOnly();
  374. } else {
  375. // Open file in writable mode to allow the program
  376. // truncate the file to downloadContext_->getTotalLength()
  377. A2_LOG_DEBUG
  378. (fmt("File size not match. File is opened in writable"
  379. " mode. Expected:%" PRId64 " Actual:%" PRId64 "",
  380. downloadContext_->getTotalLength(),
  381. actualFileSize));
  382. }
  383. }
  384. // Call Load, Save and file allocation command here
  385. if(progressInfoFile->exists()) {
  386. // load .aria2 file if it exists.
  387. progressInfoFile->load();
  388. pieceStorage_->getDiskAdaptor()->openFile();
  389. } else {
  390. if(pieceStorage_->getDiskAdaptor()->fileExists()) {
  391. if(!option_->getAsBool(PREF_CHECK_INTEGRITY) &&
  392. !option_->getAsBool(PREF_ALLOW_OVERWRITE) &&
  393. !option_->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  394. // TODO we need this->haltRequested = true?
  395. throw DOWNLOAD_FAILURE_EXCEPTION2
  396. (fmt(MSG_FILE_ALREADY_EXISTS,
  397. downloadContext_->getBasePath().c_str()),
  398. error_code::FILE_ALREADY_EXISTS);
  399. } else {
  400. pieceStorage_->getDiskAdaptor()->openFile();
  401. }
  402. if(option_->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  403. pieceStorage_->markAllPiecesDone();
  404. }
  405. } else {
  406. pieceStorage_->getDiskAdaptor()->openFile();
  407. }
  408. }
  409. progressInfoFile_ = progressInfoFile;
  410. if(!torrentAttrs->privateTorrent &&
  411. (option_->getAsBool(PREF_ENABLE_DHT) ||
  412. (!e->getOption()->getAsBool(PREF_DISABLE_IPV6) &&
  413. option_->getAsBool(PREF_ENABLE_DHT6)))) {
  414. if(option_->getAsBool(PREF_ENABLE_DHT)) {
  415. std::vector<Command*> dhtCommands;
  416. DHTSetup().setup(dhtCommands, e, AF_INET);
  417. e->addCommand(dhtCommands);
  418. }
  419. if(!e->getOption()->getAsBool(PREF_DISABLE_IPV6) &&
  420. option_->getAsBool(PREF_ENABLE_DHT6)) {
  421. std::vector<Command*> dhtCommands;
  422. DHTSetup().setup(dhtCommands, e, AF_INET6);
  423. e->addCommand(dhtCommands);
  424. }
  425. const std::vector<std::pair<std::string, uint16_t> >& nodes =
  426. torrentAttrs->nodes;
  427. // TODO Are nodes in torrent IPv4 only?
  428. if(!nodes.empty() && DHTRegistry::isInitialized()) {
  429. DHTEntryPointNameResolveCommand* command =
  430. new DHTEntryPointNameResolveCommand(e->newCUID(), e, nodes);
  431. command->setTaskQueue(DHTRegistry::getData().taskQueue);
  432. command->setTaskFactory(DHTRegistry::getData().taskFactory);
  433. command->setRoutingTable(DHTRegistry::getData().routingTable);
  434. command->setLocalNode(DHTRegistry::getData().localNode);
  435. e->addCommand(command);
  436. }
  437. }
  438. SharedHandle<CheckIntegrityEntry> entry(new BtCheckIntegrityEntry(this));
  439. // --bt-seed-unverified=true is given and download has completed, skip
  440. // validation for piece hashes.
  441. if(option_->getAsBool(PREF_BT_SEED_UNVERIFIED) &&
  442. pieceStorage_->downloadFinished()) {
  443. entry->onDownloadFinished(commands, e);
  444. } else {
  445. processCheckIntegrityEntry(commands, entry, e);
  446. }
  447. return;
  448. }
  449. }
  450. #endif // ENABLE_BITTORRENT
  451. if(downloadContext_->getFileEntries().size() == 1) {
  452. // TODO I assume here when totallength is set to DownloadContext and it is
  453. // not 0, then filepath is also set DownloadContext correctly....
  454. if(option_->getAsBool(PREF_DRY_RUN) ||
  455. downloadContext_->getTotalLength() == 0) {
  456. createNextCommand(commands, e, 1);
  457. } else {
  458. if(e->getRequestGroupMan()->isSameFileBeingDownloaded(this)) {
  459. throw DOWNLOAD_FAILURE_EXCEPTION2
  460. (fmt(EX_DUPLICATE_FILE_DOWNLOAD,
  461. downloadContext_->getBasePath().c_str()),
  462. error_code::DUPLICATE_DOWNLOAD);
  463. }
  464. SharedHandle<BtProgressInfoFile> progressInfoFile
  465. (new DefaultBtProgressInfoFile
  466. (downloadContext_, SharedHandle<PieceStorage>(), option_.get()));
  467. adjustFilename(progressInfoFile);
  468. initPieceStorage();
  469. SharedHandle<CheckIntegrityEntry> checkEntry =
  470. createCheckIntegrityEntry();
  471. if(checkEntry) {
  472. processCheckIntegrityEntry(commands, checkEntry, e);
  473. }
  474. }
  475. } else {
  476. // TODO --dry-run is not supported for multifile download for now.
  477. if(option_->getAsBool(PREF_DRY_RUN)) {
  478. throw DOWNLOAD_FAILURE_EXCEPTION
  479. ("--dry-run in multi-file download is not supported yet.");
  480. }
  481. // TODO file size is known in this context?
  482. // In this context, multiple FileEntry objects are in
  483. // DownloadContext.
  484. if(e->getRequestGroupMan()->isSameFileBeingDownloaded(this)) {
  485. throw DOWNLOAD_FAILURE_EXCEPTION2
  486. (fmt(EX_DUPLICATE_FILE_DOWNLOAD,
  487. downloadContext_->getBasePath().c_str()),
  488. error_code::DUPLICATE_DOWNLOAD);
  489. }
  490. initPieceStorage();
  491. if(downloadContext_->getFileEntries().size() > 1) {
  492. pieceStorage_->setupFileFilter();
  493. }
  494. SharedHandle<BtProgressInfoFile> progressInfoFile
  495. (new DefaultBtProgressInfoFile(downloadContext_,
  496. pieceStorage_,
  497. option_.get()));
  498. removeDefunctControlFile(progressInfoFile);
  499. // Call Load, Save and file allocation command here
  500. if(progressInfoFile->exists()) {
  501. // load .aria2 file if it exists.
  502. progressInfoFile->load();
  503. pieceStorage_->getDiskAdaptor()->openFile();
  504. } else {
  505. if(pieceStorage_->getDiskAdaptor()->fileExists()) {
  506. if(!isCheckIntegrityReady() &&
  507. !option_->getAsBool(PREF_ALLOW_OVERWRITE)) {
  508. // TODO we need this->haltRequested = true?
  509. throw DOWNLOAD_FAILURE_EXCEPTION2
  510. (fmt(MSG_FILE_ALREADY_EXISTS,
  511. downloadContext_->getBasePath().c_str()),
  512. error_code::FILE_ALREADY_EXISTS);
  513. } else {
  514. pieceStorage_->getDiskAdaptor()->openFile();
  515. }
  516. } else {
  517. pieceStorage_->getDiskAdaptor()->openFile();
  518. }
  519. }
  520. progressInfoFile_ = progressInfoFile;
  521. SharedHandle<CheckIntegrityEntry> checkIntegrityEntry
  522. (new StreamCheckIntegrityEntry(this));
  523. processCheckIntegrityEntry(commands, checkIntegrityEntry, e);
  524. }
  525. }
  526. void RequestGroup::processCheckIntegrityEntry
  527. (std::vector<Command*>& commands,
  528. const SharedHandle<CheckIntegrityEntry>& entry,
  529. DownloadEngine* e)
  530. {
  531. int64_t actualFileSize = pieceStorage_->getDiskAdaptor()->size();
  532. if(actualFileSize > downloadContext_->getTotalLength()) {
  533. entry->cutTrailingGarbage();
  534. }
  535. #ifdef ENABLE_MESSAGE_DIGEST
  536. if((option_->getAsBool(PREF_CHECK_INTEGRITY) ||
  537. downloadContext_->isChecksumVerificationNeeded()) &&
  538. entry->isValidationReady()) {
  539. entry->initValidator();
  540. // Don't save control file(.aria2 file) when user presses
  541. // control-c key while aria2 is checking hashes. If control file
  542. // doesn't exist when aria2 launched, the completed length in
  543. // saved control file will be 0 byte and this confuses user.
  544. // enableSaveControlFile() will be called after hash checking is
  545. // done. See CheckIntegrityCommand.
  546. disableSaveControlFile();
  547. e->getCheckIntegrityMan()->pushEntry(entry);
  548. } else
  549. #endif // ENABLE_MESSAGE_DIGEST
  550. {
  551. entry->onDownloadIncomplete(commands, e);
  552. }
  553. }
  554. void RequestGroup::initPieceStorage()
  555. {
  556. SharedHandle<PieceStorage> tempPieceStorage;
  557. if(downloadContext_->knowsTotalLength() &&
  558. // Following conditions are needed for chunked encoding with
  559. // content-length = 0. Google's dl server used this before.
  560. (downloadContext_->getTotalLength() > 0
  561. #ifdef ENABLE_BITTORRENT
  562. || downloadContext_->hasAttribute(CTX_ATTR_BT)
  563. #endif // ENABLE_BITTORRENT
  564. )) {
  565. #ifdef ENABLE_BITTORRENT
  566. DefaultPieceStorage* ps =
  567. new DefaultPieceStorage(downloadContext_, option_.get());
  568. SharedHandle<PieceStorage> psHolder(ps);
  569. if(downloadContext_->hasAttribute(CTX_ATTR_BT)) {
  570. if(isUriSuppliedForRequsetFileEntry
  571. (downloadContext_->getFileEntries().begin(),
  572. downloadContext_->getFileEntries().end())) {
  573. // Use LongestSequencePieceSelector when HTTP/FTP/BitTorrent
  574. // integrated downloads. Currently multi-file integrated
  575. // download is not supported.
  576. A2_LOG_DEBUG("Using LongestSequencePieceSelector");
  577. SharedHandle<PieceSelector> longestPieceSelector
  578. (new LongestSequencePieceSelector());
  579. ps->setPieceSelector(longestPieceSelector);
  580. }
  581. if(option_->defined(PREF_BT_PRIORITIZE_PIECE)) {
  582. std::vector<size_t> result;
  583. util::parsePrioritizePieceRange
  584. (result, option_->get(PREF_BT_PRIORITIZE_PIECE),
  585. downloadContext_->getFileEntries(),
  586. downloadContext_->getPieceLength());
  587. if(!result.empty()) {
  588. std::random_shuffle(result.begin(), result.end(),
  589. *(SimpleRandomizer::getInstance().get()));
  590. SharedHandle<PriorityPieceSelector> priSelector
  591. (new PriorityPieceSelector(ps->getPieceSelector()));
  592. priSelector->setPriorityPiece(result.begin(), result.end());
  593. ps->setPieceSelector(priSelector);
  594. }
  595. }
  596. }
  597. #else // !ENABLE_BITTORRENT
  598. DefaultPieceStorage* ps =
  599. new DefaultPieceStorage(downloadContext_, option_.get());
  600. SharedHandle<PieceStorage> psHolder(ps);
  601. #endif // !ENABLE_BITTORRENT
  602. if(requestGroupMan_) {
  603. ps->setWrDiskCache(requestGroupMan_->getWrDiskCache());
  604. }
  605. if(diskWriterFactory_) {
  606. ps->setDiskWriterFactory(diskWriterFactory_);
  607. }
  608. tempPieceStorage.swap(psHolder);
  609. } else {
  610. UnknownLengthPieceStorage* ps =
  611. new UnknownLengthPieceStorage(downloadContext_);
  612. SharedHandle<PieceStorage> psHolder(ps);
  613. if(diskWriterFactory_) {
  614. ps->setDiskWriterFactory(diskWriterFactory_);
  615. }
  616. tempPieceStorage.swap(psHolder);
  617. }
  618. tempPieceStorage->initStorage();
  619. SharedHandle<SegmentMan> tempSegmentMan(new SegmentMan(downloadContext_,
  620. tempPieceStorage));
  621. pieceStorage_.swap(tempPieceStorage);
  622. segmentMan_.swap(tempSegmentMan);
  623. }
  624. void RequestGroup::dropPieceStorage()
  625. {
  626. segmentMan_.reset();
  627. pieceStorage_.reset();
  628. }
  629. bool RequestGroup::downloadFinishedByFileLength()
  630. {
  631. // assuming that a control file doesn't exist.
  632. if(!isPreLocalFileCheckEnabled() ||
  633. option_->getAsBool(PREF_ALLOW_OVERWRITE)) {
  634. return false;
  635. }
  636. if(!downloadContext_->knowsTotalLength()) {
  637. return false;
  638. }
  639. File outfile(getFirstFilePath());
  640. if(outfile.exists() && downloadContext_->getTotalLength() == outfile.size()) {
  641. return true;
  642. } else {
  643. return false;
  644. }
  645. }
  646. void RequestGroup::adjustFilename
  647. (const SharedHandle<BtProgressInfoFile>& infoFile)
  648. {
  649. if(!isPreLocalFileCheckEnabled()) {
  650. // OK, no need to care about filename.
  651. return;
  652. }
  653. if(!option_->getAsBool(PREF_DRY_RUN) &&
  654. option_->getAsBool(PREF_REMOVE_CONTROL_FILE) &&
  655. infoFile->exists()) {
  656. infoFile->removeFile();
  657. A2_LOG_NOTICE(fmt(_("Removed control file for %s because it is requested by"
  658. " user."),
  659. infoFile->getFilename().c_str()));
  660. }
  661. if(infoFile->exists()) {
  662. // Use current filename
  663. } else {
  664. File outfile(getFirstFilePath());
  665. if(outfile.exists() && option_->getAsBool(PREF_CONTINUE) &&
  666. outfile.size() <= downloadContext_->getTotalLength()) {
  667. // File exists but user decided to resume it.
  668. } else {
  669. #ifdef ENABLE_MESSAGE_DIGEST
  670. if(outfile.exists() && isCheckIntegrityReady()) {
  671. // check-integrity existing file
  672. } else {
  673. #endif // ENABLE_MESSAGE_DIGEST
  674. shouldCancelDownloadForSafety();
  675. #ifdef ENABLE_MESSAGE_DIGEST
  676. }
  677. #endif // ENABLE_MESSAGE_DIGEST
  678. }
  679. }
  680. }
  681. void RequestGroup::removeDefunctControlFile
  682. (const SharedHandle<BtProgressInfoFile>& progressInfoFile)
  683. {
  684. // Remove the control file if download file doesn't exist
  685. if(progressInfoFile->exists() &&
  686. !pieceStorage_->getDiskAdaptor()->fileExists()) {
  687. progressInfoFile->removeFile();
  688. A2_LOG_NOTICE(fmt(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  689. progressInfoFile->getFilename().c_str(),
  690. downloadContext_->getBasePath().c_str()));
  691. }
  692. }
  693. void RequestGroup::loadAndOpenFile
  694. (const SharedHandle<BtProgressInfoFile>& progressInfoFile)
  695. {
  696. try {
  697. if(!isPreLocalFileCheckEnabled()) {
  698. pieceStorage_->getDiskAdaptor()->initAndOpenFile();
  699. return;
  700. }
  701. removeDefunctControlFile(progressInfoFile);
  702. if(progressInfoFile->exists()) {
  703. progressInfoFile->load();
  704. pieceStorage_->getDiskAdaptor()->openExistingFile();
  705. } else {
  706. File outfile(getFirstFilePath());
  707. if(outfile.exists() && option_->getAsBool(PREF_CONTINUE) &&
  708. outfile.size() <= getTotalLength()) {
  709. pieceStorage_->getDiskAdaptor()->openExistingFile();
  710. pieceStorage_->markPiecesDone(outfile.size());
  711. } else {
  712. #ifdef ENABLE_MESSAGE_DIGEST
  713. if(outfile.exists() && isCheckIntegrityReady()) {
  714. pieceStorage_->getDiskAdaptor()->openExistingFile();
  715. } else {
  716. #endif // ENABLE_MESSAGE_DIGEST
  717. pieceStorage_->getDiskAdaptor()->initAndOpenFile();
  718. #ifdef ENABLE_MESSAGE_DIGEST
  719. }
  720. #endif // ENABLE_MESSAGE_DIGEST
  721. }
  722. }
  723. setProgressInfoFile(progressInfoFile);
  724. } catch(RecoverableException& e) {
  725. throw DOWNLOAD_FAILURE_EXCEPTION2(fmt(EX_DOWNLOAD_ABORTED), e);
  726. }
  727. }
  728. // assuming that a control file does not exist
  729. void RequestGroup::shouldCancelDownloadForSafety()
  730. {
  731. if(option_->getAsBool(PREF_ALLOW_OVERWRITE)) {
  732. return;
  733. }
  734. File outfile(getFirstFilePath());
  735. if(outfile.exists()) {
  736. if(option_->getAsBool(PREF_AUTO_FILE_RENAMING)) {
  737. if(tryAutoFileRenaming()) {
  738. A2_LOG_NOTICE(fmt(MSG_FILE_RENAMED, getFirstFilePath().c_str()));
  739. } else {
  740. throw DOWNLOAD_FAILURE_EXCEPTION2
  741. (fmt("File renaming failed: %s", getFirstFilePath().c_str()),
  742. error_code::FILE_RENAMING_FAILED);
  743. }
  744. } else {
  745. throw DOWNLOAD_FAILURE_EXCEPTION2
  746. (fmt(MSG_FILE_ALREADY_EXISTS, getFirstFilePath().c_str()),
  747. error_code::FILE_ALREADY_EXISTS);
  748. }
  749. }
  750. }
  751. bool RequestGroup::tryAutoFileRenaming()
  752. {
  753. std::string filepath = getFirstFilePath();
  754. if(filepath.empty()) {
  755. return false;
  756. }
  757. for(int i = 1; i < 10000; ++i) {
  758. std::string newfilename = fmt("%s.%d", filepath.c_str(), i);
  759. File newfile(newfilename);
  760. File ctrlfile(newfile.getPath()+DefaultBtProgressInfoFile::getSuffix());
  761. if(!newfile.exists() || (newfile.exists() && ctrlfile.exists())) {
  762. downloadContext_->getFirstFileEntry()->setPath(newfile.getPath());
  763. return true;
  764. }
  765. }
  766. return false;
  767. }
  768. void RequestGroup::createNextCommandWithAdj(std::vector<Command*>& commands,
  769. DownloadEngine* e, int numAdj)
  770. {
  771. int numCommand;
  772. if(getTotalLength() == 0) {
  773. numCommand = 1+numAdj;
  774. } else {
  775. numCommand = std::min(downloadContext_->getNumPieces(),
  776. static_cast<size_t>(numConcurrentCommand_));
  777. numCommand += numAdj;
  778. }
  779. if(numCommand > 0) {
  780. createNextCommand(commands, e, numCommand);
  781. }
  782. }
  783. void RequestGroup::createNextCommand(std::vector<Command*>& commands,
  784. DownloadEngine* e)
  785. {
  786. int numCommand;
  787. if(getTotalLength() == 0) {
  788. if(numStreamCommand_ > 0) {
  789. numCommand = 0;
  790. } else {
  791. numCommand = 1;
  792. }
  793. } else {
  794. if(numStreamCommand_ >= numConcurrentCommand_) {
  795. numCommand = 0;
  796. } else {
  797. numCommand =
  798. std::min(downloadContext_->getNumPieces(),
  799. static_cast<size_t>(numConcurrentCommand_-numStreamCommand_));
  800. }
  801. }
  802. if(numCommand > 0) {
  803. createNextCommand(commands, e, numCommand);
  804. }
  805. }
  806. void RequestGroup::createNextCommand(std::vector<Command*>& commands,
  807. DownloadEngine* e,
  808. int numCommand)
  809. {
  810. for(; numCommand > 0; --numCommand) {
  811. Command* command = new CreateRequestCommand(e->newCUID(), this, e);
  812. commands.push_back(command);
  813. }
  814. if(!commands.empty()) {
  815. e->setNoWait(true);
  816. }
  817. }
  818. std::string RequestGroup::getFirstFilePath() const
  819. {
  820. assert(downloadContext_);
  821. if(inMemoryDownload()) {
  822. return "[MEMORY]"+
  823. File(downloadContext_->getFirstFileEntry()->getPath()).getBasename();
  824. } else {
  825. return downloadContext_->getFirstFileEntry()->getPath();
  826. }
  827. }
  828. int64_t RequestGroup::getTotalLength() const
  829. {
  830. if(!pieceStorage_) {
  831. return 0;
  832. } else {
  833. if(pieceStorage_->isSelectiveDownloadingMode()) {
  834. return pieceStorage_->getFilteredTotalLength();
  835. } else {
  836. return pieceStorage_->getTotalLength();
  837. }
  838. }
  839. }
  840. int64_t RequestGroup::getCompletedLength() const
  841. {
  842. if(!pieceStorage_) {
  843. return 0;
  844. } else {
  845. if(pieceStorage_->isSelectiveDownloadingMode()) {
  846. return pieceStorage_->getFilteredCompletedLength();
  847. } else {
  848. return pieceStorage_->getCompletedLength();
  849. }
  850. }
  851. }
  852. void RequestGroup::validateFilename(const std::string& expectedFilename,
  853. const std::string& actualFilename) const
  854. {
  855. if(expectedFilename.empty()) {
  856. return;
  857. }
  858. if(expectedFilename != actualFilename) {
  859. throw DL_ABORT_EX(fmt(EX_FILENAME_MISMATCH,
  860. expectedFilename.c_str(),
  861. actualFilename.c_str()));
  862. }
  863. }
  864. void RequestGroup::validateTotalLength(int64_t expectedTotalLength,
  865. int64_t actualTotalLength) const
  866. {
  867. if(expectedTotalLength <= 0) {
  868. return;
  869. }
  870. if(expectedTotalLength != actualTotalLength) {
  871. throw DL_ABORT_EX
  872. (fmt(EX_SIZE_MISMATCH, expectedTotalLength, actualTotalLength));
  873. }
  874. }
  875. void RequestGroup::validateFilename(const std::string& actualFilename) const
  876. {
  877. validateFilename(downloadContext_->getFileEntries().front()->getBasename(), actualFilename);
  878. }
  879. void RequestGroup::validateTotalLength(int64_t actualTotalLength) const
  880. {
  881. validateTotalLength(getTotalLength(), actualTotalLength);
  882. }
  883. void RequestGroup::increaseStreamCommand()
  884. {
  885. ++numStreamCommand_;
  886. }
  887. void RequestGroup::decreaseStreamCommand()
  888. {
  889. --numStreamCommand_;
  890. }
  891. void RequestGroup::increaseStreamConnection()
  892. {
  893. ++numStreamConnection_;
  894. }
  895. void RequestGroup::decreaseStreamConnection()
  896. {
  897. --numStreamConnection_;
  898. }
  899. int RequestGroup::getNumConnection() const
  900. {
  901. int numConnection = numStreamConnection_;
  902. #ifdef ENABLE_BITTORRENT
  903. if(btRuntime_) {
  904. numConnection += btRuntime_->getConnections();
  905. }
  906. #endif // ENABLE_BITTORRENT
  907. return numConnection;
  908. }
  909. void RequestGroup::increaseNumCommand()
  910. {
  911. ++numCommand_;
  912. }
  913. void RequestGroup::decreaseNumCommand()
  914. {
  915. --numCommand_;
  916. if(!numCommand_ && requestGroupMan_) {
  917. A2_LOG_DEBUG(fmt("GID#%s - Request queue check", gid_->toHex().c_str()));
  918. requestGroupMan_->requestQueueCheck();
  919. }
  920. }
  921. TransferStat RequestGroup::calculateStat() const
  922. {
  923. TransferStat stat = downloadContext_->getNetStat().toTransferStat();
  924. #ifdef ENABLE_BITTORRENT
  925. if(btRuntime_) {
  926. stat.allTimeUploadLength = btRuntime_->getUploadLengthAtStartup()+
  927. stat.sessionUploadLength;
  928. }
  929. #endif // ENABLE_BITTORRENT
  930. return stat;
  931. }
  932. void RequestGroup::setHaltRequested(bool f, HaltReason haltReason)
  933. {
  934. haltRequested_ = f;
  935. if(haltRequested_) {
  936. pauseRequested_ = false;
  937. haltReason_ = haltReason;
  938. }
  939. #ifdef ENABLE_BITTORRENT
  940. if(btRuntime_) {
  941. btRuntime_->setHalt(f);
  942. }
  943. #endif // ENABLE_BITTORRENT
  944. }
  945. void RequestGroup::setForceHaltRequested(bool f, HaltReason haltReason)
  946. {
  947. setHaltRequested(f, haltReason);
  948. forceHaltRequested_ = f;
  949. }
  950. void RequestGroup::setPauseRequested(bool f)
  951. {
  952. pauseRequested_ = f;
  953. }
  954. void RequestGroup::releaseRuntimeResource(DownloadEngine* e)
  955. {
  956. #ifdef ENABLE_BITTORRENT
  957. e->getBtRegistry()->remove(gid_->getNumericId());
  958. btRuntime_ = 0;
  959. peerStorage_ = 0;
  960. #endif // ENABLE_BITTORRENT
  961. if(pieceStorage_) {
  962. pieceStorage_->removeAdvertisedPiece(0);
  963. }
  964. // Don't reset segmentMan_ and pieceStorage_ here to provide
  965. // progress information via RPC
  966. progressInfoFile_.reset();
  967. downloadContext_->releaseRuntimeResource();
  968. }
  969. void RequestGroup::preDownloadProcessing()
  970. {
  971. A2_LOG_DEBUG(fmt("Finding PreDownloadHandler for path %s.",
  972. getFirstFilePath().c_str()));
  973. try {
  974. for(std::vector<SharedHandle<PreDownloadHandler> >::const_iterator itr =
  975. preDownloadHandlers_.begin(), eoi = preDownloadHandlers_.end();
  976. itr != eoi; ++itr) {
  977. if((*itr)->canHandle(this)) {
  978. (*itr)->execute(this);
  979. return;
  980. }
  981. }
  982. } catch(RecoverableException& ex) {
  983. A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, ex);
  984. return;
  985. }
  986. A2_LOG_DEBUG("No PreDownloadHandler found.");
  987. return;
  988. }
  989. void RequestGroup::postDownloadProcessing
  990. (std::vector<SharedHandle<RequestGroup> >& groups)
  991. {
  992. A2_LOG_DEBUG(fmt("Finding PostDownloadHandler for path %s.",
  993. getFirstFilePath().c_str()));
  994. try {
  995. for(std::vector<SharedHandle<PostDownloadHandler> >::const_iterator itr =
  996. postDownloadHandlers_.begin(), eoi = postDownloadHandlers_.end();
  997. itr != eoi; ++itr) {
  998. if((*itr)->canHandle(this)) {
  999. (*itr)->getNextRequestGroups(groups, this);
  1000. return;
  1001. }
  1002. }
  1003. } catch(RecoverableException& ex) {
  1004. A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, ex);
  1005. }
  1006. A2_LOG_DEBUG("No PostDownloadHandler found.");
  1007. }
  1008. void RequestGroup::initializePreDownloadHandler()
  1009. {
  1010. #ifdef ENABLE_BITTORRENT
  1011. if(option_->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  1012. preDownloadHandlers_.push_back(DownloadHandlerFactory::getBtPreDownloadHandler());
  1013. }
  1014. #endif // ENABLE_BITTORRENT
  1015. #ifdef ENABLE_METALINK
  1016. if(option_->get(PREF_FOLLOW_METALINK) == V_MEM) {
  1017. preDownloadHandlers_.push_back(DownloadHandlerFactory::getMetalinkPreDownloadHandler());
  1018. }
  1019. #endif // ENABLE_METALINK
  1020. }
  1021. void RequestGroup::initializePostDownloadHandler()
  1022. {
  1023. #ifdef ENABLE_BITTORRENT
  1024. if(option_->getAsBool(PREF_FOLLOW_TORRENT) ||
  1025. option_->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  1026. postDownloadHandlers_.push_back(DownloadHandlerFactory::getBtPostDownloadHandler());
  1027. }
  1028. #endif // ENABLE_BITTORRENT
  1029. #ifdef ENABLE_METALINK
  1030. if(option_->getAsBool(PREF_FOLLOW_METALINK) ||
  1031. option_->get(PREF_FOLLOW_METALINK) == V_MEM) {
  1032. postDownloadHandlers_.push_back(DownloadHandlerFactory::getMetalinkPostDownloadHandler());
  1033. }
  1034. #endif // ENABLE_METALINK
  1035. }
  1036. bool RequestGroup::isDependencyResolved()
  1037. {
  1038. if(!dependency_) {
  1039. return true;
  1040. }
  1041. return dependency_->resolve();
  1042. }
  1043. void RequestGroup::dependsOn(const SharedHandle<Dependency>& dep)
  1044. {
  1045. dependency_ = dep;
  1046. }
  1047. void RequestGroup::setDiskWriterFactory
  1048. (const SharedHandle<DiskWriterFactory>& diskWriterFactory)
  1049. {
  1050. diskWriterFactory_ = diskWriterFactory;
  1051. }
  1052. void RequestGroup::addPostDownloadHandler
  1053. (const SharedHandle<PostDownloadHandler>& handler)
  1054. {
  1055. postDownloadHandlers_.push_back(handler);
  1056. }
  1057. void RequestGroup::addPreDownloadHandler
  1058. (const SharedHandle<PreDownloadHandler>& handler)
  1059. {
  1060. preDownloadHandlers_.push_back(handler);
  1061. }
  1062. void RequestGroup::clearPostDownloadHandler()
  1063. {
  1064. postDownloadHandlers_.clear();
  1065. }
  1066. void RequestGroup::clearPreDownloadHandler()
  1067. {
  1068. preDownloadHandlers_.clear();
  1069. }
  1070. void RequestGroup::setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage)
  1071. {
  1072. pieceStorage_ = pieceStorage;
  1073. }
  1074. void RequestGroup::setProgressInfoFile
  1075. (const SharedHandle<BtProgressInfoFile>& progressInfoFile)
  1076. {
  1077. progressInfoFile_ = progressInfoFile;
  1078. }
  1079. bool RequestGroup::needsFileAllocation() const
  1080. {
  1081. return isFileAllocationEnabled() &&
  1082. option_->getAsLLInt(PREF_NO_FILE_ALLOCATION_LIMIT) <= getTotalLength() &&
  1083. !pieceStorage_->getDiskAdaptor()->fileAllocationIterator()->finished();
  1084. }
  1085. SharedHandle<DownloadResult> RequestGroup::createDownloadResult() const
  1086. {
  1087. A2_LOG_DEBUG(fmt("GID#%s - Creating DownloadResult.",
  1088. gid_->toHex().c_str()));
  1089. TransferStat st = calculateStat();
  1090. SharedHandle<DownloadResult> res(new DownloadResult());
  1091. res->gid = gid_;
  1092. res->fileEntries = downloadContext_->getFileEntries();
  1093. res->inMemoryDownload = inMemoryDownload_;
  1094. res->sessionDownloadLength = st.sessionDownloadLength;
  1095. res->sessionTime = downloadContext_->calculateSessionTime();
  1096. res->result = downloadResult();
  1097. res->followedBy = followedByGIDs_;
  1098. res->belongsTo = belongsToGID_;
  1099. res->option = option_;
  1100. res->metadataInfo = metadataInfo_;
  1101. res->totalLength = getTotalLength();
  1102. res->completedLength = getCompletedLength();
  1103. res->uploadLength = st.allTimeUploadLength;
  1104. if(pieceStorage_) {
  1105. if(pieceStorage_->getBitfieldLength() > 0) {
  1106. res->bitfield.assign(pieceStorage_->getBitfield(),
  1107. pieceStorage_->getBitfield()+
  1108. pieceStorage_->getBitfieldLength());
  1109. }
  1110. }
  1111. #ifdef ENABLE_BITTORRENT
  1112. if(downloadContext_->hasAttribute(CTX_ATTR_BT)) {
  1113. const unsigned char* p = bittorrent::getInfoHash(downloadContext_);
  1114. res->infoHash.assign(p, p+INFO_HASH_LENGTH);
  1115. }
  1116. #endif // ENABLE_BITTORRENT
  1117. res->pieceLength = downloadContext_->getPieceLength();
  1118. res->numPieces = downloadContext_->getNumPieces();
  1119. res->dir = option_->get(PREF_DIR);
  1120. return res;
  1121. }
  1122. void RequestGroup::reportDownloadFinished()
  1123. {
  1124. A2_LOG_NOTICE(fmt(MSG_FILE_DOWNLOAD_COMPLETED,
  1125. downloadContext_->getBasePath().c_str()));
  1126. uriSelector_->resetCounters();
  1127. #ifdef ENABLE_BITTORRENT
  1128. if(downloadContext_->hasAttribute(CTX_ATTR_BT)) {
  1129. TransferStat stat = calculateStat();
  1130. int64_t completedLength = getCompletedLength();
  1131. double shareRatio = completedLength == 0 ? 0.0 :
  1132. 1.0*stat.allTimeUploadLength/completedLength;
  1133. SharedHandle<TorrentAttribute> attrs =
  1134. bittorrent::getTorrentAttrs(downloadContext_);
  1135. if(!attrs->metadata.empty()) {
  1136. A2_LOG_NOTICE(fmt(MSG_SHARE_RATIO_REPORT,
  1137. shareRatio,
  1138. util::abbrevSize(stat.allTimeUploadLength).c_str(),
  1139. util::abbrevSize(completedLength).c_str()));
  1140. }
  1141. }
  1142. #endif // ENABLE_BITTORRENT
  1143. }
  1144. void RequestGroup::setURISelector(const SharedHandle<URISelector>& uriSelector)
  1145. {
  1146. uriSelector_ = uriSelector;
  1147. }
  1148. void RequestGroup::applyLastModifiedTimeToLocalFiles()
  1149. {
  1150. if(pieceStorage_ && lastModifiedTime_.good()) {
  1151. A2_LOG_INFO(fmt("Applying Last-Modified time: %s",
  1152. lastModifiedTime_.toHTTPDate().c_str()));
  1153. size_t n =
  1154. pieceStorage_->getDiskAdaptor()->utime(Time(), lastModifiedTime_);
  1155. A2_LOG_INFO(fmt("Last-Modified attrs of %lu files were updated.",
  1156. static_cast<unsigned long>(n)));
  1157. }
  1158. }
  1159. void RequestGroup::updateLastModifiedTime(const Time& time)
  1160. {
  1161. if(time.good() && lastModifiedTime_ < time) {
  1162. lastModifiedTime_ = time;
  1163. }
  1164. }
  1165. void RequestGroup::increaseAndValidateFileNotFoundCount()
  1166. {
  1167. ++fileNotFoundCount_;
  1168. const int maxCount = option_->getAsInt(PREF_MAX_FILE_NOT_FOUND);
  1169. if(maxCount > 0 && fileNotFoundCount_ >= maxCount &&
  1170. downloadContext_->getNetStat().getSessionDownloadLength() == 0) {
  1171. throw DOWNLOAD_FAILURE_EXCEPTION2
  1172. (fmt("Reached max-file-not-found count=%d", maxCount),
  1173. error_code::MAX_FILE_NOT_FOUND);
  1174. }
  1175. }
  1176. void RequestGroup::markInMemoryDownload()
  1177. {
  1178. inMemoryDownload_ = true;
  1179. }
  1180. void RequestGroup::setTimeout(time_t timeout)
  1181. {
  1182. timeout_ = timeout;
  1183. }
  1184. bool RequestGroup::doesDownloadSpeedExceed()
  1185. {
  1186. int spd = downloadContext_->getNetStat().calculateDownloadSpeed();
  1187. return maxDownloadSpeedLimit_ > 0 && maxDownloadSpeedLimit_ < spd;
  1188. }
  1189. bool RequestGroup::doesUploadSpeedExceed()
  1190. {
  1191. int spd = downloadContext_->getNetStat().calculateUploadSpeed();
  1192. return maxUploadSpeedLimit_ > 0 && maxUploadSpeedLimit_ < spd;
  1193. }
  1194. void RequestGroup::saveControlFile() const
  1195. {
  1196. if(saveControlFile_) {
  1197. progressInfoFile_->save();
  1198. }
  1199. }
  1200. void RequestGroup::removeControlFile() const
  1201. {
  1202. progressInfoFile_->removeFile();
  1203. }
  1204. void RequestGroup::setDownloadContext
  1205. (const SharedHandle<DownloadContext>& downloadContext)
  1206. {
  1207. downloadContext_ = downloadContext;
  1208. if(downloadContext_) {
  1209. downloadContext_->setOwnerRequestGroup(this);
  1210. }
  1211. }
  1212. bool RequestGroup::p2pInvolved() const
  1213. {
  1214. #ifdef ENABLE_BITTORRENT
  1215. return downloadContext_->hasAttribute(CTX_ATTR_BT);
  1216. #else // !ENABLE_BITTORRENT
  1217. return false;
  1218. #endif // !ENABLE_BITTORRENT
  1219. }
  1220. } // namespace aria2