summaryrefslogtreecommitdiff
path: root/src/storage.h
blob: 86dc48ff9814b35f29fa47c900a931af1c3a7aab (plain)
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
115
116
117
118
119
120
121
122
#pragma once

#include "erebos/storage.h"

#include <future>
#include <unordered_map>
#include <unordered_set>

namespace fs = std::filesystem;

using std::optional;
using std::shared_future;
using std::shared_ptr;
using std::unique_ptr;
using std::unordered_map;
using std::unordered_set;
using std::variant;
using std::vector;

namespace erebos {

class StorageBackend
{
public:
	StorageBackend() = default;
	virtual ~StorageBackend() = default;

	virtual bool contains(const Digest &) const = 0;

	virtual optional<vector<uint8_t>> loadBytes(const Digest &) const = 0;
	virtual void storeBytes(const Digest &, const vector<uint8_t> &) = 0;

	virtual optional<vector<uint8_t>> loadKey(const Digest &) const = 0;
	virtual void storeKey(const Digest &, const vector<uint8_t> &) = 0;
};

class FilesystemStorage : public StorageBackend
{
public:
	FilesystemStorage(const fs::path &);
	virtual ~FilesystemStorage() = default;

	virtual bool contains(const Digest &) const override;

	virtual optional<vector<uint8_t>> loadBytes(const Digest &) const override;
	virtual void storeBytes(const Digest &, const vector<uint8_t> &) override;

	virtual optional<vector<uint8_t>> loadKey(const Digest &) const override;
	virtual void storeKey(const Digest &, const vector<uint8_t> &) override;

private:
	static constexpr size_t CHUNK = 16384;

	fs::path objectPath(const Digest &) const;
	fs::path keyPath(const Digest &) const;

	fs::path root;
};

class MemoryStorage : public StorageBackend
{
public:
	MemoryStorage() = default;
	virtual ~MemoryStorage() = default;

	virtual bool contains(const Digest &) const override;

	virtual optional<vector<uint8_t>> loadBytes(const Digest &) const override;
	virtual void storeBytes(const Digest &, const vector<uint8_t> &) override;

	virtual optional<vector<uint8_t>> loadKey(const Digest &) const override;
	virtual void storeKey(const Digest &, const vector<uint8_t> &) override;

private:
	unordered_map<Digest, vector<uint8_t>> storage;
	unordered_map<Digest, vector<uint8_t>> keys;
};

class ChainStorage : public StorageBackend
{
public:
	ChainStorage(shared_ptr<StorageBackend> storage):
		ChainStorage(std::move(storage), nullptr) {}
	ChainStorage(shared_ptr<StorageBackend> storage, unique_ptr<ChainStorage> parent):
		storage(std::move(storage)), parent(std::move(parent)) {}
	virtual ~ChainStorage() = default;

	virtual bool contains(const Digest &) const override;

	virtual optional<vector<uint8_t>> loadBytes(const Digest &) const override;
	virtual void storeBytes(const Digest &, const vector<uint8_t> &) override;

	virtual optional<vector<uint8_t>> loadKey(const Digest &) const override;
	virtual void storeKey(const Digest &, const vector<uint8_t> &) override;

private:
	shared_ptr<StorageBackend> storage;
	unique_ptr<ChainStorage> parent;
};

struct Storage::Priv
{
	shared_ptr<StorageBackend> backend;

	Digest storeBytes(const vector<uint8_t> &) const;
	optional<vector<uint8_t>> loadBytes(const Digest & digest) const;

	template<class S>
	optional<Digest> copy(const typename S::Ref &, vector<Digest> *) const;
	template<class S>
	optional<Digest> copy(const ObjectT<S> &, vector<Digest> *) const;
};

struct Ref::Priv
{
	const unique_ptr<PartialStorage> storage;
	const Digest digest;
};

vector<Stored<Object>> collectStoredObjects(const Stored<Object> &);

}