GCC Code Coverage Report


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