aboutsummaryrefslogtreecommitdiff
path: root/zenserver/projectstore.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2022-06-10 15:06:10 +0200
committerStefan Boberg <[email protected]>2022-06-10 15:06:10 +0200
commit8a6c127c3206d59cb73be1caa7d93a1fe4303e6e (patch)
tree32d7e025f00c93467cf0b3948c0d9f90cae77ee1 /zenserver/projectstore.cpp
parentgc: improved message indicating no GC is scheduled (diff)
downloadzen-8a6c127c3206d59cb73be1caa7d93a1fe4303e6e.tar.xz
zen-8a6c127c3206d59cb73be1caa7d93a1fe4303e6e.zip
fixed issue where projects would not be discovered via DiscoverProjects due to use of stem() vs filename()
added /prj/{project}/oplog/{log}/{op} endpoint to allow retrieval of an op entry by LSN. Supports returning CbObject or CbPackage format payloads
Diffstat (limited to 'zenserver/projectstore.cpp')
-rw-r--r--zenserver/projectstore.cpp110
1 files changed, 100 insertions, 10 deletions
diff --git a/zenserver/projectstore.cpp b/zenserver/projectstore.cpp
index d18ae9e1a..7a55911da 100644
--- a/zenserver/projectstore.cpp
+++ b/zenserver/projectstore.cpp
@@ -450,7 +450,7 @@ ProjectStore::Oplog::IterateOplog(std::function<void(CbObject)>&& Handler)
}
std::optional<CbObject>
-ProjectStore::Oplog::GetOplog(const Oid& Key)
+ProjectStore::Oplog::GetOpByKey(const Oid& Key)
{
RwLock::SharedLockScope _(m_OplogLock);
@@ -465,6 +465,19 @@ ProjectStore::Oplog::GetOplog(const Oid& Key)
return {};
}
+std::optional<CbObject>
+ProjectStore::Oplog::GetOpByIndex(int Index)
+{
+ RwLock::SharedLockScope _(m_OplogLock);
+
+ if (const auto AddressEntryIt = m_OpAddressMap.find(Index); AddressEntryIt != m_OpAddressMap.end())
+ {
+ return m_Storage->GetOp(AddressEntryIt->second);
+ }
+
+ return {};
+}
+
bool
ProjectStore::Oplog::AddFileMapping(Oid FileId, IoHash Hash, std::string_view ServerPath, std::string_view ClientPath)
{
@@ -809,7 +822,7 @@ ProjectStore::Project::DiscoverOplogs()
for (const std::filesystem::path& DirPath : DirContent.Directories)
{
- OpenOplog(PathToUtf8(DirPath.stem()));
+ OpenOplog(PathToUtf8(DirPath.filename()));
}
}
@@ -893,7 +906,7 @@ ProjectStore::DiscoverProjects()
for (const std::filesystem::path& DirPath : DirContent.Directories)
{
- std::string DirName = PathToUtf8(DirPath.stem());
+ std::string DirName = PathToUtf8(DirPath.filename());
Project* Project = OpenProject(DirName);
if (Project)
@@ -917,8 +930,6 @@ ProjectStore::IterateProjects(std::function<void(Project& Prj)>&& Fn)
void
ProjectStore::Flush()
{
- // TODO
-
RwLock::SharedLockScope _(m_ProjectsLock);
for (auto& Kv : m_Projects)
@@ -1057,6 +1068,8 @@ HttpProjectService::HttpProjectService(CidStore& Store, ProjectStore* Projects)
m_Router.AddPattern("chunk", "([[:xdigit:]]{24})");
m_Router.AddPattern("hash", "([[:xdigit:]]{40})");
+ // This would ideally just be the response for the root /prj endpoint but this is
+ // currently not possible for (arbitrary, external) technical reasons
m_Router.RegisterRoute(
"list",
[this](HttpRouterRequest& Req) {
@@ -1064,6 +1077,7 @@ HttpProjectService::HttpProjectService(CidStore& Store, ProjectStore* Projects)
CbWriter Response;
Response.BeginArray();
+
m_ProjectStore->IterateProjects([&Response](ProjectStore::Project& Prj) {
Response.BeginObject();
Response << "Id"sv << Prj.Identifier;
@@ -1265,7 +1279,7 @@ HttpProjectService::HttpProjectService(CidStore& Store, ProjectStore* Projects)
ProjectStore::Oplog& Log = *FoundLog;
- Oid Obj = Oid::FromHexString(ChunkId);
+ const Oid Obj = Oid::FromHexString(ChunkId);
IoBuffer Chunk = Log.FindChunk(Obj);
if (!Chunk)
@@ -1606,12 +1620,88 @@ HttpProjectService::HttpProjectService(CidStore& Store, ProjectStore* Projects)
m_Router.RegisterRoute(
"{project}/oplog/{log}/{op}",
- [](HttpRouterRequest& Req) {
+ [this](HttpRouterRequest& Req) {
HttpServerRequest& HttpReq = Req.ServerRequest();
- // TODO: look up op and respond with the payload!
+ const std::string& ProjectId = Req.GetCapture(1);
+ const std::string& OplogId = Req.GetCapture(2);
+ const std::string& OpIdString = Req.GetCapture(3);
+
+ ProjectStore::Oplog* FoundLog = m_ProjectStore->OpenProjectOplog(ProjectId, OplogId);
+
+ if (FoundLog == nullptr)
+ {
+ return HttpReq.WriteResponse(HttpResponseCode::NotFound);
+ }
+
+ ProjectStore::Oplog& Oplog = *FoundLog;
+
+ if (const std::optional<int32_t> OpId = zen::ParseInt<uint32_t>(OpIdString))
+ {
+ if (std::optional<CbObject> MaybeOp = Oplog.GetOpByIndex(OpId.value()))
+ {
+ CbObject& Op = MaybeOp.value();
+ if (Req.ServerRequest().AcceptContentType() == ZenContentType::kCbPackage)
+ {
+ CbPackage Package;
+ Package.SetObject(Op);
+
+ Op.IterateAttachments([&](CbFieldView FieldView) {
+ const IoHash AttachmentHash = FieldView.AsAttachment();
+ IoBuffer Payload = m_CidStore.FindChunkByCid(AttachmentHash);
+
+ // We force this for now as content type is not consistently tracked (will
+ // be fixed in CidStore refactor)
+ Payload.SetContentType(ZenContentType::kCompressedBinary);
+
+ if (Payload)
+ {
+ switch (Payload.GetContentType())
+ {
+ case ZenContentType::kCbObject:
+ if (CbObject Object = LoadCompactBinaryObject(Payload))
+ {
+ Package.AddAttachment(CbAttachment(Object));
+ }
+ else
+ {
+ // Error - malformed object
+
+ ZEN_ERROR("malformed object returned for {}", AttachmentHash);
+ }
+ break;
+
+ case ZenContentType::kCompressedBinary:
+ if (CompressedBuffer Compressed = CompressedBuffer::FromCompressed(SharedBuffer(Payload)))
+ {
+ Package.AddAttachment(CbAttachment(Compressed));
+ }
+ else
+ {
+ // Error - not compressed!
+
+ ZEN_ERROR("invalid compressed binary returned for {}", AttachmentHash);
+ }
+ break;
+
+ default:
+ Package.AddAttachment(CbAttachment(SharedBuffer(Payload)));
+ break;
+ }
+ }
+ });
+
+ return HttpReq.WriteResponse(HttpResponseCode::Accepted, Package);
+ }
+ else
+ {
+ // Client cannot accept a package, so we only send the core object
+ return HttpReq.WriteResponse(HttpResponseCode::Accepted, Op);
+ }
+ }
+ }
- HttpReq.WriteResponse(HttpResponseCode::Accepted, HttpContentType::kText, u8"yeee"sv);
+ return HttpReq.WriteResponse(HttpResponseCode::NotFound);
},
HttpVerb::kGet);
@@ -1718,7 +1808,7 @@ HttpProjectService::HttpProjectService(CidStore& Store, ProjectStore* Projects)
if (auto OpKey = Params.GetValue("opkey"); !OpKey.empty())
{
Oid OpKeyId = OpKeyStringAsOId(OpKey);
- std::optional<CbObject> Op = FoundLog->GetOplog(OpKeyId);
+ std::optional<CbObject> Op = FoundLog->GetOpByKey(OpKeyId);
if (Op.has_value())
{