GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/history_sqlite.cc
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 233 256 91.0%
Branches: 189 352 53.7%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "history_sqlite.h"
6
7 using namespace std; // NOLINT
8
9 namespace history {
10
11 const std::string SqliteHistory::kPreviousRevisionKey = "previous_revision";
12
13
14 21 SqliteHistory* SqliteHistory::Open(const std::string &file_name) {
15 21 const bool read_write = false;
16 21 return Open(file_name, read_write);
17 }
18
19
20 8 SqliteHistory* SqliteHistory::OpenWritable(const std::string &file_name) {
21 8 const bool read_write = true;
22 8 return Open(file_name, read_write);
23 }
24
25
26 29 SqliteHistory* SqliteHistory::Open(const std::string &file_name,
27 const bool read_write) {
28
1/2
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
29 SqliteHistory *history = new SqliteHistory();
29
3/6
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 29 times.
29 if (NULL == history || !history->OpenDatabase(file_name, read_write)) {
30 delete history;
31 return NULL;
32 }
33
34 58 LogCvmfs(kLogHistory, kLogDebug,
35 "opened history database '%s' for repository '%s' %s",
36 29 file_name.c_str(), history->fqrn().c_str(),
37
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 21 times.
29 ((history->IsWritable()) ? "(writable)" : ""));
38
39 29 return history;
40 }
41
42
43 84 SqliteHistory* SqliteHistory::Create(const std::string &file_name,
44 const std::string &fqrn) {
45
1/2
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
84 SqliteHistory *history = new SqliteHistory();
46
3/6
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
84 if (NULL == history || !history->CreateDatabase(file_name, fqrn)) {
47 delete history;
48 return NULL;
49 }
50
51 84 LogCvmfs(kLogHistory, kLogDebug, "created empty history database '%s' for"
52 "repository '%s'",
53 file_name.c_str(), fqrn.c_str());
54 84 return history;
55 }
56
57
58 29 bool SqliteHistory::OpenDatabase(
59 const std::string &file_name,
60 const bool read_write
61 ) {
62
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 assert(!database_.IsValid());
63 29 const HistoryDatabase::OpenMode mode = (read_write)
64
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 21 times.
29 ? HistoryDatabase::kOpenReadWrite
65 : HistoryDatabase::kOpenReadOnly;
66 29 database_ = HistoryDatabase::Open(file_name, mode);
67
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (!database_.IsValid()) {
68 return false;
69 }
70
71
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 if (!database_->HasProperty(HistoryDatabase::kFqrnKey)) {
72 LogCvmfs(kLogHistory, kLogDebug, "opened history database does not provide "
73 "an FQRN under '%s'",
74 HistoryDatabase::kFqrnKey.c_str());
75 return false;
76 }
77
78
1/2
✓ Branch 3 taken 29 times.
✗ Branch 4 not taken.
29 set_fqrn(database_->GetProperty<std::string>(HistoryDatabase::kFqrnKey));
79 29 PrepareQueries();
80 29 return true;
81 }
82
83
84 84 bool SqliteHistory::CreateDatabase(const std::string &file_name,
85 const std::string &repo_name) {
86
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
84 assert(!database_.IsValid());
87
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
84 assert(fqrn().empty());
88 84 set_fqrn(repo_name);
89 84 database_ = HistoryDatabase::Create(file_name);
90
3/6
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 84 times.
84 if (!database_.IsValid() || !database_->InsertInitialValues(repo_name)) {
91 LogCvmfs(kLogHistory, kLogDebug,
92 "failed to initialize empty database '%s', for repository '%s'",
93 file_name.c_str(), repo_name.c_str());
94 return false;
95 }
96
97 84 PrepareQueries();
98 84 return true;
99 }
100
101
102 113 void SqliteHistory::PrepareQueries() {
103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 113 times.
113 assert(database_.IsValid());
104
105
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 find_tag_ = new SqlFindTag (database_.weak_ref());
106
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 find_tag_by_date_ = new SqlFindTagByDate (database_.weak_ref());
107
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 count_tags_ = new SqlCountTags (database_.weak_ref());
108
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 list_tags_ = new SqlListTags (database_.weak_ref());
109
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 get_hashes_ = new SqlGetHashes (database_.weak_ref());
110
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 list_rollback_tags_ = new SqlListRollbackTags (database_.weak_ref());
111
1/2
✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
113 list_branches_ = new SqlListBranches (database_.weak_ref());
112
113
2/2
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 2 times.
113 if (database_->ContainsRecycleBin()) {
114
1/2
✓ Branch 3 taken 111 times.
✗ Branch 4 not taken.
111 recycle_list_ = new SqlRecycleBinList(database_.weak_ref());
115 }
116
117
2/2
✓ Branch 1 taken 92 times.
✓ Branch 2 taken 21 times.
113 if (IsWritable()) {
118
1/2
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 insert_tag_ = new SqlInsertTag (database_.weak_ref());
119
1/2
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 remove_tag_ = new SqlRemoveTag (database_.weak_ref());
120
1/2
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 rollback_tag_ = new SqlRollbackTag (database_.weak_ref());
121
1/2
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 recycle_empty_ = new SqlRecycleBinFlush (database_.weak_ref());
122
1/2
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 insert_branch_ = new SqlInsertBranch (database_.weak_ref());
123
1/2
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 find_branch_head_ = new SqlFindBranchHead (database_.weak_ref());
124 }
125 113 }
126
127
128 22 bool SqliteHistory::BeginTransaction() const {
129 22 return database_->BeginTransaction();
130 }
131
132
133 18 bool SqliteHistory::CommitTransaction() const {
134 18 return database_->CommitTransaction();
135 }
136
137
138 40 bool SqliteHistory::SetPreviousRevision(const shash::Any &history_hash) {
139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 assert(database_.IsValid());
140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 assert(IsWritable());
141
1/2
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
40 return database_->SetProperty(kPreviousRevisionKey, history_hash.ToString());
142 }
143
144
145 6 shash::Any SqliteHistory::previous_revision() const {
146
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 assert(database_.IsValid());
147 const std::string hash_str =
148
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 database_->GetProperty<std::string>(kPreviousRevisionKey);
149
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12 return shash::MkFromHexPtr(shash::HexPtr(hash_str), shash::kSuffixHistory);
150 6 }
151
152
153 189 bool SqliteHistory::IsWritable() const {
154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 189 times.
189 assert(database_.IsValid());
155 189 return database_->read_write();
156 }
157
158 29 unsigned SqliteHistory::GetNumberOfTags() const {
159
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 assert(database_.IsValid());
160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 assert(count_tags_.IsValid());
161 29 bool retval = count_tags_->FetchRow();
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 assert(retval);
163 29 const unsigned count = count_tags_->RetrieveCount();
164 29 retval = count_tags_->Reset();
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 assert(retval);
166 29 return count;
167 }
168
169
170 4251 bool SqliteHistory::Insert(const History::Tag &tag) {
171
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4251 times.
4251 assert(database_.IsValid());
172
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4251 times.
4251 assert(insert_tag_.IsValid());
173
174
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4251 return insert_tag_->BindTag(tag) &&
175
3/4
✓ Branch 0 taken 4251 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 4249 times.
✓ Branch 5 taken 2 times.
8500 insert_tag_->Execute() &&
176
1/2
✓ Branch 2 taken 4249 times.
✗ Branch 3 not taken.
8500 insert_tag_->Reset();
177 }
178
179
180 13 bool SqliteHistory::Remove(const std::string &name) {
181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 assert(database_.IsValid());
182
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 assert(remove_tag_.IsValid());
183
184
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 Tag condemned_tag;
185
3/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 12 times.
13 if (!GetByName(name, &condemned_tag)) {
186 1 return true;
187 }
188
189
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 return remove_tag_->BindName(name) &&
190
3/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
24 remove_tag_->Execute() &&
191
2/4
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
24 remove_tag_->Reset();
192 13 }
193
194
195 23 bool SqliteHistory::Exists(const std::string &name) const {
196
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 Tag existing_tag;
197
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
46 return GetByName(name, &existing_tag);
198 23 }
199
200
201 60 bool SqliteHistory::GetByName(const std::string &name, Tag *tag) const {
202
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 assert(database_.IsValid());
203
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 assert(find_tag_.IsValid());
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 assert(NULL != tag);
205
206
5/6
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 47 times.
✓ Branch 8 taken 13 times.
✓ Branch 9 taken 47 times.
60 if (!find_tag_->BindName(name) || !find_tag_->FetchRow()) {
207 13 find_tag_->Reset();
208 13 return false;
209 }
210
211 47 *tag = find_tag_->RetrieveTag();
212 47 return find_tag_->Reset();
213 }
214
215
216 6 bool SqliteHistory::GetByDate(const time_t timestamp, Tag *tag) const {
217
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 assert(database_.IsValid());
218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 assert(find_tag_by_date_.IsValid());
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(NULL != tag);
220
221
3/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
12 if (!find_tag_by_date_->BindTimestamp(timestamp) ||
222
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 !find_tag_by_date_->FetchRow())
223 {
224 2 find_tag_by_date_->Reset();
225 2 return false;
226 }
227
228 4 *tag = find_tag_by_date_->RetrieveTag();
229 4 return find_tag_by_date_->Reset();
230 }
231
232
233 8 bool SqliteHistory::List(std::vector<Tag> *tags) const {
234
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 assert(list_tags_.IsValid());
235 8 return RunListing(tags, list_tags_.weak_ref());
236 }
237
238
239 template <class SqlListingT>
240 22 bool SqliteHistory::RunListing(std::vector<Tag> *list, SqlListingT *sql) const {
241
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
22 assert(database_.IsValid());
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
22 assert(NULL != list);
243
244
2/2
✓ Branch 1 taken 1171 times.
✓ Branch 2 taken 11 times.
2364 while (sql->FetchRow()) {
245
1/2
✓ Branch 2 taken 1171 times.
✗ Branch 3 not taken.
2342 list->push_back(sql->RetrieveTag());
246 }
247
248 22 return sql->Reset();
249 }
250
251
252 3 bool SqliteHistory::GetBranchHead(const string &branch_name, Tag *tag) const {
253
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 assert(database_.IsValid());
254
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 assert(find_branch_head_.IsValid());
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(tag != NULL);
256
257
3/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
6 if (!find_branch_head_->BindBranchName(branch_name) ||
258
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 !find_branch_head_->FetchRow())
259 {
260 1 find_branch_head_->Reset();
261 1 return false;
262 }
263
264 2 *tag = find_branch_head_->RetrieveTag();
265 2 return find_branch_head_->Reset();
266 }
267
268
269 3 bool SqliteHistory::ExistsBranch(const string &branch_name) const {
270 3 vector<Branch> branches;
271
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if (!ListBranches(&branches))
272 return false;
273
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
8 for (unsigned i = 0; i < branches.size(); ++i) {
274
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5 times.
7 if (branches[i].branch == branch_name)
275 2 return true;
276 }
277 1 return false;
278 3 }
279
280
281 18 bool SqliteHistory::InsertBranch(const Branch &branch) {
282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 assert(database_.IsValid());
283
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 assert(insert_branch_.IsValid());
284
285
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 return insert_branch_->BindBranch(branch) &&
286
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 1 times.
34 insert_branch_->Execute() &&
287
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
34 insert_branch_->Reset();
288 }
289
290
291 1 bool SqliteHistory::PruneBranches() {
292 // Parent pointers might point to abandoned branches. Redirect them to the
293 // parent of the abandoned branch. This has to be repeated until the fix
294 // point is reached. It always works because we never delete the root branch
295 1 sqlite::Sql sql_fix_parent_pointers(database_->sqlite_db(),
296 "INSERT OR REPLACE INTO branches (branch, parent, initial_revision) "
297 "SELECT branches.branch, abandoned_parent, branches.initial_revision "
298 " FROM branches "
299 " INNER JOIN (SELECT DISTINCT branches.branch AS abandoned_branch, "
300 " branches.parent AS abandoned_parent FROM branches "
301 " LEFT OUTER JOIN tags ON (branches.branch=tags.branch)"
302 " WHERE tags.branch IS NULL) "
303
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 " ON (branches.parent=abandoned_branch);");
304 // Detect if fix point is reached
305 1 sqlite::Sql sql_remaining_rows(database_->sqlite_db(),
306 "SELECT count(*) FROM branches "
307 "INNER JOIN "
308 " (SELECT DISTINCT branches.branch AS abandoned_branch FROM branches "
309 " LEFT OUTER JOIN tags ON (branches.branch=tags.branch) "
310 " WHERE tags.branch IS NULL) "
311
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 "ON (branches.parent=abandoned_branch);");
312
313 bool retval;
314 do {
315
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 retval = sql_remaining_rows.FetchRow();
316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!retval)
317 return false;
318
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 int64_t count = sql_remaining_rows.RetrieveInt64(0);
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(count >= 0);
320
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (count == 0)
321 1 break;
322
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 retval = sql_remaining_rows.Reset();
323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(retval);
324
325
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 retval = sql_fix_parent_pointers.Execute();
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!retval)
327 return false;
328
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 retval = sql_fix_parent_pointers.Reset();
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(retval);
330 2 } while (true);
331
332 1 sqlite::Sql sql_remove_branches(database_->sqlite_db(),
333 "DELETE FROM branches "
334
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
3 "WHERE branch NOT IN (SELECT DISTINCT branch FROM tags);");
335
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 retval = sql_remove_branches.Execute();
336 1 return retval;
337 1 }
338
339
340 10 bool SqliteHistory::ListBranches(vector<Branch> *branches) const {
341
2/2
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 10 times.
37 while (list_branches_->FetchRow()) {
342
1/2
✓ Branch 3 taken 27 times.
✗ Branch 4 not taken.
27 branches->push_back(list_branches_->RetrieveBranch());
343 }
344
345 10 return list_branches_->Reset();
346 }
347
348
349 13 bool SqliteHistory::ListRecycleBin(std::vector<shash::Any> *hashes) const {
350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 assert(database_.IsValid());
351
352
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11 times.
13 if (!database_->ContainsRecycleBin()) {
353 2 return false;
354 }
355
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 assert(NULL != hashes);
357 11 hashes->clear();
358
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 11 times.
12 while (recycle_list_->FetchRow()) {
359
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 hashes->push_back(recycle_list_->RetrieveHash());
360 }
361
362 11 return recycle_list_->Reset();
363 }
364
365
366 4 bool SqliteHistory::EmptyRecycleBin() {
367
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 assert(database_.IsValid());
368
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 assert(IsWritable());
369
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 assert(recycle_empty_.IsValid());
370
1/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 return recycle_empty_->Execute() &&
371
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 recycle_empty_->Reset();
372 }
373
374
375 3 bool SqliteHistory::Rollback(const Tag &updated_target_tag) {
376
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 assert(database_.IsValid());
377
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 assert(IsWritable());
378
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 assert(rollback_tag_.IsValid());
379
380
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 Tag old_target_tag;
381 3 bool success = false;
382
383 // open a transaction (if non open yet)
384
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const bool need_to_commit = BeginTransaction();
385
386 // retrieve the old version of the target tag from the history
387
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 success = GetByName(updated_target_tag.name, &old_target_tag);
388
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!success) {
389
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 LogCvmfs(kLogHistory, kLogDebug, "failed to retrieve old target tag '%s'",
390 updated_target_tag.name.c_str());
391 1 return false;
392 }
393
394 // sanity checks
395
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 assert(old_target_tag.description == updated_target_tag.description);
396
397 // rollback the history to the target tag
398 // (essentially removing all intermediate tags + the old target tag)
399
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 success = rollback_tag_->BindTargetTag(old_target_tag) &&
400
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 rollback_tag_->Execute() &&
401
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 rollback_tag_->Reset();
402
4/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
2 if (!success || Exists(old_target_tag.name)) {
403 LogCvmfs(kLogHistory, kLogDebug, "failed to remove intermediate tags "
404 "until '%s' - '%" PRIu64 "'",
405 old_target_tag.name.c_str(),
406 old_target_tag.revision);
407 return false;
408 }
409
410 // insert the provided updated target tag into the history concluding the
411 // rollback operation
412
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 success = Insert(updated_target_tag);
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!success) {
414 LogCvmfs(kLogHistory, kLogDebug, "failed to insert updated target tag '%s'",
415 updated_target_tag.name.c_str());
416 return false;
417 }
418
419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (need_to_commit) {
420 success = CommitTransaction();
421 assert(success);
422 }
423
424 2 return true;
425 3 }
426
427
428 4 bool SqliteHistory::ListTagsAffectedByRollback(
429 const std::string &target_tag_name,
430 std::vector<Tag> *tags) const {
431 // retrieve the old version of the target tag from the history
432
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 Tag target_tag;
433
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3 times.
4 if (!GetByName(target_tag_name, &target_tag)) {
434
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 LogCvmfs(kLogHistory, kLogDebug, "failed to retrieve target tag '%s'",
435 target_tag_name.c_str());
436 1 return false;
437 }
438
439 // prepage listing command to find affected tags for a potential rollback
440
2/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
3 if (!list_rollback_tags_->BindTargetTag(target_tag)) {
441 LogCvmfs(kLogHistory, kLogDebug,
442 "failed to prepare rollback listing query");
443 return false;
444 }
445
446 // run the listing and return the results
447
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 return RunListing(tags, list_rollback_tags_.weak_ref());
448 4 }
449
450
451 2 bool SqliteHistory::GetHashes(std::vector<shash::Any> *hashes) const {
452
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 assert(database_.IsValid());
453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(NULL != hashes);
454
455
2/2
✓ Branch 2 taken 2001 times.
✓ Branch 3 taken 2 times.
2003 while (get_hashes_->FetchRow()) {
456
1/2
✓ Branch 3 taken 2001 times.
✗ Branch 4 not taken.
2001 hashes->push_back(get_hashes_->RetrieveHash());
457 }
458
459 2 return get_hashes_->Reset();
460 }
461
462
463 10 void SqliteHistory::TakeDatabaseFileOwnership() {
464
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 assert(database_.IsValid());
465 10 database_->TakeFileOwnership();
466 10 }
467
468
469 void SqliteHistory::DropDatabaseFileOwnership() {
470 assert(database_.IsValid());
471 database_->DropFileOwnership();
472 }
473
474 } // namespace history
475