From bda26eb2ce25eea8c3dc94263982567697f90113 Mon Sep 17 00:00:00 2001 From: happyZYM Date: Sun, 5 May 2024 14:35:35 +0000 Subject: [PATCH] finish writing snapshot --- dataguard/src/snapshot.cpp | 103 +++++++++++++++++++++++++++ storage/include/storage/disk_map.hpp | 1 + test/snapshot_test.cpp | 16 ++++- 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/dataguard/src/snapshot.cpp b/dataguard/src/snapshot.cpp index 465173b..54c3304 100644 --- a/dataguard/src/snapshot.cpp +++ b/dataguard/src/snapshot.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "map.hpp" #include "storage/config.h" #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++) { 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> snapshot_relationship; + std::string cur, anc; + sjtu::map> son_list; + sjtu::map 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 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 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 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'; } \ No newline at end of file diff --git a/storage/include/storage/disk_map.hpp b/storage/include/storage/disk_map.hpp index 8b2b3d2..69af901 100644 --- a/storage/include/storage/disk_map.hpp +++ b/storage/include/storage/disk_map.hpp @@ -93,6 +93,7 @@ class DiskMap : public DataDriverBase { return true; } void Flush() { + if (indexer == nullptr) return; indexer->Flush(); data_storage->Flush(); } diff --git a/test/snapshot_test.cpp b/test/snapshot_test.cpp index ed05b4e..cc062ad 100644 --- a/test/snapshot_test.cpp +++ b/test/snapshot_test.cpp @@ -195,7 +195,7 @@ TEST(Basic, T2) { 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 + 3); - snap_shot_manager.SwitchToSnapShot("INIT"); + snap_shot_manager.SwitchToSnapShot("snap1"); snap_shot_manager.CheckOutFrontier(); } { @@ -211,6 +211,7 @@ TEST(Basic, T2) { disk_map.Put(i, tmp); } snap_shot_manager.CreateSnapShot("snap3"); + snap_shot_manager.RemoveSnapShot("snap1"); snap_shot_manager.SwitchToSnapShot("snap2"); 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); snap_shot_manager.SwitchToSnapShot("INIT"); snap_shot_manager.CheckOutFrontier(); + snap_shot_manager.RemoveSnapShot("snap2"); + snap_shot_manager.SwitchToSnapShot("snap3"); + snap_shot_manager.CheckOutFrontier(); + } + { + DiskMap disk_map("index", "/tmp/T2/index.db", "data", "/tmp/T2/data.db"); + SnapShotManager snap_shot_manager; + sjtu::vector 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); } } \ No newline at end of file