CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
repository_transaction.cc
Go to the documentation of this file.
1 
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 "manifest.h"
15 #include "publish/except.h"
17 #include "publish/settings.h"
18 #include "util/exception.h"
19 #include "util/logging.h"
20 #include "util/pointer.h"
21 #include "util/posix.h"
22 
23 namespace publish {
24 
25 
27  bool waiting_on_lease = false;
28  if (managed_node_.IsValid()) {
29  int rvi = managed_node_->Check(false /* is_quiet */);
30  if (rvi != 0) throw EPublish("cannot establish writable mountpoint");
31  }
32 
33  BackoffThrottle throttle(500, 5000, 10000);
34  // Negative timeouts (i.e.: no retry) will result in a deadline that has
35  // already passed and thus has the correct effect
36  uint64_t deadline = platform_monotonic_time() +
37  settings_.transaction().GetTimeoutS();
38  if (settings_.transaction().GetTimeoutS() == 0)
39  deadline = uint64_t(-1);
40 
41  while (true) {
42  try {
43  TransactionImpl(waiting_on_lease);
44  break;
45  } catch (const publish::EPublish& e) {
47  session_->Drop();
49  }
50 
53  {
54  if (platform_monotonic_time() > deadline)
55  throw;
56 
57  waiting_on_lease = true;
58  LogCvmfs(kLogCvmfs, kLogStdout, "repository busy, retrying");
59  throttle.Throttle();
60  continue;
61  }
62 
63  throw;
64  } // try-catch
65  } // while (true)
66 
67  if (managed_node_.IsValid())
68  managed_node_->Open();
69 }
70 
71 
72 void Publisher::TransactionImpl(bool waiting_on_lease) {
73  if (in_transaction_.IsSet()) {
74  throw EPublish("another transaction is already open",
76  }
77 
78  InitSpoolArea();
79 
80  // On error, Transaction() will release the transaction lock and drop
81  // the session
82  session_->Acquire();
83 
84  // We might have a valid lease for a non-existing path. Nevertheless, we run
85  // run into problems when merging catalogs later, so for the time being we
86  // disallow transactions on non-existing paths.
87  if (!settings_.transaction().lease_path().empty()) {
88  std::string path = GetParentPath(
89  "/" + settings_.transaction().lease_path());
92  bool retval = catalog_mgr->LookupPath(path, catalog::kLookupDefault,
93  &dirent);
94  if (!retval) {
95  throw EPublish("cannot open transaction on non-existing path " + path,
97  }
98  if (!dirent.IsDirectory()) {
99  throw EPublish(
100  "cannot open transaction on " + path + ", which is not a directory",
102  }
103  }
104 
105 
107  settings_.transaction().spool_area().checkout_marker()));
108  // TODO(jblomer): take root hash from r/o mountpoint?
109 
110 
111  if (settings_.storage().type() == upload::SpoolerDefinition::Gateway && waiting_on_lease) {
112  DownloadRootObjects(settings_.url(), settings_.fqrn(), settings_.transaction().spool_area().tmp_dir());
113  int rvi = managed_node_->Check(true /* is_quiet */);
114  if (rvi != 0) throw EPublish("cannot establish writable mountpoint");
115  }
116 
119  if (marker.IsValid())
120  settings_.GetTransaction()->SetBaseHash(marker->hash());
121  else
122  settings_.GetTransaction()->SetBaseHash(manifest_->catalog_hash());
123 
124  if (settings_.transaction().HasTemplate()) {
126  "CernVM-FS: cloning template %s --> %s ... ",
127  settings_.transaction().template_from().c_str(),
128  settings_.transaction().template_to().c_str());
130 
131  try {
132  catalog_mgr_->CloneTree(settings_.transaction().template_from(),
133  settings_.transaction().template_to());
134  } catch (const ECvmfsException &e) {
135  std::string panic_msg = e.what();
137  // TODO(aandvalenzuela): release session token (gateway publishing)
138  throw publish::EPublish("cannot clone directory tree. " + panic_msg,
140  }
141 
142  Sync();
143  SendTalkCommand(settings_.transaction().spool_area().readonly_talk_socket(),
144  "chroot " + settings_.transaction().base_hash().ToString() + "\n");
145  LogCvmfs(kLogCvmfs, llvl_ | kLogStdout, "[done]");
146  // TODO(jblomer): fix-me
147  // PushReflog();
148  }
149 
151  "(%s) opened transaction", settings_.fqrn().c_str());
152 }
153 
154 } // namespace publish
void TransactionImpl(bool waiting_on_lease=false)
const SettingsRepository settings_
Definition: repository.h:137
void CloneTree(const std::string &from_dir, const std::string &to_dir)
void ConstructSyncManagers()
Definition: repository.cc:677
catalog::SimpleCatalogManager * GetSimpleCatalogManager()
Definition: repository.cc:118
UniquePtr< ManagedNode > managed_node_
Definition: repository.h:381
bool IsDirectory() const
const unsigned kLookupDefault
Definition: catalog_mgr.h:43
catalog::WritableCatalogManager * catalog_mgr_
Definition: repository.h:385
void Throttle()
Definition: backoff.cc:50
shash::Any hash() const
void DownloadRootObjects(const std::string &url, const std::string &fqrn, const std::string &tmp_dir)
Definition: repository.cc:133
void Sync()
Definition: repository.cc:774
void InitSpoolArea()
Definition: repository.cc:571
shash::Any catalog_hash() const
Definition: manifest.h:132
uint64_t platform_monotonic_time()
std::string SendTalkCommand(const std::string &socket, const std::string &cmd)
UniquePtr< Session > session_
Definition: repository.h:380
manifest::Manifest * manifest_
Definition: repository.h:148
EFailures failure() const
Definition: except.h:45
ServerFlagFile in_transaction_
Definition: repository.h:370
PathString GetParentPath(const PathString &path)
Definition: shortstring.cc:15
std::string fqrn() const
Definition: settings.h:373
int llvl_
Definition: repository.h:369
std::string url() const
Definition: settings.h:374
void ConstructSpoolers()
Definition: repository.cc:242
static CheckoutMarker * CreateFrom(const std::string &path)
std::string tmp_dir() const
Definition: settings.h:376
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528