GCC Code Coverage Report


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