CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
repository_transaction.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
6 #include "publish/repository.h"
7 
8 #include <string>
9 
10 #include "backoff.h"
11 #include "catalog_mgr_ro.h"
12 #include "catalog_mgr_rw.h"
13 #include "directory_entry.h"
14 #include "logging.h"
15 #include "manifest.h"
16 #include "publish/except.h"
18 #include "publish/settings.h"
19 #include "util/exception.h"
20 #include "util/pointer.h"
21 #include "util/posix.h"
22 
23 namespace publish {
24 
26  // The process that opens the transaction does not stay alive for the life
27  // time of the transaction
28  const std::string transaction_lock =
29  settings_.transaction().spool_area().transaction_lock();
31  ServerLockFile::IsLocked(transaction_lock, true /* ignore_stale */);
32 
33  const std::string publishing_lock =
34  settings_.transaction().spool_area().publishing_lock();
36  ServerLockFile::IsLocked(publishing_lock, false /* ignore_stale */);
37 
39 }
40 
41 
43  if (managed_node_) {
44  int rvi = managed_node_->Check(false /* is_quiet */);
45  if (rvi != 0) throw EPublish("cannot establish writable mountpoint");
46  }
47 
48  BackoffThrottle throttle(500, 5000, 10000);
49  // Negative timeouts (i.e.: no retry) will result in a deadline that has
50  // already passed and thus has the correct effect
51  uint64_t deadline = platform_monotonic_time() +
52  settings_.transaction().GetTimeoutS();
53  if (settings_.transaction().GetTimeoutS() == 0)
54  deadline = uint64_t(-1);
55 
56  while (true) {
57  try {
59  break;
60  } catch (const publish::EPublish& e) {
62  session_->Drop();
64  settings_.transaction().spool_area().transaction_lock());
65  }
66 
69  {
70  if (platform_monotonic_time() > deadline)
71  throw;
72 
73  LogCvmfs(kLogCvmfs, kLogStdout, "repository busy, retrying");
74  throttle.Throttle();
76  continue;
77  }
78 
79  throw;
80  } // try-catch
81  } // while (true)
82 
83  if (managed_node_)
84  managed_node_->Open();
85 }
86 
87 
89  if (in_transaction_) {
90  throw EPublish("another transaction is already open",
92  }
93 
94  InitSpoolArea();
95 
96  // On error, Transaction() will release the transaction lock and drop
97  // the session
98  const std::string transaction_lock =
99  settings_.transaction().spool_area().transaction_lock();
100  ServerLockFile::Acquire(transaction_lock, true /* ignore_stale */);
101  session_->Acquire();
102 
103  // We might have a valid lease for a non-existing path. Nevertheless, we run
104  // run into problems when merging catalogs later, so for the time being we
105  // disallow transactions on non-existing paths.
106  if (!settings_.transaction().lease_path().empty()) {
107  std::string path = GetParentPath(
108  "/" + settings_.transaction().lease_path());
111  bool retval = catalog_mgr->LookupPath(path, catalog::kLookupSole, &dirent);
112  if (!retval) {
113  throw EPublish("cannot open transaction on non-existing path " + path,
115  }
116  if (!dirent.IsDirectory()) {
117  throw EPublish(
118  "cannot open transaction on " + path + ", which is not a directory",
120  }
121  }
122 
124 
126  settings_.transaction().spool_area().checkout_marker()));
127  // TODO(jblomer): take root hash from r/o mountpoint?
128  if (marker.IsValid())
129  settings_.GetTransaction()->SetBaseHash(marker->hash());
130  else
131  settings_.GetTransaction()->SetBaseHash(manifest_->catalog_hash());
132 
133  if (settings_.transaction().HasTemplate()) {
135  "CernVM-FS: cloning template %s --> %s ... ",
136  settings_.transaction().template_from().c_str(),
137  settings_.transaction().template_to().c_str());
139 
140  try {
141  catalog_mgr_->CloneTree(settings_.transaction().template_from(),
142  settings_.transaction().template_to());
143  } catch (const ECvmfsException &e) {
144  std::string panic_msg = e.what();
145  ServerLockFile::Release(transaction_lock);
146  // TODO(aandvalenzuela): release session token (gateway publishing)
147  throw publish::EPublish("cannot clone directory tree. " + panic_msg,
149  }
150 
151  Sync();
152  SendTalkCommand(settings_.transaction().spool_area().readonly_talk_socket(),
153  "chroot " + settings_.transaction().base_hash().ToString() + "\n");
154  LogCvmfs(kLogCvmfs, llvl_ | kLogStdout, "[done]");
155  // TODO(jblomer): fix-me
156  // PushReflog();
157  }
158 
159  in_transaction_ = true;
161  "(%s) opened transaction", settings_.fqrn().c_str());
162 }
163 
164 } // namespace publish
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
void CheckTransactionStatus()
const SettingsRepository settings_
Definition: repository.h:136
void CloneTree(const std::string &from_dir, const std::string &to_dir)
void ConstructSyncManagers()
Definition: repository.cc:703
catalog::SimpleCatalogManager * GetSimpleCatalogManager()
Definition: repository.cc:118
UniquePtr< ManagedNode > managed_node_
Definition: repository.h:375
bool IsDirectory() const
bool in_transaction_
Definition: repository.h:364
std::string GetParentPath(const std::string &path)
Definition: posix.cc:129
bool is_publishing_
Definition: repository.h:365
catalog::WritableCatalogManager * catalog_mgr_
Definition: repository.h:379
void Throttle()
Definition: backoff.cc:50
shash::Any hash() const
static bool Acquire(const std::string &path, bool ignore_stale)
void Sync()
Definition: repository.cc:785
void InitSpoolArea()
Definition: repository.cc:583
shash::Any catalog_hash() const
Definition: manifest.h:124
uint64_t platform_monotonic_time()
std::string SendTalkCommand(const std::string &socket, const std::string &cmd)
UniquePtr< Session > session_
Definition: repository.h:374
manifest::Manifest * manifest_
Definition: repository.h:147
EFailures failure() const
Definition: except.h:45
static void Release(const std::string &path)
std::string fqrn() const
Definition: settings.h:367
int llvl_
Definition: repository.h:363
void ConstructSpoolers()
Definition: repository.cc:248
static bool IsLocked(const std::string &path, bool ignore_stale)
static CheckoutMarker * CreateFrom(const std::string &path)