GCC Code Coverage Report


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