GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/history.h
Date: 2025-07-13 02:35:07
Exec Total Coverage
Lines: 24 24 100.0%
Branches: 9 16 56.2%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_HISTORY_H_
6 #define CVMFS_HISTORY_H_
7
8 #include <stdint.h>
9 #include <time.h>
10
11 #include <string>
12 #include <vector>
13
14 #include "crypto/hash.h"
15
16 namespace history {
17
18 /**
19 * This is the abstract base class for repository history. It maintains a list
20 * of named snapshots in a Tag structure.
21 *
22 * Each tag contains meta information (i.e. description, date) and points to
23 * one specific catalog revision (revision, root catalog hash). Furthermore
24 * tags are associated with _one_ branch. This can be used in clients
25 * to selectively apply file system snapshots of a specific branch.
26 *
27 * Note: The public interface of the History class is virtual, in order to over-
28 * write it in a testing environment. As we are dealing with an SQLite
29 * database anyway, the overhead of this should not matter.
30 * It could be implemented using CRTP if necessary, but would require com-
31 * plex code to do so.
32 */
33 class History {
34 public:
35 struct Branch {
36 6028 Branch() : initial_revision(0) { }
37 7106 Branch(const std::string &b, const std::string &p, uint64_t r)
38
1/2
✓ Branch 2 taken 7106 times.
✗ Branch 3 not taken.
7106 : branch(b), parent(p), initial_revision(r) { }
39 std::string branch;
40 std::string parent;
41 uint64_t initial_revision;
42
43 486 bool operator==(const Branch &other) const {
44
1/2
✓ Branch 2 taken 486 times.
✗ Branch 3 not taken.
972 return (this->branch == other.branch) && (this->parent == other.parent)
45
2/4
✓ Branch 0 taken 486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 486 times.
✗ Branch 3 not taken.
972 && (this->initial_revision == other.initial_revision);
46 }
47
48 // Used for sorting in unit tests
49 1162 bool operator<(const Branch &other) const {
50 1162 return (this->branch < other.branch);
51 }
52 };
53
54 /**
55 * The Tag structure contains information about one specific named snap-
56 * shot stored in the history database. Tags can be retrieved from this
57 * history class both by 'name' and by 'date'. By 'date' branches only look
58 * in the default branch. Naturally, tags can also be saved into the History
59 * using this struct as a container.
60 */
61 struct Tag {
62
1/2
✓ Branch 2 taken 632984 times.
✗ Branch 3 not taken.
632984 Tag() : size(0), revision(0), timestamp(0) { }
63
64 11298 Tag(const std::string &n, const shash::Any &h, const uint64_t s,
65 const uint64_t r, const time_t t, const std::string &d,
66 const std::string &b)
67 11298 : name(n)
68 11298 , root_hash(h)
69 11298 , size(s)
70 11298 , revision(r)
71 11298 , timestamp(t)
72
1/2
✓ Branch 1 taken 11298 times.
✗ Branch 2 not taken.
11298 , description(d)
73
1/2
✓ Branch 1 taken 11298 times.
✗ Branch 2 not taken.
11298 , branch(b) { }
74
75 bool operator==(const Tag &other) const {
76 return (this->branch == other.branch)
77 && (this->revision == other.revision);
78 }
79
80 1683395 bool operator<(const Tag &other) const {
81
2/2
✓ Branch 0 taken 1676688 times.
✓ Branch 1 taken 6707 times.
1683395 if (this->timestamp == other.timestamp)
82 1676688 return this->revision < other.revision;
83 6707 return this->timestamp < other.timestamp;
84 }
85
86 bool operator>(const Tag &other) const {
87 if (this->timestamp == other.timestamp)
88 return this->revision > other.revision;
89 return this->timestamp > other.timestamp;
90 }
91
92 std::string name;
93 shash::Any root_hash;
94 uint64_t size;
95 uint64_t revision;
96 time_t timestamp;
97 std::string description;
98 /**
99 * The default branch is the empty string.
100 */
101 std::string branch;
102 }; // struct Tag
103
104
105 public:
106 16862 virtual ~History() { }
107
108 virtual bool IsWritable() const = 0;
109 virtual unsigned GetNumberOfTags() const = 0;
110
111 /**
112 * Opens a new database transaction in the underlying SQLite database
113 * This can greatly improve performance when used before inserting or
114 * removing multiple tags.
115 */
116 virtual bool BeginTransaction() const = 0;
117
118 /**
119 * Closes a transaction (see BeginTransaction())
120 */
121 virtual bool CommitTransaction() const = 0;
122
123 /**
124 * Sets the internal pointer to the previous revision of this History file.
125 * Note: This must be handled by the user code.
126 *
127 * @param history_hash the content hash of the previous revision
128 */
129 virtual bool SetPreviousRevision(const shash::Any &history_hash) = 0;
130 virtual shash::Any previous_revision() const = 0;
131
132 virtual bool Insert(const Tag &tag) = 0;
133 virtual bool Remove(const std::string &name) = 0;
134 virtual bool Exists(const std::string &name) const = 0;
135 virtual bool GetByName(const std::string &name, Tag *tag) const = 0;
136 virtual bool GetByDate(const time_t timestamp, Tag *tag) const = 0;
137 virtual bool List(std::vector<Tag> *tags) const = 0;
138
139 virtual bool GetBranchHead(const std::string &branch_name,
140 Tag *tag) const = 0;
141 virtual bool ExistsBranch(const std::string &branch_name) const = 0;
142 virtual bool InsertBranch(const Branch &branch) = 0;
143 /**
144 * When removing tags, branches can become abandoned. Remove abandoned
145 * branches and redirect the parent pointer of their child branches.
146 */
147 virtual bool PruneBranches() = 0;
148 virtual bool ListBranches(std::vector<Branch> *branches) const = 0;
149
150 /**
151 * The recycle bin operations are deprecated, only emptying and listing are
152 * preserved for migration and testing.
153 */
154 virtual bool ListRecycleBin(std::vector<shash::Any> *hashes) const = 0;
155 virtual bool EmptyRecycleBin() = 0;
156
157 /**
158 * Rolls back the history to the provided target tag and deletes all tags
159 * in between. Works on the default branch only.
160 *
161 * Note: this assumes that the provided target tag was already updated with
162 * the republished root catalog information.
163 *
164 * @param updated_target_tag the tag to be rolled back to (updated: see Note)
165 * @return true on success
166 */
167 virtual bool Rollback(const Tag &updated_target_tag) = 0;
168
169 /**
170 * Lists the tags that would be deleted by a rollback to the tag specified.
171 *
172 * Note: This doesn't change the database but is mainly used for sanity checks
173 * and user output.
174 *
175 * @param target_tag_name the tag name for the planned rollback
176 * @param tags pointer to the result tag list to be filled
177 * @return true on success
178 */
179 virtual bool ListTagsAffectedByRollback(const std::string &target_tag_name,
180 std::vector<Tag> *tags) const = 0;
181
182 /**
183 * Provides a list of all referenced catalog hashes in this History.
184 * The hashes will be ordered by their timestamp in ascending order.
185 *
186 * @param hashes pointer to the result vector to be filled
187 */
188 virtual bool GetHashes(std::vector<shash::Any> *hashes) const = 0;
189
190 // database file management controls
191 virtual void TakeDatabaseFileOwnership() = 0;
192 virtual void DropDatabaseFileOwnership() = 0;
193 virtual bool OwnsDatabaseFile() const = 0;
194
195 virtual bool Vacuum() = 0;
196
197 4939 const std::string &fqrn() const { return fqrn_; }
198
199 protected:
200 8431 void set_fqrn(const std::string &fqrn) { fqrn_ = fqrn; }
201
202 private:
203 std::string fqrn_;
204 };
205
206 } // namespace history
207
208 #endif // CVMFS_HISTORY_H_
209