aboutsummaryrefslogtreecommitdiff
path: root/zenserver/cache/structuredcache.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-05-11 13:05:39 +0200
committerStefan Boberg <[email protected]>2021-05-11 13:05:39 +0200
commitf8d9ac5d13dd37b8b57af0478e77ba1e75c813aa (patch)
tree1daf7621e110d48acd5e12e3073ce48ef0dd11b2 /zenserver/cache/structuredcache.cpp
downloadzen-f8d9ac5d13dd37b8b57af0478e77ba1e75c813aa.tar.xz
zen-f8d9ac5d13dd37b8b57af0478e77ba1e75c813aa.zip
Adding zenservice code
Diffstat (limited to 'zenserver/cache/structuredcache.cpp')
-rw-r--r--zenserver/cache/structuredcache.cpp129
1 files changed, 129 insertions, 0 deletions
diff --git a/zenserver/cache/structuredcache.cpp b/zenserver/cache/structuredcache.cpp
new file mode 100644
index 000000000..0d62f297c
--- /dev/null
+++ b/zenserver/cache/structuredcache.cpp
@@ -0,0 +1,129 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/fmtutils.h>
+#include <zencore/httpserver.h>
+
+#include "cachestore.h"
+#include "structuredcache.h"
+#include "upstream/jupiter.h"
+
+#include <spdlog/spdlog.h>
+#include <filesystem>
+
+namespace zen {
+
+HttpStructuredCacheService::HttpStructuredCacheService(std::filesystem::path RootPath, zen::CasStore& InStore)
+: m_CasStore(InStore)
+, m_CacheStore(InStore, RootPath)
+{
+ spdlog::info("initializing structured cache at '{}'", RootPath);
+}
+
+HttpStructuredCacheService::~HttpStructuredCacheService()
+{
+ spdlog::info("closing structured cache");
+}
+
+const char*
+HttpStructuredCacheService::BaseUri() const
+{
+ return "/z$/";
+}
+
+void
+HttpStructuredCacheService::HandleRequest(zen::HttpServerRequest& Request)
+{
+ CacheRef Ref;
+
+ if (!ValidateUri(Request, /* out */ Ref))
+ {
+ return Request.WriteResponse(zen::HttpResponse::BadRequest); // invalid URL
+ }
+
+ switch (auto Verb = Request.RequestVerb())
+ {
+ using enum zen::HttpVerb;
+
+ case kHead:
+ case kGet:
+ {
+ CacheValue Value;
+ bool Success = m_CacheStore.Get(Ref.BucketSegment, Ref.HashKey, /* out */ Value);
+
+ if (!Success)
+ {
+ Request.WriteResponse(zen::HttpResponse::NotFound);
+ }
+ else
+ {
+ if (Verb == kHead)
+ {
+ Request.SetSuppressResponseBody();
+ Request.WriteResponse(zen::HttpResponse::OK, zen::HttpContentType::kBinary, Value.Value);
+ }
+ else
+ {
+ Request.WriteResponse(zen::HttpResponse::OK, zen::HttpContentType::kBinary, Value.Value);
+ }
+ }
+ }
+ break;
+
+ case kPut:
+ {
+ if (zen::IoBuffer Body = Request.ReadPayload())
+ {
+ CacheValue Value;
+ Value.Value = Body;
+
+ m_CacheStore.Put(Ref.BucketSegment, Ref.HashKey, Value);
+
+ Request.WriteResponse(zen::HttpResponse::Created);
+ }
+ else
+ {
+ return;
+ }
+ }
+ break;
+
+ case kPost:
+ break;
+
+ default:
+ break;
+ }
+}
+
+[[nodiscard]] bool
+HttpStructuredCacheService::ValidateUri(zen::HttpServerRequest& Request, CacheRef& OutRef)
+{
+ std::string_view Key = Request.RelativeUri();
+ std::string_view::size_type BucketSplitOffset = Key.find_last_of('/');
+
+ if (BucketSplitOffset == std::string_view::npos)
+ {
+ return false;
+ }
+
+ OutRef.BucketSegment = Key.substr(0, BucketSplitOffset);
+ std::string_view HashSegment = Key.substr(BucketSplitOffset + 1);
+
+ if (HashSegment.size() != (2 * sizeof OutRef.HashKey.Hash))
+ {
+ return false;
+ }
+
+ bool IsOk = zen::ParseHexBytes(HashSegment.data(), HashSegment.size(), OutRef.HashKey.Hash);
+
+ if (!IsOk)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace zen