#include "PhashLoad.h" #include "PhashLoad.h" #include "PhashLoad.h" #include "PhashLoad.h" #include "PhashLoad.h" #include "../urbackupcommon/fileclient/FileClient.h" #include "../Interface/Server.h" #include "../Interface/File.h" #include "ClientMain.h" #include "server_settings.h" #include "database.h" #include "../common/data.h" extern std::string server_token; PhashLoad::PhashLoad(FileClient* fc, logid_t logid, std::string async_id) : has_error(false), fc(fc), logid(logid), async_id(async_id), phash_file_pos(0), phash_file(NULL), eof(false), has_timeout_error(false), orig_progress_log_callback(fc->getProgressLogCallback()) { } PhashLoad::~PhashLoad() { ScopedDeleteFile del_file(phash_file); } void PhashLoad::operator()() { fc->setProgressLogCallback(NULL); fc->setNoFreeSpaceCallback(NULL); std::string cfn = "SCRIPT|phash_{9c28ff72-5a74-487b-b5e1-8f1c96cd0cf4}/phash_" + async_id + "|0|0|" + server_token; std::unique_ptr phash_file_dl(Server->openTemporaryFile()); if (phash_file_dl.get() == NULL) { ServerLogger::Log(logid, "Error opening random file for parallel hash load. "+os_last_error_str(), LL_ERROR); has_error = true; return; } int mode = MODE_READ_SEQUENTIAL; #ifdef _WIN32 mode = MODE_READ_DEVICE; #endif phash_file = Server->openFile(phash_file_dl->getFilename(), mode); if(phash_file == NULL) { ScopedDeleteFn del_file(phash_file_dl->getFilename()); ServerLogger::Log(logid, "Error re-opening random file for parallel hash load. " + os_last_error_str(), LL_ERROR); has_error = true; return; } fc->setReconnectTries(5000); _u32 rc = fc->GetFile(cfn, phash_file_dl.get(), true, false, 0, true, 0); if (rc != ERR_SUCCESS) { ServerLogger::Log(logid, "Error during parallel hash load: "+fc->getErrorString(rc), LL_ERROR); has_error = true; if (rc == ERR_CONN_LOST || rc == ERR_TIMEOUT) { has_timeout_error = true; } return; } else { ServerLogger::Log(logid, "Parallel hash loading finished successfully", LL_INFO); fc->FinishScript(cfn); } eof = true; } bool PhashLoad::getHash(int64 file_id, std::string & hash) { while (true) { while (phash_file == NULL || phash_file_pos + static_cast(sizeof(_u16)) > phash_file->Size()) { if ((has_error || eof) && phash_file_pos + static_cast(sizeof(_u16)) > phash_file->Size()) { ServerLogger::Log(logid, "Getting parallel file hash record size of id " + convert(file_id) + " from " + phash_file->getFilename() + " failed. " + (eof ? "EOF." : "Had error."), LL_ERROR); return false; } Server->wait(1000); } _u16 msgsize; if (phash_file->Read(phash_file_pos, reinterpret_cast(&msgsize), sizeof(msgsize)) != sizeof(msgsize)) { ServerLogger::Log(logid, "Error reading record size (" + convert(sizeof(msgsize)) + " bytes) from parallel hash file " + phash_file->getFilename() + ". " + os_last_error_str(), LL_ERROR); return false; } msgsize = little_endian(msgsize); while (phash_file_pos + static_cast(sizeof(_u16)) + msgsize > phash_file->Size()) { if ((has_error || eof) && phash_file_pos + static_cast(sizeof(_u16)) + msgsize > phash_file->Size()) { ServerLogger::Log(logid, "Getting parallel file hash record data of id " + convert(file_id) + " from " + phash_file->getFilename() + " failed. " + (eof ? "EOF." : "Had error."), LL_ERROR); return false; } Server->wait(1000); } std::string msgdata = phash_file->Read(phash_file_pos + sizeof(_u16), msgsize); if (msgdata.size() != msgsize) { ServerLogger::Log(logid, "Error reading parallel hash file record (size "+convert(msgsize)+" read only "+convert(msgdata.size())+") " "from parallel hash file " + phash_file->getFilename() + ". " + os_last_error_str(), LL_ERROR); return false; } phash_file_pos += sizeof(_u16) + msgsize; CRData data(msgdata.data(), msgdata.size()); char id; if (!data.getChar(&id)) return false; if (id == 0) continue; if (id != 1) { ServerLogger::Log(logid, "Unknown parallel hash file record id", LL_ERROR); return false; } int64 curr_file_id; if (!data.getVarInt(&curr_file_id)) { ServerLogger::Log(logid, "Error reading parallel hash file id", LL_ERROR); return false; } if (!data.getStr2(&hash)) { ServerLogger::Log(logid, "Error reading parallel hash file hash", LL_ERROR); return false; } if (curr_file_id > file_id) { phash_file_pos -= sizeof(_u16) + msgsize; hash.clear(); ServerLogger::Log(logid, "Current parallel hash position greated than requested. "+convert(curr_file_id)+" > "+convert(file_id), LL_ERROR); return false; } else if (curr_file_id < file_id) { ServerLogger::Log(logid, "Skip phash for id " + convert(curr_file_id) + " " + base64_encode_dash(hash), LL_DEBUG); hash.clear(); continue; } ServerLogger::Log(logid, "Phash for id " + convert(file_id) + " is " + base64_encode_dash(hash), LL_DEBUG); return true; } } bool PhashLoad::hasError() { return has_error; } void PhashLoad::shutdown() { fc->Shutdown(); } bool PhashLoad::isDownloading() { return fc->isDownloading(); } void PhashLoad::setProgressLogEnabled(bool b) { if (b) { fc->setProgressLogCallback(orig_progress_log_callback); } else { fc->setProgressLogCallback(NULL); } }