1
0

SegmentMan.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. #ifndef _D_SEGMENT_MAN_H_
  36. #define _D_SEGMENT_MAN_H_
  37. #include "common.h"
  38. #include "Logger.h"
  39. #include "Segment.h"
  40. #include "Option.h"
  41. #include "DiskWriter.h"
  42. #include "Request.h"
  43. #include "BitfieldMan.h"
  44. #include "PeerStat.h"
  45. using namespace std;
  46. #define SEGMENT_FILE_EXTENSION ".aria2"
  47. class SegmentEntry {
  48. public:
  49. int32_t cuid;
  50. SegmentHandle segment;
  51. public:
  52. SegmentEntry(int32_t cuid, const SegmentHandle& segment)
  53. :cuid(cuid), segment(segment) {}
  54. ~SegmentEntry() {}
  55. };
  56. typedef SharedHandle<SegmentEntry> SegmentEntryHandle;
  57. typedef deque<SegmentEntryHandle> SegmentEntries;
  58. typedef deque<PeerStatHandle> PeerStats;
  59. /**
  60. * This class holds the download progress of the one download entry.
  61. */
  62. class SegmentMan {
  63. private:
  64. const Logger* logger;
  65. BitfieldMan* bitfield;
  66. SegmentEntries usedSegmentEntries;
  67. PeerStats peerStats;
  68. void read(FILE* file);
  69. FILE* openSegFile(const string& segFilename, const string& mode) const;
  70. SegmentHandle onNullBitfield(int32_t cuid);
  71. SegmentHandle checkoutSegment(int32_t cuid, int32_t index);
  72. SegmentEntryHandle findSlowerSegmentEntry(const PeerStatHandle& peerStat) const;
  73. SegmentEntryHandle getSegmentEntryByIndex(int32_t index) {
  74. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  75. itr != usedSegmentEntries.end(); ++itr) {
  76. const SegmentEntryHandle& segmentEntry = *itr;
  77. if(segmentEntry->segment->index == index) {
  78. return segmentEntry;
  79. }
  80. }
  81. return 0;
  82. }
  83. SegmentEntryHandle getSegmentEntryByCuid(int32_t cuid) {
  84. for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
  85. itr != usedSegmentEntries.end(); ++itr) {
  86. const SegmentEntryHandle& segmentEntry = *itr;
  87. if(segmentEntry->cuid == cuid) {
  88. return segmentEntry;
  89. }
  90. }
  91. return 0;
  92. }
  93. SegmentEntries::iterator getSegmentEntryIteratorByCuid(int32_t cuid) {
  94. for(SegmentEntries::iterator itr = usedSegmentEntries.begin();
  95. itr != usedSegmentEntries.end(); ++itr) {
  96. const SegmentEntryHandle& segmentEntry = *itr;
  97. if(segmentEntry->cuid == cuid) {
  98. return itr;
  99. }
  100. }
  101. return usedSegmentEntries.end();
  102. }
  103. public:
  104. /**
  105. * The total number of bytes to download.
  106. * If Transfer-Encoding is Chunked or Content-Length header is not provided,
  107. * then this value is set to be 0.
  108. */
  109. int64_t totalSize;
  110. /**
  111. * Represents whether this download is splittable.
  112. * In Split download(or segmented download), http client establishes
  113. * more than one connections to the server, and downloads sevral parts of
  114. * a file at the same time. This boosts download speed.
  115. * This value is true by default. If total number of bytes is not known or
  116. * Chunked transfer encoding is used, then this value is set to be 0 by
  117. * DownloadCommand class.
  118. */
  119. bool isSplittable;
  120. /**
  121. * Represents whether the download is start or not.
  122. * The default value is false.
  123. */
  124. bool downloadStarted;
  125. /**
  126. * Respresents the file name of the downloaded file.
  127. * If the URL does not contain file name part(http://www.rednoah.com/, for
  128. * example), this value may be 0 length string.
  129. * The default value is 0 length string.
  130. */
  131. string filename;
  132. /**
  133. * directory to store a file
  134. */
  135. string dir;
  136. /**
  137. * User defined file name for downloaded content
  138. */
  139. string ufilename;
  140. /**
  141. * Represents the number of failures(usually, DlAbortEx) in downloads.
  142. */
  143. int32_t errors;
  144. const Option* option;
  145. DiskWriterHandle diskWriter;
  146. Requests reserved;
  147. #ifdef ENABLE_MESSAGE_DIGEST
  148. Strings pieceHashes;
  149. int32_t chunkHashLength;
  150. MessageDigestContext::DigestAlgo digestAlgo;
  151. #endif // ENABLE_MESSAGE_DIGEST
  152. SegmentMan();
  153. ~SegmentMan();
  154. // Initializes totalSize, isSplittable, downloadStarted, errors.
  155. // Clears command queue. Also, closes diskWriter.
  156. void init();
  157. /**
  158. * Returns dir+"/"+filename.
  159. * If filename is empty, then returns dir+"/"+"inex.html";
  160. */
  161. string getFilePath() const {
  162. return (dir == "" ? "." : dir)+"/"+
  163. (ufilename == "" ?
  164. (filename == "" ? "index.html" : filename) : ufilename);
  165. }
  166. string getSegmentFilePath() const {
  167. return getFilePath()+SEGMENT_FILE_EXTENSION;
  168. }
  169. /**
  170. * Returns true only if the segment data file exists.
  171. * The file name of the segment data is filename appended by ".aria2".
  172. * If isSplittable is false, then returns simply false without any operation.
  173. */
  174. bool segmentFileExists() const;
  175. /**
  176. * Loads the segment data file.
  177. * If isSplittable is false, then returns without any operation.
  178. */
  179. void load();
  180. /**
  181. * Saves the segment data file.
  182. * If isSplittable is false, then returns without any operation.
  183. */
  184. void save() const;
  185. /**
  186. * Removes the segment data file.
  187. * If isSplittable is false, then returns without any operation.
  188. */
  189. void remove() const;
  190. /**
  191. * Returs true when the download has finished.
  192. * If downloadStarted is false or the number of the segments of this object
  193. * holds is 0, then returns false.
  194. */
  195. bool finished() const;
  196. /**
  197. * if finished() is true, then call remove()
  198. */
  199. void removeIfFinished() const;
  200. /**
  201. * Returns a vacant segment.
  202. * If there is no vacant segment, then returns a segment instance whose
  203. * isNull call is true.
  204. */
  205. SegmentHandle getSegment(int32_t cuid);
  206. /**
  207. * Returns a segment whose index is index.
  208. * If it has already assigned
  209. * to another cuid or has been downloaded, then returns a segment instance
  210. * whose isNull call is true.
  211. */
  212. SegmentHandle getSegment(int32_t cuid, int32_t index);
  213. /**
  214. * Updates download status.
  215. */
  216. //bool updateSegment(int cuid, const Segment& segment);
  217. /**
  218. * Cancels all the segment which the command having given cuid
  219. * uses.
  220. */
  221. void cancelSegment(int32_t cuid);
  222. /**
  223. * Tells SegmentMan that the segment has been downloaded successfully.
  224. */
  225. bool completeSegment(int32_t cuid, const SegmentHandle& segment);
  226. /**
  227. * Initializes bitfield with the provided length parameters.
  228. */
  229. void initBitfield(int32_t segmentLength, int64_t totalLength);
  230. BitfieldMan* getBitfield() const
  231. {
  232. return bitfield;
  233. }
  234. /**
  235. * Returns true if the segment whose index is index has been downloaded.
  236. */
  237. bool hasSegment(int32_t index) const;
  238. /**
  239. * Returns the length of bytes downloaded.
  240. */
  241. int64_t getDownloadLength() const;
  242. /**
  243. * Registers given peerStat if it has not been registerd.
  244. * Otherwise does nothing.
  245. */
  246. void registerPeerStat(const PeerStatHandle& peerStat);
  247. /**
  248. * Returns peerStat whose cuid is given cuid. If it is not found, returns
  249. * 0.
  250. */
  251. PeerStatHandle getPeerStat(int32_t cuid) const {
  252. for(PeerStats::const_iterator itr = peerStats.begin(); itr != peerStats.end(); ++itr) {
  253. const PeerStatHandle& peerStat = *itr;
  254. if(peerStat->getCuid() == cuid) {
  255. return peerStat;
  256. }
  257. }
  258. return 0;
  259. }
  260. /**
  261. * Returns current download speed in bytes per sec.
  262. */
  263. int32_t calculateDownloadSpeed() const;
  264. bool fileExists() const;
  265. bool shouldCancelDownloadForSafety() const;
  266. void markAllPiecesDone();
  267. void markPieceDone(int64_t length);
  268. /**
  269. * This function must be called when none of segment entries is used.
  270. */
  271. void purgeSegmentEntry()
  272. {
  273. usedSegmentEntries.clear();
  274. }
  275. #ifdef ENABLE_MESSAGE_DIGEST
  276. void checkIntegrity();
  277. void tryChunkChecksumValidation(const SegmentHandle& segment);
  278. bool isChunkChecksumValidationReady() const;
  279. #endif // ENABLE_MESSAGE_DIGEST
  280. };
  281. typedef SharedHandle<SegmentMan> SegmentManHandle;
  282. #endif // _D_SEGMENT_MAN_H_