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