SegmentMan.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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 "SegmentMan.h"
  36. #include "DlAbortEx.h"
  37. #include "Util.h"
  38. #include "File.h"
  39. #include "message.h"
  40. #include "prefs.h"
  41. #include "LogFactory.h"
  42. #include "BitfieldManFactory.h"
  43. #ifdef ENABLE_MESSAGE_DIGEST
  44. #include "MessageDigestHelper.h"
  45. #endif // ENABLE_MESSAGE_DIGEST
  46. #include "a2io.h"
  47. #include <errno.h>
  48. SegmentMan::SegmentMan():logger(LogFactory::getInstance()),
  49. bitfield(0),
  50. totalSize(0),
  51. isSplittable(true),
  52. downloadStarted(false),
  53. dir("."),
  54. errors(0),
  55. diskWriter(0)
  56. {}
  57. SegmentMan::~SegmentMan() {
  58. delete bitfield;
  59. }
  60. bool SegmentMan::segmentFileExists() const {
  61. if(!isSplittable) {
  62. return false;
  63. }
  64. string segFilename = getSegmentFilePath();
  65. File f(segFilename);
  66. if(f.isFile()) {
  67. logger->info(MSG_SEGMENT_FILE_EXISTS, segFilename.c_str());
  68. return true;
  69. } else {
  70. logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, segFilename.c_str());
  71. return false;
  72. }
  73. }
  74. void SegmentMan::load() {
  75. if(!isSplittable) {
  76. return;
  77. }
  78. string segFilename = getSegmentFilePath();
  79. logger->info(MSG_LOADING_SEGMENT_FILE, segFilename.c_str());
  80. FILE* segFile = openSegFile(segFilename, "r+b");
  81. try {
  82. read(segFile);
  83. fclose(segFile);
  84. } catch(string ex) {
  85. fclose(segFile);
  86. throw new DlAbortEx(EX_SEGMENT_FILE_READ,
  87. segFilename.c_str(), strerror(errno));
  88. }
  89. logger->info(MSG_LOADED_SEGMENT_FILE);
  90. }
  91. void SegmentMan::save() const {
  92. if(!isSplittable || totalSize == 0 || !bitfield) {
  93. return;
  94. }
  95. string segFilename = getSegmentFilePath();
  96. logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
  97. FILE* segFile = openSegFile(segFilename, "wb");
  98. try {
  99. if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
  100. throw string("writeError");
  101. }
  102. int32_t segmentLength = bitfield->getBlockLength();
  103. if(fwrite(&segmentLength, sizeof(segmentLength), 1, segFile) < 1) {
  104. throw string("writeError");
  105. }
  106. if(bitfield) {
  107. int32_t bitfieldLength = bitfield->getBitfieldLength();
  108. if(fwrite(&bitfieldLength, sizeof(bitfieldLength), 1, segFile) < 1) {
  109. throw string("writeError");
  110. }
  111. if(fwrite(bitfield->getBitfield(), bitfield->getBitfieldLength(),
  112. 1, segFile) < 1) {
  113. throw string("writeError");
  114. }
  115. } else {
  116. int32_t i = 0;
  117. if(fwrite(&i, sizeof(i), 1, segFile) < 1) {
  118. throw string("writeError");
  119. }
  120. }
  121. int32_t usedSegmentCount = usedSegmentEntries.size();
  122. if(fwrite(&usedSegmentCount, sizeof(usedSegmentCount), 1, segFile) < 1) {
  123. throw string("writeError");
  124. }
  125. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  126. itr != usedSegmentEntries.end(); itr++) {
  127. if(fwrite((*itr)->segment.get(), sizeof(Segment), 1, segFile) < 1) {
  128. throw string("writeError");
  129. }
  130. }
  131. fclose(segFile);
  132. logger->info(MSG_SAVED_SEGMENT_FILE);
  133. } catch(string ex) {
  134. fclose(segFile);
  135. throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
  136. segFilename.c_str(), strerror(errno));
  137. }
  138. }
  139. FILE* SegmentMan::openSegFile(const string& segFilename, const string& mode) const {
  140. FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
  141. if(segFile == NULL) {
  142. throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
  143. segFilename.c_str(), strerror(errno));
  144. }
  145. return segFile;
  146. }
  147. void SegmentMan::read(FILE* file) {
  148. assert(file != NULL);
  149. if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
  150. throw string("readError");
  151. }
  152. int32_t segmentSize;
  153. if(fread(&segmentSize, sizeof(segmentSize), 1, file) < 1) {
  154. throw string("readError");
  155. }
  156. int32_t bitfieldLength;
  157. if(fread(&bitfieldLength, sizeof(bitfieldLength), 1, file) < 1) {
  158. throw string("readError");
  159. }
  160. if(bitfieldLength > 0) {
  161. initBitfield(segmentSize, totalSize);
  162. unsigned char* savedBitfield = new unsigned char[bitfield->getBitfieldLength()];
  163. if(fread(savedBitfield, bitfield->getBitfieldLength(), 1, file) < 1) {
  164. delete [] savedBitfield;
  165. throw string("readError");
  166. } else {
  167. bitfield->setBitfield(savedBitfield, bitfield->getBitfieldLength());
  168. delete [] savedBitfield;
  169. }
  170. }
  171. int32_t segmentCount;
  172. if(fread(&segmentCount, sizeof(segmentCount), 1, file) < 1) {
  173. throw string("readError");
  174. }
  175. while(segmentCount--) {
  176. SegmentHandle seg;
  177. if(fread(seg.get(), sizeof(Segment), 1, file) < 1) {
  178. throw string("readError");
  179. }
  180. usedSegmentEntries.push_back(SegmentEntryHandle(new SegmentEntry(0, seg)));
  181. }
  182. }
  183. void SegmentMan::remove() const {
  184. if(!isSplittable) {
  185. return;
  186. }
  187. if(segmentFileExists()) {
  188. File f(getSegmentFilePath());
  189. f.remove();
  190. }
  191. }
  192. bool SegmentMan::finished() const {
  193. if(!downloadStarted) {
  194. return false;
  195. }
  196. if(!bitfield) {
  197. return false;
  198. }
  199. assert(bitfield);
  200. return bitfield->isAllBitSet();
  201. }
  202. void SegmentMan::removeIfFinished() const {
  203. if(finished()) {
  204. remove();
  205. }
  206. }
  207. void SegmentMan::init() {
  208. totalSize = 0;
  209. isSplittable = false;
  210. downloadStarted = false;
  211. errors = 0;
  212. //segments.clear();
  213. usedSegmentEntries.clear();
  214. delete bitfield;
  215. bitfield = 0;
  216. peerStats.clear();
  217. diskWriter->closeFile();
  218. }
  219. void SegmentMan::initBitfield(int32_t segmentLength, int64_t totalLength) {
  220. delete bitfield;
  221. this->bitfield = BitfieldManFactory::getFactoryInstance()->createBitfieldMan(segmentLength, totalLength);
  222. }
  223. SegmentHandle SegmentMan::checkoutSegment(int32_t cuid, int32_t index) {
  224. logger->debug("Attach segment#%d to CUID#%d.", index, cuid);
  225. bitfield->setUseBit(index);
  226. SegmentEntryHandle segmentEntry = getSegmentEntryByIndex(index);
  227. SegmentHandle segment(0);
  228. if(segmentEntry.isNull()) {
  229. segment = new Segment(index, bitfield->getBlockLength(index),
  230. bitfield->getBlockLength());
  231. SegmentEntryHandle entry = new SegmentEntry(cuid, segment);
  232. usedSegmentEntries.push_back(entry);
  233. } else {
  234. segmentEntry->cuid = cuid;
  235. segment = segmentEntry->segment;
  236. }
  237. logger->debug("index=%d, length=%d, segmentLength=%d, writtenLength=%d",
  238. segment->index, segment->length, segment->segmentLength,
  239. segment->writtenLength);
  240. return segment;
  241. }
  242. SegmentHandle SegmentMan::onNullBitfield(int32_t cuid) {
  243. if(usedSegmentEntries.size() == 0) {
  244. SegmentHandle segment = new Segment(0, 0, 0);
  245. usedSegmentEntries.push_back(SegmentEntryHandle(new SegmentEntry(cuid, segment)));
  246. return segment;
  247. } else {
  248. SegmentEntryHandle segmentEntry = getSegmentEntryByCuid(cuid);
  249. if(segmentEntry.isNull()) {
  250. return 0;
  251. } else {
  252. return segmentEntry->segment;
  253. }
  254. }
  255. }
  256. SegmentEntryHandle SegmentMan::findSlowerSegmentEntry(const PeerStatHandle& peerStat) const {
  257. int32_t speed = (int32_t)(peerStat->getAvgDownloadSpeed()*0.8);
  258. SegmentEntryHandle slowSegmentEntry(0);
  259. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  260. itr != usedSegmentEntries.end(); ++itr) {
  261. const SegmentEntryHandle& segmentEntry = *itr;
  262. if(segmentEntry->cuid == 0) {
  263. continue;
  264. }
  265. PeerStatHandle p = getPeerStat(segmentEntry->cuid);
  266. if(!p.get() || p->getCuid() == peerStat->getCuid() ||
  267. p->getStatus() != PeerStat::ACTIVE ||
  268. !p->getDownloadStartTime().elapsed(option->getAsInt(PREF_STARTUP_IDLE_TIME))) {
  269. continue;
  270. }
  271. int32_t pSpeed = p->calculateDownloadSpeed();
  272. if(pSpeed < speed) {
  273. speed = pSpeed;
  274. slowSegmentEntry = segmentEntry;
  275. }
  276. }
  277. return slowSegmentEntry;
  278. }
  279. SegmentHandle SegmentMan::getSegment(int32_t cuid) {
  280. if(!bitfield) {
  281. return onNullBitfield(cuid);
  282. }
  283. SegmentEntryHandle segmentEntry = getSegmentEntryByCuid(cuid);
  284. if(!segmentEntry.isNull()) {
  285. return segmentEntry->segment;
  286. }
  287. int32_t index = bitfield->getSparseMissingUnusedIndex();
  288. if(index == -1) {
  289. PeerStatHandle myPeerStat = getPeerStat(cuid);
  290. if(!myPeerStat.get()) {
  291. return 0;
  292. }
  293. SegmentEntryHandle slowSegmentEntry = findSlowerSegmentEntry(myPeerStat);
  294. if(slowSegmentEntry.get()) {
  295. logger->info(MSG_SEGMENT_FORWARDING,
  296. slowSegmentEntry->cuid,
  297. slowSegmentEntry->segment->index,
  298. cuid);
  299. PeerStatHandle slowPeerStat = getPeerStat(slowSegmentEntry->cuid);
  300. slowPeerStat->requestIdle();
  301. cancelSegment(slowSegmentEntry->cuid);
  302. return checkoutSegment(cuid, slowSegmentEntry->segment->index);
  303. } else {
  304. return 0;
  305. }
  306. } else {
  307. return checkoutSegment(cuid, index);
  308. }
  309. }
  310. SegmentHandle SegmentMan::getSegment(int32_t cuid, int32_t index) {
  311. if(!bitfield) {
  312. return onNullBitfield(cuid);
  313. }
  314. if(index < 0 || (int32_t)bitfield->countBlock() <= index) {
  315. return 0;
  316. }
  317. if(bitfield->isBitSet(index) || bitfield->isUseBitSet(index)) {
  318. return 0;
  319. } else {
  320. return checkoutSegment(cuid, index);
  321. }
  322. }
  323. /*
  324. bool SegmentMan::updateSegment(int cuid, const Segment& segment) {
  325. if(segment.isNull()) {
  326. return false;
  327. }
  328. SegmentEntryHandle segmentEntry = getSegmentEntryByCuid(cuid);
  329. if(segmentEntry.isNull()) {
  330. return false;
  331. } else {
  332. segmentEntry->segment = segment;
  333. return true;
  334. }
  335. }
  336. */
  337. void SegmentMan::cancelSegment(int32_t cuid) {
  338. if(bitfield) {
  339. for(SegmentEntries::iterator itr = usedSegmentEntries.begin();
  340. itr != usedSegmentEntries.end(); ++itr) {
  341. if((*itr)->cuid == cuid) {
  342. bitfield->unsetUseBit((*itr)->segment->index);
  343. (*itr)->cuid = 0;
  344. break;
  345. }
  346. }
  347. } else {
  348. usedSegmentEntries.clear();
  349. }
  350. }
  351. bool SegmentMan::completeSegment(int32_t cuid, const SegmentHandle& segment) {
  352. if(segment->isNull()) {
  353. return false;
  354. }
  355. if(bitfield) {
  356. bitfield->unsetUseBit(segment->index);
  357. bitfield->setBit(segment->index);
  358. } else {
  359. initBitfield(option->getAsInt(PREF_SEGMENT_SIZE), segment->writtenLength);
  360. bitfield->setAllBit();
  361. }
  362. SegmentEntries::iterator itr = getSegmentEntryIteratorByCuid(cuid);
  363. if(itr == usedSegmentEntries.end()) {
  364. return false;
  365. } else {
  366. usedSegmentEntries.erase(itr);
  367. return true;
  368. }
  369. }
  370. bool SegmentMan::hasSegment(int32_t index) const {
  371. if(bitfield) {
  372. return bitfield->isBitSet(index);
  373. } else {
  374. return false;
  375. }
  376. }
  377. int64_t SegmentMan::getDownloadLength() const {
  378. int64_t dlLength = 0;
  379. if(bitfield) {
  380. dlLength += bitfield->getCompletedLength();
  381. }
  382. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  383. itr != usedSegmentEntries.end(); itr++) {
  384. dlLength += (*itr)->segment->writtenLength;
  385. }
  386. return dlLength;
  387. }
  388. void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
  389. PeerStatHandle temp = getPeerStat(peerStat->getCuid());
  390. if(!temp.get()) {
  391. peerStats.push_back(peerStat);
  392. }
  393. }
  394. int32_t SegmentMan::calculateDownloadSpeed() const {
  395. int32_t speed = 0;
  396. for(PeerStats::const_iterator itr = peerStats.begin();
  397. itr != peerStats.end(); itr++) {
  398. const PeerStatHandle& peerStat = *itr;
  399. if(peerStat->getStatus() == PeerStat::ACTIVE) {
  400. speed += peerStat->calculateDownloadSpeed();
  401. }
  402. }
  403. return speed;
  404. }
  405. bool SegmentMan::fileExists() const {
  406. return File(getFilePath()).exists();
  407. }
  408. bool SegmentMan::shouldCancelDownloadForSafety() const {
  409. return fileExists() && !segmentFileExists() &&
  410. option->get(PREF_ALLOW_OVERWRITE) != V_TRUE;
  411. }
  412. void SegmentMan::markAllPiecesDone()
  413. {
  414. if(bitfield) {
  415. bitfield->setAllBit();
  416. }
  417. }
  418. void SegmentMan::markPieceDone(int64_t length)
  419. {
  420. if(bitfield) {
  421. if(length == bitfield->getTotalLength()) {
  422. bitfield->setAllBit();
  423. } else {
  424. bitfield->clearAllBit();
  425. int32_t numSegment = length/bitfield->getBlockLength();
  426. int32_t remainingLength = length%bitfield->getBlockLength();
  427. bitfield->setBitRange(0, numSegment-1);
  428. if(remainingLength > 0) {
  429. SegmentHandle segment = new Segment();
  430. segment->index = numSegment;
  431. segment->length = bitfield->getBlockLength(numSegment);
  432. segment->segmentLength = bitfield->getBlockLength();
  433. segment->writtenLength = remainingLength;
  434. usedSegmentEntries.push_back(new SegmentEntry(0, segment));
  435. }
  436. }
  437. }
  438. }
  439. #ifdef ENABLE_MESSAGE_DIGEST
  440. bool SegmentMan::isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const {
  441. return !chunkChecksum.isNull() && bitfield && totalSize > 0 &&
  442. chunkChecksum->getEstimatedDataLength() >= totalSize;
  443. }
  444. #endif // ENABLE_MESSAGE_DIGEST
  445. #ifdef ENABLE_MESSAGE_DIGEST
  446. void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum)
  447. {
  448. if(!isChunkChecksumValidationReady(chunkChecksum)) {
  449. return;
  450. }
  451. int32_t hashStartIndex;
  452. int32_t hashEndIndex;
  453. Util::indexRange(hashStartIndex, hashEndIndex,
  454. segment->getPosition(),
  455. segment->writtenLength,
  456. chunkChecksum->getChecksumLength());
  457. if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkChecksum->getChecksumLength(),
  458. chunkChecksum->getChecksumLength())) {
  459. ++hashStartIndex;
  460. }
  461. if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkChecksum->getChecksumLength(),
  462. chunkChecksum->getChecksumLength())) {
  463. --hashEndIndex;
  464. }
  465. logger->debug("hashStartIndex=%d, hashEndIndex=%d",
  466. hashStartIndex, hashEndIndex);
  467. if(hashStartIndex > hashEndIndex) {
  468. logger->debug(MSG_NO_CHUNK_CHECKSUM);
  469. return;
  470. }
  471. int64_t hashOffset = ((int64_t)hashStartIndex)*chunkChecksum->getChecksumLength();
  472. int32_t startIndex;
  473. int32_t endIndex;
  474. Util::indexRange(startIndex, endIndex,
  475. hashOffset,
  476. (hashEndIndex-hashStartIndex+1)*chunkChecksum->getChecksumLength(),
  477. bitfield->getBlockLength());
  478. logger->debug("startIndex=%d, endIndex=%d", startIndex, endIndex);
  479. if(bitfield->isBitRangeSet(startIndex, endIndex)) {
  480. for(int32_t index = hashStartIndex; index <= hashEndIndex; ++index) {
  481. int64_t offset = ((int64_t)index)*chunkChecksum->getChecksumLength();
  482. int32_t dataLength =
  483. offset+chunkChecksum->getChecksumLength() <= totalSize ?
  484. chunkChecksum->getChecksumLength() : totalSize-offset;
  485. string actualChecksum = MessageDigestHelper::digest(chunkChecksum->getAlgo(), diskWriter, offset, dataLength);
  486. if(chunkChecksum->validateChunk(actualChecksum, index)) {
  487. logger->info(MSG_GOOD_CHUNK_CHECKSUM, actualChecksum.c_str());
  488. } else {
  489. logger->info(EX_INVALID_CHUNK_CHECKSUM,
  490. index, Util::llitos(offset, true).c_str(),
  491. chunkChecksum->getChecksum(index).c_str(), actualChecksum.c_str());
  492. logger->debug("Unset bit from %d to %d(inclusive)", startIndex, endIndex);
  493. bitfield->unsetBitRange(startIndex, endIndex);
  494. break;
  495. }
  496. }
  497. }
  498. }
  499. #endif // ENABLE_MESSAGE_DIGEST