diff options
Diffstat (limited to 'zenhttp/httpshared.cpp')
| -rw-r--r-- | zenhttp/httpshared.cpp | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/zenhttp/httpshared.cpp b/zenhttp/httpshared.cpp index a7dca5441..e2f061a87 100644 --- a/zenhttp/httpshared.cpp +++ b/zenhttp/httpshared.cpp @@ -17,6 +17,10 @@ #include <span> #include <vector> +ZEN_THIRD_PARTY_INCLUDES_START +#include <tsl/robin_map.h> +ZEN_THIRD_PARTY_INCLUDES_END + namespace zen { std::vector<IoBuffer> @@ -93,10 +97,12 @@ FormatPackageMessage(const CbPackage& Data, FormatFlags Flags) ResponseBuffers.push_back(std::move(RefBuffer)); }; - auto IsLocalRef = [](const CompositeBuffer& AttachmentBinary, - bool DenyPartialLocalReferences, - CbAttachmentReferenceHeader& LocalRef, - std::string& Path8) -> bool { + tsl::robin_map<void*, std::string> FileNameMap; + + auto IsLocalRef = [&FileNameMap](const CompositeBuffer& AttachmentBinary, + bool DenyPartialLocalReferences, + CbAttachmentReferenceHeader& LocalRef, + std::string& Path8) -> bool { const SharedBuffer& Segment = AttachmentBinary.GetSegments().front(); IoBufferFileReference Ref; const IoBuffer& SegmentBuffer = Segment.AsIoBuffer(); @@ -111,9 +117,17 @@ FormatPackageMessage(const CbPackage& Data, FormatFlags Flags) return false; } - ExtendablePathBuilder<256> LocalRefFile; - LocalRefFile.Append(std::filesystem::absolute(PathFromHandle(Ref.FileHandle))); - Path8 = LocalRefFile.ToUtf8(); + if (auto It = FileNameMap.find(Ref.FileHandle); It != FileNameMap.end()) + { + Path8 = It->second; + } + else + { + ExtendablePathBuilder<256> LocalRefFile; + LocalRefFile.Append(std::filesystem::absolute(PathFromHandle(Ref.FileHandle))); + Path8 = LocalRefFile.ToUtf8(); + FileNameMap.insert_or_assign(Ref.FileHandle, Path8); + } LocalRef.AbsolutePathLength = gsl::narrow<uint16_t>(Path8.size()); LocalRef.PayloadByteOffset = Ref.FileChunkOffset; @@ -131,7 +145,7 @@ FormatPackageMessage(const CbPackage& Data, FormatFlags Flags) else if (CompressedBuffer AttachmentBuffer = Attachment.AsCompressedBinary()) { CompositeBuffer Compressed = AttachmentBuffer.GetCompressed(); - IoHash AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash()); + IoHash AttachmentHash = Attachment.GetHash(); // If the data is either not backed by a file, or there are multiple // fragments then we cannot marshal it by local reference. We might @@ -158,7 +172,7 @@ FormatPackageMessage(const CbPackage& Data, FormatFlags Flags) { *AttachmentInfo++ = {.PayloadSize = AttachmentBuffer.GetCompressedSize(), .Flags = CbAttachmentEntry::kIsCompressed, - .AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash())}; + .AttachmentHash = AttachmentHash}; for (const SharedBuffer& Segment : Compressed.GetSegments()) { @@ -177,7 +191,7 @@ FormatPackageMessage(const CbPackage& Data, FormatFlags Flags) } else if (CompositeBuffer AttachmentBinary = Attachment.AsCompositeBinary()) { - IoHash AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash()); + IoHash AttachmentHash = Attachment.GetHash(); bool MarshalByLocalRef = EnumHasAllFlags(Flags, FormatFlags::kAllowLocalReferences) && (AttachmentBinary.GetSegments().size() == 1); bool DenyPartialLocalReferences = EnumHasAllFlags(Flags, FormatFlags::kDenyPartialLocalReferences); @@ -211,6 +225,7 @@ FormatPackageMessage(const CbPackage& Data, FormatFlags Flags) ZEN_NOT_IMPLEMENTED("Unknown attachment kind"); } } + FileNameMap.clear(); return ResponseBuffers; } @@ -262,6 +277,11 @@ ParsePackageMessage(IoBuffer Payload, std::function<IoBuffer(const IoHash&, uint CbPackage Package; + std::vector<CbAttachment> Attachments; + Attachments.reserve(ChunkCount); // Guessing here... + + tsl::robin_map<std::string, IoBuffer> PartialFileBuffers; + for (uint32_t i = 0; i < ChunkCount; ++i) { const CbAttachmentEntry& Entry = AttachmentEntries[i]; @@ -283,23 +303,18 @@ ParsePackageMessage(IoBuffer Payload, std::function<IoBuffer(const IoHash&, uint std::filesystem::path Path{std::u8string_view(PathPointer, AttachRefHdr->AbsolutePathLength)}; - if (IoBuffer ChunkReference = - IoBufferBuilder::MakeFromFile(Path, AttachRefHdr->PayloadByteOffset, AttachRefHdr->PayloadByteSize)) + IoBuffer FullFileBuffer; + if (auto It = PartialFileBuffers.find(Path.string()); It != PartialFileBuffers.end()) { - CompressedBuffer CompBuf(CompressedBuffer::FromCompressed(SharedBuffer(ChunkReference))); - if (!CompBuf) - { - throw std::runtime_error(fmt::format("invalid format for chunk #{} at '{}' (offset {}, size {})", - i, - PathToUtf8(Path), - AttachRefHdr->PayloadByteOffset, - AttachRefHdr->PayloadByteSize)); - } - CbAttachment Attachment(std::move(CompBuf)); - Package.AddAttachment(Attachment); + FullFileBuffer = It->second; } else { + FullFileBuffer = PartialFileBuffers.insert_or_assign(Path.string(), IoBufferBuilder::MakeFromFile(Path)).first->second; + } + + if (!FullFileBuffer) + { // Unable to open chunk reference throw std::runtime_error(fmt::format("unable to resolve chunk #{} at '{}' (offset {}, size {})", i, @@ -307,6 +322,21 @@ ParsePackageMessage(IoBuffer Payload, std::function<IoBuffer(const IoHash&, uint AttachRefHdr->PayloadByteOffset, AttachRefHdr->PayloadByteSize)); } + + IoBuffer ChunkReference = AttachRefHdr->PayloadByteOffset == 0 && AttachRefHdr->PayloadByteSize == FullFileBuffer.GetSize() + ? FullFileBuffer + : IoBuffer(FullFileBuffer, AttachRefHdr->PayloadByteOffset, AttachRefHdr->PayloadByteSize); + + CompressedBuffer CompBuf(CompressedBuffer::FromCompressedNoValidate(std::move(ChunkReference))); + if (!CompBuf) + { + throw std::runtime_error(fmt::format("invalid format for chunk #{} at '{}' (offset {}, size {})", + i, + PathToUtf8(Path), + AttachRefHdr->PayloadByteOffset, + AttachRefHdr->PayloadByteSize)); + } + Attachments.emplace_back(CbAttachment(std::move(CompBuf), Entry.AttachmentHash)); } else if (Entry.Flags & CbAttachmentEntry::kIsCompressed) { @@ -341,8 +371,7 @@ ParsePackageMessage(IoBuffer Payload, std::function<IoBuffer(const IoHash&, uint throw std::runtime_error(fmt::format("invalid format for chunk #{} expected compressed buffer for attachment", i)); } - CbAttachment Attachment(std::move(CompBuf)); - Package.AddAttachment(Attachment); + Attachments.emplace_back(CbAttachment(std::move(CompBuf), Entry.AttachmentHash)); } } else /* not compressed */ @@ -367,10 +396,13 @@ ParsePackageMessage(IoBuffer Payload, std::function<IoBuffer(const IoHash&, uint AttachmentBufferCopy.GetMutableView().CopyFrom(AttachmentBuffer.GetView()); CbAttachment Attachment(SharedBuffer{AttachmentBufferCopy}); - Package.AddAttachment(Attachment); + Attachments.emplace_back(SharedBuffer{AttachmentBufferCopy}); } } } + PartialFileBuffers.clear(); + + Package.AddAttachments(Attachments); return Package; } @@ -517,12 +549,13 @@ CbPackageReader::Finalize() if (Entry.Flags & CbAttachmentEntry::kIsCompressed) { - m_Attachments.push_back(CbAttachment(CompressedBuffer::FromCompressed(SharedBuffer(ChunkReference)))); + m_Attachments.push_back(CbAttachment(CompressedBuffer::FromCompressed(SharedBuffer(ChunkReference)), Entry.AttachmentHash)); } else { - m_Attachments.push_back(CbAttachment( - CompressedBuffer::Compress(SharedBuffer(ChunkReference), OodleCompressor::NotSet, OodleCompressionLevel::None))); + CompressedBuffer Compressed = + CompressedBuffer::Compress(SharedBuffer(ChunkReference), OodleCompressor::NotSet, OodleCompressionLevel::None); + m_Attachments.push_back(CbAttachment(std::move(Compressed), IoHash::FromBLAKE3(Compressed.GetRawHash()))); } } |