GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/reflog.cc
Date: 2026-08-30 02:40:36
Exec Total Coverage
Lines: 157 184 85.3%
Branches: 85 177 48.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "reflog.h"
6
7 #include <fcntl.h>
8 #include <unistd.h>
9
10 #include <cassert>
11
12 #include "util/posix.h"
13 #include "util/string.h"
14
15 namespace manifest {
16
17 183 Reflog *Reflog::Open(const std::string &database_path) {
18 183 Reflog *reflog = new Reflog();
19
3/6
✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 183 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 183 times.
183 if (NULL == reflog || !reflog->OpenDatabase(database_path)) {
20 delete reflog;
21 return NULL;
22 }
23
24
1/2
✓ Branch 3 taken 183 times.
✗ Branch 4 not taken.
183 LogCvmfs(kLogReflog, kLogDebug,
25 "opened Reflog database '%s' for repository '%s'",
26 366 database_path.c_str(), reflog->fqrn().c_str());
27
28 183 return reflog;
29 }
30
31
32 796 Reflog *Reflog::Create(const std::string &database_path,
33 const std::string &repo_name) {
34 796 Reflog *reflog = new Reflog();
35
3/6
✓ Branch 0 taken 796 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 796 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 796 times.
796 if (NULL == reflog || !reflog->CreateDatabase(database_path, repo_name)) {
36 delete reflog;
37 return NULL;
38 }
39
40 796 LogCvmfs(kLogReflog, kLogDebug,
41 "created empty reflog database '%s' for "
42 "repository '%s'",
43 database_path.c_str(), repo_name.c_str());
44 796 return reflog;
45 }
46
47
48 30 bool Reflog::ReadChecksum(const std::string &path, shash::Any *checksum) {
49
1/2
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
30 const int fd = open(path.c_str(), O_RDONLY);
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (fd < 0) {
51 return false;
52 }
53 30 std::string hex_hash;
54
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 const bool retval = GetLineFd(fd, &hex_hash);
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (retval == 0) {
56 close(fd);
57 return false;
58 }
59
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 close(fd);
60
2/4
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
30 *checksum = shash::MkFromHexPtr(shash::HexPtr(Trim(hex_hash)));
61 30 return true;
62 30 }
63
64
65 30 bool Reflog::WriteChecksum(const std::string &path, const shash::Any &value) {
66
1/2
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
30 const int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
67 kDefaultFileMode);
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (fd < 0) {
69 return false;
70 }
71
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 std::string hex_hash = value.ToString();
72
1/2
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
30 const bool retval = SafeWrite(fd, hex_hash.data(), hex_hash.length());
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (retval == 0) {
74 close(fd);
75 return false;
76 }
77
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 close(fd);
78 30 return true;
79 30 }
80
81
82 796 bool Reflog::CreateDatabase(const std::string &database_path,
83 const std::string &repo_name) {
84
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 796 times.
796 assert(database_.get() == nullptr);
85 1592 database_ = std::unique_ptr<ReflogDatabase>(
86 796 ReflogDatabase::Create(database_path));
87 796 if (database_.get() == nullptr
88
3/6
✓ Branch 0 taken 796 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 796 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 796 times.
796 || !database_->InsertInitialValues(repo_name)) {
89 LogCvmfs(kLogReflog, kLogDebug, "failed to initialize empty database '%s'",
90 database_path.c_str());
91 return false;
92 }
93
94 796 PrepareQueries();
95 796 return true;
96 }
97
98
99 183 bool Reflog::OpenDatabase(const std::string &database_path) {
100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
183 assert(database_.get() == nullptr);
101
102 183 const ReflogDatabase::OpenMode mode = ReflogDatabase::kOpenReadWrite;
103 366 database_ = std::unique_ptr<ReflogDatabase>(
104 183 ReflogDatabase::Open(database_path, mode));
105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
183 if (database_.get() == nullptr) {
106 return false;
107 }
108
109 183 PrepareQueries();
110 183 return true;
111 }
112
113
114 979 void Reflog::PrepareQueries() {
115
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
979 assert(database_.get() != nullptr);
116 1958 insert_reference_ = std::unique_ptr<SqlInsertReference>(
117
1/2
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 new SqlInsertReference(database_.get()));
118 1958 count_references_ = std::unique_ptr<SqlCountReferences>(
119
1/2
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 new SqlCountReferences(database_.get()));
120 1958 list_references_ = std::unique_ptr<SqlListReferences>(
121
1/2
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 new SqlListReferences(database_.get()));
122 1958 remove_reference_ = std::unique_ptr<SqlRemoveReference>(
123
1/2
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 new SqlRemoveReference(database_.get()));
124 1958 contains_reference_ = std::unique_ptr<SqlContainsReference>(
125
1/2
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 new SqlContainsReference(database_.get()));
126 1958 get_timestamp_ = std::unique_ptr<SqlGetTimestamp>(
127
1/2
✓ Branch 3 taken 979 times.
✗ Branch 4 not taken.
1958 new SqlGetTimestamp(database_.get()));
128 979 }
129
130
131 49 bool Reflog::AddCertificate(const shash::Any &certificate) {
132
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
49 assert(certificate.HasSuffix()
133 && certificate.suffix == shash::kSuffixCertificate);
134 49 return AddReference(certificate, SqlReflog::kRefCertificate);
135 }
136
137
138 70 bool Reflog::AddCatalog(const shash::Any &catalog) {
139
2/4
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
✗ Branch 4 not taken.
70 assert(catalog.HasSuffix() && catalog.suffix == shash::kSuffixCatalog);
140 70 return AddReference(catalog, SqlReflog::kRefCatalog);
141 }
142
143
144 28 bool Reflog::AddHistory(const shash::Any &history) {
145
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 assert(history.HasSuffix() && history.suffix == shash::kSuffixHistory);
146 28 return AddReference(history, SqlReflog::kRefHistory);
147 }
148
149
150 49 bool Reflog::AddMetainfo(const shash::Any &metainfo) {
151
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
49 assert(metainfo.HasSuffix() && metainfo.suffix == shash::kSuffixMetainfo);
152 49 return AddReference(metainfo, SqlReflog::kRefMetainfo);
153 }
154
155
156 56 uint64_t Reflog::CountEntries() {
157
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 assert(database_.get() != nullptr);
158 56 const bool success_exec = count_references_->Execute();
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 assert(success_exec);
160 56 const uint64_t count = count_references_->RetrieveCount();
161 56 const bool success_reset = count_references_->Reset();
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 assert(success_reset);
163 56 return count;
164 }
165
166
167 28 bool Reflog::List(SqlReflog::ReferenceType type,
168 std::vector<shash::Any> *hashes) const {
169 28 return ListOlderThan(type, static_cast<uint64_t>(-1), hashes);
170 }
171
172
173 49 bool Reflog::ListOlderThan(SqlReflog::ReferenceType type,
174 uint64_t timestamp,
175 std::vector<shash::Any> *hashes) const {
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 assert(database_.get() != nullptr);
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 assert(NULL != hashes);
178
179 49 hashes->clear();
180
181 49 bool success_bind = list_references_->BindType(type);
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 assert(success_bind);
183 49 success_bind = list_references_->BindOlderThan(timestamp);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 assert(success_bind);
185
2/2
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 49 times.
140 while (list_references_->FetchRow()) {
186
1/2
✓ Branch 3 taken 91 times.
✗ Branch 4 not taken.
91 hashes->push_back(list_references_->RetrieveHash());
187 }
188
189 49 return list_references_->Reset();
190 }
191
192
193 28 bool Reflog::Remove(const shash::Any &hash) {
194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 assert(database_.get() != nullptr);
195
196 SqlReflog::ReferenceType type;
197
4/5
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
28 switch (hash.suffix) {
198 7 case shash::kSuffixCatalog:
199 7 type = SqlReflog::kRefCatalog;
200 7 break;
201 7 case shash::kSuffixHistory:
202 7 type = SqlReflog::kRefHistory;
203 7 break;
204 7 case shash::kSuffixCertificate:
205 7 type = SqlReflog::kRefCertificate;
206 7 break;
207 7 case shash::kSuffixMetainfo:
208 7 type = SqlReflog::kRefMetainfo;
209 7 break;
210 default:
211 return false;
212 }
213
214 28 return remove_reference_->BindReference(hash, type)
215
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
28 && remove_reference_->Execute() && remove_reference_->Reset();
216 }
217
218
219 28 bool Reflog::ContainsCertificate(const shash::Any &certificate) const {
220
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 assert(certificate.HasSuffix()
221 && certificate.suffix == shash::kSuffixCertificate);
222 28 return ContainsReference(certificate, SqlReflog::kRefCertificate);
223 }
224
225
226 28 bool Reflog::ContainsCatalog(const shash::Any &catalog) const {
227
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 assert(catalog.HasSuffix() && catalog.suffix == shash::kSuffixCatalog);
228 28 return ContainsReference(catalog, SqlReflog::kRefCatalog);
229 }
230
231
232 14 bool Reflog::GetCatalogTimestamp(const shash::Any &catalog,
233 uint64_t *timestamp) const {
234
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
14 assert(catalog.HasSuffix() && catalog.suffix == shash::kSuffixCatalog);
235 14 const bool result = GetReferenceTimestamp(catalog, SqlReflog::kRefCatalog,
236 timestamp);
237 14 return result;
238 }
239
240
241 28 bool Reflog::ContainsHistory(const shash::Any &history) const {
242
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 assert(history.HasSuffix() && history.suffix == shash::kSuffixHistory);
243 28 return ContainsReference(history, SqlReflog::kRefHistory);
244 }
245
246
247 28 bool Reflog::ContainsMetainfo(const shash::Any &metainfo) const {
248
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 assert(metainfo.HasSuffix() && metainfo.suffix == shash::kSuffixMetainfo);
249 28 return ContainsReference(metainfo, SqlReflog::kRefMetainfo);
250 }
251
252
253 196 bool Reflog::AddReference(const shash::Any &hash,
254 const SqlReflog::ReferenceType type) {
255 196 return insert_reference_->BindReference(hash, type)
256
3/6
✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 196 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 196 times.
✗ Branch 9 not taken.
196 && insert_reference_->Execute() && insert_reference_->Reset();
257 }
258
259
260 112 bool Reflog::ContainsReference(const shash::Any &hash,
261 const SqlReflog::ReferenceType type) const {
262 112 const bool fetching = contains_reference_->BindReference(hash, type)
263
2/4
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
112 && contains_reference_->FetchRow();
264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(fetching);
265
266 112 const bool answer = contains_reference_->RetrieveAnswer();
267 112 const bool reset = contains_reference_->Reset();
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 assert(reset);
269
270 112 return answer;
271 }
272
273
274 14 bool Reflog::GetReferenceTimestamp(const shash::Any &hash,
275 const SqlReflog::ReferenceType type,
276 uint64_t *timestamp) const {
277 14 const bool retval = get_timestamp_->BindReference(hash, type)
278
3/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 7 times.
14 && get_timestamp_->FetchRow();
279
280
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if (retval) {
281 7 *timestamp = get_timestamp_->RetrieveTimestamp();
282 }
283
284 14 const bool reset = get_timestamp_->Reset();
285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 assert(reset);
286
287 14 return retval;
288 }
289
290
291 void Reflog::BeginTransaction() {
292 assert(database_.get() != nullptr);
293 database_->BeginTransaction();
294 }
295
296
297 void Reflog::CommitTransaction() {
298 assert(database_.get() != nullptr);
299 database_->CommitTransaction();
300 }
301
302
303 148 void Reflog::TakeDatabaseFileOwnership() {
304
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 148 times.
148 assert(database_.get() != nullptr);
305 148 database_->TakeFileOwnership();
306 148 }
307
308
309 void Reflog::DropDatabaseFileOwnership() {
310 assert(database_.get() != nullptr);
311 database_->DropFileOwnership();
312 }
313
314
315 /**
316 * Use only once the database was closed.
317 */
318 962 void Reflog::HashDatabase(const std::string &database_path,
319 shash::Any *hash_reflog) {
320 962 const bool retval = HashFile(database_path, hash_reflog);
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 962 times.
962 assert(retval);
322 962 }
323
324
325 260 std::string Reflog::fqrn() const {
326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 260 times.
260 assert(database_.get() != nullptr);
327 260 return database_->GetProperty<std::string>(ReflogDatabase::kFqrnKey);
328 }
329
330
331 std::string Reflog::database_file() const {
332 assert(database_.get() != nullptr);
333 return database_->filename();
334 }
335
336 } // namespace manifest
337