GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/repository.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 13 0.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_PUBLISH_REPOSITORY_H_
6 #define CVMFS_PUBLISH_REPOSITORY_H_
7
8 #include <string>
9 #include <vector>
10
11 #include "gateway_util.h"
12 #include "history.h" // for History::Tag
13 #include "publish/settings.h"
14 #include "repository_util.h"
15 #include "upload_spooler_result.h"
16 #include "util/pointer.h"
17 #include "util/single_copy.h"
18
19 namespace catalog {
20 class DeltaCounters;
21 class DirectoryEntry;
22 class SimpleCatalogManager;
23 class WritableCatalogManager;
24 }
25 namespace download {
26 class DownloadManager;
27 }
28 namespace history {
29 class SqliteHistory;
30 }
31 namespace manifest {
32 class Manifest;
33 class Reflog;
34 }
35 namespace perf {
36 class Statistics;
37 class StatisticsTemplate;
38 }
39 namespace signature {
40 class SignatureManager;
41 }
42 class SyncParameters;
43 namespace upload {
44 class Spooler;
45 }
46 namespace whitelist {
47 class Whitelist;
48 }
49
50 namespace publish {
51
52 class SyncMediator;
53 class SyncUnion;
54
55 /**
56 * Users create derived instances to react on repository diffs
57 */
58 class __attribute__((visibility("default"))) DiffListener {
59 public:
60 virtual ~DiffListener() {}
61 virtual void OnInit(const history::History::Tag &from_tag,
62 const history::History::Tag &to_tag) = 0;
63 virtual void OnStats(const catalog::DeltaCounters &delta) = 0;
64 virtual void OnAdd(const std::string &path,
65 const catalog::DirectoryEntry &entry) = 0;
66 virtual void OnRemove(const std::string &path,
67 const catalog::DirectoryEntry &entry) = 0;
68 virtual void OnModify(const std::string &path,
69 const catalog::DirectoryEntry &entry_from,
70 const catalog::DirectoryEntry &entry_to) = 0;
71 };
72
73
74 class __attribute__((visibility("default"))) Env {
75 public:
76 /**
77 * Depending on the desired course of action, the permitted capabilities of the
78 * binary (cap_dac_read_search, cap_sys_admin) needs to be dropped or gained.
79 * Dropped for creating user namespaces in `enter`, gained for walking through
80 * overlayfs.
81 */
82 static void DropCapabilities();
83
84 /**
85 * If in an ephemeral writable shell, return the session directory.
86 * Otherwise return the empty string.
87 */
88 static std::string GetEnterSessionDir();
89 };
90
91
92 class __attribute__((visibility("default"))) Repository : SingleCopy {
93 public:
94 /**
95 * Tag names beginning with @ are interpreted as raw hashes
96 */
97 static const char kRawHashSymbol = '@';
98
99 static std::string GetFqrnFromUrl(const std::string &url);
100
101 explicit Repository(const SettingsRepository &settings,
102 const bool exists = true);
103 virtual ~Repository();
104
105 void Check();
106 void GarbageCollect();
107 void List();
108
109 /**
110 * From and to are either tag names or catalog root hashes preceded by
111 * a '@'.
112 */
113 void Diff(const std::string &from, const std::string &to,
114 DiffListener *diff_listener);
115
116 /**
117 * Checks whether the $url/.cvmfs_master_replica is available
118 */
119 bool IsMasterReplica();
120
121 const signature::SignatureManager *signature_mgr() const {
122 return signature_mgr_;
123 }
124 const whitelist::Whitelist *whitelist() const { return whitelist_; }
125 const manifest::Manifest *manifest() const { return manifest_; }
126 // Inheritance of History and SqliteHistory unknown in the header
127 const history::History *history() const;
128 std::string meta_info() const { return meta_info_; }
129
130 protected:
131 void DownloadRootObjects(
132 const std::string &url,
133 const std::string &fqrn,
134 const std::string &tmp_dir);
135 catalog::SimpleCatalogManager *GetSimpleCatalogManager();
136
137 const SettingsRepository settings_;
138
139 perf::Statistics *statistics_;
140 signature::SignatureManager *signature_mgr_;
141 download::DownloadManager *download_mgr_;
142 /**
143 * The read-only catalog manager, loaded on demand
144 */
145 catalog::SimpleCatalogManager *simple_catalog_mgr_;
146 whitelist::Whitelist *whitelist_;
147 manifest::Reflog *reflog_;
148 manifest::Manifest *manifest_;
149 history::SqliteHistory *history_;
150 // TODO(jblomer): make MetaInfo class
151 std::string meta_info_;
152 };
153
154 class __attribute__((visibility("default"))) Publisher : public Repository {
155 public:
156 /**
157 * Encapsulates operations on a dedicated publisher
158 */
159 class ManagedNode {
160 public:
161 /**
162 * Collection of publisher failure states (see Check())
163 */
164 enum EFailures {
165 kFailOk = 0,
166 kFailRdOnlyBroken = 0x01,
167 kFailRdOnlyOutdated = 0x02,
168 kFailRdOnlyWrongRevision = 0x04,
169 kFailUnionBroken = 0x08,
170 kFailUnionWritable = 0x10,
171 kFailUnionLocked = 0x20,
172 };
173
174 explicit ManagedNode(Publisher *p) : publisher_(p) {}
175 /**
176 * Verifies the mountpoints and the transaction status. Returns a bit map
177 * of EFailures codes.
178 */
179 int Check(bool is_quiet = false);
180 /**
181 * Re-mount /cvmfs/$fqrn read-writable
182 */
183 void Open();
184 /**
185 * Re-mount /cvmfs/$fqrn read-only
186 */
187 void Lock();
188 /**
189 * Regular unmount of the read-write and the read-only layer and, if this
190 * does not work, a forced unmount
191 */
192 void Unmount();
193 /**
194 * Mounts the read-only layer followed by the union layer
195 */
196 void Mount();
197 /**
198 * Move scratch space to waste bin and clear it out asynchronously
199 */
200 void ClearScratch();
201
202 private:
203 /**
204 * Possible state transitions for the cvmfs read-only mountpoint and the
205 * union file system on /cvmfs/$fqrn
206 */
207 enum EMountpointAlterations {
208 kAlterUnionUnmount,
209 kAlterUnionLazyUnmount,
210 kAlterRdOnlyUnmount,
211 kAlterRdOnlyKillUnmount,
212 kAlterRdOnlyLazyUnmount,
213 kAlterUnionMount,
214 kAlterRdOnlyMount,
215 kAlterUnionOpen,
216 kAlterUnionLock,
217 kAlterScratchWipe,
218 };
219
220 void AlterMountpoint(EMountpointAlterations how, int log_level);
221 void SetRootHash(const shash::Any &hash);
222
223 Publisher *publisher_;
224 }; // class ManagedNode
225
226
227 /**
228 * A session encapsulates an active storage (gateway) lease
229 */
230 class Session : ::SingleCopy {
231 public:
232 struct Settings {
233 Settings() : llvl(0) {}
234 std::string service_endpoint;
235 /**
236 * $fqrn/$lease_path
237 */
238 std::string repo_path;
239 std::string gw_key_path;
240 std::string token_path;
241 int llvl;
242 };
243
244 /**
245 * For non-gateway nodes, we have an implicit lease for the entire
246 * repository
247 */
248 Session() : keep_alive_(false), has_lease_(true) {}
249 explicit Session(const Settings &settings_session);
250 explicit Session(const SettingsPublisher &settings_publisher, int llvl = 0);
251 /**
252 * Drops the lease unless keep_alive_ is set
253 */
254 ~Session();
255
256 void Acquire();
257 void Drop();
258 void SetKeepAlive(bool value);
259
260 bool has_lease() const { return has_lease_; }
261 std::string token_path() const { return settings_.token_path; }
262
263 private:
264 Settings settings_;
265 /**
266 * If set to true, the session is not closed on destruction, i.e. the
267 * lease is not dropped and the lease token is not removed. A newly created
268 * Session object will pick up an existing lease token and not re-acquire
269 * it.
270 */
271 bool keep_alive_;
272 bool has_lease_;
273 }; // class Session
274
275 /**
276 * The directory layout of the publisher node must be of matching revision
277 */
278 static const unsigned kRequiredLayoutRevision = 143;
279
280 static Publisher *Create(const SettingsPublisher &settings);
281
282 explicit Publisher(const SettingsPublisher &settings,
283 const bool exists = true);
284 virtual ~Publisher();
285
286 void UpdateMetaInfo();
287 void Transaction();
288 void Abort();
289 void Publish();
290 void Ingest();
291 void Sync();
292
293 /**
294 * Automatically exit the ephemeral shell after abort or commit.
295 * TODO(avalenzu): Most of the logic of the enter shell is in the CmdEnter UI class.
296 * We should move at least the core functionality to libcvmfs_server and this includes
297 * the ExitShell() method.
298 */
299 void ExitShell();
300
301 /**
302 * Must not edit magic tags 'trunk' and 'trunk-previous'.
303 * Removal of non-existing tags is silently ignored. The caller needs to
304 * ensure that the data provided in new tags makes sense.
305 */
306 void EditTags(const std::vector<history::History::Tag> &add_tags,
307 const std::vector<std::string> &rm_tags);
308 /**
309 * Create empty $url/.cvmfs_master_replica
310 */
311 void MarkReplicatible(bool value);
312
313 void Rollback();
314 void Resign();
315 void Migrate();
316
317 const SettingsPublisher &settings() const { return settings_; }
318 const ServerFlagFile &in_transaction() const { return in_transaction_; }
319 const ServerLockFile &is_publishing() const { return is_publishing_; }
320 Session *session() const { return session_.weak_ref(); }
321 const upload::Spooler *spooler_files() const { return spooler_files_; }
322 const upload::Spooler *spooler_catalogs() const { return spooler_catalogs_; }
323
324 private:
325 /**
326 * Used just before a spooler is required, e.g. in Create()
327 */
328 void ConstructSpoolers();
329 /**
330 * Initializes the spooler, the writable catalog manager, and the sync
331 * mediator
332 */
333 void ConstructSyncManagers();
334 void WipeScratchArea();
335
336 void CreateKeychain();
337 void CreateStorage();
338 void CreateSpoolArea();
339 void CreateRootObjects();
340
341 void ExportKeychain();
342 void CreateDirectoryAsOwner(const std::string &path, int mode);
343 void InitSpoolArea();
344
345 void PushCertificate();
346 void PushHistory();
347 void PushManifest();
348 void PushMetainfo();
349 void PushReflog();
350 void PushWhitelist();
351
352 void OnProcessCertificate(const upload::SpoolerResult &result);
353 void OnProcessHistory(const upload::SpoolerResult &result);
354 void OnProcessMetainfo(const upload::SpoolerResult &result);
355 void OnUploadManifest(const upload::SpoolerResult &result);
356 void OnUploadReflog(const upload::SpoolerResult &result);
357 void OnUploadWhitelist(const upload::SpoolerResult &result);
358
359 void CheckTagName(const std::string &name);
360
361 void TransactionRetry();
362 void TransactionImpl();
363
364 SettingsPublisher settings_;
365 UniquePtr<perf::StatisticsTemplate> statistics_publish_;
366 /**
367 * The log level, set to kLogNone if settings_.is_silent() == true
368 */
369 int llvl_;
370 ServerFlagFile in_transaction_;
371 ServerLockFile is_publishing_;
372 gateway::GatewayKey gw_key_;
373 /**
374 * Only really used gateway mode when a transaction is opened. The session
375 * takes an existing session token if it exists and drops the lease in abort.
376 * TODO(jblomer): that is not yet done. Once publish, tag, etc. are
377 * implemented, the lease should be dropped after the last successful write
378 * operation.
379 */
380 UniquePtr<Session> session_;
381 UniquePtr<ManagedNode> managed_node_;
382
383 upload::Spooler *spooler_files_;
384 upload::Spooler *spooler_catalogs_;
385 catalog::WritableCatalogManager *catalog_mgr_;
386 SyncParameters *sync_parameters_;
387 SyncMediator *sync_mediator_;
388 publish::SyncUnion *sync_union_;
389 };
390
391 class __attribute__((visibility("default"))) Replica : public Repository {
392 public:
393 static Replica *Create();
394 explicit Replica(const SettingsReplica &settings);
395 virtual ~Replica();
396
397 void Snapshot();
398 };
399
400 } // namespace publish
401
402 #endif // CVMFS_PUBLISH_REPOSITORY_H_
403