GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_mgr_client.cc
Date: 2026-07-26 02:35:14
Exec Total Coverage
Lines: 212 233 91.0%
Branches: 189 331 57.1%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM file system.
3 */
4
5
6 #include "catalog_mgr_client.h"
7
8 #include <string>
9 #include <vector>
10
11 #include "cache_posix.h"
12 #include "crypto/signature.h"
13 #include "fetch.h"
14 #include "manifest.h"
15 #include "mountpoint.h"
16 #include "quota.h"
17 #include "statistics.h"
18 #include "util/posix.h" // IWYU pragma: keep
19 #include "util/string.h"
20
21 using namespace std; // NOLINT
22
23 namespace catalog {
24
25 /**
26 * Triggered when the catalog is attached (db file opened)
27 */
28 735 void ClientCatalogManager::ActivateCatalog(Catalog *catalog) {
29 const Counters &counters = const_cast<const Catalog *>(catalog)
30 735 ->GetCounters();
31
2/2
✓ Branch 1 taken 703 times.
✓ Branch 2 taken 32 times.
735 if (catalog->IsRoot()) {
32 703 all_inodes_ = counters.GetAllEntries();
33 }
34 735 loaded_inodes_ += counters.GetSelfEntries();
35 735 }
36
37
38 1123 ClientCatalogManager::ClientCatalogManager(MountPoint *mountpoint)
39 : AbstractCatalogManager<Catalog>(mountpoint->statistics())
40
1/2
✓ Branch 1 taken 1123 times.
✗ Branch 2 not taken.
1123 , repo_name_(mountpoint->fqrn())
41 1123 , fetcher_(mountpoint->fetcher())
42 1123 , signature_mgr_(mountpoint->signature_mgr())
43
1/2
✓ Branch 2 taken 1123 times.
✗ Branch 3 not taken.
1123 , workspace_(mountpoint->file_system()->workspace())
44 1123 , offline_mode_(false)
45 1123 , all_inodes_(0)
46 1123 , loaded_inodes_(0)
47
1/2
✓ Branch 1 taken 1123 times.
✗ Branch 2 not taken.
1123 , fixed_root_catalog_()
48 1123 , fixed_alt_root_catalog_(false)
49
2/4
✓ Branch 5 taken 1123 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1123 times.
✗ Branch 9 not taken.
2246 , root_fd_(-1) {
50
1/2
✓ Branch 1 taken 1123 times.
✗ Branch 2 not taken.
1123 LogCvmfs(kLogCatalog, kLogDebug, "constructing client catalog manager");
51
3/6
✓ Branch 3 taken 1123 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1123 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1123 times.
✗ Branch 11 not taken.
1123 n_certificate_hits_ = mountpoint->statistics()->Register(
52 "cache.n_certificate_hits", "Number of certificate hits");
53
3/6
✓ Branch 3 taken 1123 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1123 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1123 times.
✗ Branch 11 not taken.
1123 n_certificate_misses_ = mountpoint->statistics()->Register(
54 "cache.n_certificate_misses", "Number of certificate misses");
55 1123 }
56
57
58 4112 ClientCatalogManager::~ClientCatalogManager() {
59 2246 LogCvmfs(kLogCache, kLogDebug, "unpinning / unloading all catalogs");
60
61 4492 for (map<PathString, shash::Any>::iterator i = mounted_catalogs_.begin(),
62 2246 iend = mounted_catalogs_.end();
63
2/2
✓ Branch 1 taken 733 times.
✓ Branch 2 taken 1123 times.
3712 i != iend;
64 1466 ++i) {
65 1466 fetcher_->cache_mgr()->quota_mgr()->Unpin(i->second);
66 }
67 4112 }
68
69
70 735 Catalog *ClientCatalogManager::CreateCatalog(const PathString &mountpoint,
71 const shash::Any &catalog_hash,
72 catalog::Catalog *parent_catalog) {
73 735 mounted_catalogs_[mountpoint] = loaded_catalogs_[mountpoint];
74 735 loaded_catalogs_.erase(mountpoint);
75
1/2
✓ Branch 2 taken 735 times.
✗ Branch 3 not taken.
735 return new Catalog(mountpoint, catalog_hash, parent_catalog);
76 }
77
78
79 268 shash::Any ClientCatalogManager::GetRootHash() {
80 268 ReadLock();
81
1/2
✓ Branch 2 taken 268 times.
✗ Branch 3 not taken.
268 shash::Any result = mounted_catalogs_[PathString("", 0)];
82 268 Unlock();
83 268 return result;
84 }
85
86
87 /**
88 * Specialized initialization that uses a fixed root hash.
89 *
90 * @returns true - root catalog was successfully mounted
91 * false - otherwise
92 */
93 373 bool ClientCatalogManager::InitFixed(const shash::Any &root_hash,
94 bool alternative_path) {
95
1/2
✓ Branch 2 taken 373 times.
✗ Branch 3 not taken.
373 LogCvmfs(kLogCatalog, kLogDebug, "Initialize catalog with fixed root hash %s",
96 746 root_hash.ToString().c_str());
97 373 WriteLock();
98 373 fixed_alt_root_catalog_ = alternative_path;
99 373 fixed_root_catalog_ = root_hash;
100
101
1/2
✓ Branch 2 taken 373 times.
✗ Branch 3 not taken.
373 const bool attached = MountCatalog(PathString("", 0), root_hash, NULL);
102 373 Unlock();
103
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 373 times.
373 if (!attached) {
105 LogCvmfs(kLogCatalog, kLogDebug, "failed to initialize fixed root catalog");
106 }
107
108 373 return attached;
109 }
110
111 /**
112 * Gets information about the most recent root catalog, including even if it is
113 * a fixed root catalog. This is needed as Remount() does not know what kind of
114 * root catalog will be remounted.
115 *
116 * Checks the locations: mounted, alien cache and remote (server) and sets the
117 * fields of variable "result". For the most recent catalog the location, hash
118 * and revision number are set.
119 *
120 *
121 * @param [out] result All fields but sqlite_path will be set:
122 * mountpoint, root_ctl_location, root_ctlg_revision, hash
123 * @return kLoadUp2Date - if most recent root catalog is already mounted
124 * kLoadNew - otherwise
125 */
126 554 LoadReturn ClientCatalogManager::GetNewRootCatalogContext(
127 CatalogContext *result) {
128
2/4
✓ Branch 1 taken 554 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 554 times.
✗ Branch 5 not taken.
554 result->SetMountpoint(PathString("", 0));
129
130 // quick escape if we have a fixed catalog
131
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 554 times.
554 if (!fixed_root_catalog_.IsNull()) {
132 result->SetHash(fixed_root_catalog_);
133 result->SetRootCtlgRevision(GetRevisionNoLock());
134
135 // it might or might not be already mounted, but we do not care
136 // as we do no need to download and save the manifest
137 // (see LoadCatalogByHash()) as such we must set the location to this
138 result->SetRootCtlgLocation(kCtlgLocationMounted);
139 offline_mode_ = false;
140
141 // we can do this here as the very first time fixed catalog is loaded it
142 // call directly MountCatalog() and will skip the call to this function
143 // here
144 return catalog::kLoadUp2Date;
145 }
146
147 // 1) Get alien cache root catalog (local)
148
149 // Happens only on init/remount, i.e. quota won't delete a cached catalog
150
1/2
✓ Branch 1 taken 554 times.
✗ Branch 2 not taken.
554 shash::Any local_newest_hash(shash::kSha1, shash::kSuffixCatalog);
151
1/2
✓ Branch 1 taken 554 times.
✗ Branch 2 not taken.
554 shash::Any mounted_hash(shash::kSha1, shash::kSuffixCatalog);
152 554 uint64_t local_newest_timestamp = 0;
153 554 uint64_t local_newest_revision = manifest::Breadcrumb::kInvalidRevision;
154
155 554 const manifest::Breadcrumb breadcrumb = fetcher_->cache_mgr()->LoadBreadcrumb(
156
1/2
✓ Branch 1 taken 554 times.
✗ Branch 2 not taken.
554 repo_name_);
157
3/4
✓ Branch 1 taken 554 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
✓ Branch 4 taken 416 times.
554 if (breadcrumb.IsValid()) {
158 138 local_newest_hash = breadcrumb.catalog_hash;
159 138 local_newest_timestamp = breadcrumb.timestamp;
160 138 local_newest_revision = breadcrumb.revision;
161
1/2
✓ Branch 3 taken 138 times.
✗ Branch 4 not taken.
276 LogCvmfs(kLogCache, kLogDebug,
162 "Cached copy publish date %s (hash %s, revision %" PRIu64 ")",
163
1/2
✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
276 StringifyTime(static_cast<int64_t>(local_newest_timestamp), true)
164 .c_str(),
165
1/2
✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
276 local_newest_hash.ToString().c_str(), breadcrumb.revision);
166 } else {
167
1/2
✓ Branch 2 taken 416 times.
✗ Branch 3 not taken.
416 LogCvmfs(kLogCache, kLogDebug, "Unable to read local checksum %s",
168
1/2
✓ Branch 1 taken 416 times.
✗ Branch 2 not taken.
832 breadcrumb.ToString().c_str());
169 }
170
171 // 2) Select local newest catalog: mounted vs alien
172
173 554 result->SetRootCtlgLocation(kCtlgLocationBreadcrumb);
174 554 LoadReturn success_code = catalog::kLoadNew;
175
176
2/2
✓ Branch 1 taken 102 times.
✓ Branch 2 taken 452 times.
554 if (mounted_catalogs_.size() > 0) {
177 const std::map<PathString, shash::Any>::iterator
178
2/4
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 102 times.
✗ Branch 5 not taken.
102 curr_hash_itr = mounted_catalogs_.find(PathString("", 0));
179 102 mounted_hash = curr_hash_itr->second;
180 }
181
182 // We only look for currently loaded catalog if the revision is newer than
183 // the breadcrumb revision and both revision numbers are valid (!= -1ul).
184 554 if ((local_newest_revision <= GetRevisionNoLock()
185
1/2
✓ Branch 0 taken 416 times.
✗ Branch 1 not taken.
416 || local_newest_revision == manifest::Breadcrumb::kInvalidRevision)
186
6/6
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 138 times.
✓ Branch 3 taken 102 times.
✓ Branch 4 taken 452 times.
✓ Branch 5 taken 102 times.
✓ Branch 6 taken 452 times.
970 && mounted_catalogs_.size() > 0) {
187 102 local_newest_hash = mounted_hash;
188 102 local_newest_revision = GetRevisionNoLock();
189 // if needed for integration test 707: breadcrumb_timestamp_newer()
190 102 local_newest_timestamp = GetTimestampNoLock() > local_newest_timestamp
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 ? GetTimestampNoLock()
192 : local_newest_timestamp;
193 102 result->SetRootCtlgLocation(kCtlgLocationMounted);
194 102 success_code = catalog::kLoadUp2Date;
195
4/6
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 416 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 452 times.
452 } else if (local_newest_revision == 0 && mounted_catalogs_.size() > 0) {
196 // breadcrumb has no revision
197 // TODO(heretherebedragons) this branch can be removed in future versions
198
199 // revisions are better, but if we dont have any we need to compare by
200 // timestamp (you can have multiple revisions in the same timestamp)
201 if (local_newest_timestamp < GetTimestampNoLock()) {
202 local_newest_hash = mounted_hash;
203 local_newest_revision = GetRevisionNoLock();
204 local_newest_timestamp = GetTimestampNoLock();
205 result->SetRootCtlgLocation(kCtlgLocationMounted);
206 success_code = catalog::kLoadUp2Date;
207 }
208 }
209
210 // 3) Get remote root catalog (fails if remote catalog is older)
211 manifest::Failures manifest_failure;
212 UniquePtr<CachedManifestEnsemble> ensemble(
213
2/4
✓ Branch 2 taken 554 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 554 times.
✗ Branch 7 not taken.
554 new CachedManifestEnsemble(fetcher_->cache_mgr(), this));
214
2/4
✓ Branch 1 taken 554 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 554 times.
✗ Branch 5 not taken.
554 manifest_failure = manifest::Fetch(
215 554 "", repo_name_, local_newest_timestamp, &local_newest_hash,
216 554 signature_mgr_, fetcher_->download_mgr(), ensemble.weak_ref());
217
218
2/2
✓ Branch 0 taken 381 times.
✓ Branch 1 taken 173 times.
554 if (manifest_failure == manifest::kFailOk) {
219 // server has newest revision or no valid local revision
220 381 if (ensemble->manifest->revision() > local_newest_revision
221
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 292 times.
379 || local_newest_revision == manifest::Breadcrumb::kInvalidRevision
222 // if revision is 0 both local and server, load catalog from server
223 // as local is most likely just "initialized" without valid value
224
6/6
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 49 times.
✓ Branch 6 taken 332 times.
✓ Branch 7 taken 49 times.
798 || (ensemble->manifest->revision() == 0
225
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 && local_newest_revision == 0)) {
226 332 result->SetHash(ensemble->manifest->catalog_hash());
227 332 result->SetRootCtlgRevision(ensemble->manifest->revision());
228 332 result->SetRootCtlgLocation(kCtlgLocationServer);
229 332 fixed_alt_root_catalog_ = ensemble->manifest->has_alt_catalog_path();
230
231
1/2
✓ Branch 1 taken 332 times.
✗ Branch 2 not taken.
332 result->TakeManifestEnsemble(
232 332 static_cast<manifest::ManifestEnsemble *>(ensemble.Release()));
233 332 offline_mode_ = false;
234
235 332 return catalog::kLoadNew;
236 }
237 }
238
1/2
✓ Branch 2 taken 222 times.
✗ Branch 3 not taken.
222 LogCvmfs(kLogCache, kLogDebug,
239 "Failed fetch manifest from server: "
240 "manifest too old or server unreachable (%d - %s)",
241 manifest_failure, manifest::Code2Ascii(manifest_failure));
242
243 // total failure: server not reachable and no valid local hash
244
6/6
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 49 times.
✓ Branch 3 taken 124 times.
✓ Branch 4 taken 49 times.
✓ Branch 5 taken 124 times.
✓ Branch 6 taken 98 times.
222 if ((manifest_failure != manifest::kFailOk) && local_newest_hash.IsNull()) {
245
1/2
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
124 LogCvmfs(kLogCache, kLogDebug, "No valid root catalog found!");
246 124 return catalog::kLoadFail;
247 }
248
249 98 if (manifest_failure == manifest::kFailOk
250
5/6
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 49 times.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 49 times.
✓ Branch 7 taken 49 times.
98 && ensemble->manifest->revision() == local_newest_revision) {
251 49 offline_mode_ = false;
252 } else {
253 49 offline_mode_ = true;
254 }
255 98 result->SetHash(local_newest_hash);
256 98 result->SetRootCtlgRevision(local_newest_revision);
257
258 // for integration test 707: breadcrumb_revision_large()
259
4/8
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 98 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 98 times.
✗ Branch 9 not taken.
98 if (breadcrumb.IsValid() && breadcrumb.catalog_hash == mounted_hash) {
260 98 success_code = catalog::kLoadUp2Date;
261 }
262
263 98 return success_code;
264 554 }
265
266 1143 std::string ClientCatalogManager::GetCatalogDescription(
267 const PathString &mountpoint, const shash::Any &hash) {
268
2/4
✓ Branch 1 taken 1143 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1143 times.
✗ Branch 5 not taken.
2286 return "file catalog at " + repo_name_ + ":"
269
2/4
✓ Branch 1 taken 1143 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1143 times.
✗ Branch 5 not taken.
3429 + (mountpoint.IsEmpty()
270
8/14
✓ Branch 0 taken 801 times.
✓ Branch 1 taken 342 times.
✓ Branch 4 taken 801 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 342 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 342 times.
✓ Branch 13 taken 801 times.
✓ Branch 15 taken 801 times.
✓ Branch 16 taken 342 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
2628 ? "/"
271 342 : string(mountpoint.GetChars(), mountpoint.GetLength()))
272
3/6
✓ Branch 2 taken 1143 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1143 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1143 times.
✗ Branch 9 not taken.
4572 + " (" + hash.ToString() + ")";
273 }
274
275 /**
276 * Loads (and fetches) a catalog by hash for a given mountpoint.
277 *
278 * Special case for root catalog: ctlg_context->root_ctlg_location must be
279 * given.
280 *
281 * @param [in, out] ctlg_context mandatory fields (input): mountpoint, hash
282 * additional mandatory fields for root catalog: root_ctlg_location
283 * output: sqlite_path is set if catalog fetch successful
284 * @return kLoadUp2Date for root catalog that is already mounted
285 * kLoadNew for any other successful load
286 * kLoadFail on failure
287 */
288 1127 LoadReturn ClientCatalogManager::LoadCatalogByHash(
289 CatalogContext *ctlg_context) {
290
1/2
✓ Branch 1 taken 1127 times.
✗ Branch 2 not taken.
1127 const string catalog_descr = GetCatalogDescription(ctlg_context->mountpoint(),
291
1/2
✓ Branch 2 taken 1127 times.
✗ Branch 3 not taken.
2254 ctlg_context->hash());
292
1/2
✓ Branch 2 taken 1127 times.
✗ Branch 3 not taken.
1127 string alt_root_catalog_path = "";
293
294 // root catalog needs special handling because of alt_root_catalog_path
295
5/8
✓ Branch 1 taken 1127 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 801 times.
✓ Branch 4 taken 326 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 801 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1127 times.
1127 if (ctlg_context->IsRootCatalog() && fixed_alt_root_catalog_) {
296 alt_root_catalog_path = ctlg_context->hash().MakeAlternativePath();
297 }
298
299
1/2
✓ Branch 2 taken 1127 times.
✗ Branch 3 not taken.
2254 const LoadReturn load_ret = FetchCatalogByHash(
300 1127 ctlg_context->hash(), catalog_descr, alt_root_catalog_path,
301 ctlg_context->GetSqlitePathPtr());
302
2/2
✓ Branch 0 taken 1078 times.
✓ Branch 1 taken 49 times.
1127 if (load_ret == catalog::kLoadNew) {
303
2/4
✓ Branch 2 taken 1078 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1078 times.
✗ Branch 6 not taken.
1078 loaded_catalogs_[ctlg_context->mountpoint()] = ctlg_context->hash();
304
305
3/4
✓ Branch 1 taken 1078 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 801 times.
✓ Branch 4 taken 277 times.
1078 if (ctlg_context->IsRootCatalog()) {
306
2/2
✓ Branch 1 taken 471 times.
✓ Branch 2 taken 330 times.
801 if (ctlg_context->root_ctlg_location() == kCtlgLocationMounted) {
307 471 return kLoadUp2Date;
308 }
309
310 // if coming from server: update breadcrumb
311
1/2
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
330 if (ctlg_context->root_ctlg_location() == kCtlgLocationServer) {
312 // Keep a copy of the manifest, it backs the repo_metainfo xattr
313 manifest_ = new manifest::Manifest(
314
4/8
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 330 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 330 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 330 times.
✗ Branch 11 not taken.
330 *ctlg_context->manifest_ensemble()->manifest);
315
316 // Store new manifest and certificate
317 330 CacheManager::Label label;
318
1/2
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
330 label.path = repo_name_;
319 330 label.flags |= CacheManager::kLabelCertificate;
320
3/4
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 293 times.
✓ Branch 4 taken 37 times.
330 if (ctlg_context->manifest_ensemble()->cert_size > 0) {
321
1/2
✓ Branch 2 taken 293 times.
✗ Branch 3 not taken.
586 fetcher_->cache_mgr()->CommitFromMem(
322
1/2
✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
586 CacheManager::LabeledObject(
323 586 ctlg_context->manifest_ensemble()->manifest->certificate(),
324 label),
325
1/2
✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
293 ctlg_context->manifest_ensemble()->cert_buf,
326
2/4
✓ Branch 1 taken 293 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 293 times.
✗ Branch 5 not taken.
293 ctlg_context->manifest_ensemble()->cert_size);
327 }
328 330 fetcher_->cache_mgr()->StoreBreadcrumb(
329
2/4
✓ Branch 1 taken 330 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 330 times.
✗ Branch 5 not taken.
330 *ctlg_context->manifest_ensemble()->manifest);
330 330 }
331 }
332 }
333
334 656 return load_ret;
335 1127 }
336
337 /**
338 * Fetch a catalog by hash either from cache or from remote.
339 * Successful load always returns kLoadNew (independent of the location) and
340 * sets the sqlite_path variable.
341 *
342 * @param [out] sqlite_path of the catalog if successfully fetched
343 * @return kLoadNew on success
344 * kLoadNoSpace out of space, no room on the device to open the catalog
345 * kLoadFail on all other failures
346 */
347 1127 LoadReturn ClientCatalogManager::FetchCatalogByHash(
348 const shash::Any &hash,
349 const string &name,
350 const std::string &alt_root_catalog_path,
351 std::string *sqlite_path) {
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1127 times.
1127 assert(hash.suffix == shash::kSuffixCatalog);
353 1127 CacheManager::Label label;
354
1/2
✓ Branch 1 taken 1127 times.
✗ Branch 2 not taken.
1127 label.path = name;
355 1127 label.flags = CacheManager::kLabelCatalog;
356
2/4
✓ Branch 1 taken 1127 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1127 times.
✗ Branch 5 not taken.
1127 const int fd = fetcher_->Fetch(CacheManager::LabeledObject(hash, label),
357 alt_root_catalog_path);
358
2/2
✓ Branch 0 taken 1078 times.
✓ Branch 1 taken 49 times.
1127 if (fd >= 0) {
359
2/2
✓ Branch 0 taken 701 times.
✓ Branch 1 taken 377 times.
1078 if (root_fd_ < 0) {
360 701 root_fd_ = fd;
361 }
362
363
1/2
✓ Branch 1 taken 1078 times.
✗ Branch 2 not taken.
1078 LogCvmfs(kLogCatalog, kLogDebug, "FetchCatalogByHash filedescriptor %d",
364 fd);
365
2/4
✓ Branch 1 taken 1078 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1078 times.
✗ Branch 5 not taken.
1078 *sqlite_path = "@" + StringifyInt(fd);
366 1078 return kLoadNew;
367 }
368
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 if (fd == -ENOSPC)
370 return kLoadNoSpace;
371
372 49 return kLoadFail;
373 1127 }
374
375 16 void ClientCatalogManager::StageNestedCatalogByHash(
376 const shash::Any &hash, const PathString &mountpoint) {
377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 assert(hash.suffix == shash::kSuffixCatalog);
378
379 16 CacheManager::Label label;
380
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 label.path = GetCatalogDescription(mountpoint, hash);
381 16 label.flags = CacheManager::kLabelCatalog;
382
3/6
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 16 times.
✗ Branch 9 not taken.
16 const int fd = fetcher_->Fetch(CacheManager::LabeledObject(hash, label));
383
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (fd >= 0)
384
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 fetcher_->cache_mgr()->Close(fd);
385 16 }
386
387 2 void ClientCatalogManager::UnloadCatalog(const Catalog *catalog) {
388
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 LogCvmfs(kLogCache, kLogDebug, "unloading catalog %s",
389
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 catalog->mountpoint().c_str());
390
391
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const map<PathString, shash::Any>::iterator iter = mounted_catalogs_.find(
392
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 catalog->mountpoint());
393
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 assert(iter != mounted_catalogs_.end());
394
1/2
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 fetcher_->cache_mgr()->quota_mgr()->Unpin(iter->second);
395
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 mounted_catalogs_.erase(iter);
396 2 const catalog::Counters &counters = catalog->GetCounters();
397
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 loaded_inodes_ -= counters.GetSelfEntries();
398 2 }
399
400
401 /**
402 * Checks if the current repository revision is blacklisted. The format
403 * of the blacklist lines is '<REPO N' where REPO is the repository name,
404 * N is the revision number, and the two parts are separated by whitespace.
405 * Any revision of REPO less than N is blacklisted.
406 * Note: no extra characters are allowed after N, not even whitespace.
407 * @return true if it is blacklisted, false otherwise
408 */
409 701 bool ClientCatalogManager::IsRevisionBlacklisted() {
410 701 const uint64_t revision = GetRevision();
411
412
1/2
✓ Branch 2 taken 701 times.
✗ Branch 3 not taken.
701 LogCvmfs(kLogCache, kLogDebug,
413 "checking if %s revision %" PRIu64 " is blacklisted",
414 repo_name_.c_str(), revision);
415
416
1/2
✓ Branch 1 taken 701 times.
✗ Branch 2 not taken.
701 vector<string> blacklist = signature_mgr_->GetBlacklist();
417
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 665 times.
701 for (unsigned i = 0; i < blacklist.size(); ++i) {
418
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 std::string line = blacklist[i];
419
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
36 if (line[0] != '<')
420 continue;
421 36 unsigned idx = repo_name_.length() + 1;
422
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (line.length() <= idx)
423 continue;
424
3/10
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 36 times.
36 if ((line[idx] != ' ') && (line[idx] != '\t'))
425 continue;
426
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
36 if (line.substr(1, idx - 1) != repo_name_)
427 continue;
428 36 ++idx;
429
5/10
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 36 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 36 times.
36 while ((line[idx] == ' ') || (line[idx] == '\t'))
430 ++idx;
431
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
36 if (idx >= line.length())
432 continue;
433 uint64_t rev;
434
3/6
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
36 if (!String2Uint64Parse(line.substr(idx), &rev))
435 continue;
436
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (revision < rev)
437 36 return true;
438
1/3
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
36 }
439
440 665 return false;
441 701 }
442
443
444 //------------------------------------------------------------------------------
445
446
447 366 void CachedManifestEnsemble::FetchCertificate(const shash::Any &hash) {
448 366 CacheManager::Label label;
449 366 label.flags |= CacheManager::kLabelCertificate;
450
1/2
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
366 label.path = catalog_mgr_->repo_name();
451 uint64_t size;
452
1/2
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
366 const bool retval = cache_mgr_->Open2Mem(
453
1/2
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
732 CacheManager::LabeledObject(hash, label), &cert_buf, &size);
454 366 cert_size = size;
455
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 364 times.
366 if (retval)
456 2 perf::Inc(catalog_mgr_->n_certificate_hits_);
457 else
458 364 perf::Inc(catalog_mgr_->n_certificate_misses_);
459 366 }
460
461 } // namespace catalog
462