GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/reflog.cc Lines: 138 164 84.1 %
Date: 2019-02-03 02:48:13 Branches: 71 145 49.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
9
  Reflog *reflog = new Reflog();
19

9
  if (NULL == reflog || !reflog->OpenDatabase(database_path)) {
20
    delete reflog;
21
    return NULL;
22
  }
23
24
  LogCvmfs(kLogReflog, kLogDebug,
25
           "opened Reflog database '%s' for repository '%s'",
26
9
           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
28
  Reflog *reflog = new Reflog();
35

28
  if (NULL == reflog || !reflog->CreateDatabase(database_path, repo_name)) {
36
    delete reflog;
37
    return NULL;
38
  }
39
40
  LogCvmfs(kLogReflog, kLogDebug, "created empty reflog database '%s' for "
41
                                  "repository '%s'",
42
28
           database_path.c_str(), repo_name.c_str());
43
28
  return reflog;
44
}
45
46
47
4
bool Reflog::ReadChecksum(const std::string &path, shash::Any* checksum) {
48
4
  int fd = open(path.c_str(), O_RDONLY);
49
4
  if (fd < 0) {
50
    return false;
51
  }
52
4
  std::string hex_hash;
53
4
  bool retval = GetLineFd(fd, &hex_hash);
54
4
  if (retval == 0) {
55
    close(fd);
56
    return false;
57
  }
58
4
  close(fd);
59
4
  *checksum = shash::MkFromHexPtr(shash::HexPtr(Trim(hex_hash)));
60
4
  return true;
61
}
62
63
64
4
bool Reflog::WriteChecksum(const std::string &path, const shash::Any &value) {
65
4
  int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, kDefaultFileMode);
66
4
  if (fd < 0) {
67
    return false;
68
  }
69
4
  std::string hex_hash = value.ToString();
70
4
  bool retval = SafeWrite(fd, hex_hash.data(), hex_hash.length());
71
4
  if (retval == 0) {
72
    close(fd);
73
    return false;
74
  }
75
4
  close(fd);
76
4
  return true;
77
}
78
79
80
28
bool Reflog::CreateDatabase(const std::string &database_path,
81
                            const std::string &repo_name) {
82
28
  assert(!database_);
83
28
  database_ = ReflogDatabase::Create(database_path);
84

28
  if (!database_ || !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
9
  assert(!database_);
98
99
9
  ReflogDatabase::OpenMode mode = ReflogDatabase::kOpenReadWrite;
100
9
  database_ = ReflogDatabase::Open(database_path, mode);
101
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
37
  assert(database_);
112
37
  insert_reference_   = new SqlInsertReference(database_.weak_ref());
113
37
  count_references_   = new SqlCountReferences(database_.weak_ref());
114
37
  list_references_    = new SqlListReferences(database_.weak_ref());
115
37
  remove_reference_   = new SqlRemoveReference(database_.weak_ref());
116
37
  contains_reference_ = new SqlContainsReference(database_.weak_ref());
117
37
  get_timestamp_      = new SqlGetTimestamp(database_.weak_ref());
118
37
}
119
120
121
7
bool Reflog::AddCertificate(const shash::Any &certificate) {
122
  assert(certificate.HasSuffix() &&
123

7
         certificate.suffix == shash::kSuffixCertificate);
124
7
  return AddReference(certificate, SqlReflog::kRefCertificate);
125
}
126
127
128
10
bool Reflog::AddCatalog(const shash::Any &catalog) {
129

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

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

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
8
  assert(database_);
148
8
  const bool success_exec = count_references_->Execute();
149
8
  assert(success_exec);
150
8
  const uint64_t count = count_references_->RetrieveCount();
151
8
  const bool success_reset = count_references_->Reset();
152
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
7
  assert(database_);
171
7
  assert(NULL != hashes);
172
173
7
  hashes->clear();
174
175
7
  bool success_bind = list_references_->BindType(type);
176
7
  assert(success_bind);
177
7
  success_bind = list_references_->BindOlderThan(timestamp);
178
7
  assert(success_bind);
179
27
  while (list_references_->FetchRow()) {
180
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
4
  assert(database_);
189
190
  SqlReflog::ReferenceType type;
191

4
  switch (hash.suffix) {
192
    case shash::kSuffixCatalog:
193
1
      type = SqlReflog::kRefCatalog;
194
1
      break;
195
    case shash::kSuffixHistory:
196
1
      type = SqlReflog::kRefHistory;
197
1
      break;
198
    case shash::kSuffixCertificate:
199
1
      type = SqlReflog::kRefCertificate;
200
1
      break;
201
    case shash::kSuffixMetainfo:
202
1
      type = SqlReflog::kRefMetainfo;
203
1
      break;
204
    default:
205
      return false;
206
  }
207
208
  return
209
    remove_reference_->BindReference(hash, type) &&
210
    remove_reference_->Execute()                 &&
211

4
    remove_reference_->Reset();
212
}
213
214
215
4
bool Reflog::ContainsCertificate(const shash::Any &certificate) const {
216
  assert(certificate.HasSuffix() &&
217

4
         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

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
  assert(catalog.HasSuffix() && catalog.suffix == shash::kSuffixCatalog);
233
  bool result = GetReferenceTimestamp(catalog, SqlReflog::kRefCatalog,
234
2
                                      timestamp);
235
2
  return result;
236
}
237
238
239
4
bool Reflog::ContainsHistory(const shash::Any &history) const {
240

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

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
    insert_reference_->BindReference(hash, type) &&
255
    insert_reference_->Execute()                 &&
256

28
    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
    contains_reference_->BindReference(hash, type) &&
264

16
    contains_reference_->FetchRow();
265
16
  assert(fetching);
266
267
16
  const bool answer = contains_reference_->RetrieveAnswer();
268
16
  const bool reset = contains_reference_->Reset();
269
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
    get_timestamp_->BindReference(hash, type) &&
282

2
    get_timestamp_->FetchRow();
283
284
2
  if (retval) {
285
1
    *timestamp = get_timestamp_->RetrieveTimestamp();
286
  }
287
288
2
  const bool reset = get_timestamp_->Reset();
289
2
  assert(reset);
290
291
2
  return retval;
292
}
293
294
295
void Reflog::BeginTransaction() {
296
  assert(database_);
297
  database_->BeginTransaction();
298
}
299
300
301
void Reflog::CommitTransaction() {
302
  assert(database_);
303
  database_->CommitTransaction();
304
}
305
306
307
4
void Reflog::TakeDatabaseFileOwnership() {
308
4
  assert(database_);
309
4
  database_->TakeFileOwnership();
310
4
}
311
312
313
void Reflog::DropDatabaseFileOwnership() {
314
  assert(database_);
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
26
  assert(retval);
328
26
}
329
330
331
20
std::string Reflog::fqrn() const {
332
20
  assert(database_);
333
20
  return database_->GetProperty<std::string>(ReflogDatabase::kFqrnKey);
334
}
335
336
337
std::string Reflog::database_file() const {
338
  assert(database_);
339
  return database_->filename();
340
}
341
342

45
}  // namespace manifest