/* */ #include "DefaultBtProgressInfoFile.h" #include "BtRegistry.h" #include "LogFactory.h" #include "prefs.h" #include "DlAbortEx.h" #include "message.h" #include "File.h" #include "Util.h" #include DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext, const Option* option): btContext(btContext), option(option), pieceStorage(PIECE_STORAGE(btContext)), btRuntime(BT_RUNTIME(btContext)), peerStorage(PEER_STORAGE(btContext)) { logger = LogFactory::getInstance(); string storeDir = option->get(PREF_DIR); filename = storeDir+"/"+btContext->getName()+".aria2"; } DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {} void DefaultBtProgressInfoFile::save() { logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str()); FILE* file = openFile(filename, "w"); try { if(fwrite(btContext->getInfoHash(), btContext->getInfoHashLength(), 1, file) < 1) { throw string("writeError:info hash"); } if(fwrite(pieceStorage->getBitfield(), pieceStorage->getBitfieldLength(), 1, file) < 1) { throw string("writeError:bitfield"); } TransferStat stat = peerStorage->calculateStat(); long long int allTimeDownloadLength = pieceStorage->getCompletedLength(); if(fwrite(&allTimeDownloadLength, sizeof(allTimeDownloadLength), 1, file) < 1) { throw string("writeError:download length"); } long long int allTimeUploadLength = btRuntime->getUploadLengthAtStartup()+ stat.getSessionUploadLength(); if(fwrite(&allTimeUploadLength, sizeof(allTimeUploadLength), 1, file) < 1) { throw string("writeError:upload length"); } fclose(file); logger->info(MSG_SAVED_SEGMENT_FILE); } catch(string ex) { fclose(file); throw new DlAbortEx(EX_SEGMENT_FILE_WRITE, filename.c_str(), strerror(errno)); } } void DefaultBtProgressInfoFile::load() { logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str()); FILE* file = openFile(filename, "r+"); unsigned char* savedInfoHash = 0; unsigned char* savedBitfield = 0; try { savedInfoHash = new unsigned char[btContext->getInfoHashLength()]; savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()]; if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) { throw string("readError"); } if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) != btContext->getInfoHashAsString()) { throw string("infoHashMismatch"); } if(fread(savedBitfield, pieceStorage->getBitfieldLength(), 1, file) < 1) { throw string("readError"); } pieceStorage->setBitfield(savedBitfield, pieceStorage->getBitfieldLength()); // allTimeDownloadLength exists for only a compatibility reason. long long int allTimeDownloadLength; if(fread(&allTimeDownloadLength, sizeof(allTimeDownloadLength), 1, file) < 1) { throw string("readError"); } long long int allTimeUploadLength; if(fread(&allTimeUploadLength, sizeof(allTimeUploadLength), 1, file) < 1) { throw string("readError"); } btRuntime->setUploadLengthAtStartup(allTimeUploadLength); delete [] savedBitfield; savedBitfield = 0; delete [] savedInfoHash; savedInfoHash = 0; fclose(file); } catch(string ex) { if(savedBitfield) { delete [] savedBitfield; } if(savedInfoHash) { delete [] savedInfoHash; } fclose(file); if(ex == "infoHashMismatch") { throw new DlAbortEx("The infoHash in torrent file doesn't match to one in .aria2 file."); } else { throw new DlAbortEx(EX_SEGMENT_FILE_READ, filename.c_str(), strerror(errno)); } } logger->info(MSG_LOADED_SEGMENT_FILE); } void DefaultBtProgressInfoFile::removeFile() { if(exists()) { File f(filename); f.remove(); } } FILE* DefaultBtProgressInfoFile::openFile(const string& filename, const string& mode) const { FILE* file = fopen(filename.c_str(), mode.c_str()); if(!file) { throw new DlAbortEx(EX_SEGMENT_FILE_OPEN, filename.c_str(), strerror(errno)); } return file; } bool DefaultBtProgressInfoFile::exists() { File f(filename); if(f.isFile()) { logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str()); return true; } else { logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, filename.c_str()); return false; } }