GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/repository_transaction.cc
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 0 69 0.0%
Branches: 0 158 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
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 "manifest.h"
15 #include "publish/except.h"
16 #include "publish/repository_util.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
26 void Publisher::TransactionRetry() {
27 if (managed_node_.IsValid()) {
28 int rvi = managed_node_->Check(false /* is_quiet */);
29 if (rvi != 0) throw EPublish("cannot establish writable mountpoint");
30 }
31
32 BackoffThrottle throttle(500, 5000, 10000);
33 // Negative timeouts (i.e.: no retry) will result in a deadline that has
34 // already passed and thus has the correct effect
35 uint64_t deadline = platform_monotonic_time() +
36 settings_.transaction().GetTimeoutS();
37 if (settings_.transaction().GetTimeoutS() == 0)
38 deadline = uint64_t(-1);
39
40 while (true) {
41 try {
42 TransactionImpl();
43 break;
44 } catch (const publish::EPublish& e) {
45 if (e.failure() != EPublish::kFailTransactionState) {
46 session_->Drop();
47 in_transaction_.Clear();
48 }
49
50 if ((e.failure() == EPublish::kFailTransactionState) ||
51 (e.failure() == EPublish::kFailLeaseBusy))
52 {
53 if (platform_monotonic_time() > deadline)
54 throw;
55
56 LogCvmfs(kLogCvmfs, kLogStdout, "repository busy, retrying");
57 throttle.Throttle();
58 continue;
59 }
60
61 throw;
62 } // try-catch
63 } // while (true)
64
65 if (managed_node_.IsValid())
66 managed_node_->Open();
67 }
68
69
70 void Publisher::TransactionImpl() {
71 if (in_transaction_.IsSet()) {
72 throw EPublish("another transaction is already open",
73 EPublish::kFailTransactionState);
74 }
75
76 InitSpoolArea();
77
78 // On error, Transaction() will release the transaction lock and drop
79 // the session
80 in_transaction_.Set();
81 session_->Acquire();
82
83 // We might have a valid lease for a non-existing path. Nevertheless, we run
84 // run into problems when merging catalogs later, so for the time being we
85 // disallow transactions on non-existing paths.
86 if (!settings_.transaction().lease_path().empty()) {
87 std::string path = GetParentPath(
88 "/" + settings_.transaction().lease_path());
89 catalog::SimpleCatalogManager *catalog_mgr = GetSimpleCatalogManager();
90 catalog::DirectoryEntry dirent;
91 bool retval = catalog_mgr->LookupPath(path, catalog::kLookupDefault,
92 &dirent);
93 if (!retval) {
94 throw EPublish("cannot open transaction on non-existing path " + path,
95 EPublish::kFailLeaseNoEntry);
96 }
97 if (!dirent.IsDirectory()) {
98 throw EPublish(
99 "cannot open transaction on " + path + ", which is not a directory",
100 EPublish::kFailLeaseNoDir);
101 }
102 }
103
104 ConstructSpoolers();
105
106 UniquePtr<CheckoutMarker> marker(CheckoutMarker::CreateFrom(
107 settings_.transaction().spool_area().checkout_marker()));
108 // TODO(jblomer): take root hash from r/o mountpoint?
109 if (marker.IsValid())
110 settings_.GetTransaction()->SetBaseHash(marker->hash());
111 else
112 settings_.GetTransaction()->SetBaseHash(manifest_->catalog_hash());
113
114 if (settings_.transaction().HasTemplate()) {
115 LogCvmfs(kLogCvmfs, llvl_ | kLogStdout | kLogNoLinebreak,
116 "CernVM-FS: cloning template %s --> %s ... ",
117 settings_.transaction().template_from().c_str(),
118 settings_.transaction().template_to().c_str());
119 ConstructSyncManagers();
120
121 try {
122 catalog_mgr_->CloneTree(settings_.transaction().template_from(),
123 settings_.transaction().template_to());
124 } catch (const ECvmfsException &e) {
125 std::string panic_msg = e.what();
126 in_transaction_.Clear();
127 // TODO(aandvalenzuela): release session token (gateway publishing)
128 throw publish::EPublish("cannot clone directory tree. " + panic_msg,
129 publish::EPublish::kFailInput);
130 }
131
132 Sync();
133 SendTalkCommand(settings_.transaction().spool_area().readonly_talk_socket(),
134 "chroot " + settings_.transaction().base_hash().ToString() + "\n");
135 LogCvmfs(kLogCvmfs, llvl_ | kLogStdout, "[done]");
136 // TODO(jblomer): fix-me
137 // PushReflog();
138 }
139
140 LogCvmfs(kLogCvmfs, llvl_ | kLogDebug | kLogSyslog,
141 "(%s) opened transaction", settings_.fqrn().c_str());
142 }
143
144 } // namespace publish
145