GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/reflog.cc
Date: 2025-07-13 02:35:07
Exec Total Coverage
Lines: 148 175 84.6%
Branches: 87 181 48.1%

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