finish writing snapshot
This commit is contained in:
@ -3,6 +3,7 @@
|
|||||||
#include <zstd.h>
|
#include <zstd.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <stdexcept>
|
||||||
#include "map.hpp"
|
#include "map.hpp"
|
||||||
#include "storage/config.h"
|
#include "storage/config.h"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
@ -438,4 +439,106 @@ void SnapShotManager::SwitchToSnapShot(const std::string &snap_shot_ID) {
|
|||||||
for (size_t i = 0; i < snapshot_relationship.size(); i++) {
|
for (size_t i = 0; i < snapshot_relationship.size(); i++) {
|
||||||
fs << snapshot_relationship[i].first << ' ' << snapshot_relationship[i].second << '\n';
|
fs << snapshot_relationship[i].first << ' ' << snapshot_relationship[i].second << '\n';
|
||||||
}
|
}
|
||||||
|
if (logger_ptr) {
|
||||||
|
logger_ptr->info("Successfully switched to snapshot {}", snap_shot_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnapShotManager::RemoveSnapShot(const std::string &snap_shot_ID) {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
if (snap_shot_ID == "INIT") {
|
||||||
|
throw std::runtime_error("Cannot remove INIT snapshot");
|
||||||
|
}
|
||||||
|
if (logger_ptr) {
|
||||||
|
logger_ptr->info("Try removing snapshot {}", snap_shot_ID);
|
||||||
|
}
|
||||||
|
std::fstream fs(meta_file, std::ios::in | std::ios::out);
|
||||||
|
std::string HEAD;
|
||||||
|
fs >> HEAD;
|
||||||
|
if (snap_shot_ID == HEAD) {
|
||||||
|
throw std::runtime_error("Cannot remove HEAD snapshot");
|
||||||
|
}
|
||||||
|
sjtu::vector<std::pair<std::string, std::string>> snapshot_relationship;
|
||||||
|
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) {
|
||||||
|
snapshot_relationship.push_back({cur, anc});
|
||||||
|
son_list[anc].push_back(cur);
|
||||||
|
get_anc[cur] = anc;
|
||||||
|
}
|
||||||
|
if (son_list.find(snap_shot_ID) == son_list.end() && get_anc.find(snap_shot_ID) == get_anc.end()) {
|
||||||
|
throw std::runtime_error("unable to find snapshot to remove");
|
||||||
|
}
|
||||||
|
fs.close();
|
||||||
|
if (son_list.find(snap_shot_ID) == son_list.end()) {
|
||||||
|
// simply remove it
|
||||||
|
if (logger_ptr) {
|
||||||
|
logger_ptr->info("Removing snapshot {}", snap_shot_ID);
|
||||||
|
logger_ptr->info("since it has no son, we can remove it directly");
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < drivers.size(); i++) {
|
||||||
|
drivers[i]->Flush();
|
||||||
|
sjtu::vector<DataDriverBase::FileEntry> files = drivers[i]->ListFiles();
|
||||||
|
for (size_t j = 0; j < files.size(); j++) {
|
||||||
|
remove((files[j].path + "." + snap_shot_ID + ".diff").c_str());
|
||||||
|
if (logger_ptr) {
|
||||||
|
logger_ptr->info("removed diff file {}", files[j].path + "." + snap_shot_ID + ".diff");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.open(meta_file, std::ios::in | std::ios::out);
|
||||||
|
fs << HEAD << '\n';
|
||||||
|
for (size_t i = 0; i < snapshot_relationship.size(); i++) {
|
||||||
|
if (snapshot_relationship[i].first != snap_shot_ID) {
|
||||||
|
fs << snapshot_relationship[i].first << ' ' << snapshot_relationship[i].second << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (get_anc.find(snap_shot_ID) == get_anc.end()) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"yor are trying to remove a snapshot that is isolated from the tree, maybe the snapshot repository is "
|
||||||
|
"currupted");
|
||||||
|
}
|
||||||
|
sjtu::vector<WayEntry> way = std::move(FindWay(snap_shot_ID));
|
||||||
|
if (logger_ptr) {
|
||||||
|
logger_ptr->info("Successfully found the way");
|
||||||
|
}
|
||||||
|
anc = get_anc[snap_shot_ID];
|
||||||
|
auto &sons = son_list[snap_shot_ID];
|
||||||
|
for (size_t i = 0; i < sons.size(); i++) {
|
||||||
|
std::string cur_song = sons[i];
|
||||||
|
for (size_t j = 0; j < drivers.size(); j++) {
|
||||||
|
drivers[j]->Flush();
|
||||||
|
sjtu::vector<DataDriverBase::FileEntry> files = drivers[j]->ListFiles();
|
||||||
|
for (size_t k = 0; k < files.size(); k++) {
|
||||||
|
std::string frontier_file = files[k].path + ".frontier";
|
||||||
|
ApplyLongChange(frontier_file, frontier_file + ".tmp", way, files[k].path);
|
||||||
|
ApplyPatch(frontier_file + ".tmp", files[k].path + "." + cur_song + ".diff", frontier_file + ".tmp." + cur_song,
|
||||||
|
false);
|
||||||
|
ApplyPatch(frontier_file + ".tmp", files[k].path + "." + snap_shot_ID + ".diff", frontier_file + ".tmp.anctmp",
|
||||||
|
true);
|
||||||
|
remove((files[k].path + "." + cur_song + ".diff").c_str());
|
||||||
|
GenerateDiff(frontier_file + ".tmp.anctmp", frontier_file + ".tmp." + cur_song,
|
||||||
|
files[k].path + "." + cur_song + ".diff");
|
||||||
|
remove((frontier_file + ".tmp").c_str());
|
||||||
|
remove((frontier_file + ".tmp." + cur_song).c_str());
|
||||||
|
remove((frontier_file + ".tmp.anctmp").c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fs.open(meta_file, std::ios::out);
|
||||||
|
fs << HEAD << '\n';
|
||||||
|
for (size_t i = 0; i < snapshot_relationship.size(); i++) {
|
||||||
|
if (snapshot_relationship[i].first == snap_shot_ID) continue;
|
||||||
|
if (snapshot_relationship[i].second == snap_shot_ID) continue;
|
||||||
|
fs << snapshot_relationship[i].first << ' ' << snapshot_relationship[i].second << '\n';
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < sons.size(); i++) fs << sons[i] << ' ' << anc << '\n';
|
||||||
}
|
}
|
@ -93,6 +93,7 @@ class DiskMap : public DataDriverBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void Flush() {
|
void Flush() {
|
||||||
|
if (indexer == nullptr) return;
|
||||||
indexer->Flush();
|
indexer->Flush();
|
||||||
data_storage->Flush();
|
data_storage->Flush();
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ TEST(Basic, T2) {
|
|||||||
snap_shot_manager.SetLogger(logger_ptr);
|
snap_shot_manager.SetLogger(logger_ptr);
|
||||||
snap_shot_manager.SetMetaFile("/tmp/T2/meta.dat");
|
snap_shot_manager.SetMetaFile("/tmp/T2/meta.dat");
|
||||||
for (int i = 0; i < 100; i += 10) EXPECT_EQ(disk_map.Get(i), i + 3);
|
for (int i = 0; i < 100; i += 10) EXPECT_EQ(disk_map.Get(i), i + 3);
|
||||||
snap_shot_manager.SwitchToSnapShot("INIT");
|
snap_shot_manager.SwitchToSnapShot("snap1");
|
||||||
snap_shot_manager.CheckOutFrontier();
|
snap_shot_manager.CheckOutFrontier();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -211,6 +211,7 @@ TEST(Basic, T2) {
|
|||||||
disk_map.Put(i, tmp);
|
disk_map.Put(i, tmp);
|
||||||
}
|
}
|
||||||
snap_shot_manager.CreateSnapShot("snap3");
|
snap_shot_manager.CreateSnapShot("snap3");
|
||||||
|
snap_shot_manager.RemoveSnapShot("snap1");
|
||||||
snap_shot_manager.SwitchToSnapShot("snap2");
|
snap_shot_manager.SwitchToSnapShot("snap2");
|
||||||
snap_shot_manager.CheckOutFrontier();
|
snap_shot_manager.CheckOutFrontier();
|
||||||
}
|
}
|
||||||
@ -237,5 +238,18 @@ TEST(Basic, T2) {
|
|||||||
for (int i = 0; i < 100; i += 10) EXPECT_EQ(disk_map.Get(i), i + 4);
|
for (int i = 0; i < 100; i += 10) EXPECT_EQ(disk_map.Get(i), i + 4);
|
||||||
snap_shot_manager.SwitchToSnapShot("INIT");
|
snap_shot_manager.SwitchToSnapShot("INIT");
|
||||||
snap_shot_manager.CheckOutFrontier();
|
snap_shot_manager.CheckOutFrontier();
|
||||||
|
snap_shot_manager.RemoveSnapShot("snap2");
|
||||||
|
snap_shot_manager.SwitchToSnapShot("snap3");
|
||||||
|
snap_shot_manager.CheckOutFrontier();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
DiskMap<int, int> disk_map("index", "/tmp/T2/index.db", "data", "/tmp/T2/data.db");
|
||||||
|
SnapShotManager snap_shot_manager;
|
||||||
|
sjtu::vector<DataDriverBase *> drivers;
|
||||||
|
drivers.push_back(&disk_map);
|
||||||
|
snap_shot_manager.Connect(drivers);
|
||||||
|
snap_shot_manager.SetLogger(logger_ptr);
|
||||||
|
snap_shot_manager.SetMetaFile("/tmp/T2/meta.dat");
|
||||||
|
for (int i = 0; i < 100; i += 10) EXPECT_EQ(disk_map.Get(i), i + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user