SegmentMan.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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 "SegmentMan.h"
  23. #include "DlAbortEx.h"
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <unistd.h>
  27. #include <errno.h>
  28. #include "Util.h"
  29. #include "File.h"
  30. #include "message.h"
  31. #include "prefs.h"
  32. SegmentMan::SegmentMan():totalSize(0),isSplittable(true),downloadStarted(false),dir(".") {}
  33. SegmentMan::~SegmentMan() {}
  34. void SegmentMan::unregisterId(int cuid) {
  35. for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
  36. if((*itr).cuid == cuid) {
  37. cuid = 0;
  38. }
  39. }
  40. }
  41. bool SegmentMan::getSegment(Segment& seg, int cuid) {
  42. //Segment s = { 0, 0, 0, false };
  43. if(segments.empty()) {
  44. logger->debug("assign new segment { sp = 0, ep = "+(totalSize == 0 ? "0" : Util::llitos(totalSize-1))+" } to cuid "+Util::llitos(cuid));
  45. //seg = { cuid, 0, totalSize == 0 ? 0 : totalSize-1, 0, false };
  46. seg.cuid = cuid;
  47. seg.sp = 0;
  48. seg.ep = totalSize == 0 ? 0 : totalSize-1;
  49. seg.ds = 0;
  50. seg.speed = 0;
  51. seg.finish = false;
  52. segments.push_back(seg);
  53. return true;
  54. }
  55. for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
  56. if((*itr).cuid == cuid && !(*itr).finish) {
  57. // logger->debug("return an existing segment { "
  58. // "sp = "+Util::ulitos((*itr).sp)+", "+
  59. // "ep = "+Util::ulitos((*itr).ep)+", "
  60. // "ds = "+Util::ulitos((*itr).ds)+" } to "+
  61. // "cuid "+Util::ulitos((*itr).cuid));
  62. seg = *itr;
  63. return true;
  64. }
  65. }
  66. if(!isSplittable) {
  67. return false;
  68. }
  69. for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
  70. Segment& s = *itr;
  71. if(s.finish) {
  72. continue;
  73. }
  74. if(s.cuid == 0) {
  75. s.cuid = cuid;
  76. seg = s;
  77. return true;
  78. }
  79. }
  80. return splitter->splitSegment(seg, cuid, segments);
  81. }
  82. void SegmentMan::updateSegment(const Segment& segment) {
  83. for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
  84. if((*itr).cuid == segment.cuid &&
  85. (*itr).sp == segment.sp &&
  86. (*itr).ep == segment.ep) {
  87. *itr = segment;
  88. break;
  89. }
  90. }
  91. }
  92. bool SegmentMan::segmentFileExists() const {
  93. if(!isSplittable) {
  94. return false;
  95. }
  96. string segFilename = getSegmentFilePath();
  97. File f(segFilename);
  98. if(f.isFile()) {
  99. logger->info(MSG_SEGMENT_FILE_EXISTS, segFilename.c_str());
  100. return true;
  101. } else {
  102. logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, segFilename.c_str());
  103. return false;
  104. }
  105. }
  106. void SegmentMan::load() {
  107. if(!isSplittable) {
  108. return;
  109. }
  110. string segFilename = getSegmentFilePath();
  111. logger->info(MSG_LOADING_SEGMENT_FILE, segFilename.c_str());
  112. FILE* segFile = openSegFile(segFilename, "r+");
  113. read(segFile);
  114. fclose(segFile);
  115. logger->info(MSG_LOADED_SEGMENT_FILE);
  116. for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end();
  117. itr++) {
  118. (*itr).cuid = 0;
  119. }
  120. }
  121. void SegmentMan::save() const {
  122. if(!isSplittable || totalSize == 0) {
  123. return;
  124. }
  125. string segFilename = getSegmentFilePath();
  126. logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
  127. FILE* segFile = openSegFile(segFilename, "w");
  128. if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
  129. throw new DlAbortEx(strerror(errno));
  130. }
  131. for(vector<Segment>::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
  132. if(fwrite(&*itr, sizeof(Segment), 1, segFile) < 1) {
  133. throw new DlAbortEx(strerror(errno));
  134. }
  135. }
  136. fclose(segFile);
  137. logger->info(MSG_SAVED_SEGMENT_FILE);
  138. }
  139. FILE* SegmentMan::openSegFile(string segFilename, string mode) const {
  140. FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
  141. if(segFile == NULL) {
  142. throw new DlAbortEx(strerror(errno));
  143. }
  144. return segFile;
  145. }
  146. void SegmentMan::read(FILE* file) {
  147. assert(file != NULL);
  148. if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
  149. throw new DlAbortEx(strerror(errno));
  150. }
  151. while(1) {
  152. Segment seg;
  153. if(fread(&seg, sizeof(Segment), 1, file) < 1) {
  154. if(ferror(file)) {
  155. throw new DlAbortEx(strerror(errno));
  156. } else if(feof(file)) {
  157. break;
  158. }
  159. }
  160. segments.push_back(seg);
  161. }
  162. }
  163. void SegmentMan::remove() const {
  164. if(!isSplittable) {
  165. return;
  166. }
  167. if(segmentFileExists()) {
  168. File f(getSegmentFilePath());
  169. f.remove();
  170. }
  171. }
  172. bool SegmentMan::finished() const {
  173. if(!downloadStarted || segments.size() == 0) {
  174. return false;
  175. }
  176. for(vector<Segment>::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
  177. if(!(*itr).finish) {
  178. return false;
  179. }
  180. }
  181. return true;
  182. }
  183. void SegmentMan::removeIfFinished() const {
  184. if(finished()) {
  185. remove();
  186. }
  187. }
  188. long long int SegmentMan::getDownloadedSize() const {
  189. long long int size = 0;
  190. for(vector<Segment>::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
  191. size += (*itr).ds;
  192. }
  193. return size;
  194. }