aboutsummaryrefslogtreecommitdiff
path: root/zenhttp/httpshared.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zenhttp/httpshared.cpp')
-rw-r--r--zenhttp/httpshared.cpp91
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())));
}
}