aboutsummaryrefslogtreecommitdiff
path: root/zenstore/CAS.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-09-19 19:30:16 +0200
committerStefan Boberg <[email protected]>2021-09-19 19:30:16 +0200
commit8f82467ea5e8e90e459d78d603c67a7938ae8ead (patch)
treea7d1a3e2d897e9a53e075485c437c440f3684ce2 /zenstore/CAS.cpp
parentAdded zenstore.h and made headers use it (diff)
downloadzen-8f82467ea5e8e90e459d78d603c67a7938ae8ead.tar.xz
zen-8f82467ea5e8e90e459d78d603c67a7938ae8ead.zip
Changed some code over from ATL to BasicFile and added Scrub() stubs.
Diffstat (limited to 'zenstore/CAS.cpp')
-rw-r--r--zenstore/CAS.cpp85
1 files changed, 62 insertions, 23 deletions
diff --git a/zenstore/CAS.cpp b/zenstore/CAS.cpp
index e77c0ed64..af0fcc609 100644
--- a/zenstore/CAS.cpp
+++ b/zenstore/CAS.cpp
@@ -11,6 +11,7 @@
#include <zencore/logging.h>
#include <zencore/memory.h>
#include <zencore/string.h>
+#include <zencore/testutils.h>
#include <zencore/thread.h>
#include <zencore/uid.h>
@@ -20,15 +21,17 @@
#include <functional>
#include <unordered_map>
-struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive-
-#include <atlfile.h>
-
//////////////////////////////////////////////////////////////////////////
namespace zen {
/**
- * Slightly less naive CAS store
+ * CAS store implementation
+ *
+ * Uses a basic strategy of splitting payloads by size, to improve ability to reclaim space
+ * quickly for unused large chunks and to maintain locality for small chunks which are
+ * frequently accessed together.
+ *
*/
class CasImpl : public CasStore
{
@@ -41,10 +44,9 @@ public:
virtual IoBuffer FindChunk(const IoHash& ChunkHash) override;
virtual void FilterChunks(CasChunkSet& InOutChunks) override;
virtual void Flush() override;
+ virtual void Scrub() override;
private:
- void PickDefaultDirectory();
-
CasContainerStrategy m_TinyStrategy;
CasContainerStrategy m_SmallStrategy;
FileCasStrategy m_LargeStrategy;
@@ -63,13 +65,16 @@ CasImpl::Initialize(const CasStoreConfiguration& InConfig)
{
m_Config = InConfig;
- ZEN_INFO("initializing CAS pool at {}", m_Config.RootDirectory);
+ ZEN_INFO("initializing CAS pool at '{}'", m_Config.RootDirectory);
// Ensure root directory exists - create if it doesn't exist already
std::filesystem::create_directories(m_Config.RootDirectory);
// Open or create manifest
+ //
+ // The manifest is not currently fully implemented. The goal is to
+ // use it for recovery and configuration
bool IsNewStore = false;
@@ -77,23 +82,22 @@ CasImpl::Initialize(const CasStoreConfiguration& InConfig)
std::filesystem::path ManifestPath = m_Config.RootDirectory;
ManifestPath /= ".ucas_root";
- CAtlFile marker;
- HRESULT hRes = marker.Create(ManifestPath.c_str(), GENERIC_READ, 0, OPEN_EXISTING);
+ std::error_code Ec;
+ BasicFile Marker;
+ Marker.Open(ManifestPath.c_str(), /* IsCreate */ false, Ec);
- if (FAILED(hRes))
+ if (Ec)
{
IsNewStore = true;
ExtendableStringBuilder<128> manifest;
- manifest.Append("#CAS_ROOT\n"); // TODO: should write something meaningful here
+ manifest.Append("#CAS_ROOT\n");
manifest.Append("ID=");
zen::Oid id = zen::Oid::NewOid();
id.ToString(manifest);
- hRes = marker.Create(ManifestPath.c_str(), GENERIC_WRITE, 0, CREATE_ALWAYS);
-
- if (SUCCEEDED(hRes))
- marker.Write(manifest.c_str(), (DWORD)manifest.Size());
+ Marker.Open(ManifestPath.c_str(), /* IsCreate */ true);
+ Marker.Write(manifest.c_str(), (DWORD)manifest.Size(), 0);
}
}
@@ -160,6 +164,14 @@ CasImpl::Flush()
m_LargeStrategy.Flush();
}
+void
+CasImpl::Scrub()
+{
+ m_SmallStrategy.Scrub();
+ m_TinyStrategy.Scrub();
+ m_LargeStrategy.Scrub();
+}
+
//////////////////////////////////////////////////////////////////////////
CasStore*
@@ -173,18 +185,45 @@ CreateCasStore()
// Testing related code follows...
//
-void
-CAS_forcelink()
-{
-}
-
TEST_CASE("CasStore")
{
+ ScopedTemporaryDirectory TempDir;
+
zen::CasStoreConfiguration config;
- config.RootDirectory = "c:\\temp\\test";
+ config.RootDirectory = TempDir.Path();
+
+ std::unique_ptr<zen::CasStore> Store{CreateCasStore()};
+ Store->Initialize(config);
+ Store->Scrub();
+
+ IoBuffer Value1{16};
+ memcpy(Value1.MutableData(), "1234567890123456", 16);
+ IoHash Hash1 = IoHash::HashBuffer(Value1.Data(), Value1.Size());
+ CasStore::InsertResult Result1 = Store->InsertChunk(Value1, Hash1);
+ CHECK(Result1.New);
+
+ IoBuffer Value2{16};
+ memcpy(Value2.MutableData(), "ABCDEFGHIJKLMNOP", 16);
+ IoHash Hash2 = IoHash::HashBuffer(Value2.Data(), Value2.Size());
+ CasStore::InsertResult Result2 = Store->InsertChunk(Value2, Hash2);
+ CHECK(Result2.New);
+
+ CasChunkSet ChunkSet;
+ ChunkSet.AddChunk(Hash1);
+ ChunkSet.AddChunk(Hash2);
+
+ Store->FilterChunks(ChunkSet);
+ CHECK(ChunkSet.GetChunkSet().size() == 0);
+
+ IoBuffer Lookup1 = Store->FindChunk(Hash1);
+ CHECK(Lookup1);
+ IoBuffer Lookup2 = Store->FindChunk(Hash2);
+ CHECK(Lookup2);
+}
- std::unique_ptr<zen::CasStore> store{CreateCasStore()};
- store->Initialize(config);
+void
+CAS_forcelink()
+{
}
} // namespace zen