GCC Code Coverage Report


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