SegmentMan.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <unistd.h>
  46. #include <errno.h>
  47. SegmentMan::SegmentMan():bitfield(0),
  48. totalSize(0),
  49. isSplittable(true),
  50. downloadStarted(false),
  51. dir("."),
  52. errors(0),
  53. diskWriter(0) {
  54. logger = LogFactory::getInstance();
  55. }
  56. SegmentMan::~SegmentMan() {
  57. delete bitfield;
  58. delete diskWriter;
  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+");
  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) {
  93. return;
  94. }
  95. string segFilename = getSegmentFilePath();
  96. logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
  97. FILE* segFile = openSegFile(segFilename, "w");
  98. try {
  99. if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
  100. throw string("writeError");
  101. }
  102. int segmentLength = bitfield->getBlockLength();
  103. if(fwrite(&segmentLength, sizeof(segmentLength), 1, segFile) < 1) {
  104. throw string("writeError");
  105. }
  106. if(bitfield) {
  107. int 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. int i = 0;
  117. if(fwrite(&i, sizeof(i), 1, segFile) < 1) {
  118. throw string("writeError");
  119. }
  120. }
  121. int 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, 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. int segmentSize;
  153. if(fread(&segmentSize, sizeof(segmentSize), 1, file) < 1) {
  154. throw string("readError");
  155. }
  156. int 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. int segmentCount;
  172. if(fread(&segmentCount, sizeof(segmentCount), 1, file) < 1) {
  173. throw string("readError");
  174. }
  175. while(segmentCount--) {
  176. Segment seg;
  177. if(fread(&seg, 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(int segmentLength, long long int totalLength) {
  220. this->bitfield = BitfieldManFactory::getNewFactory()->createBitfieldMan(segmentLength, totalLength);
  221. }
  222. class FindSegmentEntryByIndex {
  223. private:
  224. int index;
  225. public:
  226. FindSegmentEntryByIndex(int index):index(index) {}
  227. bool operator()(const SegmentEntryHandle& entry) {
  228. return entry->segment.index == index;
  229. }
  230. };
  231. class FindSegmentEntryByCuid {
  232. private:
  233. int cuid;
  234. public:
  235. FindSegmentEntryByCuid(int cuid):cuid(cuid) {}
  236. bool operator()(const SegmentEntryHandle& entry) {
  237. return entry->cuid == cuid;
  238. }
  239. };
  240. Segment SegmentMan::checkoutSegment(int cuid, int index) {
  241. logger->debug("Attach segment#%d to CUID#%d.", index, cuid);
  242. bitfield->setUseBit(index);
  243. SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
  244. usedSegmentEntries.end(),
  245. FindSegmentEntryByIndex(index));
  246. Segment segment;
  247. if(itr == usedSegmentEntries.end()) {
  248. segment = Segment(index, bitfield->getBlockLength(index),
  249. bitfield->getBlockLength());
  250. SegmentEntryHandle entry =
  251. SegmentEntryHandle(new SegmentEntry(cuid, segment));
  252. usedSegmentEntries.push_back(entry);
  253. } else {
  254. (*itr)->cuid = cuid;
  255. segment = (*itr)->segment;
  256. }
  257. logger->debug("index=%d, length=%d, segmentLength=%d, writtenLength=%d",
  258. segment.index, segment.length, segment.segmentLength,
  259. segment.writtenLength);
  260. return segment;
  261. }
  262. bool SegmentMan::onNullBitfield(Segment& segment, int cuid) {
  263. if(usedSegmentEntries.size() == 0) {
  264. segment = Segment(0, 0, 0);
  265. usedSegmentEntries.push_back(SegmentEntryHandle(new SegmentEntry(cuid, segment)));
  266. return true;
  267. } else {
  268. SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
  269. usedSegmentEntries.end(),
  270. FindSegmentEntryByCuid(cuid));
  271. if(itr == usedSegmentEntries.end()) {
  272. return false;
  273. } else {
  274. segment = (*itr)->segment;
  275. return true;
  276. }
  277. }
  278. }
  279. SegmentEntryHandle SegmentMan::findSlowerSegmentEntry(const PeerStatHandle& peerStat) const {
  280. int speed = (int)(peerStat->getAvgDownloadSpeed()*0.8);
  281. SegmentEntryHandle slowSegmentEntry(0);
  282. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  283. itr != usedSegmentEntries.end(); itr++) {
  284. const SegmentEntryHandle& segmentEntry = *itr;
  285. if(segmentEntry->cuid == 0) {
  286. continue;
  287. }
  288. PeerStatHandle p = getPeerStat(segmentEntry->cuid);
  289. if(!p.get() || p->getCuid() == peerStat->getCuid() ||
  290. p->getStatus() != PeerStat::ACTIVE ||
  291. !p->getDownloadStartTime().elapsed(option->getAsInt(PREF_STARTUP_IDLE_TIME))) {
  292. continue;
  293. }
  294. int pSpeed = p->calculateDownloadSpeed();
  295. if(pSpeed < speed) {
  296. speed = pSpeed;
  297. slowSegmentEntry = segmentEntry;
  298. }
  299. }
  300. return slowSegmentEntry;
  301. }
  302. bool SegmentMan::getSegment(Segment& segment, int cuid) {
  303. if(!bitfield) {
  304. return onNullBitfield(segment, cuid);
  305. }
  306. SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
  307. usedSegmentEntries.end(),
  308. FindSegmentEntryByCuid(cuid));
  309. if(itr != usedSegmentEntries.end()) {
  310. segment = (*itr)->segment;
  311. return true;
  312. }
  313. int index = bitfield->getSparseMissingUnusedIndex();
  314. if(index == -1) {
  315. PeerStatHandle myPeerStat = getPeerStat(cuid);
  316. if(!myPeerStat.get()) {
  317. return false;
  318. }
  319. SegmentEntryHandle slowSegmentEntry = findSlowerSegmentEntry(myPeerStat);
  320. if(slowSegmentEntry.get()) {
  321. logger->info("CUID#%d cancels segment index=%d. CUID#%d handles it instead.",
  322. slowSegmentEntry->cuid,
  323. slowSegmentEntry->segment.index,
  324. cuid);
  325. PeerStatHandle slowPeerStat = getPeerStat(slowSegmentEntry->cuid);
  326. slowPeerStat->requestIdle();
  327. cancelSegment(slowSegmentEntry->cuid);
  328. segment = checkoutSegment(cuid, slowSegmentEntry->segment.index);
  329. return true;
  330. } else {
  331. return false;
  332. }
  333. } else {
  334. segment = checkoutSegment(cuid, index);
  335. return true;
  336. }
  337. }
  338. bool SegmentMan::getSegment(Segment& segment, int cuid, int index) {
  339. if(!bitfield) {
  340. return onNullBitfield(segment, cuid);
  341. }
  342. if(index < 0 || (int32_t)bitfield->countBlock() <= index) {
  343. return false;
  344. }
  345. if(bitfield->isBitSet(index) || bitfield->isUseBitSet(index)) {
  346. return false;
  347. } else {
  348. segment = checkoutSegment(cuid, index);
  349. return true;
  350. }
  351. }
  352. bool SegmentMan::updateSegment(int cuid, const Segment& segment) {
  353. if(segment.isNull()) {
  354. return false;
  355. }
  356. SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
  357. usedSegmentEntries.end(),
  358. FindSegmentEntryByCuid(cuid));
  359. if(itr == usedSegmentEntries.end()) {
  360. return false;
  361. } else {
  362. (*itr)->segment = segment;
  363. return true;
  364. }
  365. }
  366. class CancelSegment {
  367. private:
  368. int cuid;
  369. BitfieldMan* bitfield;
  370. public:
  371. CancelSegment(int cuid, BitfieldMan* bitfield):cuid(cuid),
  372. bitfield(bitfield) {}
  373. void operator()(SegmentEntryHandle& entry) {
  374. if(entry->cuid == cuid) {
  375. bitfield->unsetUseBit(entry->segment.index);
  376. entry->cuid = 0;
  377. }
  378. }
  379. };
  380. void SegmentMan::cancelSegment(int cuid) {
  381. if(bitfield) {
  382. for_each(usedSegmentEntries.begin(), usedSegmentEntries.end(),
  383. CancelSegment(cuid, bitfield));
  384. } else {
  385. usedSegmentEntries.clear();
  386. }
  387. }
  388. bool SegmentMan::completeSegment(int cuid, const Segment& segment) {
  389. if(segment.isNull()) {
  390. return false;
  391. }
  392. if(bitfield) {
  393. bitfield->unsetUseBit(segment.index);
  394. bitfield->setBit(segment.index);
  395. } else {
  396. initBitfield(option->getAsInt(PREF_SEGMENT_SIZE), segment.writtenLength);
  397. bitfield->setAllBit();
  398. }
  399. SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
  400. usedSegmentEntries.end(),
  401. FindSegmentEntryByCuid(cuid));
  402. if(itr == usedSegmentEntries.end()) {
  403. return false;
  404. } else {
  405. usedSegmentEntries.erase(itr);
  406. return true;
  407. }
  408. }
  409. bool SegmentMan::hasSegment(int index) const {
  410. if(bitfield) {
  411. return bitfield->isBitSet(index);
  412. } else {
  413. return false;
  414. }
  415. }
  416. long long int SegmentMan::getDownloadLength() const {
  417. long long int dlLength = 0;
  418. if(bitfield) {
  419. dlLength += bitfield->getCompletedLength();
  420. }
  421. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  422. itr != usedSegmentEntries.end(); itr++) {
  423. dlLength += (*itr)->segment.writtenLength;
  424. }
  425. return dlLength;
  426. }
  427. void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
  428. PeerStatHandle temp = getPeerStat(peerStat->getCuid());
  429. if(!temp.get()) {
  430. peerStats.push_back(peerStat);
  431. }
  432. }
  433. int SegmentMan::calculateDownloadSpeed() const {
  434. int speed = 0;
  435. for(PeerStats::const_iterator itr = peerStats.begin();
  436. itr != peerStats.end(); itr++) {
  437. const PeerStatHandle& peerStat = *itr;
  438. if(peerStat->getStatus() == PeerStat::ACTIVE) {
  439. speed += peerStat->calculateDownloadSpeed();
  440. }
  441. }
  442. return speed;
  443. }