1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System. |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#ifndef CVMFS_CACHE_H_ |
6 |
|
|
#define CVMFS_CACHE_H_ |
7 |
|
|
|
8 |
|
|
#ifndef __STDC_FORMAT_MACROS |
9 |
|
|
#define __STDC_FORMAT_MACROS |
10 |
|
|
#endif |
11 |
|
|
|
12 |
|
|
#include <stdint.h> |
13 |
|
|
|
14 |
|
|
#include <string> |
15 |
|
|
|
16 |
|
|
#include "hash.h" |
17 |
|
|
#include "util/pointer.h" |
18 |
|
|
|
19 |
|
|
|
20 |
|
|
class QuotaManager; |
21 |
|
|
|
22 |
|
|
enum CacheManagerIds { |
23 |
|
|
kUnknownCacheManager = 0, |
24 |
|
|
kPosixCacheManager, |
25 |
|
|
kRamCacheManager, |
26 |
|
|
kTieredCacheManager, |
27 |
|
|
kExternalCacheManager, |
28 |
|
|
}; |
29 |
|
|
|
30 |
|
|
enum CacheModes { |
31 |
|
|
kCacheReadWrite = 0, |
32 |
|
|
kCacheReadOnly, |
33 |
|
|
}; |
34 |
|
|
|
35 |
|
|
|
36 |
|
|
/** |
37 |
|
|
* The Cache Manager provides (virtual) file descriptors to content-addressable |
38 |
|
|
* objects in the cache. The implementation can use a POSIX file system or |
39 |
|
|
* other means such as a key-value store. A file descriptor must remain |
40 |
|
|
* readable until closed, no matter if it is removed from the backend storage |
41 |
|
|
* or not (POSIX semantics). |
42 |
|
|
* |
43 |
|
|
* Writing into the cache is streamed and transactional: a file descriptor must |
44 |
|
|
* be acquired from StartTxn and the object is only visible in the cache after |
45 |
|
|
* CommitTxn. The state of the transaction is carried in an opque transaction |
46 |
|
|
* object, which needs to be provided by the caller. The size of the object is |
47 |
|
|
* returned by SizeOfTxn. This way, users of derived classes can take care of |
48 |
|
|
* the storage allocation (e.g. on the stack), while the derived class |
49 |
|
|
* determines the contents of the transaction object. For race-free read access |
50 |
|
|
* to objects that are just being written to the cache, the OpenFromTxn routine |
51 |
|
|
* is used just before the transaction is committed. |
52 |
|
|
* |
53 |
|
|
* Writing to the cache can be coupled to a quota manager. The quota manager |
54 |
|
|
* maintains some extra information for data chunks: whether they are |
55 |
|
|
* volatile, whether they are pinned, and a description (usually the path that |
56 |
|
|
* corresponds to a data chunk). By default the NoopQuotaManager is used, which |
57 |
|
|
* ignores all this extra information. The CtrlTxn() function is used to |
58 |
|
|
* specify this extra information sometime between StartTxn() and CommitTxn(). |
59 |
|
|
* |
60 |
|
|
* The integer return values can be negative and, in this case, represent a |
61 |
|
|
* -errno failure code. Otherwise the return value 0 indicates a success, or |
62 |
|
|
* >= 0 for a file descriptor. |
63 |
|
|
*/ |
64 |
|
|
class CacheManager : SingleCopy { |
65 |
|
|
public: |
66 |
|
|
/** |
67 |
|
|
* Sizes of objects should be known for StartTxn(). For file catalogs we |
68 |
|
|
* cannot ensure that, however, because the size field for nested catalogs |
69 |
|
|
* was only recently added. |
70 |
|
|
*/ |
71 |
|
|
static const uint64_t kSizeUnknown; |
72 |
|
|
|
73 |
|
|
/** |
74 |
|
|
* Relevant for the quota management |
75 |
|
|
*/ |
76 |
|
|
enum ObjectType { |
77 |
|
|
kTypeRegular = 0, |
78 |
|
|
kTypeCatalog, // implies pinned |
79 |
|
|
kTypePinned, |
80 |
|
|
kTypeVolatile, |
81 |
|
|
}; |
82 |
|
|
|
83 |
|
|
/** |
84 |
|
|
* Meta-data of an object that the cache may or may not maintain. Good cache |
85 |
|
|
* implementations should at least distinguish between volatile and regular |
86 |
|
|
* objects. |
87 |
|
|
*/ |
88 |
|
5972 |
struct ObjectInfo { |
89 |
|
420 |
ObjectInfo() : type(kTypeRegular), description() { } |
90 |
|
4804 |
ObjectInfo(ObjectType t, const std::string &d) : type(t), description(d) { } |
91 |
|
|
|
92 |
|
|
ObjectType type; |
93 |
|
|
/** |
94 |
|
|
* Typically the path that triggered storing the object in the cache |
95 |
|
|
*/ |
96 |
|
|
std::string description; |
97 |
|
|
}; |
98 |
|
|
|
99 |
|
|
/** |
100 |
|
|
* A content hash together with a (partial) ObjectInfo meta-data. |
101 |
|
|
*/ |
102 |
|
731 |
struct BlessedObject { |
103 |
|
420 |
explicit BlessedObject(const shash::Any &id) : id(id), info() { } |
104 |
|
142 |
BlessedObject(const shash::Any &id, const ObjectInfo info) |
105 |
|
|
: id(id) |
106 |
|
142 |
, info(info) { } |
107 |
|
1 |
BlessedObject(const shash::Any &id, ObjectType type) |
108 |
|
|
: id(id) |
109 |
|
1 |
, info(type, "") { } |
110 |
|
|
BlessedObject(const shash::Any &id, const std::string &description) |
111 |
|
|
: id(id) |
112 |
|
|
, info(kTypeRegular, description) { } |
113 |
|
168 |
BlessedObject( |
114 |
|
|
const shash::Any &id, |
115 |
|
|
ObjectType type, |
116 |
|
|
const std::string &description) |
117 |
|
|
: id(id) |
118 |
|
168 |
, info(type, description) { } |
119 |
|
|
|
120 |
|
|
shash::Any id; |
121 |
|
|
ObjectInfo info; |
122 |
|
|
}; |
123 |
|
|
// Convenience constructors, users can call Open(CacheManager::Bless(my_hash)) |
124 |
|
420 |
static inline BlessedObject Bless(const shash::Any &id) { |
125 |
|
420 |
return BlessedObject(id); |
126 |
|
|
} |
127 |
|
142 |
static inline BlessedObject Bless( |
128 |
|
|
const shash::Any &id, |
129 |
|
|
const ObjectInfo &info) |
130 |
|
|
{ |
131 |
|
142 |
return BlessedObject(id, info); |
132 |
|
|
} |
133 |
|
1 |
static inline BlessedObject Bless(const shash::Any &id, ObjectType type) { |
134 |
|
1 |
return BlessedObject(id, type); |
135 |
|
|
} |
136 |
|
|
static inline BlessedObject Bless( |
137 |
|
|
const shash::Any &id, |
138 |
|
|
const std::string &description) |
139 |
|
|
{ |
140 |
|
|
return BlessedObject(id, description); |
141 |
|
|
} |
142 |
|
168 |
static inline BlessedObject Bless( |
143 |
|
|
const shash::Any &id, |
144 |
|
|
ObjectType type, |
145 |
|
|
const std::string &description) |
146 |
|
|
{ |
147 |
|
168 |
return BlessedObject(id, type, description); |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
virtual CacheManagerIds id() = 0; |
151 |
|
|
/** |
152 |
|
|
* Return a human readable description of the cache instance. Used in |
153 |
|
|
* cvmfs_talk. |
154 |
|
|
*/ |
155 |
|
|
virtual std::string Describe() = 0; |
156 |
|
|
|
157 |
|
|
virtual bool AcquireQuotaManager(QuotaManager *quota_mgr) = 0; |
158 |
|
|
|
159 |
|
|
virtual ~CacheManager(); |
160 |
|
|
/** |
161 |
|
|
* Opening an object might get it from a third-party source, e.g. when the |
162 |
|
|
* tiered cache manager issues a copy-up operation. In this case it is |
163 |
|
|
* beneficial to register the object with the accurate meta-data, in the same |
164 |
|
|
* way it is done during transactions. |
165 |
|
|
*/ |
166 |
|
|
virtual int Open(const BlessedObject &object) = 0; |
167 |
|
|
virtual int64_t GetSize(int fd) = 0; |
168 |
|
|
virtual int Close(int fd) = 0; |
169 |
|
|
virtual int64_t Pread(int fd, void *buf, uint64_t size, uint64_t offset) = 0; |
170 |
|
|
virtual int Dup(int fd) = 0; |
171 |
|
|
virtual int Readahead(int fd) = 0; |
172 |
|
|
|
173 |
|
|
virtual uint32_t SizeOfTxn() = 0; |
174 |
|
|
virtual int StartTxn(const shash::Any &id, uint64_t size, void *txn) = 0; |
175 |
|
|
virtual void CtrlTxn(const ObjectInfo &object_info, |
176 |
|
|
const int flags, // reserved for future use |
177 |
|
|
void *txn) = 0; |
178 |
|
|
virtual int64_t Write(const void *buf, uint64_t sz, void *txn) = 0; |
179 |
|
|
virtual int Reset(void *txn) = 0; |
180 |
|
|
virtual int AbortTxn(void *txn) = 0; |
181 |
|
|
virtual int OpenFromTxn(void *txn) = 0; |
182 |
|
|
virtual int CommitTxn(void *txn) = 0; |
183 |
|
|
|
184 |
|
|
virtual void Spawn() = 0; |
185 |
|
|
|
186 |
|
|
int OpenPinned(const shash::Any &id, |
187 |
|
|
const std::string &description, |
188 |
|
|
bool is_catalog); |
189 |
|
|
int ChecksumFd(int fd, shash::Any *id); |
190 |
|
|
bool Open2Mem(const shash::Any &id, const std::string &description, |
191 |
|
|
unsigned char **buffer, uint64_t *size); |
192 |
|
|
bool CommitFromMem(const shash::Any &id, |
193 |
|
|
const unsigned char *buffer, |
194 |
|
|
const uint64_t size, |
195 |
|
|
const std::string &description); |
196 |
|
|
|
197 |
|
73 |
QuotaManager *quota_mgr() { return quota_mgr_; } |
198 |
|
|
|
199 |
|
|
// Rescue the open file table during reload of the fuse module. For the |
200 |
|
|
// POSIX cache, nothing needs to be done because the table is keep in the |
201 |
|
|
// kernel for the process. Other cache managers need to do it manually. |
202 |
|
|
void *SaveState(const int fd_progress); |
203 |
|
|
void RestoreState(const int fd_progress, void *state); |
204 |
|
|
void FreeState(const int fd_progress, void *state); |
205 |
|
|
|
206 |
|
|
/** |
207 |
|
|
* While not strictly necessary, cache managers often have a directory |
208 |
|
|
* associated with them. This directory is currently used to find the |
209 |
|
|
* cached manifest copy, the cvmfschecksum.$reponame file. This is important |
210 |
|
|
* to make pre-loaded alien caches work, even in a tiered setup. |
211 |
|
|
*/ |
212 |
|
51 |
virtual std::string GetBackingDirectory() { return ""; } |
213 |
|
|
|
214 |
|
|
protected: |
215 |
|
|
CacheManager(); |
216 |
|
|
|
217 |
|
|
// Unless overwritten, Saving/Restoring states will crash the Fuse module |
218 |
|
|
virtual void *DoSaveState() { return NULL; } |
219 |
|
|
virtual bool DoRestoreState(void *data) { return false; } |
220 |
|
|
virtual bool DoFreeState(void *data) { return false; } |
221 |
|
|
|
222 |
|
|
/** |
223 |
|
|
* Never NULL but defaults to NoopQuotaManager. |
224 |
|
|
*/ |
225 |
|
|
QuotaManager *quota_mgr_; |
226 |
|
|
|
227 |
|
|
private: |
228 |
|
|
static const unsigned kStateVersion = 0; |
229 |
|
|
|
230 |
|
|
/** |
231 |
|
|
* Wraps around the concrete cache manager's state block in memory. The |
232 |
|
|
* state pointer is used in DoSaveState, DoRestoreState, DoFreeState. |
233 |
|
|
*/ |
234 |
|
|
struct State : SingleCopy { |
235 |
|
4 |
State() |
236 |
|
|
: version(kStateVersion) |
237 |
|
|
, manager_type(kUnknownCacheManager) |
238 |
|
4 |
, concrete_state(NULL) |
239 |
|
4 |
{ } |
240 |
|
|
|
241 |
|
|
unsigned version; |
242 |
|
|
CacheManagerIds manager_type; |
243 |
|
|
void *concrete_state; |
244 |
|
|
}; |
245 |
|
|
}; // class CacheManager |
246 |
|
|
|
247 |
|
|
#endif // CVMFS_CACHE_H_ |