CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
statistics_database.cc
Go to the documentation of this file.
1 
5 #include "statistics_database.h"
6 
7 #include "util/exception.h"
8 
9 
12 
13 // Changelog
14 // 1 --> 2: (Sep 4 2019)
15 // * change column name `finished_time` -> `finish_time`
16 // in publish_statistics table
17 // * add column `revision` to publish_statistics table
18 // * change column name `duplicated_files` -> `chunks_duplicated`
19 // in publish_statistics table
20 // * add column `chunks_added` to publish_statistics table
21 // * add column `symlinks_added` to publish_statistics table
22 // * add column `symlinks_removed` to publish_statistics table
23 // * add column `symlinks_changed` to publish_statistics table
24 // * change column name `finished_time` -> `finish_time`
25 // in gc_statistics table
26 // 2 --> 3: (Jan 14 2020)
27 // * add `success` column to publish_statistics table (1 for success
28 // 0 for fail)
29 // * add `success` column to gc_statistics table (1 for success
30 // 0 for fail)
31 // 3 --> 4: (Feb 1 2022)
32 // * add column `n_duplicate_delete_requests` to gc_statistics table
33 
35 unsigned int StatisticsDatabase::instances = 0;
37 
38 
39 namespace {
40 
41 struct PublishStats {
42  std::string revision;
43  std::string files_added;
44  std::string files_removed;
45  std::string files_changed;
46  std::string chunks_added;
47  std::string chunks_duplicated;
48  std::string catalogs_added;
49  std::string dirs_added;
50  std::string dirs_removed;
51  std::string dirs_changed;
52  std::string symlinks_added;
53  std::string symlinks_removed;
54  std::string symlinks_changed;
55  std::string bytes_added;
56  std::string bytes_removed;
57  std::string bytes_uploaded;
59 
60  explicit PublishStats(const perf::Statistics *statistics)
61  : revision(statistics->Lookup("publish.revision")->ToString())
62  , files_added(statistics->Lookup("publish.n_files_added")->ToString())
63  , files_removed(statistics->Lookup("publish.n_files_removed")->ToString())
64  , files_changed(statistics->Lookup("publish.n_files_changed")->ToString())
65  , chunks_added(statistics->Lookup("publish.n_chunks_added")->ToString())
66  , chunks_duplicated(
67  statistics->Lookup("publish.n_chunks_duplicated")->ToString())
68  , catalogs_added(
69  statistics->Lookup("publish.n_catalogs_added")->ToString())
70  , dirs_added(
71  statistics->Lookup("publish.n_directories_added")->ToString())
72  , dirs_removed(
73  statistics->Lookup("publish.n_directories_removed")->ToString())
74  , dirs_changed(
75  statistics->Lookup("publish.n_directories_changed")->ToString())
76  , symlinks_added(
77  statistics->Lookup("publish.n_symlinks_added")->ToString())
78  , symlinks_removed(
79  statistics->Lookup("publish.n_symlinks_removed")->ToString())
80  , symlinks_changed(
81  statistics->Lookup("publish.n_symlinks_changed")->ToString())
82  , bytes_added(statistics->Lookup("publish.sz_added_bytes")->ToString())
83  , bytes_removed(
84  statistics->Lookup("publish.sz_removed_bytes")->ToString())
85  , bytes_uploaded(
86  statistics->Lookup("publish.sz_uploaded_bytes")->ToString())
87  , catalog_bytes_uploaded(
88  statistics->Lookup("publish.sz_uploaded_catalog_bytes")
89  ->ToString()) { }
90 };
91 
92 
93 struct GcStats {
94  std::string n_preserved_catalogs;
95  std::string n_condemned_catalogs;
96  std::string n_condemned_objects;
97  std::string sz_condemned_bytes;
99 
100  explicit GcStats(const perf::Statistics *statistics) {
101  perf::Counter *c = NULL;
102  c = statistics->Lookup("gc.n_preserved_catalogs");
103  n_preserved_catalogs = c ? c->ToString() : "0";
104  c = statistics->Lookup("gc.n_condemned_catalogs");
105  n_condemned_catalogs = c ? c->ToString() : "0";
106  c = statistics->Lookup("gc.n_condemned_objects");
107  n_condemned_objects = c ? c->ToString() : "0";
108  c = statistics->Lookup("gc.sz_condemned_bytes");
109  sz_condemned_bytes = c ? c->ToString() : "0";
110  c = statistics->Lookup("gc.n_duplicate_delete_requests");
111  n_duplicate_delete_requests = c ? c->ToString() : "0";
112  }
113 };
114 
115 
122 std::string PrepareStatementIntoPublish(const perf::Statistics *statistics,
123  const std::string &start_time,
124  const std::string &finish_time,
125  const bool success) {
126  struct PublishStats stats = PublishStats(statistics);
127  std::string insert_statement = "INSERT INTO publish_statistics ("
128  "start_time,"
129  "finish_time,"
130  "revision,"
131  "files_added,"
132  "files_removed,"
133  "files_changed,"
134  "chunks_added,"
135  "chunks_duplicated,"
136  "catalogs_added,"
137  "directories_added,"
138  "directories_removed,"
139  "directories_changed,"
140  "symlinks_added,"
141  "symlinks_removed,"
142  "symlinks_changed,"
143  "sz_bytes_added,"
144  "sz_bytes_removed,"
145  "sz_bytes_uploaded,"
146  "sz_catalog_bytes_uploaded,"
147  "success)"
148  " VALUES("
149  "'"
150  + start_time + "'," + "'" + finish_time + "',"
151  + stats.revision + "," + stats.files_added
152  + "," + stats.files_removed + ","
153  + stats.files_changed + ","
154  + stats.chunks_added + ","
155  + stats.chunks_duplicated + ","
156  + stats.catalogs_added + "," + stats.dirs_added
157  + "," + stats.dirs_removed + ","
158  + stats.dirs_changed + ","
159  + stats.symlinks_added + ","
160  + stats.symlinks_removed + ","
161  + stats.symlinks_changed + ","
162  + stats.bytes_added + "," + stats.bytes_removed
163  + "," + stats.bytes_uploaded + ","
164  + stats.catalog_bytes_uploaded + ","
165  + (success ? "1" : "0") + ");";
166  return insert_statement;
167 }
168 
169 
179 std::string PrepareStatementIntoGc(const perf::Statistics *statistics,
180  const std::string &start_time,
181  const std::string &finish_time,
182  const std::string &repo_name,
183  const bool success) {
184  struct GcStats stats = GcStats(statistics);
185  std::string insert_statement = "";
186  if (StatisticsDatabase::GcExtendedStats(repo_name)) {
187  insert_statement = "INSERT INTO gc_statistics ("
188  "start_time,"
189  "finish_time,"
190  "n_preserved_catalogs,"
191  "n_condemned_catalogs,"
192  "n_condemned_objects,"
193  "sz_condemned_bytes,"
194  "n_duplicate_delete_requests,"
195  "success)"
196  " VALUES("
197  "'"
198  + start_time + "'," + "'" + finish_time + "',"
199  + stats.n_preserved_catalogs + ","
200  + stats.n_condemned_catalogs + ","
201  + stats.n_condemned_objects + ","
202  + stats.sz_condemned_bytes + ","
203  + stats.n_duplicate_delete_requests + ","
204  + (success ? "1" : "0") + ");";
205  } else {
206  // insert values except sz_condemned_bytes
207  insert_statement = "INSERT INTO gc_statistics ("
208  "start_time,"
209  "finish_time,"
210  "n_preserved_catalogs,"
211  "n_condemned_catalogs,"
212  "n_condemned_objects,"
213  "n_duplicate_delete_requests,"
214  "success)"
215  " VALUES("
216  "'"
217  + start_time + "'," + "'" + finish_time + "',"
218  + stats.n_preserved_catalogs + ","
219  + stats.n_condemned_catalogs + ","
220  + stats.n_condemned_objects + ","
221  + stats.n_duplicate_delete_requests + ","
222  + (success ? "1" : "0") + ");";
223  }
224  return insert_statement;
225 }
226 
227 } // namespace
228 
229 
232  bool ret1 = sqlite::Sql(sqlite_db(),
233  "CREATE TABLE publish_statistics ("
234  "publish_id INTEGER PRIMARY KEY,"
235  "start_time TEXT,"
236  "finish_time TEXT,"
237  "revision INTEGER,"
238  "files_added INTEGER,"
239  "files_removed INTEGER,"
240  "files_changed INTEGER,"
241  "chunks_added INTEGER,"
242  "chunks_duplicated INTEGER,"
243  "catalogs_added INTEGER,"
244  "directories_added INTEGER,"
245  "directories_removed INTEGER,"
246  "directories_changed INTEGER,"
247  "symlinks_added INTEGER,"
248  "symlinks_removed INTEGER,"
249  "symlinks_changed INTEGER,"
250  "sz_bytes_added INTEGER,"
251  "sz_bytes_removed INTEGER,"
252  "sz_bytes_uploaded INTEGER,"
253  "sz_catalog_bytes_uploaded INTEGER,"
254  "success INTEGER);")
255  .Execute();
256  bool ret2 = sqlite::Sql(sqlite_db(),
257  "CREATE TABLE gc_statistics ("
258  "gc_id INTEGER PRIMARY KEY,"
259  "start_time TEXT,"
260  "finish_time TEXT,"
261  "n_preserved_catalogs INTEGER,"
262  "n_condemned_catalogs INTEGER,"
263  "n_condemned_objects INTEGER,"
264  "sz_condemned_bytes INTEGER,"
265  "n_duplicate_delete_requests INTEGER,"
266  "success INTEGER);")
267  .Execute();
268  return ret1 & ret2;
269 }
270 
271 
274  return (schema_version() > kLatestCompatibleSchema - 0.1
276 }
277 
278 
282  && (schema_revision() == 1)) {
284  "upgrading schema revision (1 --> 2) of "
285  "statistics database");
286 
287  sqlite::Sql publish_upgrade2_1(
288  this->sqlite_db(),
289  "ALTER TABLE "
290  "publish_statistics RENAME COLUMN finished_time TO finish_time;");
291  sqlite::Sql publish_upgrade2_2(this->sqlite_db(),
292  "ALTER TABLE "
293  "publish_statistics ADD revision INTEGER;");
294  sqlite::Sql publish_upgrade2_3(this->sqlite_db(),
295  "ALTER TABLE "
296  "publish_statistics RENAME COLUMN "
297  "duplicated_files TO chunks_duplicated;");
298  sqlite::Sql publish_upgrade2_4(
299  this->sqlite_db(), "ALTER TABLE "
300  "publish_statistics ADD chunks_added INTEGER;");
301  sqlite::Sql publish_upgrade2_5(
302  this->sqlite_db(), "ALTER TABLE "
303  "publish_statistics ADD symlinks_added INTEGER;");
304  sqlite::Sql publish_upgrade2_6(
305  this->sqlite_db(), "ALTER TABLE "
306  "publish_statistics ADD symlinks_removed INTEGER;");
307  sqlite::Sql publish_upgrade2_7(
308  this->sqlite_db(), "ALTER TABLE "
309  "publish_statistics ADD symlinks_changed INTEGER;");
310  sqlite::Sql publish_upgrade2_8(
311  this->sqlite_db(), "ALTER TABLE "
312  "publish_statistics ADD catalogs_added INTEGER;");
313  sqlite::Sql publish_upgrade2_9(
314  this->sqlite_db(),
315  "ALTER TABLE "
316  "publish_statistics ADD sz_catalog_bytes_uploaded INTEGER;");
317 
318  if (!publish_upgrade2_1.Execute() || !publish_upgrade2_2.Execute()
319  || !publish_upgrade2_3.Execute() || !publish_upgrade2_4.Execute()
320  || !publish_upgrade2_5.Execute() || !publish_upgrade2_6.Execute()
321  || !publish_upgrade2_7.Execute() || !publish_upgrade2_8.Execute()
322  || !publish_upgrade2_9.Execute()) {
324  "failed to upgrade publish_statistics"
325  " table of statistics database");
326  return false;
327  }
328 
329  sqlite::Sql gc_upgrade2_1(this->sqlite_db(),
330  "ALTER TABLE gc_statistics"
331  " RENAME COLUMN finished_time TO finish_time;");
332 
333  if (!gc_upgrade2_1.Execute()) {
335  "failed to upgrade gc_statistics"
336  " table of statistics database");
337  return false;
338  }
339 
341  if (!StoreSchemaRevision()) {
343  "failed to upgrade schema revision"
344  " of statistics database");
345  return false;
346  }
347  }
348 
350  && (schema_revision() == 2)) {
352  "upgrading schema revision (2 --> 3) of "
353  "statistics database");
354 
355  sqlite::Sql publish_upgrade3_1(this->sqlite_db(),
356  "ALTER TABLE "
357  "publish_statistics ADD success INTEGER;");
358 
359  if (!publish_upgrade3_1.Execute()) {
361  "failed to upgrade publish_statistics"
362  " table of statistics database");
363  return false;
364  }
365 
366  sqlite::Sql gc_upgrade3_1(this->sqlite_db(), "ALTER TABLE gc_statistics"
367  " ADD success INTEGER;");
368 
369  if (!gc_upgrade3_1.Execute()) {
371  "failed to upgrade gc_statistics"
372  " table of statistics database");
373  return false;
374  }
375 
377  if (!StoreSchemaRevision()) {
379  "failed to upgrade schema revision"
380  " of statistics database");
381  return false;
382  }
383  }
384 
386  && (schema_revision() == 3)) {
388  "upgrading schema revision (3 --> 4) of "
389  "statistics database");
390 
391  sqlite::Sql gc_upgrade4_1(this->sqlite_db(),
392  "ALTER TABLE gc_statistics"
393  " ADD n_duplicate_delete_requests INTEGER;");
394 
395  if (!gc_upgrade4_1.Execute()) {
397  "failed to upgrade gc_statistics "
398  "table of statistics database");
399  return false;
400  }
401 
403  if (!StoreSchemaRevision()) {
405  "failed to upgrade schema revision "
406  "of statistics database");
407  return false;
408  }
409  }
410  return true;
411 }
412 
413 
415  ++compact_calls;
416  return !compacting_fails;
417 }
418 
419 
421 
422 
424  const std::string repo_name) {
425  StatisticsDatabase *db;
426  std::string db_file_path;
427  uint32_t days_to_keep;
428  GetDBParams(repo_name, &db_file_path, &days_to_keep);
429  if (FileExists(db_file_path)) {
430  db = StatisticsDatabase::Open(db_file_path, kOpenReadWrite);
431  if (db == NULL) {
432  PANIC(kLogSyslogErr, "Couldn't create StatisticsDatabase object!");
433  } else if (db->GetProperty<std::string>("repo_name") != repo_name) {
435  "'repo_name' property of the statistics database %s "
436  "is incorrect. Please fix the database.",
437  db_file_path.c_str());
438  }
439  if (!db->Prune(days_to_keep)) {
440  LogCvmfs(kLogCvmfs, kLogSyslogErr, "Failed to prune statistics database");
441  }
442  } else {
443  db = StatisticsDatabase::Create(db_file_path);
444  if (db == NULL) {
445  PANIC(kLogSyslogErr, "Couldn't create StatisticsDatabase object!");
446  // insert repo_name into properties table
447  } else if (!db->SetProperty("repo_name", repo_name)) {
448  PANIC(kLogSyslogErr, "Couldn't insert repo_name into properties table!");
449  }
450  }
451  db->repo_name_ = repo_name;
452  return db;
453 }
454 
455 
457  const perf::Statistics *statistics,
458  const std::string &start_time,
459  const bool success) {
460  std::string finish_time = GetGMTimestamp();
461  std::string statement = PrepareStatementIntoPublish(statistics, start_time,
462  finish_time, success);
463  return StoreEntry(statement);
464 }
465 
466 
468  const std::string &start_time,
469  const bool success) {
470  std::string finish_time = GetGMTimestamp();
471  std::string statement = PrepareStatementIntoGc(
472  statistics, start_time, finish_time, repo_name_, success);
473  return StoreEntry(statement);
474 }
475 
476 
477 bool StatisticsDatabase::StoreEntry(const std::string &insert_statement) {
478  sqlite::Sql insert(this->sqlite_db(), insert_statement);
479 
480  if (!insert.Execute()) {
482  "Couldn't store statistics in %s: insert.Execute failed!",
483  this->filename().c_str());
484  return false;
485  }
486 
487  LogCvmfs(kLogCvmfs, kLogStdout, "Statistics stored at: %s",
488  this->filename().c_str());
489  return true;
490 }
491 
492 
493 bool StatisticsDatabase::Prune(uint32_t days) {
494  if (days == 0)
495  return true;
496 
497  std::string
498  publish_stmt = "DELETE FROM publish_statistics WHERE "
499  "julianday('now','start of day')-julianday(start_time) > "
500  + StringifyUint(days) + ";";
501 
502  std::string
503  gc_stmt = "DELETE FROM gc_statistics WHERE "
504  "julianday('now','start of day')-julianday(start_time) > "
505  + StringifyUint(days) + ";";
506 
507  sqlite::Sql publish_sql(this->sqlite_db(), publish_stmt);
508  sqlite::Sql gc_sql(this->sqlite_db(), gc_stmt);
509  if (!publish_sql.Execute() || !gc_sql.Execute()) {
511  "Couldn't prune statistics DB %s: SQL Execute() failed!",
512  this->filename().c_str());
513  return false;
514  }
515  if (!this->Vacuum()) {
517  "Couldn't prune statistics DB %s: Vacuum() failed!",
518  this->filename().c_str());
519  return false;
520  }
521 
522  return true;
523 }
524 
525 
527  std::string local_path) {
528  if (local_path == "") {
529  local_path = this->filename();
530  }
531 
532  spooler->WaitForUpload();
533  unsigned errors_before = spooler->GetNumberOfErrors();
534  spooler->Mkdir("stats");
535  spooler->RemoveAsync("stats/stats.db");
536  spooler->WaitForUpload();
537  spooler->Upload(local_path, "stats/stats.db");
538  spooler->WaitForUpload();
539  unsigned errors_after = spooler->GetNumberOfErrors();
540 
541  if (errors_before != errors_after) {
543  "Could not upload statistics DB file into storage backend");
544  return false;
545  }
546  return true;
547 }
548 
549 
551  std::string local_path) {
552  if (local_path == "") {
553  local_path = this->filename();
554  }
555 
556  uploader->WaitForUpload();
557  unsigned errors_before = uploader->GetNumberOfErrors();
558 
559  uploader->RemoveAsync("stats/stats.db");
560  uploader->WaitForUpload();
561  uploader->UploadFile(local_path, "stats/stats.db");
562  uploader->WaitForUpload();
563  unsigned errors_after = uploader->GetNumberOfErrors();
564  return errors_before == errors_after;
565 }
566 
567 
568 void StatisticsDatabase::GetDBParams(const std::string &repo_name,
569  std::string *path,
570  uint32_t *days_to_keep) {
571  // default location
572  const std::string db_default_path = "/var/spool/cvmfs/" + repo_name
573  + "/stats.db";
574  const std::string repo_config_file = "/etc/cvmfs/repositories.d/" + repo_name
575  + "/server.conf";
576  SimpleOptionsParser parser;
577 
578  if (!parser.TryParsePath(repo_config_file)) {
580  "Could not parse repository configuration: %s.",
581  repo_config_file.c_str());
582  *path = db_default_path;
583  *days_to_keep = kDefaultDaysToKeep;
584  return;
585  }
586 
587  std::string statistics_db = "";
588  if (!parser.GetValue("CVMFS_STATISTICS_DB", &statistics_db)) {
590  "Parameter %s was not set in the repository configuration file. "
591  "Using default value: %s",
592  "CVMFS_STATISTICS_DB", db_default_path.c_str());
593  *path = db_default_path;
594  } else {
595  std::string dirname = GetParentPath(statistics_db);
596  int mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
597  | S_IXOTH; // 755
598  if (!MkdirDeep(dirname, mode, true)) {
600  "Couldn't write statistics at the specified path %s.",
601  statistics_db.c_str());
602  *path = db_default_path;
603  } else {
604  *path = statistics_db;
605  }
606  }
607 
608  std::string days_to_keep_str = "";
609  if (!parser.GetValue("CVMFS_STATS_DB_DAYS_TO_KEEP", &statistics_db)) {
611  "Parameter %s was not set in the repository configuration file. "
612  "Using default value: %s",
613  "CVMFS_STATS_DB_DAYS_TO_KEEP",
615  *days_to_keep = kDefaultDaysToKeep;
616  } else {
617  *days_to_keep = static_cast<uint32_t>(String2Uint64(days_to_keep_str));
618  }
619 }
620 
621 
628 bool StatisticsDatabase::GcExtendedStats(const std::string &repo_name) {
629  SimpleOptionsParser parser;
630  std::string param_value = "";
631  const std::string repo_config_file = "/etc/cvmfs/repositories.d/" + repo_name
632  + "/server.conf";
633 
634  if (!parser.TryParsePath(repo_config_file)) {
636  "Could not parse repository configuration: %s.",
637  repo_config_file.c_str());
638  return false;
639  }
640  if (!parser.GetValue("CVMFS_EXTENDED_GC_STATS", &param_value)) {
642  "Parameter %s was not set in the repository configuration file. "
643  "condemned_bytes were not counted.",
644  "CVMFS_EXTENDED_GC_STATS");
645  } else if (parser.IsOn(param_value)) {
646  return true;
647  }
648  return false;
649 }
650 
651 
652 StatisticsDatabase::StatisticsDatabase(const std::string &filename,
653  const OpenMode open_mode)
654  : sqlite::Database<StatisticsDatabase>(filename, open_mode)
655  , create_empty_db_calls(0)
656  , check_compatibility_calls(0)
657  , live_upgrade_calls(0)
658  , compact_calls(0) {
660 }
661 
662 const uint32_t StatisticsDatabase::kDefaultDaysToKeep = 365;
virtual void WaitForUpload() const
StatisticsDatabase(const std::string &filename, const OpenMode open_mode)
std::string ToString()
Definition: statistics.cc:24
bool Execute()
Definition: sql.cc:41
std::string GetGMTimestamp(const std::string &format)
Definition: string.cc:654
std::string PrepareStatementIntoGc(const perf::Statistics *statistics, const std::string &start_time, const std::string &finish_time, const std::string &repo_name, const bool success)
const std::string & filename() const
Definition: sql.h:146
bool UploadStatistics(upload::Spooler *spooler, std::string local_path="")
bool StoreGCStatistics(const perf::Statistics *statistics, const std::string &start_time, const bool success)
#define PANIC(...)
Definition: exception.h:29
static unsigned int instances
bool IsOn(const std::string &param_value) const
Definition: options.cc:401
unsigned int live_upgrade_calls
bool Prune(uint32_t days)
std::string StringifyUint(const uint64_t value)
Definition: string.cc:83
void set_schema_revision(const unsigned rev)
Definition: sql.h:250
std::string PrepareStatementIntoPublish(const perf::Statistics *statistics, const std::string &start_time, const std::string &finish_time, const bool success)
static StatisticsDatabase * Open(const std::string &filename, const OpenMode open_mode)
T GetProperty(const std::string &key) const
Definition: sql_impl.h:301
unsigned schema_revision() const
Definition: sql.h:148
static bool compacting_fails
bool FileExists(const std::string &path)
Definition: posix.cc:803
Counter * Lookup(const std::string &name) const
Definition: statistics.cc:63
bool TryParsePath(const std::string &config_file)
Definition: options.cc:109
static const float kLatestCompatibleSchema
bool MkdirDeep(const std::string &path, const mode_t mode, bool verify_writable)
Definition: posix.cc:855
unsigned int create_empty_db_calls
static float kLatestSchema
sqlite3 * sqlite_db() const
Definition: sql.h:145
unsigned int check_compatibility_calls
static unsigned kLatestSchemaRevision
bool GetValue(const std::string &key, std::string *value) const
Definition: options.cc:368
virtual unsigned int GetNumberOfErrors() const =0
static StatisticsDatabase * OpenStandardDB(const std::string repo_name)
bool SetProperty(const std::string &key, const T value)
Definition: sql_impl.h:320
static bool GcExtendedStats(const std::string &repo_name)
bool StoreEntry(const std::string &insert_statement)
void UploadFile(const std::string &local_path, const std::string &remote_path, const CallbackTN *callback=NULL)
bool StorePublishStatistics(const perf::Statistics *statistics, const std::string &start_time, const bool success)
static const uint32_t kDefaultDaysToKeep
bool IsEqualSchema(const float value, const float compare) const
Definition: sql.h:129
uint64_t String2Uint64(const string &value)
Definition: string.cc:240
unsigned int compact_calls
void RemoveAsync(const std::string &file_to_delete)
PathString GetParentPath(const PathString &path)
Definition: shortstring.cc:14
static void GetDBParams(const std::string &repo_name, std::string *path, uint32_t *days_to_keep)
static StatisticsDatabase * Create(const std::string &filename)
bool CompactDatabase() const
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545