CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
catalog_mgr_client.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
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 
29 void ClientCatalogManager::ActivateCatalog(Catalog *catalog) {
30  const Counters &counters = const_cast<const Catalog*>(catalog)->GetCounters();
31  if (catalog->IsRoot()) {
32  all_inodes_ = counters.GetAllEntries();
33  }
34  loaded_inodes_ += counters.GetSelfEntries();
35 }
36 
37 
38 ClientCatalogManager::ClientCatalogManager(MountPoint *mountpoint)
39  : AbstractCatalogManager<Catalog>(mountpoint->statistics())
40  , repo_name_(mountpoint->fqrn())
41  , fetcher_(mountpoint->fetcher())
42  , signature_mgr_(mountpoint->signature_mgr())
43  , workspace_(mountpoint->file_system()->workspace())
44  , offline_mode_(false)
45  , all_inodes_(0)
46  , loaded_inodes_(0)
47  , fixed_root_catalog_()
48  , fixed_alt_root_catalog_(false)
49  , root_fd_(-1)
50 {
51  LogCvmfs(kLogCatalog, kLogDebug, "constructing client catalog manager");
52  n_certificate_hits_ = mountpoint->statistics()->Register(
53  "cache.n_certificate_hits", "Number of certificate hits");
54  n_certificate_misses_ = mountpoint->statistics()->Register(
55  "cache.n_certificate_misses", "Number of certificate misses");
56 }
57 
58 
60  LogCvmfs(kLogCache, kLogDebug, "unpinning / unloading all catalogs");
61 
62  for (map<PathString, shash::Any>::iterator i = mounted_catalogs_.begin(),
63  iend = mounted_catalogs_.end(); i != iend; ++i)
64  {
65  fetcher_->cache_mgr()->quota_mgr()->Unpin(i->second);
66  }
67 }
68 
69 
71  const PathString &mountpoint,
72  const shash::Any &catalog_hash,
73  catalog::Catalog *parent_catalog
74 ) {
75  mounted_catalogs_[mountpoint] = loaded_catalogs_[mountpoint];
76  loaded_catalogs_.erase(mountpoint);
77  return new Catalog(mountpoint, catalog_hash, parent_catalog);
78 }
79 
80 
82  ReadLock();
83  shash::Any result = mounted_catalogs_[PathString("", 0)];
84  Unlock();
85  return result;
86 }
87 
88 
96  const shash::Any &root_hash,
97  bool alternative_path)
98 {
99  LogCvmfs(kLogCatalog, kLogDebug, "Initialize catalog with fixed root hash %s",
100  root_hash.ToString().c_str());
101  WriteLock();
102  fixed_alt_root_catalog_ = alternative_path;
103  fixed_root_catalog_ = root_hash;
104 
105  bool attached = MountCatalog(PathString("", 0), root_hash, NULL);
106  Unlock();
107 
108  if (!attached) {
109  LogCvmfs(kLogCatalog, kLogDebug, "failed to initialize fixed root catalog");
110  }
111 
112  return attached;
113 }
114 
131  CatalogContext *result) {
132  result->SetMountpoint(PathString("", 0));
133 
134  // quick escape if we have a fixed catalog
135  if (!fixed_root_catalog_.IsNull()) {
136  result->SetHash(fixed_root_catalog_);
138 
139  // it might or might not be already mounted, but we do not care
140  // as we do no need to download and save the manifest
141  // (see LoadCatalogByHash()) as such we must set the location to this
143  offline_mode_ = false;
144 
145  // we can do this here as the very first time fixed catalog is loaded it
146  // call directly MountCatalog() and will skip the call to this function
147  // here
148  return catalog::kLoadUp2Date;
149  }
150 
151  // 1) Get alien cache root catalog (local)
152 
153  // Happens only on init/remount, i.e. quota won't delete a cached catalog
154  shash::Any local_newest_hash(shash::kSha1, shash::kSuffixCatalog);
156  uint64_t local_newest_timestamp = 0;
157  uint64_t local_newest_revision = manifest::Breadcrumb::kInvalidRevision;
158 
159  manifest::Breadcrumb breadcrumb =
161  if (breadcrumb.IsValid()) {
162  local_newest_hash = breadcrumb.catalog_hash;
163  local_newest_timestamp = breadcrumb.timestamp;
164  local_newest_revision = breadcrumb.revision;
166  "Cached copy publish date %s (hash %s, revision %" PRIu64 ")",
167  StringifyTime(static_cast<int64_t>(local_newest_timestamp), true).c_str(),
168  local_newest_hash.ToString().c_str(), breadcrumb.revision);
169  } else {
170  LogCvmfs(kLogCache, kLogDebug, "Unable to read local checksum %s",
171  breadcrumb.ToString().c_str());
172  }
173 
174  // 2) Select local newest catalog: mounted vs alien
175 
177  LoadReturn success_code = catalog::kLoadNew;
178 
179  if (mounted_catalogs_.size() > 0) {
180  const std::map<PathString, shash::Any>::iterator curr_hash_itr =
181  mounted_catalogs_.find(PathString("", 0));
182  mounted_hash = curr_hash_itr->second;
183  }
184 
185  // We only look for currently loaded catalog if the revision is newer than
186  // the breadcrumb revision and both revision numbers are valid (!= -1ul).
187  if ((local_newest_revision <= GetRevisionNoLock()
188  || local_newest_revision == manifest::Breadcrumb::kInvalidRevision)
189  && mounted_catalogs_.size() > 0) {
190  local_newest_hash = mounted_hash;
191  local_newest_revision = GetRevisionNoLock();
192  // if needed for integration test 707: breadcrumb_timestamp_newer()
193  local_newest_timestamp = GetTimestampNoLock() > local_newest_timestamp ?
194  GetTimestampNoLock() : local_newest_timestamp;
196  success_code = catalog::kLoadUp2Date;
197  } else if (local_newest_revision == 0 && mounted_catalogs_.size() > 0) {
198  // breadcrumb has no revision
199  // TODO(heretherebedragons) this branch can be removed in future versions
200 
201  // revisions are better, but if we dont have any we need to compare by
202  // timestamp (you can have multiple revisions in the same timestamp)
203  if (local_newest_timestamp < GetTimestampNoLock()) {
204  local_newest_hash = mounted_hash;
205  local_newest_revision = GetRevisionNoLock();
206  local_newest_timestamp = GetTimestampNoLock();
208  success_code = catalog::kLoadUp2Date;
209  }
210  }
211 
212  // 3) Get remote root catalog (fails if remote catalog is older)
213  manifest::Failures manifest_failure;
216  manifest_failure = manifest::Fetch("", repo_name_, local_newest_timestamp,
217  &local_newest_hash, signature_mgr_,
219  ensemble.weak_ref());
220 
221  if (manifest_failure == manifest::kFailOk) {
222  // server has newest revision or no valid local revision
223  if (ensemble->manifest->revision() > local_newest_revision
224  || local_newest_revision == manifest::Breadcrumb::kInvalidRevision
225  // if revision is 0 both local and server, load catalog from server
226  // as local is most likely just "initialized" without valid value
227  || (ensemble->manifest->revision() == 0 &&
228  local_newest_revision == 0)) {
229  result->SetHash(ensemble->manifest->catalog_hash());
230  result->SetRootCtlgRevision(ensemble->manifest->revision());
232  fixed_alt_root_catalog_ = ensemble->manifest->has_alt_catalog_path();
233 
234  result->TakeManifestEnsemble(
235  static_cast<manifest::ManifestEnsemble*>(
236  ensemble.Release()));
237  offline_mode_ = false;
238 
239  return catalog::kLoadNew;
240  }
241  }
243  "Failed fetch manifest from server: "
244  "manifest too old or server unreachable (%d - %s)",
245  manifest_failure, manifest::Code2Ascii(manifest_failure));
246 
247  // total failure: server not reachable and no valid local hash
248  if ((manifest_failure != manifest::kFailOk) && local_newest_hash.IsNull()) {
249  LogCvmfs(kLogCache, kLogDebug, "No valid root catalog found!");
250  return catalog::kLoadFail;
251  }
252 
253  if (manifest_failure == manifest::kFailOk
254  && ensemble->manifest->revision() == local_newest_revision) {
255  offline_mode_ = false;
256  } else {
257  offline_mode_ = true;
258  }
259  result->SetHash(local_newest_hash);
260  result->SetRootCtlgRevision(local_newest_revision);
261 
262  // for integration test 707: breadcrumb_revision_large()
263  if (breadcrumb.IsValid() && breadcrumb.catalog_hash == mounted_hash) {
264  success_code = catalog::kLoadUp2Date;
265  }
266 
267  return success_code;
268 }
269 
271  const PathString &mountpoint, const shash::Any &hash)
272 {
273  return "file catalog at " + repo_name_ + ":" +
274  (mountpoint.IsEmpty() ? "/"
275  : string(mountpoint.GetChars(),
276  mountpoint.GetLength())) +
277  " (" + hash.ToString() + ")";
278 }
279 
293  CatalogContext *ctlg_context) {
294  string catalog_descr = GetCatalogDescription(ctlg_context->mountpoint(),
295  ctlg_context->hash());
296  string alt_root_catalog_path = "";
297 
298  // root catalog needs special handling because of alt_root_catalog_path
299  if (ctlg_context->IsRootCatalog() && fixed_alt_root_catalog_) {
300  alt_root_catalog_path = ctlg_context->hash().MakeAlternativePath();
301  }
302 
303  const LoadReturn load_ret = FetchCatalogByHash(ctlg_context->hash(),
304  catalog_descr, alt_root_catalog_path,
305  ctlg_context->GetSqlitePathPtr());
306  if (load_ret == catalog::kLoadNew) {
307  loaded_catalogs_[ctlg_context->mountpoint()] = ctlg_context->hash();
308 
309  if (ctlg_context->IsRootCatalog()) {
310  if (ctlg_context->root_ctlg_location() == kCtlgLocationMounted) {
311  return kLoadUp2Date;
312  }
313 
314  // if coming from server: update breadcrumb
315  if (ctlg_context->root_ctlg_location() == kCtlgLocationServer) {
316  // Store new manifest and certificate
317  CacheManager::Label label;
318  label.path = repo_name_;
323  label),
324  ctlg_context->manifest_ensemble()->cert_buf,
325  ctlg_context->manifest_ensemble()->cert_size);
327  *ctlg_context->manifest_ensemble()->manifest);
328  }
329  }
330  }
331 
332  return load_ret;
333 }
334 
346  const shash::Any &hash,
347  const string &name,
348  const std::string &alt_root_catalog_path,
349  std::string *sqlite_path)
350 {
352  CacheManager::Label label;
353  label.path = name;
355  int fd = fetcher_->Fetch(CacheManager::LabeledObject(hash, label),
356  alt_root_catalog_path);
357  if (fd >= 0) {
358  if (root_fd_ < 0) {
359  root_fd_ = fd;
360  }
361 
363  "FetchCatalogByHash filedescriptor %d", fd);
364  *sqlite_path = "@" + StringifyInt(fd);
365  return kLoadNew;
366  }
367 
368  if (fd == -ENOSPC)
369  return kLoadNoSpace;
370 
371  return kLoadFail;
372 }
373 
375  const shash::Any &hash,
376  const PathString &mountpoint)
377 {
379 
380  CacheManager::Label label;
381  label.path = GetCatalogDescription(mountpoint, hash);
383  int fd = fetcher_->Fetch(CacheManager::LabeledObject(hash, label));
384  if (fd >= 0)
385  fetcher_->cache_mgr()->Close(fd);
386 }
387 
389  LogCvmfs(kLogCache, kLogDebug, "unloading catalog %s",
390  catalog->mountpoint().c_str());
391 
392  map<PathString, shash::Any>::iterator iter =
393  mounted_catalogs_.find(catalog->mountpoint());
394  assert(iter != mounted_catalogs_.end());
395  fetcher_->cache_mgr()->quota_mgr()->Unpin(iter->second);
396  mounted_catalogs_.erase(iter);
397  const catalog::Counters &counters = catalog->GetCounters();
398  loaded_inodes_ -= counters.GetSelfEntries();
399 }
400 
401 
411  uint64_t revision = GetRevision();
412 
413  LogCvmfs(kLogCache, kLogDebug, "checking if %s revision %" PRIu64
414  " is blacklisted", repo_name_.c_str(), revision);
415 
416  vector<string> blacklist = signature_mgr_->GetBlacklist();
417  for (unsigned i = 0; i < blacklist.size(); ++i) {
418  std::string line = blacklist[i];
419  if (line[0] != '<')
420  continue;
421  unsigned idx = repo_name_.length() + 1;
422  if (line.length() <= idx)
423  continue;
424  if ((line[idx] != ' ') && (line[idx] != '\t'))
425  continue;
426  if (line.substr(1, idx - 1) != repo_name_)
427  continue;
428  ++idx;
429  while ((line[idx] == ' ') || (line[idx] == '\t'))
430  ++idx;
431  if (idx >= line.length())
432  continue;
433  uint64_t rev;
434  if (!String2Uint64Parse(line.substr(idx), &rev))
435  continue;
436  if (revision < rev)
437  return true;
438  }
439 
440  return false;
441 }
442 
443 
444 //------------------------------------------------------------------------------
445 
446 
448  CacheManager::Label label;
450  label.path = catalog_mgr_->repo_name();
451  uint64_t size;
452  bool retval = cache_mgr_->Open2Mem(CacheManager::LabeledObject(hash, label),
453  &cert_buf, &size);
454  cert_size = size;
455  if (retval)
457  else
459 }
460 
461 } // namespace catalog
shash::Any hash() const
Definition: catalog_mgr.h:125
Counter * Register(const std::string &name, const std::string &desc)
Definition: statistics.cc:160
const Counters & GetCounters() const
Definition: catalog.h:175
bool IsNull() const
Definition: hash.h:383
bool IsRoot() const
Definition: catalog.h:193
download::DownloadManager * download_mgr()
Definition: fetch.h:128
uint64_t timestamp
Definition: manifest.h:40
std::string MakeAlternativePath() const
Definition: hash.h:325
perf::Statistics * statistics()
Definition: mountpoint.h:534
shash::Any catalog_hash
Definition: manifest.h:39
static const int kLabelCatalog
Definition: cache.h:80
virtual void Unpin(const shash::Any &hash)=0
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:249
CacheManager * cache_mgr()
Definition: fetch.h:127
static const uint64_t kInvalidRevision
Definition: manifest.h:23
RootCatalogLocation root_ctlg_location() const
Definition: catalog_mgr.h:129
virtual manifest::Breadcrumb LoadBreadcrumb(const std::string &)
Definition: cache.h:217
virtual void StageNestedCatalogByHash(const shash::Any &hash, const PathString &mountpoint)
Counters_t GetSelfEntries() const
assert((mem||(size==0))&&"Out Of Memory")
virtual bool StoreBreadcrumb(const manifest::Manifest &)
Definition: cache.h:220
string StringifyTime(const time_t seconds, const bool utc)
Definition: string.cc:105
std::map< PathString, shash::Any > loaded_catalogs_
bool String2Uint64Parse(const std::string &value, uint64_t *result)
Definition: string.cc:245
manifest::ManifestEnsemble * manifest_ensemble() const
Definition: catalog_mgr.h:131
uint64_t revision
Definition: manifest.h:41
void SetMountpoint(const PathString &mountpoint)
Definition: catalog_mgr.h:135
std::string repo_name() const
void TakeManifestEnsemble(manifest::ManifestEnsemble *manifest_ensemble)
Definition: catalog_mgr.h:145
static const int kLabelCertificate
Definition: cache.h:85
LoadReturn FetchCatalogByHash(const shash::Any &hash, const std::string &name, const std::string &alt_catalog_path, std::string *catalog_path)
int Fetch(const CacheManager::LabeledObject &object, const std::string &alt_url="")
Definition: fetch.cc:81
signature::SignatureManager * signature_mgr_
Definition: repository.h:140
bool CommitFromMem(const LabeledObject &object, const unsigned char *buffer, const uint64_t size)
Definition: cache.cc:79
const char kSuffixCatalog
Definition: hash.h:54
std::map< PathString, shash::Any > mounted_catalogs_
Failures Fetch(const std::string &base_url, const std::string &repository_name, const uint64_t minimum_timestamp, const shash::Any *base_catalog, signature::SignatureManager *signature_manager, download::DownloadManager *download_manager, ManifestEnsemble *ensemble)
const signature::SignatureManager * signature_mgr() const
Definition: repository.h:121
shash::Any certificate() const
Definition: manifest.h:134
void FetchCertificate(const shash::Any &hash)
PathString mountpoint() const
Definition: catalog.h:179
virtual LoadReturn LoadCatalogByHash(CatalogContext *ctlg_context)
string StringifyInt(const int64_t value)
Definition: string.cc:78
void Inc(class Counter *counter)
Definition: statistics.h:50
ClientCatalogManager * catalog_mgr_
virtual int Close(int fd)=0
void SetRootCtlgLocation(RootCatalogLocation root_ctlg_location)
Definition: catalog_mgr.h:140
bool InitFixed(const shash::Any &root_hash, bool alternative_path)
std::string GetCatalogDescription(const PathString &mountpoint, const shash::Any &hash)
signature::SignatureManager * signature_mgr_
QuotaManager * quota_mgr()
Definition: cache.h:193
catalog::Catalog * CreateCatalog(const PathString &mountpoint, const shash::Any &catalog_hash, catalog::Catalog *parent_catalog)
std::string * GetSqlitePathPtr()
Definition: catalog_mgr.h:122
bool IsEmpty() const
Definition: shortstring.h:137
std::string ToString() const
Definition: manifest.cc:72
ShortString< kDefaultMaxPath, 0 > PathString
Definition: shortstring.h:217
PathString mountpoint() const
Definition: catalog_mgr.h:126
Catalog * MountCatalog(const PathString &mountpoint, const shash::Any &hash, Catalog *parent_catalog)
bool IsValid() const
Definition: manifest.h:35
virtual LoadReturn GetNewRootCatalogContext(CatalogContext *result)
std::string path
Definition: cache.h:133
bool Open2Mem(const LabeledObject &object, unsigned char **buffer, uint64_t *size)
Definition: cache.cc:126
void SetHash(shash::Any hash)
Definition: catalog_mgr.h:134
manifest::Manifest * manifest() const
unsigned GetLength() const
Definition: shortstring.h:131
Suffix suffix
Definition: hash.h:126
Counters_t GetAllEntries() const
const char * c_str() const
Definition: shortstring.h:145
const char * GetChars() const
Definition: shortstring.h:123
static void size_t size
Definition: smalloc.h:54
std::vector< std::string > GetBlacklist()
Definition: signature.cc:578
void UnloadCatalog(const catalog::Catalog *catalog)
void SetRootCtlgRevision(uint64_t root_ctlg_revision)
Definition: catalog_mgr.h:138
const char * Code2Ascii(const Failures error)
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528