DefaultBtProgressInfoFile.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 "DefaultBtProgressInfoFile.h"
  36. #include "BtRegistry.h"
  37. #include "LogFactory.h"
  38. #include "prefs.h"
  39. #include "DlAbortEx.h"
  40. #include "message.h"
  41. #include "File.h"
  42. #include "Util.h"
  43. #include "a2io.h"
  44. #include <errno.h>
  45. DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext,
  46. const Option* option):
  47. btContext(btContext),
  48. option(option),
  49. pieceStorage(PIECE_STORAGE(btContext)),
  50. btRuntime(BT_RUNTIME(btContext)),
  51. peerStorage(PEER_STORAGE(btContext))
  52. {
  53. logger = LogFactory::getInstance();
  54. string storeDir = option->get(PREF_DIR);
  55. filename = storeDir+"/"+btContext->getName()+".aria2";
  56. }
  57. DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
  58. void DefaultBtProgressInfoFile::save() {
  59. logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str());
  60. string filenameTemp = filename+"__temp";
  61. FILE* file = openFile(filenameTemp, "wb");
  62. try {
  63. if(fwrite(btContext->getInfoHash(),
  64. btContext->getInfoHashLength(), 1, file) < 1) {
  65. throw string("writeError:info hash");
  66. }
  67. if(fwrite(pieceStorage->getBitfield(),
  68. pieceStorage->getBitfieldLength(), 1, file) < 1) {
  69. throw string("writeError:bitfield");
  70. }
  71. TransferStat stat = peerStorage->calculateStat();
  72. int64_t allTimeDownloadLength = pieceStorage->getCompletedLength();
  73. if(fwrite(&allTimeDownloadLength,
  74. sizeof(allTimeDownloadLength), 1, file) < 1) {
  75. throw string("writeError:download length");
  76. }
  77. int64_t allTimeUploadLength =
  78. btRuntime->getUploadLengthAtStartup()+
  79. stat.getSessionUploadLength();
  80. if(fwrite(&allTimeUploadLength,
  81. sizeof(allTimeUploadLength), 1, file) < 1) {
  82. throw string("writeError:upload length");
  83. }
  84. fclose(file);
  85. logger->info(MSG_SAVED_SEGMENT_FILE);
  86. } catch(string ex) {
  87. fclose(file);
  88. throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
  89. filename.c_str(), strerror(errno));
  90. }
  91. if(rename(filenameTemp.c_str(), filename.c_str()) == -1) {
  92. throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
  93. filename.c_str(), strerror(errno));
  94. }
  95. }
  96. void DefaultBtProgressInfoFile::load() {
  97. logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str());
  98. FILE* file = openFile(filename, "r+b");
  99. unsigned char* savedInfoHash = 0;
  100. unsigned char* savedBitfield = 0;
  101. try {
  102. savedInfoHash = new unsigned char[btContext->getInfoHashLength()];
  103. savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()];
  104. if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) {
  105. throw string("readError");
  106. }
  107. if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) !=
  108. btContext->getInfoHashAsString()) {
  109. throw string("infoHashMismatch");
  110. }
  111. if(fread(savedBitfield, pieceStorage->getBitfieldLength(), 1, file) < 1) {
  112. throw string("readError");
  113. }
  114. pieceStorage->setBitfield(savedBitfield,
  115. pieceStorage->getBitfieldLength());
  116. // allTimeDownloadLength exists for only a compatibility reason.
  117. int64_t allTimeDownloadLength;
  118. if(fread(&allTimeDownloadLength,
  119. sizeof(allTimeDownloadLength), 1, file) < 1) {
  120. throw string("readError");
  121. }
  122. int64_t allTimeUploadLength;
  123. if(fread(&allTimeUploadLength,
  124. sizeof(allTimeUploadLength), 1, file) < 1) {
  125. throw string("readError");
  126. }
  127. btRuntime->setUploadLengthAtStartup(allTimeUploadLength);
  128. delete [] savedBitfield;
  129. savedBitfield = 0;
  130. delete [] savedInfoHash;
  131. savedInfoHash = 0;
  132. fclose(file);
  133. } catch(string ex) {
  134. if(savedBitfield) {
  135. delete [] savedBitfield;
  136. }
  137. if(savedInfoHash) {
  138. delete [] savedInfoHash;
  139. }
  140. fclose(file);
  141. if(ex == "infoHashMismatch") {
  142. throw new DlAbortEx(EX_INFOHASH_MISMATCH_IN_SEGFILE);
  143. } else {
  144. throw new DlAbortEx(EX_SEGMENT_FILE_READ,
  145. filename.c_str(), strerror(errno));
  146. }
  147. }
  148. logger->info(MSG_LOADED_SEGMENT_FILE);
  149. }
  150. void DefaultBtProgressInfoFile::removeFile() {
  151. if(exists()) {
  152. File f(filename);
  153. f.remove();
  154. }
  155. }
  156. FILE* DefaultBtProgressInfoFile::openFile(const string& filename,
  157. const string& mode) const
  158. {
  159. FILE* file = fopen(filename.c_str(), mode.c_str());
  160. if(!file) {
  161. throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
  162. filename.c_str(), strerror(errno));
  163. }
  164. return file;
  165. }
  166. bool DefaultBtProgressInfoFile::exists() {
  167. File f(filename);
  168. if(f.isFile()) {
  169. logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str());
  170. return true;
  171. } else {
  172. logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, filename.c_str());
  173. return false;
  174. }
  175. }