diff options
| author | Dan Engelbrecht <[email protected]> | 2025-11-27 16:05:56 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-11-27 16:05:56 +0100 |
| commit | 4984e8cd5c38cf77c8cb978f75f808bce0577f2d (patch) | |
| tree | c298828c6290a669500788f96f8ea25be41ff88a /src/zenstore/scrubcontext.cpp | |
| parent | remove bad assert (#670) (diff) | |
| download | zen-4984e8cd5c38cf77c8cb978f75f808bce0577f2d.tar.xz zen-4984e8cd5c38cf77c8cb978f75f808bce0577f2d.zip | |
automatic scrub on startup (#667)
- Improvement: Deeper validation of data when scrub is activated (cas/cache/project)
- Improvement: Enabled more multi threading when running scrub operations
- Improvement: Added means to force a scrub operation at startup with a new release using ZEN_DATA_FORCE_SCRUB_VERSION variable in xmake.lua
Diffstat (limited to 'src/zenstore/scrubcontext.cpp')
| -rw-r--r-- | src/zenstore/scrubcontext.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/zenstore/scrubcontext.cpp b/src/zenstore/scrubcontext.cpp index fbcd7d33c..8f8ec09a7 100644 --- a/src/zenstore/scrubcontext.cpp +++ b/src/zenstore/scrubcontext.cpp @@ -2,6 +2,10 @@ #include "zenstore/scrubcontext.h" +#include <zencore/compress.h> +#include <zencore/fmtutils.h> +#include <zencore/logging.h> +#include <zencore/string.h> #include <zencore/workthreadpool.h> namespace zen { @@ -62,4 +66,64 @@ ScrubContext::ThrowIfDeadlineExpired() const throw ScrubDeadlineExpiredException(); } +bool +ValidateCompressedBuffer(const CompositeBuffer& Buffer, const IoHash* OptionalExpectedHash) +{ + IoHash HeaderRawHash; + uint64_t RawSize = 0; + uint64_t TotalCompressedSize = 0; + if (!CompressedBuffer::ValidateCompressedHeader(Buffer, HeaderRawHash, RawSize, &TotalCompressedSize)) + { + if (OptionalExpectedHash) + { + ZEN_SCOPED_WARN("compressed buffer header validation failed for chunk with hash {}", *OptionalExpectedHash); + } + else + { + ZEN_SCOPED_WARN("compressed buffer header validation failed"); + } + return false; + } + + if (OptionalExpectedHash != nullptr && HeaderRawHash != (*OptionalExpectedHash)) + { + ZEN_SCOPED_WARN("compressed buffer hash {} does not match expected hash {}", HeaderRawHash, *OptionalExpectedHash); + return false; + } + + if (TotalCompressedSize != Buffer.GetSize()) + { + ZEN_SCOPED_WARN("compressed buffer size does not match total compressed size in header for chunk {}", HeaderRawHash); + return false; + } + + CompressedBuffer Compressed = CompressedBuffer::FromCompressed(Buffer, /* out */ HeaderRawHash, /* out */ RawSize); + + IoHashStream HashStream; + if (!Compressed.DecompressToStream( + 0, + RawSize, + [&HashStream](uint64_t SourceOffset, uint64_t SourceSize, uint64_t Offset, const CompositeBuffer& Range) -> bool { + ZEN_UNUSED(SourceOffset, SourceSize, Offset); + for (const SharedBuffer& Segment : Range.GetSegments()) + { + HashStream.Append(Segment); + } + return true; + })) + { + ZEN_SCOPED_WARN("compressed buffer could not be decompressed for chunk {}", HeaderRawHash); + return false; + } + + IoHash DecompressedHash = HashStream.GetHash(); + + if (HeaderRawHash != DecompressedHash) + { + ZEN_SCOPED_WARN("decompressed hash {} differs from header hash {}", DecompressedHash, HeaderRawHash); + return false; + } + return true; +} + } // namespace zen |