GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/cache.h
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 31 40 77.5%
Branches: 8 10 80.0%

Line Branch Exec Source
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 "compression.h"
17 #include "crypto/hash.h"
18 #include "manifest.h"
19 #include "util/pointer.h"
20
21
22 class QuotaManager;
23
24 enum CacheManagerIds {
25 kUnknownCacheManager = 0,
26 kPosixCacheManager,
27 kRamCacheManager,
28 kTieredCacheManager,
29 kExternalCacheManager,
30 kStreamingCacheManager,
31 };
32
33 enum CacheModes {
34 kCacheReadWrite = 0,
35 kCacheReadOnly,
36 };
37
38
39 /**
40 * The Cache Manager provides (virtual) file descriptors to content-addressable
41 * objects in the cache. The implementation can use a POSIX file system or
42 * other means such as a key-value store. A file descriptor must remain
43 * readable until closed, no matter if it is removed from the backend storage
44 * or not (POSIX semantics).
45 *
46 * Writing into the cache is streamed and transactional: a file descriptor must
47 * be acquired from StartTxn and the object is only visible in the cache after
48 * CommitTxn. The state of the transaction is carried in an opque transaction
49 * object, which needs to be provided by the caller. The size of the object is
50 * returned by SizeOfTxn. This way, users of derived classes can take care of
51 * the storage allocation (e.g. on the stack), while the derived class
52 * determines the contents of the transaction object. For race-free read access
53 * to objects that are just being written to the cache, the OpenFromTxn routine
54 * is used just before the transaction is committed.
55 *
56 * Writing to the cache can be coupled to a quota manager. The quota manager
57 * maintains some extra information for data chunks: whether they are
58 * volatile, whether they are pinned, and a description (usually the path that
59 * corresponds to a data chunk). By default the NoopQuotaManager is used, which
60 * ignores all this extra information. The CtrlTxn() function is used to
61 * specify this extra information sometime between StartTxn() and CommitTxn().
62 *
63 * The integer return values can be negative and, in this case, represent a
64 * -errno failure code. Otherwise the return value 0 indicates a success, or
65 * >= 0 for a file descriptor.
66 */
67 class CacheManager : SingleCopy {
68 public:
69 /**
70 * Sizes of objects should be known for StartTxn(). For file catalogs we
71 * cannot ensure that, however, because the size field for nested catalogs
72 * was only recently added.
73 */
74 static const uint64_t kSizeUnknown;
75
76 /**
77 * Relevant for the quota management and for downloading (URL construction).
78 * Used in Label::flags.
79 */
80 static const int kLabelCatalog = 0x01;
81 static const int kLabelPinned = 0x02;
82 static const int kLabelVolatile = 0x04;
83 static const int kLabelExternal = 0x08;
84 static const int kLabelChunked = 0x10;
85 static const int kLabelCertificate = 0x20;
86 static const int kLabelMetainfo = 0x40;
87 static const int kLabelHistory = 0x80;
88
89 /**
90 * Meta-data of an object that the cache may or may not maintain/use.
91 * Good cache implementations should at least distinguish between volatile
92 * and regular objects. The data in the label are sufficient to download an
93 * object, if necessary.
94 */
95 struct Label {
96 4840 Label() : flags(0)
97 4840 , size(kSizeUnknown)
98 4840 , zip_algorithm(zlib::kZlibDefault)
99 4840 , range_offset(-1)
100 4840 {}
101
102 260 bool IsCatalog() const { return flags & kLabelCatalog; }
103 135 bool IsPinned() const { return flags & kLabelPinned; }
104 46 bool IsExternal() const { return flags & kLabelExternal; }
105 1 bool IsCertificate() const { return flags & kLabelCertificate; }
106
107 /**
108 * The description for the quota manager
109 */
110 3177 std::string GetDescription() const {
111
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 3131 times.
3177 if (flags & kLabelCatalog)
112 46 return "file catalog at " + path;
113
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3120 times.
3131 if (flags & kLabelCertificate)
114 11 return "certificate for " + path;
115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3120 times.
3120 if (flags & kLabelMetainfo)
116 return "metainfo for " + path;
117
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3119 times.
3120 if (flags & kLabelHistory)
118 1 return "tag database for " + path;
119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3119 times.
3119 if (flags & kLabelChunked)
120 return "Part of " + path;
121 3119 return path;
122 }
123
124 int flags;
125 uint64_t size; ///< unzipped size, if known
126 zlib::Algorithms zip_algorithm;
127 off_t range_offset;
128 /**
129 * The logical path on the mountpoint connected to the object. For meta-
130 * data objects, e.g. certificate, catalog, it's the repository name (which
131 * does not start with a slash).
132 */
133 std::string path;
134 };
135
136 /**
137 * A content hash together with the meta-data from a (partial) label.
138 */
139 struct LabeledObject {
140 493 explicit LabeledObject(const shash::Any &id) : id(id), label() { }
141 2154 LabeledObject(const shash::Any &id, const Label &l)
142 2154 : id(id)
143 2154 , label(l) { }
144
145 shash::Any id;
146 Label label;
147 };
148
149 virtual CacheManagerIds id() = 0;
150 /**
151 * Return a human readable description of the cache instance. Used in
152 * cvmfs_talk.
153 */
154 virtual std::string Describe() = 0;
155
156 virtual bool AcquireQuotaManager(QuotaManager *quota_mgr) = 0;
157
158 virtual ~CacheManager();
159 /**
160 * Opening an object might get it from a third-party source, e.g. when the
161 * tiered cache manager issues a copy-up operation. In this case it is
162 * beneficial to register the object with the accurate meta-data, in the same
163 * way it is done during transactions.
164 */
165 virtual int Open(const LabeledObject &object) = 0;
166 virtual int64_t GetSize(int fd) = 0;
167 virtual int Close(int fd) = 0;
168 virtual int64_t Pread(int fd, void *buf, uint64_t size, uint64_t offset) = 0;
169 virtual int Dup(int fd) = 0;
170 virtual int Readahead(int fd) = 0;
171
172 virtual uint32_t SizeOfTxn() = 0;
173 virtual int StartTxn(const shash::Any &id, uint64_t size, void *txn) = 0;
174 virtual void CtrlTxn(const Label &label,
175 const int flags, // reserved for future use
176 void *txn) = 0;
177 virtual int64_t Write(const void *buf, uint64_t sz, void *txn) = 0;
178 virtual int Reset(void *txn) = 0;
179 virtual int AbortTxn(void *txn) = 0;
180 virtual int OpenFromTxn(void *txn) = 0;
181 virtual int CommitTxn(void *txn) = 0;
182
183 virtual void Spawn() = 0;
184
185 int ChecksumFd(int fd, shash::Any *id);
186 int OpenPinned(const LabeledObject &object);
187 bool Open2Mem(const LabeledObject &object,
188 unsigned char **buffer, uint64_t *size);
189 bool CommitFromMem(const LabeledObject &object,
190 const unsigned char *buffer,
191 const uint64_t size);
192
193 43 QuotaManager *quota_mgr() { return quota_mgr_; }
194
195 // Rescue the open file table during reload of the fuse module. For the
196 // POSIX cache, nothing needs to be done because the table is keep in the
197 // kernel for the process. Other cache managers need to do it manually.
198 void *SaveState(const int fd_progress);
199 /**
200 * When RestoreState is called, the cache has already exactly one file
201 * descriptor open: the root file catalog. This file descriptor might be
202 * remapped to another number. A return value of -1 means no action needs
203 * to take place. A smaller value indicates an error.
204 */
205 int RestoreState(const int fd_progress, void *state);
206 void FreeState(const int fd_progress, void *state);
207 CacheManagerIds PeekState(void *state) {
208 return static_cast<State *>(state)->manager_type;
209 }
210
211 /**
212 * While not strictly necessary, cache managers often have a directory
213 * associated with them. This directory is currently used to find the
214 * cached manifest copy, the cvmfschecksum.$reponame file. This is important
215 * to make pre-loaded alien caches work, even in a tiered setup.
216 */
217 11 virtual manifest::Breadcrumb LoadBreadcrumb(const std::string & /*fqrn*/) {
218 11 return manifest::Breadcrumb();
219 }
220 virtual bool StoreBreadcrumb(const manifest::Manifest &/*manifest*/) {
221 return false;
222 }
223
224 protected:
225 CacheManager();
226
227 // Unless overwritten, Saving/Restoring states will crash the Fuse module
228 virtual void *DoSaveState() { return NULL; }
229 virtual int DoRestoreState(void *data) { return false; }
230 virtual bool DoFreeState(void *data) { return false; }
231
232 /**
233 * Never NULL but defaults to NoopQuotaManager.
234 */
235 QuotaManager *quota_mgr_;
236
237 private:
238 static const unsigned kStateVersion = 0;
239
240 /**
241 * Wraps around the concrete cache manager's state block in memory. The
242 * state pointer is used in DoSaveState, DoRestoreState, DoFreeState.
243 */
244 struct State : SingleCopy {
245 4 State()
246 8 : version(kStateVersion)
247 4 , manager_type(kUnknownCacheManager)
248 4 , concrete_state(NULL)
249 4 { }
250
251 unsigned version;
252 CacheManagerIds manager_type;
253 void *concrete_state;
254 };
255 }; // class CacheManager
256
257 #endif // CVMFS_CACHE_H_
258