diff options
| author | Dan Engelbrecht <[email protected]> | 2024-11-25 23:59:25 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-11-25 23:59:25 +0100 |
| commit | 220078251f4ac334df6542c7e29b78a2db0caec6 (patch) | |
| tree | a96666fd48d074d6f7d43b1e8b9962e3f2ee8e2b | |
| parent | 5.5.14-pre0 (diff) | |
| download | zen-220078251f4ac334df6542c7e29b78a2db0caec6.tar.xz zen-220078251f4ac334df6542c7e29b78a2db0caec6.zip | |
snapshot crash (#234)
* snapshot test
* use proper IoBuffer constructor to take handle ownership
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | src/zenserver-test/zenserver-test.cpp | 97 | ||||
| -rw-r--r-- | src/zenserver/projectstore/projectstore.cpp | 7 |
3 files changed, 102 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b90377fcf..c021e421b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,6 @@ ## - Feature: Added `--malloc` option for selecting which memory allocator should be used. Currently the available options are `--malloc=mimalloc`, `--malloc=rpmalloc`, `--malloc=stomp` or `--malloc=ansi`. Some of these options are currently not available on all targets, but all are available on Windows. `rpmalloc` is currently not supported on Linux or Mac due to toolchain limitations. - Feature: Added support for generating Unreal Insights-compatible traces for memory usage analysis. Currently only supported for Windows. Activate memory tracing by passing `--trace=memory` on the command line, alongside one of `--tracehost=<ip>` or `--tracefile=<path>` to enable tracing over network or to a file. -- Bugfix: Don't add RawSize and Size in ProjectStore::GetProjectFiles response if we can't get the payload - Bugfix: Use validation of payload size/existance in all chunk fetch operations in file cas - Bugfix: Fixed deadlock in oplog snapshot - Bugifx: Validate that we can actually fetch the payload when checking attachments in response to a `/prep` call diff --git a/src/zenserver-test/zenserver-test.cpp b/src/zenserver-test/zenserver-test.cpp index 382c9a095..1eba769d2 100644 --- a/src/zenserver-test/zenserver-test.cpp +++ b/src/zenserver-test/zenserver-test.cpp @@ -137,6 +137,16 @@ main(int argc, char** argv) namespace zen::tests { +IoBuffer +MakeCbObjectPayload(std::function<void(CbObjectWriter& Writer)> WriteCB) +{ + CbObjectWriter Writer; + WriteCB(Writer); + IoBuffer Payload = Writer.Save().GetBuffer().AsIoBuffer(); + Payload.SetContentType(ZenContentType::kCbObject); + return Payload; +}; + TEST_CASE("default.single") { std::filesystem::path TestDir = TestEnv.CreateNewTestDir(); @@ -412,7 +422,92 @@ TEST_CASE("project.basic") ZEN_INFO("+++++++"); } - SUBCASE("build store op commit") { ZEN_INFO("-------"); } + + SUBCASE("snapshot") + { + zen::CbObjectWriter OpWriter; + OpWriter << "key" + << "foo"; + + const std::string_view ChunkId{ + "00000000" + "00000000" + "00010000"}; + auto FileOid = zen::Oid::FromHexString(ChunkId); + + OpWriter.BeginArray("files"); + OpWriter.BeginObject(); + OpWriter << "id" << FileOid; + OpWriter << "clientpath" + << "/{engine}/client/side/path"; + OpWriter << "serverpath" << BinPath.c_str(); + OpWriter.EndObject(); + OpWriter.EndArray(); + + zen::CbObject Op = OpWriter.Save(); + + zen::CbPackage OpPackage(Op); + + zen::BinaryWriter MemOut; + legacy::SaveCbPackage(OpPackage, MemOut); + + { + zen::StringBuilder<64> PostUri; + PostUri << BaseUri << "/new"; + auto Response = cpr::Post(cpr::Url{PostUri.c_str()}, cpr::Body{(const char*)MemOut.Data(), MemOut.Size()}); + + REQUIRE(!Response.error); + CHECK(Response.status_code == 201); + } + + // Read file data, it is raw and uncompressed + { + zen::StringBuilder<128> ChunkGetUri; + ChunkGetUri << BaseUri << "/" << ChunkId; + auto Response = cpr::Get(cpr::Url{ChunkGetUri.c_str()}); + + REQUIRE(!Response.error); + CHECK(Response.status_code == 200); + IoBuffer Data(IoBuffer::Wrap, Response.text.data(), Response.text.length()); + IoBuffer ReferenceData = IoBufferBuilder::MakeFromFile(RootPath / BinPath); + CHECK(ReferenceData.GetSize() == Data.GetSize()); + CHECK(ReferenceData.GetView().EqualBytes(Data.GetView())); + } + + { + IoBuffer Payload = MakeCbObjectPayload([&](CbObjectWriter& Writer) { Writer.AddString("method"sv, "snapshot"sv); }); + zen::StringBuilder<64> PostUri; + PostUri << BaseUri << "/rpc"; + auto Response = cpr::Post(cpr::Url{PostUri.c_str()}, + cpr::Body{(const char*)Payload.Data(), Payload.Size()}, + cpr::Header{{"Content-Type", "application/x-ue-cb"}}); + REQUIRE(!Response.error); + CHECK(Response.status_code == 200); + } + + // Read chunk data, it is now compressed + { + zen::StringBuilder<128> ChunkGetUri; + ChunkGetUri << BaseUri << "/" << ChunkId; + auto Response = cpr::Get(cpr::Url{ChunkGetUri.c_str()}, cpr::Header{{"Accept-Type", "application/x-ue-comp"}}); + + REQUIRE(!Response.error); + CHECK(Response.status_code == 200); + IoBuffer Data(IoBuffer::Wrap, Response.text.data(), Response.text.length()); + IoHash RawHash; + uint64_t RawSize; + CompressedBuffer Compressed = CompressedBuffer::FromCompressed(SharedBuffer(Data), RawHash, RawSize); + CHECK(Compressed); + IoBuffer DataDecompressed = Compressed.Decompress().AsIoBuffer(); + IoBuffer ReferenceData = IoBufferBuilder::MakeFromFile(RootPath / BinPath); + CHECK(RawSize == ReferenceData.GetSize()); + CHECK(ReferenceData.GetSize() == DataDecompressed.GetSize()); + CHECK(ReferenceData.GetView().EqualBytes(DataDecompressed.GetView())); + } + + ZEN_INFO("+++++++"); + } + SUBCASE("test chunk not found error") { for (size_t I = 0; I < 65; I++) diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp index 68ab122ef..460d62112 100644 --- a/src/zenserver/projectstore/projectstore.cpp +++ b/src/zenserver/projectstore/projectstore.cpp @@ -4893,7 +4893,12 @@ ProjectStore::Rpc(HttpServerRequest& HttpReq, } else { - IoBuffer ChunkBuffer = IoBufferBuilder::MakeFromFileHandle(ChunkTempFile.Detach()); + void* FileHandle = ChunkTempFile.Detach(); + IoBuffer ChunkBuffer(IoBuffer::File, + FileHandle, + 0, + Compressed.GetCompressed().GetSize(), + /*IsWholeFile*/ true); ChunkBuffer.SetDeleteOnClose(true); AddedChunks.insert_or_assign(RawHash, AddedChunk{.Buffer = std::move(ChunkBuffer), .RawSize = RawSize}); |