SegmentMan.h 9.0 KB

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