aboutsummaryrefslogtreecommitdiff
path: root/zenstore/cidstore.cpp
blob: 4e5188f1c84a883dabd77fa2aa862a7c3731949d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright Epic Games, Inc. All Rights Reserved.

#include "zenstore/cidstore.h"

#include <zencore/filesystem.h>
#include <zenstore/CAS.h>
#include <zenstore/caslog.h>

#include <spdlog/spdlog.h>
#include <filesystem>

namespace zen {

struct CidStore::CidState
{
	CidState(CasStore& InCasStore) : m_CasStore(InCasStore) {}

	struct IndexEntry
	{
		IoHash Uncompressed;
		IoHash Compressed;
	};

	CasStore&				m_CasStore;
	TCasLogFile<IndexEntry> m_LogFile;

	RwLock						   m_Lock;
	tsl::robin_map<IoHash, IoHash> m_CidMap;

	void AddCompressedCid(const IoHash& DecompressedId, const IoHash& Compressed)
	{
		RwLock::ExclusiveLockScope _(m_Lock);
		m_CidMap.insert_or_assign(DecompressedId, Compressed);
		m_LogFile.Append({.Uncompressed = DecompressedId, .Compressed = Compressed});
	}

	IoBuffer FindChunkByCid(const IoHash& DecompressedId)
	{
		IoHash CompressedHash;
		{
			RwLock::SharedLockScope _(m_Lock);
			if (auto It = m_CidMap.find(DecompressedId); It != m_CidMap.end())
			{
				CompressedHash = It->second;
			}
		}

		if (CompressedHash != IoHash::Zero)
		{
			return m_CasStore.FindChunk(CompressedHash);
		}

		return IoBuffer();
	}

	bool ContainsChunk(const IoHash& DecompressedId)
	{
		RwLock::SharedLockScope _(m_Lock);
		return m_CidMap.find(DecompressedId) != m_CidMap.end();
	}

	void InitializeIndex(const std::filesystem::path& RootDir)
	{
		zen::CreateDirectories(RootDir);
		std::filesystem::path SlogPath{RootDir / "cid.slog"};

		bool IsNew = !std::filesystem::exists(SlogPath);

		m_LogFile.Open(SlogPath, IsNew);

		m_LogFile.Replay([&](const IndexEntry& Ie) { m_CidMap.insert_or_assign(Ie.Uncompressed, Ie.Compressed); });

		spdlog::debug("CID index initialized: {} entries found", m_CidMap.size());
	}

	void Flush() { m_LogFile.Flush(); }
};

//////////////////////////////////////////////////////////////////////////

CidStore::CidStore(CasStore& InCasStore, const std::filesystem::path& RootDir) : m_Impl(std::make_unique<CidState>(InCasStore))
{
	m_Impl->InitializeIndex(RootDir);
}

CidStore::~CidStore()
{
}

void
CidStore::AddCompressedCid(const IoHash& DecompressedId, const IoHash& Compressed)
{
	m_Impl->AddCompressedCid(DecompressedId, Compressed);
}

IoBuffer
CidStore::FindChunkByCid(const IoHash& DecompressedId)
{
	return m_Impl->FindChunkByCid(DecompressedId);
}

bool
CidStore::ContainsChunk(const IoHash& DecompressedId)
{
	return m_Impl->ContainsChunk(DecompressedId);
}

void
CidStore::Flush()
{
	m_Impl->Flush();
}

}  // namespace zen