From c6d01458b4545500a964491c2602da3c3079bfc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Roman=20Smr=C5=BE?= <roman.smrz@seznam.cz>
Date: Tue, 9 Aug 2022 22:11:08 +0200
Subject: Stored roots lookup

---
 src/main.cpp    | 14 ++++++++++++++
 src/storage.cpp | 28 ++++++++++++++++++++++++++++
 src/storage.h   |  3 +++
 3 files changed, 45 insertions(+)

(limited to 'src')

diff --git a/src/main.cpp b/src/main.cpp
index a3facea..4dc4582 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -149,6 +149,19 @@ void storedGeneration(const vector<string> & args)
 	printLine(ss.str());
 }
 
+void storedRoots(const vector<string> & args)
+{
+	auto ref = st.ref(Digest(args.at(0)));
+	if (!ref)
+		throw invalid_argument("ref " + args.at(0) + " not found");
+
+	ostringstream ss;
+	ss << "stored-roots " << string(ref->digest());
+	for (const auto & dgst : ref->roots())
+		ss << " " << string(dgst);
+	printLine(ss.str());
+}
+
 void createIdentity(const vector<string> & args)
 {
 	optional<Identity> identity;
@@ -339,6 +352,7 @@ void attachReject(const vector<string> & params)
 vector<Command> commands = {
 	{ "store", store },
 	{ "stored-generation", storedGeneration },
+	{ "stored-roots", storedRoots },
 	{ "create-identity", createIdentity },
 	{ "start-server", startServer },
 	{ "stop-server", stopServer },
diff --git a/src/storage.cpp b/src/storage.cpp
index 5784309..c2d097e 100644
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -1029,6 +1029,34 @@ Generation Ref::generationLocked() const
 	return gen;
 }
 
+vector<Digest> Ref::roots() const
+{
+	scoped_lock lock(p->storage->p->rootsCacheLock);
+	return rootsLocked();
+}
+
+vector<Digest> Ref::rootsLocked() const
+{
+	auto it = p->storage->p->rootsCache.find(p->digest);
+	if (it != p->storage->p->rootsCache.end())
+		return it->second;
+
+	vector<Digest> roots;
+	auto prev = previous();
+
+	if (prev.empty()) {
+		roots.push_back(p->digest);
+	} else {
+		for (const auto & p : previous())
+			for (const auto & r : p.rootsLocked())
+				roots.push_back(r);
+
+		std::sort(roots.begin(), roots.end());
+		roots.erase(std::unique(roots.begin(), roots.end()), roots.end());
+	}
+	return roots;
+}
+
 
 template<class S>
 RecordT<S>::Item::operator bool() const
diff --git a/src/storage.h b/src/storage.h
index ef335b8..30e4213 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -167,6 +167,9 @@ struct PartialStorage::Priv
 
 	mutable mutex generationCacheLock {};
 	mutable unordered_map<Digest, Generation> generationCache {};
+
+	mutable mutex rootsCacheLock {};
+	mutable unordered_map<Digest, vector<Digest>> rootsCache {};
 };
 
 struct PartialRef::Priv
-- 
cgit v1.2.3