urbackup_backend/urbackupserver/ServerDownloadThread.h

232 lines
5.6 KiB
C++

#pragma once
#include <string>
#include <deque>
#include <algorithm>
#include <assert.h>
#include "../Interface/Mutex.h"
#include "../Interface/Condition.h"
#include "../Interface/Pipe.h"
#include "../Interface/File.h"
#include "../Interface/Thread.h"
#include "../urbackupcommon/fileclient/FileClient.h"
#include "../urbackupcommon/fileclient/FileClientChunked.h"
#include "ClientMain.h"
#include "../urbackupcommon/file_metadata.h"
class FileClient;
class FileClientChunked;
namespace
{
enum EFileClient
{
EFileClient_Full,
EFileClient_Chunked
};
enum EQueueAction
{
EQueueAction_Fileclient,
EQueueAction_Quit,
EQueueAction_StopShadowcopy,
EQueueAction_StartShadowcopy,
EQueueAction_Skip
};
struct SPatchDownloadFiles
{
bool prepared;
bool prepare_error;
IFile* orig_file;
IFile* patchfile;
IFile* chunkhashes;
bool delete_chunkhashes;
IFile* hashoutput;
std::wstring hashpath;
std::wstring filepath_old;
};
struct SQueueItem
{
SQueueItem()
: id(std::string::npos),
fileclient(EFileClient_Full),
queued(false),
action(EQueueAction_Fileclient),
is_script(false)
{
}
size_t id;
std::wstring fn;
std::wstring short_fn;
std::wstring curr_path;
std::wstring os_path;
_i64 predicted_filesize;
EFileClient fileclient;
bool queued;
EQueueAction action;
SPatchDownloadFiles patch_dl_files;
FileMetadata metadata;
bool is_script;
bool is_dir;
};
class IdRange
{
public:
IdRange()
: min_id(std::string::npos), max_id(0), finalized(false)
{}
void add(size_t id)
{
max_id = (std::max)(id, max_id);
min_id = (std::min)(id, min_id);
ids.push_back(id);
finalized=false;
}
void finalize()
{
std::sort(ids.begin(), ids.end());
finalized=true;
}
bool hasId(size_t id)
{
assert(finalized);
if(id>=min_id && id<=max_id)
{
return std::binary_search(ids.begin(), ids.end(), id);
}
else
{
return false;
}
}
private:
bool finalized;
std::vector<size_t> ids;
size_t min_id;
size_t max_id;
};
}
class ServerDownloadThread : public IThread, public FileClient::QueueCallback, public FileClientChunked::QueueCallback
{
public:
ServerDownloadThread(FileClient& fc, FileClientChunked* fc_chunked, const std::wstring& backuppath, const std::wstring& backuppath_hashes, const std::wstring& last_backuppath, const std::wstring& last_backuppath_complete, bool hashed_transfer, bool save_incomplete_file, int clientid,
const std::wstring& clientname,
bool use_tmpfiles, const std::wstring& tmpfile_path, const std::string& server_token, bool use_reflink, int backupid, bool r_incremental, IPipe* hashpipe_prepare, ClientMain* client_main,
int filesrv_protocol_version, int incremental_num, logid_t logid);
~ServerDownloadThread();
void operator()(void);
void addToQueueFull(size_t id, const std::wstring &fn, const std::wstring &short_fn, const std::wstring &curr_path, const std::wstring &os_path,
_i64 predicted_filesize, const FileMetadata& metadata, bool is_script, bool is_dir, bool at_front=false);
void addToQueueChunked(size_t id, const std::wstring &fn, const std::wstring &short_fn, const std::wstring &curr_path,
const std::wstring &os_path, _i64 predicted_filesize, const FileMetadata& metadata, bool is_script);
void addToQueueStartShadowcopy(const std::wstring& fn);
void addToQueueStopShadowcopy(const std::wstring& fn);
void queueStop(bool immediately);
void queueSkip();
bool load_file(SQueueItem todl);
bool load_file_patch(SQueueItem todl);
bool logScriptOutput(std::wstring cfn, const SQueueItem &todl);
bool isDownloadOk(size_t id);
bool isDownloadPartial(size_t id);
bool isAllDownloadsOk();
size_t getMaxOkId();
bool isOffline();
void hashFile(std::wstring dstpath, std::wstring hashpath, IFile *fd, IFile *hashoutput, std::string old_file, int64 t_filesize,
const FileMetadata& metadata, bool is_script);
virtual bool getQueuedFileChunked(std::string& remotefn, IFile*& orig_file, IFile*& patchfile, IFile*& chunkhashes, IFile*& hashoutput, _i64& predicted_filesize);
virtual void resetQueueFull();
virtual std::string getQueuedFileFull(FileClient::MetadataQueue& metadata);
virtual void unqueueFileFull(const std::string& fn);
virtual void unqueueFileChunked(const std::string& remotefn);
virtual void resetQueueChunked();
private:
void sleepQueue(IScopedLock& lock);
std::wstring getDLPath(SQueueItem todl);
SPatchDownloadFiles preparePatchDownloadFiles(SQueueItem todl, bool& full_dl);
void start_shadowcopy(const std::string &path);
void stop_shadowcopy(const std::string &path);
bool link_or_copy_file(SQueueItem todl);
FileClient& fc;
FileClientChunked* fc_chunked;
const std::wstring& backuppath;
const std::wstring& backuppath_hashes;
const std::wstring& last_backuppath;
const std::wstring& last_backuppath_complete;
bool hashed_transfer;
bool save_incomplete_file;
int clientid;
const std::wstring& clientname;
bool use_tmpfiles;
const std::wstring& tmpfile_path;
const std::string& server_token;
bool use_reflink;
int backupid;
bool r_incremental;
IPipe* hashpipe_prepare;
ClientMain* client_main;
int filesrv_protocol_version;
bool skipping;
int incremental_num;
bool is_offline;
std::deque<SQueueItem> dl_queue;
size_t queue_size;
bool all_downloads_ok;
IdRange download_nok_ids;
IdRange download_partial_ids;
size_t max_ok_id;
IMutex* mutex;
ICondition* cond;
logid_t logid;
};