| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/history.h |
| Date: | 2025-11-09 02:35:23 |
| 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 | 3114 | Branch() : initial_revision(0) { } | |
| 37 | 5743 | Branch(const std::string &b, const std::string &p, uint64_t r) | |
| 38 |
1/2✓ Branch 2 taken 5743 times.
✗ Branch 3 not taken.
|
5743 | : branch(b), parent(p), initial_revision(r) { } |
| 39 | std::string branch; | ||
| 40 | std::string parent; | ||
| 41 | uint64_t initial_revision; | ||
| 42 | |||
| 43 | 753 | bool operator==(const Branch &other) const { | |
| 44 |
1/2✓ Branch 2 taken 753 times.
✗ Branch 3 not taken.
|
1506 | return (this->branch == other.branch) && (this->parent == other.parent) |
| 45 |
2/4✓ Branch 0 taken 753 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 753 times.
✗ Branch 3 not taken.
|
1506 | && (this->initial_revision == other.initial_revision); |
| 46 | } | ||
| 47 | |||
| 48 | // Used for sorting in unit tests | ||
| 49 | 1321 | bool operator<(const Branch &other) const { | |
| 50 | 1321 | 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 367012 times.
✗ Branch 3 not taken.
|
367012 | Tag() : size(0), revision(0), timestamp(0) { } |
| 63 | |||
| 64 | 5649 | 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 | 5649 | : name(n) | |
| 68 | 5649 | , root_hash(h) | |
| 69 | 5649 | , size(s) | |
| 70 | 5649 | , revision(r) | |
| 71 | 5649 | , timestamp(t) | |
| 72 |
1/2✓ Branch 1 taken 5649 times.
✗ Branch 2 not taken.
|
5649 | , description(d) |
| 73 |
1/2✓ Branch 1 taken 5649 times.
✗ Branch 2 not taken.
|
5649 | , branch(b) { } |
| 74 | |||
| 75 | bool operator==(const Tag &other) const { | ||
| 76 | return (this->branch == other.branch) | ||
| 77 | && (this->revision == other.revision); | ||
| 78 | } | ||
| 79 | |||
| 80 | 317982 | bool operator<(const Tag &other) const { | |
| 81 |
2/2✓ Branch 0 taken 314379 times.
✓ Branch 1 taken 3603 times.
|
317982 | if (this->timestamp == other.timestamp) |
| 82 | 314379 | return this->revision < other.revision; | |
| 83 | 3603 | 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 | 15782 | 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 | 6877 | const std::string &fqrn() const { return fqrn_; } | |
| 198 | |||
| 199 | protected: | ||
| 200 | 7891 | 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 |