aboutsummaryrefslogtreecommitdiff
path: root/zenserver/cache/structuredcachestore.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-05-24 21:04:01 +0200
committerStefan Boberg <[email protected]>2021-05-24 21:04:01 +0200
commitd75de15200195e0854f9ba36a94bc659fb811b09 (patch)
tree521e98362f7eccf13cef52f4a398812133c0330a /zenserver/cache/structuredcachestore.cpp
parentAdded support for early release of scoped RWLock helpers (diff)
downloadzen-d75de15200195e0854f9ba36a94bc659fb811b09.tar.xz
zen-d75de15200195e0854f9ba36a94bc659fb811b09.zip
Z$ now tracks content type for large objects as well as small. Large objects are tracked in index
Diffstat (limited to 'zenserver/cache/structuredcachestore.cpp')
-rw-r--r--zenserver/cache/structuredcachestore.cpp126
1 files changed, 92 insertions, 34 deletions
diff --git a/zenserver/cache/structuredcachestore.cpp b/zenserver/cache/structuredcachestore.cpp
index 59588af48..91893d6b3 100644
--- a/zenserver/cache/structuredcachestore.cpp
+++ b/zenserver/cache/structuredcachestore.cpp
@@ -130,6 +130,8 @@ ZenCacheMemoryLayer::Put(std::string_view InBucket, const zen::IoHash& HashKey,
ZEN_ASSERT(Bucket != nullptr);
+ // Note that since the underlying IoBuffer is retained, the content type is also
+
Bucket->Put(HashKey, Value);
}
@@ -165,9 +167,19 @@ ZenCacheMemoryLayer::CacheBucket::Put(const zen::IoHash& HashKey, const ZenCache
struct DiskLocation
{
- uint64_t Offset;
+ uint64_t OffsetAndFlags;
uint32_t Size;
uint32_t IndexDataSize;
+
+ static const uint64_t kOffsetMask = 0x00FF'ffFF'ffFF'ffFFull;
+ static const uint64_t kFlagsMask = 0xff00'0000'0000'0000ull;
+ static const uint64_t kStandaloneFile = 0x8000'0000'0000'0000ull;
+ static const uint64_t kStructured = 0x4000'0000'0000'0000ull;
+
+ static uint64_t CombineOffsetAndFlags(uint64_t Offset, uint64_t Flags) { return Offset | Flags; }
+
+ inline uint64_t Offset() const { return OffsetAndFlags & kOffsetMask; }
+ inline uint64_t IsFlagSet(uint64_t Flag) const { return OffsetAndFlags & Flag; }
};
struct DiskIndexEntry
@@ -297,7 +309,7 @@ ZenCacheDiskLayer::CacheBucket::OpenOrCreate(std::filesystem::path BucketDir)
m_SlogFile.Replay([&](const DiskIndexEntry& Record) {
m_Index[Record.Key] = Record.Location;
- MaxFileOffset = std::max<uint64_t>(MaxFileOffset, Record.Location.Offset + Record.Location.Size);
+ MaxFileOffset = std::max<uint64_t>(MaxFileOffset, Record.Location.Offset() + Record.Location.Size);
});
}
@@ -325,32 +337,44 @@ ZenCacheDiskLayer::CacheBucket::Get(const zen::IoHash& HashKey, ZenCacheValue& O
return false;
}
+ zen::RwLock::SharedLockScope _(m_IndexLock);
+
+ if (auto it = m_Index.find(HashKey); it != m_Index.end())
{
- zen::RwLock::SharedLockScope _(m_IndexLock);
+ const DiskLocation& Loc = it->second;
+
+ ZenContentType ContentType = ZenContentType::kBinary;
+
+ if (Loc.IsFlagSet(DiskLocation::kStructured))
+ {
+ ContentType = ZenContentType::kCbObject;
+ }
- if (auto it = m_Index.find(HashKey); it != m_Index.end())
+ if (!Loc.IsFlagSet(DiskLocation::kStandaloneFile))
{
- OutValue.Value = IoBufferBuilder::MakeFromFileHandle(m_SobsFile.Handle(), it->second.Offset, it->second.Size);
+ OutValue.Value = IoBufferBuilder::MakeFromFileHandle(m_SobsFile.Handle(), Loc.Offset(), Loc.Size);
+ OutValue.Value.SetContentType(ContentType);
return true;
}
- }
+ else
+ {
+ _.ReleaseNow();
- WideStringBuilder<128> DataFilePath;
- BuildPath(DataFilePath, HashKey);
+ WideStringBuilder<128> DataFilePath;
+ BuildPath(DataFilePath, HashKey);
- zen::IoBuffer Data = IoBufferBuilder::MakeFromFile(DataFilePath.c_str());
+ if (zen::IoBuffer Data = IoBufferBuilder::MakeFromFile(DataFilePath.c_str()))
+ {
+ OutValue.Value = Data;
+ OutValue.Value.SetContentType(ContentType);
- if (!Data)
- {
- return false;
+ return true;
+ }
+ }
}
- OutValue.Value = Data;
-
- // TODO: should populate index?
-
- return true;
+ return false;
}
void
@@ -365,30 +389,38 @@ ZenCacheDiskLayer::CacheBucket::Put(const zen::IoHash& HashKey, const ZenCacheVa
{
return PutLargeObject(HashKey, Value);
}
+ else
+ {
+ // Small object put
- // Small object put
+ uint64_t EntryFlags = 0;
- zen::RwLock::ExclusiveLockScope _(m_IndexLock);
+ if (Value.Value.GetContentType() == ZenContentType::kCbObject)
+ {
+ EntryFlags |= DiskLocation::kStructured;
+ }
- DiskLocation Loc{.Offset = m_WriteCursor, .Size = gsl::narrow<uint32_t>(Value.Value.Size())};
+ zen::RwLock::ExclusiveLockScope _(m_IndexLock);
- m_WriteCursor = zen::RoundUp(m_WriteCursor + Loc.Size, 16);
+ DiskLocation Loc{.OffsetAndFlags = DiskLocation::CombineOffsetAndFlags(m_WriteCursor, EntryFlags),
+ .Size = gsl::narrow<uint32_t>(Value.Value.Size())};
- if (auto it = m_Index.find(HashKey); it == m_Index.end())
- {
- // Previously unknown object
- m_Index.insert({HashKey, Loc});
- }
- else
- {
- // TODO: should check if write is idempotent and bail out if it is?
- it.value() = Loc;
- }
+ m_WriteCursor = zen::RoundUp(m_WriteCursor + Loc.Size, 16);
- m_SlogFile.Append({.Key = HashKey, .Location = Loc});
- m_SobsFile.Write(Value.Value.Data(), Loc.Size, Loc.Offset);
+ if (auto it = m_Index.find(HashKey); it == m_Index.end())
+ {
+ // Previously unknown object
+ m_Index.insert({HashKey, Loc});
+ }
+ else
+ {
+ // TODO: should check if write is idempotent and bail out if it is?
+ it.value() = Loc;
+ }
- return;
+ m_SlogFile.Append({.Key = HashKey, .Location = Loc});
+ m_SobsFile.Write(Value.Value.Data(), Loc.Size, Loc.Offset());
+ }
}
void
@@ -429,6 +461,32 @@ ZenCacheDiskLayer::CacheBucket::PutLargeObject(const zen::IoHash& HashKey, const
{
zen::ThrowSystemException(hRes, "Failed to finalize file '{}'"_format(zen::WideToUtf8(DataFilePath)));
}
+
+ // Update index
+
+ uint64_t EntryFlags = 0;
+
+ if (Value.Value.GetContentType() == ZenContentType::kCbObject)
+ {
+ EntryFlags |= DiskLocation::kStructured;
+ }
+
+ zen::RwLock::ExclusiveLockScope _(m_IndexLock);
+
+ DiskLocation Loc{.OffsetAndFlags = DiskLocation::CombineOffsetAndFlags(0, EntryFlags), .Size = 0};
+
+ if (auto it = m_Index.find(HashKey); it == m_Index.end())
+ {
+ // Previously unknown object
+ m_Index.insert({HashKey, Loc});
+ }
+ else
+ {
+ // TODO: should check if write is idempotent and bail out if it is?
+ it.value() = Loc;
+ }
+
+ m_SlogFile.Append({.Key = HashKey, .Location = Loc});
}
//////////////////////////////////////////////////////////////////////////