aboutsummaryrefslogtreecommitdiff
path: root/zenstore/chunkbundler.h
blob: 4b24ec9580ed424ba0d305b63e666f5f12578562 (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
// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include <zencore/zencore.h>

#include <zenstore/basicfile.h>
#include <zenstore/cas.h>
#include <zenstore/caslog.h>
#include <zenstore/gc.h>

#include <atomic>
#include <unordered_map>

namespace spdlog {
class logger;
}

namespace zen {

class ChunkBundlerValidator
{
public:
	virtual bool ValidateChunk(IoBuffer Buffer, IoHash Key) = 0;
};

#pragma pack(push)
#pragma pack(1)

struct CompactDiskLocation
{
	uint16_t BlockIndex;
	uint32_t Offset;
	uint32_t Size;
};

struct CompactDiskIndexEntry
{
	static const uint8_t kTombstone = 0x01;

	IoHash				Key;
	CompactDiskLocation Location;
	ZenContentType		ContentType = ZenContentType::kUnknownContentType;
	uint8_t				Flags		= 0;
};

#pragma pack(pop)

static_assert(sizeof(CompactDiskIndexEntry) == 32);

class ChunkBundler final
{
public:
	ChunkBundler(std::filesystem::path RootDirectory, ChunkBundlerValidator* Validator);
	~ChunkBundler();

	struct InsertResult
	{
		bool New = false;
	};

	void		  Initialize(const std::string_view ContainerBaseName, uint64_t MaxBlockSize, uint64_t Alignment, bool IsNewStore);
	InsertResult  InsertChunk(const void* ChunkData, size_t ChunkSize, const IoHash& ChunkHash);
	InsertResult  InsertChunk(IoBuffer Chunk, const IoHash& ChunkHash);
	IoBuffer	  FindChunk(const IoHash& ChunkHash);
	bool		  HaveChunk(const IoHash& ChunkHash);
	void		  FilterChunks(CasChunkSet& InOutChunks);
	void		  Flush();
	void		  Scrub(ScrubContext& Ctx);
	void		  CollectGarbage(GcContext& GcCtx);
	GcStorageSize StorageSize() const;

private:
	spdlog::logger& Log() { return m_Log; }

	ChunkBundlerValidator*			   m_Validator;
	spdlog::logger&					   m_Log;
	uint64_t						   m_PayloadAlignment = 1 << 4;
	uint64_t						   m_MaxBlockSize	  = 1L << 30;	// 1 Gb
	bool							   m_IsInitialized	  = false;
	BasicFile						   m_SmallObjectIndex;
	std::filesystem::path			   RootDirectory;
	TCasLogFile<CompactDiskIndexEntry> m_OpLog;
	std::filesystem::path			   m_RootDirectory;
	std::string						   m_ContainerBaseName;

	RwLock															m_LocationMapLock;
	std::unordered_map<IoHash, CompactDiskLocation, IoHash::Hasher> m_LocationMap;
	std::unordered_map<uint16_t, std::shared_ptr<BasicFile>>		m_OpenBlocks;
	uint16_t														m_CurrentFileIndex = 0;

	RwLock															m_InsertLock;  // used to serialize inserts
	std::weak_ptr<BasicFile>										m_CurrentBlock;
	std::atomic_uint32_t											m_CurrentInsertOffset{};

	std::atomic_uint64_t											m_CurrentIndexOffset{};
	std::atomic_uint64_t											m_TotalSize{};

	void MakeIndexSnapshot();
};

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

void chunkbundler_forcelink();

}  // namespace zen