diff options
| author | Per Larsson <[email protected]> | 2021-11-12 11:08:53 +0100 |
|---|---|---|
| committer | Per Larsson <[email protected]> | 2021-11-12 11:08:53 +0100 |
| commit | 3faf0b57c625152a8facfca1c4995bd9edc95707 (patch) | |
| tree | 0ae1ff078147091bafb7f5f4799943cebd0a7f50 /zenutil | |
| parent | Changed from batch to RPC. (diff) | |
| download | zen-3faf0b57c625152a8facfca1c4995bd9edc95707.tar.xz zen-3faf0b57c625152a8facfca1c4995bd9edc95707.zip | |
Movec cache utility types to zenutil and fixed unit tests.
Diffstat (limited to 'zenutil')
| -rw-r--r-- | zenutil/cache/cachekey.cpp | 9 | ||||
| -rw-r--r-- | zenutil/cache/cachepolicy.cpp | 161 | ||||
| -rw-r--r-- | zenutil/include/zenutil/cache/cache.h | 6 | ||||
| -rw-r--r-- | zenutil/include/zenutil/cache/cachekey.h | 83 | ||||
| -rw-r--r-- | zenutil/include/zenutil/cache/cachepolicy.h | 64 | ||||
| -rw-r--r-- | zenutil/zenutil.vcxproj | 5 | ||||
| -rw-r--r-- | zenutil/zenutil.vcxproj.filters | 20 |
7 files changed, 348 insertions, 0 deletions
diff --git a/zenutil/cache/cachekey.cpp b/zenutil/cache/cachekey.cpp new file mode 100644 index 000000000..545b47f11 --- /dev/null +++ b/zenutil/cache/cachekey.cpp @@ -0,0 +1,9 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zenutil/cache/cachekey.h> + +namespace zen { + +const CacheKey CacheKey::Empty = CacheKey{.Bucket = std::string(), .Hash = IoHash()}; + +} // namespace zen diff --git a/zenutil/cache/cachepolicy.cpp b/zenutil/cache/cachepolicy.cpp new file mode 100644 index 000000000..968f6aa53 --- /dev/null +++ b/zenutil/cache/cachepolicy.cpp @@ -0,0 +1,161 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zenutil/cache/cachepolicy.h> + +#include <zencore/compactbinary.h> +#include <zencore/compactbinarybuilder.h> +#include <zencore/string.h> + +namespace zen { + +using namespace std::literals; + +namespace detail { namespace cacheopt { + constexpr std::string_view Local = "local"sv; + constexpr std::string_view Remote = "remote"sv; + constexpr std::string_view Data = "data"sv; + constexpr std::string_view Meta = "meta"sv; + constexpr std::string_view Value = "value"sv; + constexpr std::string_view Attachments = "attachments"sv; +}} // namespace detail::cacheopt + +CachePolicy +ParseQueryCachePolicy(std::string_view QueryPolicy, CachePolicy Default) +{ + if (QueryPolicy.empty()) + { + return Default; + } + + CachePolicy Result = CachePolicy::None; + + ForEachStrTok(QueryPolicy, ',', [&Result](const std::string_view& Token) { + if (Token == detail::cacheopt::Local) + { + Result |= CachePolicy::QueryLocal; + } + if (Token == detail::cacheopt::Remote) + { + Result |= CachePolicy::QueryRemote; + } + return true; + }); + + return Result; +} + +CachePolicy +ParseStoreCachePolicy(std::string_view StorePolicy, CachePolicy Default) +{ + if (StorePolicy.empty()) + { + return Default; + } + + CachePolicy Result = CachePolicy::None; + + ForEachStrTok(StorePolicy, ',', [&Result](const std::string_view& Token) { + if (Token == detail::cacheopt::Local) + { + Result |= CachePolicy::StoreLocal; + } + if (Token == detail::cacheopt::Remote) + { + Result |= CachePolicy::StoreRemote; + } + return true; + }); + + return Result; +} + +CachePolicy +ParseSkipCachePolicy(std::string_view SkipPolicy, CachePolicy Default) +{ + if (SkipPolicy.empty()) + { + return Default; + } + + CachePolicy Result = CachePolicy::None; + + ForEachStrTok(SkipPolicy, ',', [&Result](const std::string_view& Token) { + if (Token == detail::cacheopt::Meta) + { + Result |= CachePolicy::SkipMeta; + } + if (Token == detail::cacheopt::Value) + { + Result |= CachePolicy::SkipValue; + } + if (Token == detail::cacheopt::Attachments) + { + Result |= CachePolicy::SkipAttachments; + } + if (Token == detail::cacheopt::Data) + { + Result |= CachePolicy::SkipData; + } + return true; + }); + + return Result; +} + +CachePolicy +CacheRecordPolicy::GetPayloadPolicy(const Oid& PayloadId) const +{ + if (const auto It = m_PayloadPolicies.find(PayloadId); It != m_PayloadPolicies.end()) + { + return It->second; + } + + return m_DefaultPayloadPolicy; +} + +bool +CacheRecordPolicy::Load(CbObjectView RecordPolicyObject, CacheRecordPolicy& OutRecordPolicy) +{ + using namespace std::literals; + + const uint32_t RecordPolicy = RecordPolicyObject["RecordPolicy"sv].AsUInt32(static_cast<uint32_t>(CachePolicy::Default)); + const uint32_t DefaultPayloadPolicy = + RecordPolicyObject["DefaultPayloadPolicy"sv].AsUInt32(static_cast<uint32_t>(CachePolicy::Default)); + + OutRecordPolicy.m_RecordPolicy = static_cast<CachePolicy>(RecordPolicy); + OutRecordPolicy.m_DefaultPayloadPolicy = static_cast<CachePolicy>(DefaultPayloadPolicy); + + for (CbFieldView PayloadPolicyView : RecordPolicyObject["PayloadPolicies"sv]) + { + CbObjectView PayloadPolicyObject = PayloadPolicyView.AsObjectView(); + const Oid PayloadId = PayloadPolicyObject["Id"sv].AsObjectId(); + const uint32_t PayloadPolicy = PayloadPolicyObject["Policy"sv].AsUInt32(); + + if (PayloadId != Oid::Zero && PayloadPolicy != 0) + { + OutRecordPolicy.m_PayloadPolicies.emplace(PayloadId, static_cast<CachePolicy>(PayloadPolicy)); + } + } + + return true; +} + +void +CacheRecordPolicy::Save(const CacheRecordPolicy& Policy, CbWriter& Writer) +{ + Writer << "RecordPolicy"sv << static_cast<uint32_t>(Policy.GetRecordPolicy()); + Writer << "DefaultPayloadPolicy"sv << static_cast<uint32_t>(Policy.GetDefaultPayloadPolicy()); + + if (!Policy.m_PayloadPolicies.empty()) + { + Writer.BeginArray("PayloadPolicies"sv); + for (const auto& Kv : Policy.m_PayloadPolicies) + { + Writer.AddObjectId("Id"sv, Kv.first); + Writer << "Policy"sv << static_cast<uint32_t>(Kv.second); + } + Writer.EndArray(); + } +} + +} // namespace zen diff --git a/zenutil/include/zenutil/cache/cache.h b/zenutil/include/zenutil/cache/cache.h new file mode 100644 index 000000000..c62ea6212 --- /dev/null +++ b/zenutil/include/zenutil/cache/cache.h @@ -0,0 +1,6 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <zenutil/cache/cachepolicy.h> +#include <zenutil/cache/cachekey.h> diff --git a/zenutil/include/zenutil/cache/cachekey.h b/zenutil/include/zenutil/cache/cachekey.h new file mode 100644 index 000000000..fb36c7759 --- /dev/null +++ b/zenutil/include/zenutil/cache/cachekey.h @@ -0,0 +1,83 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <zencore/iohash.h> +#include <zencore/string.h> +#include <zencore/uid.h> + +#include <zenutil/cache/cachepolicy.h> + +namespace zen { + +struct CacheKey +{ + std::string Bucket; + IoHash Hash; + + static CacheKey Create(std::string_view Bucket, const IoHash& Hash) { return {.Bucket = ToLower(Bucket), .Hash = Hash}; } + + static const CacheKey Empty; +}; + +inline bool +operator==(const CacheKey& A, const CacheKey& B) +{ + return A.Bucket == B.Bucket && A.Hash == B.Hash; +} + +inline bool +operator!=(const CacheKey& A, const CacheKey& B) +{ + return A.Bucket != B.Bucket || A.Hash != B.Hash; +} + +inline bool +operator<(const CacheKey& A, const CacheKey& B) +{ + const std::string& BucketA = A.Bucket; + const std::string& BucketB = B.Bucket; + return BucketA == BucketB ? A.Hash < B.Hash : BucketA < BucketB; +} + +struct CacheChunkRequest +{ + CacheKey Key; + IoHash ChunkId; + Oid PayloadId; + uint64_t RawOffset = 0ull; + uint64_t RawSize = ~uint64_t(0); + CachePolicy Policy = CachePolicy::Default; +}; + +inline bool +operator<(const CacheChunkRequest& A, const CacheChunkRequest& B) +{ + if (A.Key < B.Key) + { + return true; + } + if (B.Key < A.Key) + { + return false; + } + if (A.ChunkId < B.ChunkId) + { + return true; + } + if (B.ChunkId < A.ChunkId) + { + return false; + } + if (A.PayloadId < B.PayloadId) + { + return true; + } + if (B.PayloadId < A.PayloadId) + { + return false; + } + return A.RawOffset < B.RawOffset; +} + +} // namespace zen diff --git a/zenutil/include/zenutil/cache/cachepolicy.h b/zenutil/include/zenutil/cache/cachepolicy.h new file mode 100644 index 000000000..da0db435c --- /dev/null +++ b/zenutil/include/zenutil/cache/cachepolicy.h @@ -0,0 +1,64 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <zencore/string.h> +#include <zencore/uid.h> + +#include <gsl/gsl-lite.hpp> +#include <unordered_map> + +namespace zen { + +class CbObjectView; +class CbWriter; + +enum class CachePolicy : uint8_t +{ + None = 0, + QueryLocal = 1 << 0, + QueryRemote = 1 << 1, + Query = QueryLocal | QueryRemote, + StoreLocal = 1 << 2, + StoreRemote = 1 << 3, + Store = StoreLocal | StoreRemote, + SkipMeta = 1 << 4, + SkipValue = 1 << 5, + SkipAttachments = 1 << 6, + SkipData = SkipMeta | SkipValue | SkipAttachments, + SkipLocalCopy = 1 << 7, + Local = QueryLocal | StoreLocal, + Remote = QueryRemote | StoreRemote, + Default = Query | Store, + Disable = None, +}; + +gsl_DEFINE_ENUM_BITMASK_OPERATORS(CachePolicy); + +CachePolicy ParseQueryCachePolicy(std::string_view QueryPolicy, CachePolicy Default = CachePolicy::Query); + +CachePolicy ParseStoreCachePolicy(std::string_view StorePolicy, CachePolicy Default = CachePolicy::Store); + +CachePolicy ParseSkipCachePolicy(std::string_view SkipPolicy, CachePolicy Default = CachePolicy::None); + +class CacheRecordPolicy +{ +public: + CacheRecordPolicy() = default; + + CachePolicy GetRecordPolicy() const { return m_RecordPolicy; } + CachePolicy GetPayloadPolicy(const Oid& PayloadId) const; + CachePolicy GetDefaultPayloadPolicy() const { return m_DefaultPayloadPolicy; } + + static bool Load(CbObjectView RecordPolicyObject, CacheRecordPolicy& OutRecordPolicy); + static void Save(const CacheRecordPolicy& Policy, CbWriter& Writer); + +private: + using PayloadPolicyMap = std::unordered_map<Oid, CachePolicy, Oid::Hasher>; + + CachePolicy m_RecordPolicy = CachePolicy::Default; + CachePolicy m_DefaultPayloadPolicy = CachePolicy::Default; + PayloadPolicyMap m_PayloadPolicies; +}; + +} // namespace zen diff --git a/zenutil/zenutil.vcxproj b/zenutil/zenutil.vcxproj index 3bf6111f7..f5db7c5b0 100644 --- a/zenutil/zenutil.vcxproj +++ b/zenutil/zenutil.vcxproj @@ -97,9 +97,14 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClCompile Include="cache\cachekey.cpp" /> + <ClCompile Include="cache\cachepolicy.cpp" /> <ClCompile Include="zenserverprocess.cpp" /> </ItemGroup> <ItemGroup> + <ClInclude Include="include\zenutil\cache\cache.h" /> + <ClInclude Include="include\zenutil\cache\cachekey.h" /> + <ClInclude Include="include\zenutil\cache\cachepolicy.h" /> <ClInclude Include="include\zenutil\zenserverprocess.h" /> </ItemGroup> <ItemGroup> diff --git a/zenutil/zenutil.vcxproj.filters b/zenutil/zenutil.vcxproj.filters index 9952e7159..368a827c2 100644 --- a/zenutil/zenutil.vcxproj.filters +++ b/zenutil/zenutil.vcxproj.filters @@ -2,11 +2,31 @@ <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <ClCompile Include="zenserverprocess.cpp" /> + <ClCompile Include="cache\cachekey.cpp"> + <Filter>cache</Filter> + </ClCompile> + <ClCompile Include="cache\cachepolicy.cpp"> + <Filter>cache</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="include\zenutil\zenserverprocess.h" /> + <ClInclude Include="include\zenutil\cache\cache.h"> + <Filter>cache</Filter> + </ClInclude> + <ClInclude Include="include\zenutil\cache\cachekey.h"> + <Filter>cache</Filter> + </ClInclude> + <ClInclude Include="include\zenutil\cache\cachepolicy.h"> + <Filter>cache</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="xmake.lua" /> </ItemGroup> + <ItemGroup> + <Filter Include="cache"> + <UniqueIdentifier>{a441c536-6a01-4ac4-85a0-2667c95027d0}</UniqueIdentifier> + </Filter> + </ItemGroup> </Project>
\ No newline at end of file |