GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/reflog.cc
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 150 177 84.7%
Branches: 87 189 46.0%

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