diff options
Diffstat (limited to 'src/zenstore/cache/cacherpc.cpp')
| -rw-r--r-- | src/zenstore/cache/cacherpc.cpp | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/src/zenstore/cache/cacherpc.cpp b/src/zenstore/cache/cacherpc.cpp index 84ca5c5e3..3cb1b03a5 100644 --- a/src/zenstore/cache/cacherpc.cpp +++ b/src/zenstore/cache/cacherpc.cpp @@ -1549,13 +1549,7 @@ CacheRpcHandler::WriteGetCacheChunksResponse([[maybe_unused]] const CacheRequest using namespace cache::detail; - const bool AcceptsPartialChunks = EnumHasAnyFlags(AcceptOptions, RpcAcceptOptions::kAllowPartialCacheChunks) && false; - // TODO: We need to redesign how we respond with partial chunks as we can get requests for multiple parts of the same chunk - // and we currently identify chunks by the full chunks RawHash making it impossible to distinguish between sections for partial chunks. - // Also, UE currently does the lookup by checking the RawHash *inside* the attachment which will break as sections of compressed - // buffers has a RawHash of zero (as we don't want to re-hash the section) - // zen side handles this as it separates the lookup hash from the hash inside the attachment, but it still can't tell two partial - // section from the same chunk apart. + const bool AcceptsPartialChunks = EnumHasAnyFlags(AcceptOptions, RpcAcceptOptions::kAllowPartialCacheChunks); CbPackage RpcResponse; CbObjectWriter Writer; @@ -1572,9 +1566,16 @@ CacheRpcHandler::WriteGetCacheChunksResponse([[maybe_unused]] const CacheRequest Writer.AddHash("RawHash"sv, Request.Key->ChunkId); if (Request.Value && !EnumHasAllFlags(Request.DownstreamPolicy, CachePolicy::SkipData)) { - if (AcceptsPartialChunks && (Request.RequestedOffset != 0 || Request.RequestedSize < Request.RawSize)) + auto IsPartialRangeRequest = [](const ChunkRequest& Request) { + if ((Request.RequestedOffset != 0) || (Request.RequestedSize != ~uint64_t(0))) + { + return true; + } + return Request.RequestedSize < Request.Value.DecodeRawSize(); + }; + if (AcceptsPartialChunks && IsPartialRangeRequest(Request)) { - uint64_t RawOffset = 0; + uint64_t FragmentRawOffset = 0; if (Request.RequestedOffset > 0) { OodleCompressor Compressor; @@ -1584,22 +1585,30 @@ CacheRpcHandler::WriteGetCacheChunksResponse([[maybe_unused]] const CacheRequest ZEN_ASSERT(bOk); if (BlockSize > 0) { - RawOffset = (Request.RequestedOffset / BlockSize) * BlockSize; + FragmentRawOffset = (Request.RequestedOffset / BlockSize) * BlockSize; } else { - RawOffset = Request.RequestedOffset; + FragmentRawOffset = Request.RequestedOffset; } } - // Technically the receiver can figure this offset out based on the assumption that we reply with - // a set of blocks that encapsulates the requested range, but since the UE side was not initially - // written to handle this we need to indicate that we do indeed reply with a partial response. - // And as we already need to add a field, why not provide some useful information so the client - // don't need to calculate this for us... - Writer.AddInteger("RawOffset", RawOffset); - Request.Value = Request.Value.GetRange(Request.RequestedOffset, Request.RequestedSize); + Request.Value = Request.Value.GetRange(Request.RequestedOffset, Request.RequestedSize); + uint64_t FragmentLength = Request.Value.DecodeRawSize(); + + IoHashStream FragmentHashStream; + FragmentHashStream.Append(Request.Key->ChunkId.Hash, sizeof(Request.Key->ChunkId.Hash)); + FragmentHashStream.Append(&FragmentRawOffset, sizeof(FragmentRawOffset)); + FragmentHashStream.Append(&FragmentLength, sizeof(FragmentLength)); + IoHash FragmentHash = FragmentHashStream.GetHash(); + + Writer.AddHash("FragmentHash", FragmentHash); + Writer.AddInteger("FragmentOffset", FragmentRawOffset); + RpcResponse.AddAttachment(CbAttachment(Request.Value, FragmentHash)); + } + else + { + RpcResponse.AddAttachment(CbAttachment(Request.Value, Request.Key->ChunkId)); } - RpcResponse.AddAttachment(CbAttachment(Request.Value, Request.Key->ChunkId)); } else { |