TorrentMan.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - a simple utility for downloading files faster
  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /* copyright --> */
  22. #include "TorrentMan.h"
  23. #include "Dictionary.h"
  24. #include "List.h"
  25. #include "ShaVisitor.h"
  26. #include "Util.h"
  27. #include "MetaFileUtil.h"
  28. #include "DlAbortEx.h"
  29. #include "File.h"
  30. #include "message.h"
  31. #include "PreAllocationDiskWriter.h"
  32. #include "DefaultDiskWriter.h"
  33. #include "MultiDiskWriter.h"
  34. #include "prefs.h"
  35. #include "CopyDiskAdaptor.h"
  36. #include "DirectDiskAdaptor.h"
  37. #include "MultiDiskAdaptor.h"
  38. #include "LogFactory.h"
  39. #include <errno.h>
  40. #include <libgen.h>
  41. #include <string.h>
  42. #include <algorithm>
  43. extern PeerHandle nullPeer;
  44. TorrentMan::TorrentMan():bitfield(0),
  45. peerEntryIdCounter(0),
  46. cuidCounter(0),
  47. downloadLength(0),
  48. uploadLength(0),
  49. preDownloadLength(0),
  50. preUploadLength(0),
  51. deltaDownloadLength(0),
  52. deltaUploadLength(0),
  53. storeDir("."),
  54. setupComplete(false),
  55. halt(false),
  56. interval(DEFAULT_ANNOUNCE_INTERVAL),
  57. minInterval(DEFAULT_ANNOUNCE_MIN_INTERVAL),
  58. complete(0),
  59. incomplete(0),
  60. connections(0),
  61. trackers(0),
  62. req(0),
  63. diskAdaptor(0)
  64. {
  65. logger = LogFactory::getInstance();
  66. }
  67. TorrentMan::~TorrentMan() {
  68. delete bitfield;
  69. delete diskAdaptor;
  70. delete req;
  71. }
  72. // TODO do not use this method in application code
  73. void TorrentMan::updatePeers(const Peers& peers) {
  74. this->peers = peers;
  75. }
  76. bool TorrentMan::addPeer(const PeerHandle& peer) {
  77. if(peers.size() >= MAX_PEER_LIST_SIZE) {
  78. deleteUnusedPeer(peers.size()-MAX_PEER_LIST_SIZE+15);
  79. }
  80. Peers::iterator itr = find(peers.begin(), peers.end(), peer);
  81. if(itr == peers.end()) {
  82. ++peerEntryIdCounter;
  83. peer->entryId = peerEntryIdCounter;
  84. peers.push_back(peer);
  85. return true;
  86. } else {
  87. const PeerHandle& peer = *itr;
  88. if(peer->error >= MAX_PEER_ERROR || peer->cuid != 0) {
  89. return false;
  90. } else {
  91. *itr = peer;
  92. return true;
  93. }
  94. }
  95. }
  96. /*
  97. void TorrentMan::updatePeer(const Peer& peer) {
  98. for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
  99. Peer& p = *itr;
  100. if(p.eid == peer.eid) {
  101. p = peer;
  102. break;
  103. }
  104. }
  105. }
  106. */
  107. bool TorrentMan::isPeerAvailable() const {
  108. return getPeer() != nullPeer;
  109. }
  110. void TorrentMan::deleteUnusedPeer(int delSize) {
  111. for(Peers::iterator itr = peers.begin();
  112. itr != peers.end() && delSize > 0;) {
  113. const PeerHandle& p = *itr;
  114. if(p->cuid == 0) {
  115. itr = peers.erase(itr);
  116. delSize--;
  117. } else {
  118. itr++;
  119. }
  120. }
  121. }
  122. PeerHandle TorrentMan::getPeer() const {
  123. if(connections > MIN_PEERS) {
  124. return nullPeer;
  125. }
  126. for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); itr++) {
  127. const PeerHandle& p = *itr;
  128. if(p->cuid == 0 && p->error < MAX_PEER_ERROR) {
  129. return p;
  130. }
  131. }
  132. return nullPeer;
  133. }
  134. bool TorrentMan::isEndGame() const {
  135. return bitfield->countMissingBlock() <= END_GAME_PIECE_NUM;
  136. }
  137. bool TorrentMan::hasMissingPiece(const PeerHandle& peer) const {
  138. return bitfield->hasMissingPiece(peer->getBitfield(),
  139. peer->getBitfieldLength());
  140. }
  141. int TorrentMan::getMissingPieceIndex(const PeerHandle& peer) const {
  142. int index = -1;
  143. if(isEndGame()) {
  144. index = bitfield->getMissingIndex(peer->getBitfield(),
  145. peer->getBitfieldLength());
  146. } else {
  147. index = bitfield->getMissingUnusedIndex(peer->getBitfield(),
  148. peer->getBitfieldLength());
  149. }
  150. return index;
  151. }
  152. int TorrentMan::getMissingFastPieceIndex(const PeerHandle& peer) const {
  153. int index = -1;
  154. if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
  155. BitfieldMan tempBitfield(pieceLength, totalLength);
  156. for(Integers::const_iterator itr = peer->getFastSet().begin();
  157. itr != peer->getFastSet().end(); itr++) {
  158. if(!hasPiece(*itr) && peer->hasPiece(*itr)) {
  159. tempBitfield.setBit(*itr);
  160. }
  161. }
  162. if(isEndGame()) {
  163. index = bitfield->getMissingIndex(tempBitfield.getBitfield(),
  164. tempBitfield.getBitfieldLength());
  165. } else {
  166. index = bitfield->getMissingUnusedIndex(tempBitfield.getBitfield(),
  167. tempBitfield.getBitfieldLength());
  168. }
  169. }
  170. return index;
  171. }
  172. Piece TorrentMan::getMissingFastPiece(const PeerHandle& peer) {
  173. int index = getMissingFastPieceIndex(peer);
  174. return checkOutPiece(index);
  175. }
  176. Piece TorrentMan::getMissingPiece(const PeerHandle& peer) {
  177. int index = getMissingPieceIndex(peer);
  178. return checkOutPiece(index);
  179. }
  180. Piece TorrentMan::checkOutPiece(int index) {
  181. if(index == -1) {
  182. return Piece::nullPiece;
  183. }
  184. bitfield->setUseBit(index);
  185. Piece piece = findUsedPiece(index);
  186. if(Piece::isNull(piece)) {
  187. Piece piece(index, bitfield->getBlockLength(index));
  188. addUsedPiece(piece);
  189. return piece;
  190. } else {
  191. return piece;
  192. }
  193. }
  194. int TorrentMan::deleteUsedPiecesByFillRate(int fillRate, int toDelete) {
  195. int deleted = 0;
  196. for(Pieces::iterator itr = usedPieces.begin();
  197. itr != usedPieces.end() && deleted < toDelete;) {
  198. Piece& piece = *itr;
  199. if(!bitfield->isUseBitSet(piece.getIndex()) &&
  200. piece.countCompleteBlock() <= piece.countBlock()*(fillRate/100.0)) {
  201. logger->debug("Deleting used piece index=%d, fillRate(%%)=%d<=%d",
  202. piece.getIndex(),
  203. (piece.countCompleteBlock()*100)/piece.countBlock(),
  204. fillRate);
  205. itr = usedPieces.erase(itr);
  206. deleted++;
  207. } else {
  208. itr++;
  209. }
  210. }
  211. return deleted;
  212. }
  213. void TorrentMan::reduceUsedPieces(int max) {
  214. int toDelete = usedPieces.size()-max;
  215. if(toDelete <= 0) {
  216. return;
  217. }
  218. int fillRate = 10;
  219. while(fillRate < 50) {
  220. int deleted = deleteUsedPiecesByFillRate(fillRate, toDelete);
  221. if(deleted == 0) {
  222. break;
  223. }
  224. toDelete -= deleted;
  225. fillRate += 10;
  226. }
  227. }
  228. void TorrentMan::addUsedPiece(const Piece& piece) {
  229. // TODO ? if nullPiece
  230. usedPieces.push_back(piece);
  231. }
  232. Piece TorrentMan::findUsedPiece(int index) const {
  233. for(Pieces::const_iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
  234. const Piece& piece = *itr;
  235. if(piece.getIndex() == index) {
  236. return piece;
  237. }
  238. }
  239. return Piece::nullPiece;
  240. }
  241. void TorrentMan::deleteUsedPiece(const Piece& piece) {
  242. if(Piece::isNull(piece)) {
  243. return;
  244. }
  245. Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(), piece);
  246. if(itr != usedPieces.end()) {
  247. usedPieces.erase(itr);
  248. }
  249. }
  250. void TorrentMan::completePiece(const Piece& piece) {
  251. if(Piece::isNull(piece)) {
  252. return;
  253. }
  254. if(!hasPiece(piece.getIndex())) {
  255. addDownloadLength(piece.getLength());
  256. }
  257. bitfield->setBit(piece.getIndex());
  258. bitfield->unsetUseBit(piece.getIndex());
  259. deleteUsedPiece(piece);
  260. if(!isEndGame()) {
  261. reduceUsedPieces(100);
  262. }
  263. }
  264. void TorrentMan::cancelPiece(const Piece& piece) {
  265. if(Piece::isNull(piece)) {
  266. return;
  267. }
  268. updatePiece(piece);
  269. bitfield->unsetUseBit(piece.getIndex());
  270. if(!isEndGame()) {
  271. if(piece.countCompleteBlock() == 0) {
  272. deleteUsedPiece(piece);
  273. }
  274. }
  275. }
  276. void TorrentMan::updatePiece(const Piece& piece) {
  277. if(Piece::isNull(piece)) {
  278. return;
  279. }
  280. Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
  281. piece);
  282. if(itr != usedPieces.end()) {
  283. *itr = piece;
  284. }
  285. }
  286. void TorrentMan::syncPiece(Piece& piece) {
  287. if(Piece::isNull(piece)) {
  288. return;
  289. }
  290. Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
  291. piece);
  292. if(itr != usedPieces.end()) {
  293. piece = *itr;
  294. return;
  295. } else {
  296. // hasPiece(piece.getIndex()) is true, then set all bit of
  297. // piece.bitfield to 1
  298. if(hasPiece(piece.getIndex())) {
  299. piece.setAllBlock();
  300. }
  301. }
  302. }
  303. void TorrentMan::initBitfield() {
  304. if(bitfield != NULL) {
  305. delete bitfield;
  306. }
  307. bitfield = new BitfieldMan(pieceLength, totalLength);
  308. }
  309. void TorrentMan::setBitfield(unsigned char* bitfield, int bitfieldLength) {
  310. if(this->bitfield == NULL) {
  311. initBitfield();
  312. }
  313. this->bitfield->setBitfield(bitfield, bitfieldLength);
  314. }
  315. bool TorrentMan::downloadComplete() const {
  316. return bitfield->isAllBitSet();
  317. }
  318. bool TorrentMan::hasAllPieces() const {
  319. return bitfield->getTotalLength() == downloadLength;
  320. }
  321. void TorrentMan::readFileEntry(FileEntries& fileEntries, Directory** pTopDir, const Dictionary* infoDic, const string& defaultName) {
  322. Data* topName = (Data*)infoDic->get("name");
  323. if(topName != NULL) {
  324. name = topName->toString();
  325. } else {
  326. char* basec = strdup(defaultName.c_str());
  327. name = string(basename(basec))+".file";
  328. free(basec);
  329. }
  330. List* files = (List*)infoDic->get("files");
  331. if(files == NULL) {
  332. // single-file mode;
  333. setFileMode(SINGLE);
  334. Data* length = (Data*)infoDic->get("length");
  335. totalLength = length->toLLInt();
  336. FileEntry fileEntry(name, totalLength, 0);
  337. fileEntries.push_back(fileEntry);
  338. } else {
  339. long long int length = 0;
  340. long long int offset = 0;
  341. // multi-file mode
  342. setFileMode(MULTI);
  343. *pTopDir = new Directory(name);
  344. const MetaList& metaList = files->getList();
  345. for(MetaList::const_iterator itr = metaList.begin(); itr != metaList.end();
  346. itr++) {
  347. Dictionary* fileDic = (Dictionary*)(*itr);
  348. Data* lengthData = (Data*)fileDic->get("length");
  349. length += lengthData->toLLInt();
  350. List* path = (List*)fileDic->get("path");
  351. const MetaList& paths = path->getList();
  352. Directory* parentDir = *pTopDir;
  353. string filePath = name;
  354. for(int i = 0; i < (int)paths.size()-1; i++) {
  355. Data* subpath = (Data*)paths.at(i);
  356. Directory* dir = new Directory(subpath->toString());
  357. parentDir->addFile(dir);
  358. parentDir = dir;
  359. filePath.append("/").append(subpath->toString());
  360. }
  361. Data* lastpath = (Data*)paths.back();
  362. filePath.append("/").append(lastpath->toString());
  363. FileEntry fileEntry(filePath, lengthData->toLLInt(), offset);
  364. fileEntries.push_back(fileEntry);
  365. offset += fileEntry.length;
  366. }
  367. totalLength = length;
  368. }
  369. }
  370. void TorrentMan::setupInternal1(const string& metaInfoFile) {
  371. peerId = "-aria2-";
  372. peerId += Util::randomAlpha(20-peerId.size());
  373. key = Util::randomAlpha(8);
  374. uploadLength = 0;
  375. downloadLength = 0;
  376. Dictionary* topDic = (Dictionary*)MetaFileUtil::parseMetaFile(metaInfoFile);
  377. const Dictionary* infoDic = (const Dictionary*)topDic->get("info");
  378. ShaVisitor v;
  379. infoDic->accept(&v);
  380. unsigned char md[20];
  381. int len;
  382. v.getHash(md, len);
  383. setInfoHash(md);
  384. FileEntries fileEntries;
  385. Directory* topDir = NULL;
  386. readFileEntry(fileEntries, &topDir, infoDic, metaInfoFile);
  387. announce = ((Data*)topDic->get("announce"))->toString();
  388. pieceLength = ((Data*)infoDic->get("piece length"))->toInt();
  389. pieces = totalLength/pieceLength+(totalLength%pieceLength ? 1 : 0);
  390. Data* piecesHashData = (Data*)infoDic->get("pieces");
  391. if(piecesHashData->getLen() != pieces*20) {
  392. throw new DlAbortEx("The number of pieces is wrong.");
  393. }
  394. for(int index = 0; index < pieces; index++) {
  395. string hex = Util::toHex((unsigned char*)&piecesHashData->getData()[index*20], 20);
  396. pieceHashes.push_back(hex);
  397. logger->debug("piece #%d, hash:%s", index, hex.c_str());
  398. }
  399. initBitfield();
  400. delete topDic;
  401. if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
  402. if(fileMode == SINGLE) {
  403. diskAdaptor = new DirectDiskAdaptor(new DefaultDiskWriter(totalLength));
  404. } else {
  405. diskAdaptor = new MultiDiskAdaptor(new MultiDiskWriter(pieceLength));
  406. }
  407. } else {
  408. diskAdaptor = new CopyDiskAdaptor(new PreAllocationDiskWriter(totalLength));
  409. ((CopyDiskAdaptor*)diskAdaptor)->setTempFilename(name+".a2tmp");
  410. }
  411. diskAdaptor->setStoreDir(storeDir);
  412. diskAdaptor->setTopDir(topDir);
  413. diskAdaptor->setFileEntries(fileEntries);
  414. }
  415. void TorrentMan::setupInternal2() {
  416. if(segmentFileExists()) {
  417. load();
  418. diskAdaptor->openExistingFile();
  419. } else {
  420. diskAdaptor->initAndOpenFile();
  421. }
  422. setupComplete = true;
  423. }
  424. void TorrentMan::setup(const string& metaInfoFile, const Integers& targetFileIndexes) {
  425. setupInternal1(metaInfoFile);
  426. Strings targetFilePaths;
  427. const FileEntries& entries = diskAdaptor->getFileEntries();
  428. for(int i = 0; i < (int)entries.size(); i++) {
  429. if(find(targetFileIndexes.begin(), targetFileIndexes.end(), i+1) != targetFileIndexes.end()) {
  430. logger->debug("index=%d is %s", i+1, entries.at(i).path.c_str());
  431. targetFilePaths.push_back(entries.at(i).path);
  432. }
  433. }
  434. setFileFilter(targetFilePaths);
  435. setupInternal2();
  436. }
  437. void TorrentMan::setup(const string& metaInfoFile, const Strings& targetFilePaths) {
  438. setupInternal1(metaInfoFile);
  439. setFileFilter(targetFilePaths);
  440. setupInternal2();
  441. }
  442. void TorrentMan::setFileFilter(const Strings& filePaths) {
  443. if(fileMode != MULTI || filePaths.empty()) {
  444. return;
  445. }
  446. diskAdaptor->removeAllDownloadEntry();
  447. for(Strings::const_iterator pitr = filePaths.begin();
  448. pitr != filePaths.end(); pitr++) {
  449. if(!diskAdaptor->addDownloadEntry(*pitr)) {
  450. throw new DlAbortEx("No such file entry %s", (*pitr).c_str());
  451. }
  452. FileEntry fileEntry = diskAdaptor->getFileEntryFromPath(*pitr);
  453. bitfield->addFilter(fileEntry.offset, fileEntry.length);
  454. }
  455. bitfield->enableFilter();
  456. }
  457. FileEntries TorrentMan::readFileEntryFromMetaInfoFile(const string& metaInfoFile) {
  458. Dictionary* topDic = (Dictionary*)MetaFileUtil::parseMetaFile(metaInfoFile);
  459. const Dictionary* infoDic = (const Dictionary*)topDic->get("info");
  460. FileEntries fileEntries;
  461. Directory* topDir = NULL;
  462. readFileEntry(fileEntries, &topDir, infoDic, metaInfoFile);
  463. if(topDir != NULL) {
  464. delete topDir;
  465. }
  466. return fileEntries;
  467. }
  468. string TorrentMan::getName() const {
  469. return name;
  470. }
  471. bool TorrentMan::hasPiece(int index) const {
  472. return bitfield->isBitSet(index);
  473. }
  474. string TorrentMan::getPieceHash(int index) const {
  475. return pieceHashes.at(index);
  476. }
  477. string TorrentMan::getSegmentFilePath() const {
  478. return storeDir+"/"+name+".aria2";
  479. }
  480. bool TorrentMan::segmentFileExists() const {
  481. string segFilename = getSegmentFilePath();
  482. File f(segFilename);
  483. if(f.isFile()) {
  484. logger->info(MSG_SEGMENT_FILE_EXISTS, segFilename.c_str());
  485. return true;
  486. } else {
  487. logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, segFilename.c_str());
  488. return false;
  489. }
  490. }
  491. FILE* TorrentMan::openSegFile(const string& segFilename, const string& mode) const {
  492. FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
  493. if(segFile == NULL) {
  494. throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
  495. segFilename.c_str(), strerror(errno));
  496. }
  497. return segFile;
  498. }
  499. void TorrentMan::load() {
  500. string segFilename = getSegmentFilePath();
  501. logger->info(MSG_LOADING_SEGMENT_FILE, segFilename.c_str());
  502. FILE* segFile = openSegFile(segFilename, "r+");
  503. try {
  504. read(segFile);
  505. fclose(segFile);
  506. } catch(string ex) {
  507. fclose(segFile);
  508. throw new DlAbortEx(EX_SEGMENT_FILE_READ,
  509. segFilename.c_str(), strerror(errno));
  510. }
  511. logger->info(MSG_LOADED_SEGMENT_FILE);
  512. }
  513. void TorrentMan::read(FILE* file) {
  514. assert(file != NULL);
  515. unsigned char savedInfoHash[INFO_HASH_LENGTH];
  516. if(fread(savedInfoHash, INFO_HASH_LENGTH, 1, file) < 1) {
  517. throw string("readError");
  518. }
  519. if(Util::toHex(savedInfoHash, INFO_HASH_LENGTH) != Util::toHex(infoHash, INFO_HASH_LENGTH)) {
  520. throw new DlAbortEx("Incorrect infoHash.");
  521. }
  522. unsigned char* savedBitfield = new unsigned char[bitfield->getBitfieldLength()];
  523. try {
  524. if(fread(savedBitfield, bitfield->getBitfieldLength(), 1, file) < 1) {
  525. throw string("readError");
  526. }
  527. setBitfield(savedBitfield, bitfield->getBitfieldLength());
  528. if(fread(&downloadLength, sizeof(downloadLength), 1, file) < 1) {
  529. throw string("readError");
  530. }
  531. if(fread(&uploadLength, sizeof(uploadLength), 1, file) < 1) {
  532. throw string("readError");
  533. }
  534. preDownloadLength = downloadLength;
  535. preUploadLength = uploadLength;
  536. delete [] savedBitfield;
  537. } catch(...) {
  538. delete [] savedBitfield;
  539. throw;
  540. }
  541. }
  542. void TorrentMan::save() const {
  543. if(!setupComplete) {
  544. return;
  545. }
  546. string segFilename = getSegmentFilePath();
  547. logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
  548. FILE* file = openSegFile(segFilename, "w");
  549. try {
  550. if(fwrite(infoHash, INFO_HASH_LENGTH, 1, file) < 1) {
  551. throw string("writeError");
  552. }
  553. if(fwrite(bitfield->getBitfield(), bitfield->getBitfieldLength(), 1, file) < 1) {
  554. throw string("writeError");
  555. }
  556. if(fwrite(&downloadLength, sizeof(downloadLength), 1, file) < 1) {
  557. throw string("writeError");
  558. }
  559. if(fwrite(&uploadLength, sizeof(uploadLength), 1, file) < 1) {
  560. throw string("writeError");
  561. }
  562. fclose(file);
  563. logger->info(MSG_SAVED_SEGMENT_FILE);
  564. } catch(string ex) {
  565. fclose(file);
  566. throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
  567. segFilename.c_str(), strerror(errno));
  568. }
  569. }
  570. void TorrentMan::remove() const {
  571. if(segmentFileExists()) {
  572. File f(getSegmentFilePath());
  573. f.remove();
  574. }
  575. }
  576. bool TorrentMan::isSelectiveDownloadingMode() const {
  577. return bitfield->isFilterEnabled();
  578. }
  579. void TorrentMan::finishSelectiveDownloadingMode() {
  580. bitfield->clearFilter();
  581. diskAdaptor->addAllDownloadEntry();
  582. }
  583. long long int TorrentMan::getCompletedLength() const {
  584. return bitfield->getCompletedLength();
  585. }
  586. long long int TorrentMan::getSelectedTotalLength() const {
  587. return bitfield->getFilteredTotalLength();
  588. }
  589. void TorrentMan::onDownloadComplete() {
  590. save();
  591. diskAdaptor->onDownloadComplete();
  592. if(isSelectiveDownloadingMode()) {
  593. finishSelectiveDownloadingMode();
  594. }
  595. }
  596. void TorrentMan::advertisePiece(int cuid, int index) {
  597. HaveEntry entry(cuid, index);
  598. haves.push_front(entry);
  599. };
  600. PieceIndexes
  601. TorrentMan::getAdvertisedPieceIndexes(int myCuid,
  602. const Time& lastCheckTime
  603. ) const
  604. {
  605. PieceIndexes indexes;
  606. for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
  607. const Haves::value_type& have = *itr;
  608. if(have.cuid == myCuid) {
  609. continue;
  610. }
  611. if(lastCheckTime.isNewer(have.registeredTime)) {
  612. break;
  613. }
  614. indexes.push_back(have.index);
  615. }
  616. return indexes;
  617. }
  618. class FindElapsedHave
  619. {
  620. private:
  621. int elapsed;
  622. public:
  623. FindElapsedHave(int elapsed):elapsed(elapsed) {}
  624. bool operator()(const HaveEntry& have) {
  625. if(have.registeredTime.elapsed(elapsed)) {
  626. return true;
  627. } else {
  628. return false;
  629. }
  630. }
  631. };
  632. void
  633. TorrentMan::removeAdvertisedPiece(int elapsed)
  634. {
  635. Haves::iterator itr = find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
  636. if(itr != haves.end()) {
  637. logger->debug("Removed %d have entries.", haves.end()-itr);
  638. haves.erase(itr, haves.end());
  639. }
  640. }