aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Larsson <[email protected]>2021-11-29 12:55:08 +0100
committerPer Larsson <[email protected]>2021-11-29 12:55:08 +0100
commit9a8e2c8d905bc1e5b62c6f5e246d2574a645b73e (patch)
treefb6cd0492812dd8ea99ba3dde27cc2b49dd978dc
parentMerged main. (diff)
downloadzen-9a8e2c8d905bc1e5b62c6f5e246d2574a645b73e.tar.xz
zen-9a8e2c8d905bc1e5b62c6f5e246d2574a645b73e.zip
Moved GC to background thread and added endpoint to trigger/status GC.
-rw-r--r--xmake.lua3
-rw-r--r--zenserver/admin/admin.cpp43
-rw-r--r--zenserver/admin/admin.h10
-rw-r--r--zenserver/xmake.lua3
-rw-r--r--zenserver/zenserver.cpp35
-rw-r--r--zenstore/gc.cpp28
-rw-r--r--zenstore/include/zenstore/gc.h22
7 files changed, 124 insertions, 20 deletions
diff --git a/xmake.lua b/xmake.lua
index 49989615c..1da00b8df 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -17,7 +17,8 @@ add_requires(
"vcpkg::curl",
"vcpkg::zlib",
"vcpkg::zstd",
- "vcpkg::http-parser")
+ "vcpkg::http-parser",
+ "vcpkg::rocksdb")
add_rules("mode.debug", "mode.release")
diff --git a/zenserver/admin/admin.cpp b/zenserver/admin/admin.cpp
index 2dd9b110f..0d7a57e36 100644
--- a/zenserver/admin/admin.cpp
+++ b/zenserver/admin/admin.cpp
@@ -5,11 +5,14 @@
#include "admin.h"
#include <zencore/compactbinarybuilder.h>
+#include <zencore/string.h>
namespace zen {
HttpAdminService::HttpAdminService()
{
+ using namespace std::literals;
+
m_Router.RegisterRoute(
"health",
[this](HttpRouterRequest& Req) {
@@ -19,12 +22,50 @@ HttpAdminService::HttpAdminService()
},
HttpVerb::kGet);
+ m_Router.RegisterRoute(
+ "gc",
+ [this](HttpRouterRequest& Req) {
+ CbObject Response;
+ if (m_GcHandler.Status)
+ {
+ Response = m_GcHandler.Status();
+ }
+ else
+ {
+ CbObjectWriter Writer;
+ Writer << "Status"sv
+ << "Ok"sv;
+ Response = Writer.Save();
+ }
+ Req.ServerRequest().WriteResponse(HttpResponseCode::OK, Response);
+ },
+ HttpVerb::kGet);
+
+ m_Router.RegisterRoute(
+ "gc",
+ [this](HttpRouterRequest& Req) {
+ CbObject Response;
+ if (m_GcHandler.Trigger)
+ {
+ Response = m_GcHandler.Trigger();
+ }
+ else
+ {
+ CbObjectWriter Writer;
+ Writer << "Status"sv
+ << "Ok"sv;
+ Response = Writer.Save();
+ }
+ Req.ServerRequest().WriteResponse(HttpResponseCode::OK, Response);
+ },
+ HttpVerb::kPost);
+
// RPC endpoint
m_Router.RegisterRoute(
"",
[this](HttpRouterRequest& Req) {
CbObject Payload = Req.ServerRequest().ReadPayloadObject();
-
+
CbObjectWriter Obj;
Obj.AddBool("ok", true);
Req.ServerRequest().WriteResponse(HttpResponseCode::OK, Obj.Save());
diff --git a/zenserver/admin/admin.h b/zenserver/admin/admin.h
index 6257f0998..f8fcab7de 100644
--- a/zenserver/admin/admin.h
+++ b/zenserver/admin/admin.h
@@ -2,6 +2,7 @@
#pragma once
+#include <zencore/compactbinary.h>
#include <zenhttp/httpserver.h>
namespace zen {
@@ -15,8 +16,17 @@ public:
virtual const char* BaseUri() const override;
virtual void HandleRequest(zen::HttpServerRequest& Request) override;
+ struct GcHandler
+ {
+ std::function<CbObject()> Trigger;
+ std::function<CbObject()> Status;
+ };
+
+ void RegisterGcHandler(GcHandler&& Handler) { m_GcHandler = std::forward<GcHandler>(Handler); }
+
private:
HttpRequestRouter m_Router;
+ GcHandler m_GcHandler;
};
} // namespace zen
diff --git a/zenserver/xmake.lua b/zenserver/xmake.lua
index bba9b6ba5..600c8d053 100644
--- a/zenserver/xmake.lua
+++ b/zenserver/xmake.lua
@@ -26,7 +26,8 @@ target("zenserver")
"vcpkg::lua",
"vcpkg::asio",
"vcpkg::json11",
- "vcpkg::http-parser"
+ "vcpkg::http-parser",
+ "vcpkg::rocksdb"
)
add_packages(
diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp
index e9c41d070..b1bcb545f 100644
--- a/zenserver/zenserver.cpp
+++ b/zenserver/zenserver.cpp
@@ -195,6 +195,21 @@ public:
.HttpServerClass = std::string(ServerOptions.HttpServerClass),
.BuildVersion = std::string(BUILD_VERSION)});
+ m_AdminService.RegisterGcHandler({.Trigger =
+ [this]() {
+ CbObjectWriter Writer;
+ const bool Started = m_Gc.Trigger();
+ Writer << "Status"sv << (Started ? "Started"sv : "Running"sv);
+ return Writer.Save();
+ },
+ .Status =
+ [this]() {
+ CbObjectWriter Writer;
+ const GcStatus Status = m_Gc.Status();
+ Writer << "Status"sv << (GcStatus::kIdle == Status ? "Idle"sv : "Running"sv);
+ return Writer.Save();
+ }});
+
// Ok so now we're configured, let's kick things off
m_Http = zen::CreateHttpServer(ServerOptions.HttpServerClass);
@@ -214,11 +229,11 @@ public:
m_CasStore->Initialize(Config);
m_CidStore = std::make_unique<zen::CidStore>(*m_CasStore, m_DataRoot / "cid");
- m_Gc.SetCidStore(m_CidStore.get());
+ m_Gc.Cas().SetCidStore(m_CidStore.get());
ZEN_INFO("instantiating project service");
- m_ProjectStore = new zen::ProjectStore(*m_CidStore, m_DataRoot / "projects", m_Gc);
+ m_ProjectStore = new zen::ProjectStore(*m_CidStore, m_DataRoot / "projects", m_Gc.Cas());
m_HttpProjectService.reset(new zen::HttpProjectService{*m_CidStore, m_ProjectStore});
#if ZEN_USE_NAMED_PIPES
@@ -440,16 +455,6 @@ public:
NiceByteRate(Ctx.ScrubbedBytes(), ElapsedTimeMs));
}
- void CollectGarbage()
- {
- Stopwatch Timer;
- ZEN_INFO("Garbage collection STARTING");
-
- m_Gc.CollectGarbage();
-
- ZEN_INFO("Garbage collection DONE after {}", NiceTimeSpanMs(Timer.GetElapsedTimeMs()));
- }
-
void Flush()
{
if (m_CasStore)
@@ -513,8 +518,8 @@ private:
zen::Ref<zen::HttpServer> m_Http;
zen::HttpStatusService m_StatusService;
zen::HttpStatsService m_StatsService;
- zen::CasGc m_Gc;
- std::unique_ptr<zen::CasStore> m_CasStore{zen::CreateCasStore(m_Gc)};
+ zen::Gc m_Gc;
+ std::unique_ptr<zen::CasStore> m_CasStore{zen::CreateCasStore(m_Gc.Cas())};
std::unique_ptr<zen::CidStore> m_CidStore;
std::unique_ptr<zen::ZenCacheStore> m_CacheStore;
zen::CasScrubber m_Scrubber{*m_CasStore};
@@ -656,7 +661,7 @@ ZenServer::InitializeStructuredCache(const ZenServerOptions& ServerOptions)
auto ValueOrDefault = [](std::string_view Value, std::string_view Default) { return Value.empty() ? Default : Value; };
ZEN_INFO("instantiating structured cache service");
- m_CacheStore = std::make_unique<ZenCacheStore>(m_Gc, m_DataRoot / "cache");
+ m_CacheStore = std::make_unique<ZenCacheStore>(m_Gc.Cas(), m_DataRoot / "cache");
std::unique_ptr<zen::UpstreamCache> UpstreamCache;
if (ServerOptions.UpstreamCacheConfig.CachePolicy != UpstreamCachePolicy::Disabled)
diff --git a/zenstore/gc.cpp b/zenstore/gc.cpp
index 278f09b0b..52bb33955 100644
--- a/zenstore/gc.cpp
+++ b/zenstore/gc.cpp
@@ -2,9 +2,11 @@
#include <zenstore/gc.h>
+#include <zencore/logging.h>
+#include <zencore/string.h>
+#include <zencore/timer.h>
#include <zenstore/CAS.h>
#include <zenstore/cidstore.h>
-#include <zencore/logging.h>
namespace zen {
@@ -202,4 +204,28 @@ CasGc::OnDroppedCidReferences(std::span<IoHash> Hashes)
ZEN_UNUSED(Hashes);
}
+bool
+Gc::Trigger()
+{
+ uint32_t Expected = uint32_t(GcStatus::kIdle);
+ if (!m_Status.compare_exchange_strong(Expected, static_cast<uint32_t>(GcStatus::kRunning)))
+ {
+ return false;
+ }
+
+ ZEN_ASSERT(GcStatus::kRunning == Status());
+
+ m_GcThread = std::jthread([this]() {
+ Stopwatch Timer;
+ ZEN_INFO("garbage collection STARTING");
+
+ m_CasGc.CollectGarbage();
+ m_Status = static_cast<uint32_t>(GcStatus::kIdle);
+
+ ZEN_INFO("garbage collection DONE after {}", NiceTimeSpanMs(Timer.GetElapsedTimeMs()));
+ });
+
+ return true;
+}
+
} // namespace zen
diff --git a/zenstore/include/zenstore/gc.h b/zenstore/include/zenstore/gc.h
index 560642803..8efe933a0 100644
--- a/zenstore/include/zenstore/gc.h
+++ b/zenstore/include/zenstore/gc.h
@@ -5,8 +5,9 @@
#include <zencore/iohash.h>
#include <zencore/thread.h>
-#include <span>
+#include <atomic>
#include <functional>
+#include <span>
#define ZEN_USE_REF_TRACKING 0 // This is not currently functional
@@ -107,4 +108,23 @@ private:
CidStore* m_CidStore;
};
+enum class GcStatus : uint32_t
+{
+ kIdle,
+ kRunning
+};
+
+class Gc
+{
+public:
+ bool Trigger();
+ CasGc& Cas() { return m_CasGc; }
+ GcStatus Status() const { return static_cast<GcStatus>(m_Status.load()); }
+
+private:
+ CasGc m_CasGc;
+ std::jthread m_GcThread;
+ std::atomic_uint32_t m_Status;
+};
+
} // namespace zen