write SwitchToSnapShot
This commit is contained in:
@ -1,12 +1,19 @@
|
||||
#ifndef SNAP_SHOT_H
|
||||
#define SNAP_SHOT_H
|
||||
#include <spdlog/async.h>
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "list.hpp"
|
||||
#include "map.hpp"
|
||||
#include "storage/driver.h"
|
||||
#include "vector.hpp"
|
||||
void GenerateDiff(const std::string &old_file, const std::string &new_file, const std::string &diff_file);
|
||||
void ApplyPatch(const std::string &old_file, const std::string &diff_file, const std::string &new_file,
|
||||
bool is_reverse);
|
||||
void CopyFile(const std::string &src, const std::string &dst);
|
||||
/**
|
||||
* @brief SnapShotManager is a class to manage the snapshot of the data drivers.
|
||||
*/
|
||||
@ -22,6 +29,87 @@ class SnapShotManager {
|
||||
bool has_set_meta_file = false;
|
||||
sjtu::vector<DataDriverBase *> drivers;
|
||||
std::string meta_file;
|
||||
std::shared_ptr<spdlog::logger> logger_ptr;
|
||||
struct WayEntry {
|
||||
std::string snap_ID;
|
||||
std::string diff_ID;
|
||||
bool is_reverse;
|
||||
};
|
||||
friend void ApplyLongChange(const std::string &old_file, const std::string &new_file,
|
||||
const sjtu::vector<SnapShotManager::WayEntry> &way);
|
||||
inline sjtu::vector<WayEntry> FindWay(std::string dest) {
|
||||
if (!has_set_meta_file) {
|
||||
throw std::runtime_error("SnapShotManager has not set the meta file");
|
||||
}
|
||||
if (!has_connected) {
|
||||
throw std::runtime_error("SnapShotManager has not connected to the data drivers");
|
||||
}
|
||||
std::fstream fs(meta_file, std::ios::in);
|
||||
std::string HEAD;
|
||||
fs >> HEAD;
|
||||
std::string cur, anc;
|
||||
sjtu::map<std::string, sjtu::vector<std::string>> son_list;
|
||||
sjtu::map<std::string, std::string> get_anc;
|
||||
while (fs >> cur >> anc) {
|
||||
son_list[anc].push_back(cur);
|
||||
get_anc[cur] = anc;
|
||||
}
|
||||
if (son_list.find(dest) == son_list.end() && get_anc.find(dest) == get_anc.end()) {
|
||||
throw std::runtime_error("unable to find destination");
|
||||
}
|
||||
sjtu::vector<WayEntry> res;
|
||||
if (HEAD == dest) return res;
|
||||
sjtu::list<std::string> Q;
|
||||
sjtu::map<std::string, WayEntry> visit_record;
|
||||
Q.push_back(dest);
|
||||
while (!Q.empty()) {
|
||||
std::string cur = Q.front();
|
||||
Q.pop_front();
|
||||
if (get_anc.find(cur) != get_anc.end()) {
|
||||
std::string v = get_anc[cur];
|
||||
if (visit_record.find(v) == visit_record.end()) {
|
||||
visit_record[v] = {cur, cur, false};
|
||||
if (v == HEAD) goto ed;
|
||||
Q.push_back(v);
|
||||
}
|
||||
}
|
||||
if (son_list.find(cur) != son_list.end()) {
|
||||
auto &s_l = son_list[cur];
|
||||
for (size_t j = 0; j < s_l.size(); j++) {
|
||||
std::string v = s_l[j];
|
||||
if (visit_record.find(v) == visit_record.end()) {
|
||||
visit_record[v] = {cur, v, true};
|
||||
if (v == HEAD) goto ed;
|
||||
Q.push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ed:;
|
||||
std::string tmp = HEAD;
|
||||
while (tmp != dest) {
|
||||
res.push_back(visit_record[tmp]);
|
||||
tmp = visit_record[tmp].snap_ID;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
inline void ApplyLongChange(const std::string &old_file, const std::string &new_file,
|
||||
const sjtu::vector<SnapShotManager::WayEntry> &way, const std::string &file_name_base) {
|
||||
CopyFile(old_file, new_file);
|
||||
for (size_t i = 0; i < way.size(); i++) {
|
||||
if (logger_ptr) {
|
||||
logger_ptr->info("Applying diff {} to {} with inverse mark {}", file_name_base + "." + way[i].diff_ID + ".diff",
|
||||
new_file, way[i].is_reverse);
|
||||
}
|
||||
ApplyPatch(new_file, file_name_base + "." + way[i].diff_ID + ".diff", new_file + ".tmp", way[i].is_reverse);
|
||||
remove(new_file.c_str());
|
||||
rename((new_file + ".tmp").c_str(), new_file.c_str());
|
||||
if (logger_ptr) {
|
||||
logger_ptr->info("Applied diff {} to {} with inverse mark {}", file_name_base + "." + way[i].diff_ID + ".diff",
|
||||
new_file, way[i].is_reverse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// For safety and simplicity, we delete all the copy/move constructor and copy/move assignment operator. Please
|
||||
@ -42,6 +130,7 @@ class SnapShotManager {
|
||||
drivers = std::move(drivers_);
|
||||
has_connected = true;
|
||||
}
|
||||
inline void SetLogger(const std::shared_ptr<spdlog::logger> &logger_ptr_) { logger_ptr = logger_ptr_; }
|
||||
inline void SetMetaFile(const std::string &meta_file_) {
|
||||
if (has_set_meta_file) throw std::runtime_error("SnapShotManager has already set the meta file");
|
||||
has_set_meta_file = true;
|
||||
@ -59,6 +148,7 @@ class SnapShotManager {
|
||||
}
|
||||
void InitializeRepository();
|
||||
void CreateSnapShot(const std::string &snap_shot_ID);
|
||||
void CheckOutFrontier();
|
||||
void SwitchToSnapShot(const std::string &snap_shot_ID);
|
||||
void RemoveSnapShot(const std::string &snap_shot_ID);
|
||||
};
|
||||
|
Reference in New Issue
Block a user