urbackup_backend/urbackupserver/FileBackup.h

310 lines
9.4 KiB
C++

#pragma once
#include "Backup.h"
#include "../Interface/Types.h"
#include "dao/ServerBackupDao.h"
#include <string>
#include "server_settings.h"
#include "../urbackupcommon/fileclient/FileClient.h"
#include "../urbackupcommon/fileclient/FileClientChunked.h"
#include <map>
#include "../urbackupcommon/file_metadata.h"
#include "server_log.h"
#include "FileMetadataDownloadThread.h"
#include <set>
class ClientMain;
class BackupServerHash;
class BackupServerPrepareHash;
class ServerPingThread;
class FileIndex;
class PhashLoad;
namespace
{
const unsigned int status_update_intervall=1000;
const unsigned int eta_update_intervall=60000;
const char* sync_fn = ".sync_f3a50226-f49a-4195-afef-c75b21781ae1";
}
struct SContinuousSequence
{
SContinuousSequence()
: id(-1), next(-1)
{
}
SContinuousSequence(int64 id, int64 next)
: id(id), next(next)
{
}
int64 id;
int64 next;
};
class FilePathCorrections
{
public:
FilePathCorrections()
: mutex(Server->createMutex()) {
}
void add(const std::string& path, const std::string& corr) {
IScopedLock lock(mutex.get());
filepath_corrections.insert(std::make_pair(path, corr));
}
bool get(const std::string& path, std::string& corr) {
IScopedLock lock(mutex.get());
std::map<std::string, std::string>::iterator it = filepath_corrections.find(path);
if (it != filepath_corrections.end())
{
corr = it->second;
return true;
}
return false;
}
private:
std::unique_ptr<IMutex> mutex;
std::map<std::string, std::string> filepath_corrections;
};
class MaxFileId
{
public:
MaxFileId()
: mutex(Server->createMutex()),
max_downloaded(std::string::npos), max_preprocessed(0),
min_downloaded(0)
{}
void setMinDownloaded(size_t id)
{
IScopedLock lock(mutex.get());
if (max_downloaded>id)
{
max_downloaded = id;
}
min_downloaded = id+1;
}
void setMaxDownloaded(size_t id)
{
IScopedLock lock(mutex.get());
for (size_t i = 0; i < postponed.size();)
{
if (postponed[i] == id)
{
postponed.erase(postponed.begin() + i);
}
else if (id > postponed[i])
{
id = postponed[i] - 1;
++i;
}
else
{
++i;
}
}
max_downloaded = id + 1;
if (max_downloaded >= min_downloaded)
{
max_downloaded = std::string::npos;
}
}
void setMaxPreProcessed(size_t id)
{
IScopedLock lock(mutex.get());
max_preprocessed = id + 1;
}
bool isFinished(size_t id)
{
IScopedLock lock(mutex.get());
if (id + 1 <= max_downloaded
&& id + 1 <= max_preprocessed)
{
return true;
}
return false;
}
std::string info()
{
IScopedLock lock(mutex.get());
std::string ret= "max_downloaded="+convert(max_downloaded)
+" max_preprocessed="+convert(max_preprocessed)
+" min_downloaded="+convert(min_downloaded)+" postponed.size="+convert(postponed.size());
if (!postponed.empty())
{
ret += " postponed:";
for (size_t i = 0; i < postponed.size(); ++i)
ret += " " + convert(postponed[i]);
}
return ret;
}
size_t get_max_preprocessed()
{
IScopedLock lock(mutex.get());
return max_preprocessed;
}
void postponeDownloaded(size_t id)
{
IScopedLock lock(mutex.get());
postponed.push_back(id);
}
private:
std::unique_ptr<IMutex> mutex;
size_t max_downloaded;
size_t max_preprocessed;
size_t min_downloaded;
std::vector<size_t> postponed;
};
class FileBackup : public Backup, public FileClient::ProgressLogCallback, public FileClient::NoFreeSpaceCallback,
public FileClientChunked::NoFreeSpaceCallback
{
public:
FileBackup(ClientMain* client_main, int clientid, std::string clientname, std::string subclientname, LogAction log_action,
bool is_incremental, int group, bool use_tmpfiles, std::string tmpfile_path, bool use_reflink, bool use_snapshots,
std::string server_token, std::string details, bool scheduled);
~FileBackup();
bool getResult();
bool hasEarlyError();
bool hasDiskError();
int getBackupid()
{
return backupid;
}
std::map<std::string, SContinuousSequence> getContinuousSequences()
{
return continuous_sequences;
}
static std::string convertToOSPathFromFileClient(std::string path);
static std::string fixFilenameForOS(std::string fn, std::set<std::string>& samedir_filenames, const std::string& curr_path, bool log_warnings, logid_t logid, FilePathCorrections& filepath_corrections);
virtual void log_progress(const std::string& fn, int64 total, int64 downloaded, int64 speed_bps);
virtual bool handle_not_enough_space(const std::string & path);
static bool create_hardlink(const std::string &linkname, const std::string &fname, bool use_ioref, bool* too_many_links, bool* copy);
protected:
virtual bool doBackup();
virtual bool doFileBackup() = 0;
ServerBackupDao::SDuration interpolateDurations(const std::vector<ServerBackupDao::SDuration>& durations);
bool request_filelist_construct(bool full, bool resume, int group,
bool with_token, bool& no_backup_dirs, bool& connect_fail, const std::string& clientsubname);
bool wait_for_async(const std::string& async_id, int64 timeout_time=10*60*1000);
bool request_client_write_tokens();
void logVssLogdata(int64 vss_duration_s);
bool getTokenFile(FileClient &fc, bool hashed_transfer, bool request);
std::string clientlistName(int ref_backupid);
void createHashThreads(bool use_reflink, bool ignore_hash_mismatches);
void destroyHashThreads();
_i64 getIncrementalSize(IFile *f, const std::vector<size_t> &diffs, bool& backup_with_components, bool all=false);
void calculateDownloadSpeed(int64 ctime, FileClient &fc, FileClientChunked* fc_chunked);
void calculateEtaFileBackup( int64 &last_eta_update, int64& eta_set_time, int64 ctime, FileClient &fc, FileClientChunked* fc_chunked,
int64 linked_bytes, int64 &last_eta_received_bytes, double &eta_estimated_speed, _i64 files_size );
bool hasChange(size_t line, const std::vector<size_t> &diffs);
bool link_file(const std::string &fn, const std::string &short_fn, const std::string &curr_path,
const std::string &os_path, const std::string& sha2, _i64 filesize, bool add_sql, FileMetadata& metadata);
void sendBackupOkay(bool b_okay);
void notifyClientBackupSuccessful(void);
void notifyClientBackupFailed();
void waitForFileThreads();
bool verify_file_backup(IFile *fileentries);
void save_debug_data(const std::string& rfn, const std::string& local_hash, const std::string& remote_hash);
std::string getSHA256(const std::string& fn);
std::string getSHA512(const std::string& fn);
std::string getSHADef(const std::string& fn);
bool constructBackupPath(bool on_snapshot, bool create_fs, std::string& errmsg);
bool constructBackupPathCdp();
std::string systemErrorInfo();
void saveUsersOnClient();
void createUserViews(IFile* file_list_f);
bool createUserView(IFile* file_list_f, const std::vector<int64>& ids, std::string accoutname, const std::vector<size_t>& identical_permission_roots);
std::vector<size_t> findIdenticalPermissionRoots(IFile* file_list_f, const std::vector<int64>& ids);
void deleteBackup();
bool createSymlink(const std::string& name, size_t depth, const std::string& symlink_target, const std::string& dir_sep, bool isdir);
bool startFileMetadataDownloadThread();
bool stopFileMetadataDownloadThread(bool stopped, size_t expected_embedded_metadata_files);
void parseSnapshotFailed(const std::string& logline);
std::string permissionsAllowAll();
bool loadWindowsBackupComponentConfigXml(FileClient &fc);
bool startPhashDownloadThread(const std::string& async_id);
bool stopPhashDownloadThread(const std::string& async_id);
bool checkRansomwareCanaries();
bool checkRansomwareCanariesInt(const std::string& last_backuppath, const std::string& ransomware_canary_paths);
bool checkRansomwareCanariesPath(const std::string& last_backuppath, const std::string& curr_path, const std::vector<std::string> path_components, size_t idx);
bool checkRansomwareCanaryFile(const std::string& last_backuppath, const std::string& curr_path, const std::string& fn_prefix);
int group;
bool use_tmpfiles;
std::string tmpfile_path;
bool use_reflink;
bool use_snapshots;
bool with_hashes;
bool cdp_path;
std::string backuppath;
std::string dir_pool_path;
std::string backuppath_hashes;
std::string backuppath_single;
IPipe *hashpipe;
IPipe *hashpipe_prepare;
std::vector<BackupServerHash*> bsh;
std::vector<THREADPOOL_TICKET> bsh_ticket;
std::vector<BackupServerPrepareHash*> bsh_prepare;
std::vector<THREADPOOL_TICKET> bsh_prepare_ticket;
std::unique_ptr<BackupServerHash> local_hash;
std::unique_ptr<BackupServerHash> local_hash2;
std::string filelist_async_id;
ServerPingThread* pingthread;
THREADPOOL_TICKET pingthread_ticket;
std::map<std::string, SContinuousSequence> continuous_sequences;
std::unique_ptr<FileIndex> fileindex;
bool disk_error;
int backupid;
std::unique_ptr<server::FileMetadataDownloadThread> metadata_download_thread;
THREADPOOL_TICKET metadata_download_thread_ticket;
std::unique_ptr<server::FileMetadataDownloadThread::FileMetadataApplyThread> metadata_apply_thread;
THREADPOOL_TICKET metadata_apply_thread_ticket;
FilePathCorrections filepath_corrections;
std::vector<std::string> shares_without_snapshot;
int64 last_speed_received_bytes;
int64 speed_set_time;
std::unique_ptr<PhashLoad> phash_load;
THREADPOOL_TICKET phash_load_ticket;
MaxFileId max_file_id;
};