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 
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_;
320  if (ctlg_context->manifest_ensemble()->cert_size > 0) {
324  label),
325  ctlg_context->manifest_ensemble()->cert_buf,
326  ctlg_context->manifest_ensemble()->cert_size);
327  }
329  *ctlg_context->manifest_ensemble()->manifest);
330  }
331  }
332  }
333 
334  return load_ret;
335 }
336 
348  const shash::Any &hash,
349  const string &name,
350  const std::string &alt_root_catalog_path,
351  std::string *sqlite_path)
352 {
354  CacheManager::Label label;
355  label.path = name;
357  int fd = fetcher_->Fetch(CacheManager::LabeledObject(hash, label),
358  alt_root_catalog_path);
359  if (fd >= 0) {
360  if (root_fd_ < 0) {
361  root_fd_ = fd;
362  }
363 
365  "FetchCatalogByHash filedescriptor %d", fd);
366  *sqlite_path = "@" + StringifyInt(fd);
367  return kLoadNew;
368  }
369 
370  if (fd == -ENOSPC)
371  return kLoadNoSpace;
372 
373  return kLoadFail;
374 }
375 
377  const shash::Any &hash,
378  const PathString &mountpoint)
379 {
381 
382  CacheManager::Label label;
383  label.path = GetCatalogDescription(mountpoint, hash);
385  int fd = fetcher_->Fetch(CacheManager::LabeledObject(hash, label));
386  if (fd >= 0)
387  fetcher_->cache_mgr()->Close(fd);
388 }
389 
391  LogCvmfs(kLogCache, kLogDebug, "unloading catalog %s",
392  catalog->mountpoint().c_str());
393 
394  map<PathString, shash::Any>::iterator iter =
395  mounted_catalogs_.find(catalog->mountpoint());
396  assert(iter != mounted_catalogs_.end());
397  fetcher_->cache_mgr()->quota_mgr()->Unpin(iter->second);
398  mounted_catalogs_.erase(iter);
399  const catalog::Counters &counters = catalog->GetCounters();
400  loaded_inodes_ -= counters.GetSelfEntries();
401 }
402 
403 
413  uint64_t revision = GetRevision();
414 
415  LogCvmfs(kLogCache, kLogDebug, "checking if %s revision %" PRIu64
416  " is blacklisted", repo_name_.c_str(), revision);
417 
418  vector<string> blacklist = signature_mgr_->GetBlacklist();
419  for (unsigned i = 0; i < blacklist.size(); ++i) {
420  std::string line = blacklist[i];
421  if (line[0] != '<')
422  continue;
423  unsigned idx = repo_name_.length() + 1;
424  if (line.length() <= idx)
425  continue;
426  if ((line[idx] != ' ') && (line[idx] != '\t'))
427  continue;
428  if (line.substr(1, idx - 1) != repo_name_)
429  continue;
430  ++idx;
431  while ((line[idx] == ' ') || (line[idx] == '\t'))
432  ++idx;
433  if (idx >= line.length())
434  continue;
435  uint64_t rev;
436  if (!String2Uint64Parse(line.substr(idx), &rev))
437  continue;
438  if (revision < rev)
439  return true;
440  }
441 
442  return false;
443 }
444 
445 
446 //------------------------------------------------------------------------------
447 
448 
450  CacheManager::Label label;
452  label.path = catalog_mgr_->repo_name();
453  uint64_t size;
454  bool retval = cache_mgr_->Open2Mem(CacheManager::LabeledObject(hash, label),
455  &cert_buf, &size);
456  cert_size = size;
457  if (retval)
459  else
461 }
462 
463 } // 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:536
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:263
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