SegmentMan.cc 6.1 KB

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