GCC Code Coverage Report


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