GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/garbage_collection/garbage_collector.h
Date: 2026-10-25 02:40:14
Exec Total Coverage
Lines: 28 31 90.3%
Branches: 2 4 50.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * The GarbageCollector class is figuring out which data objects (represented by
5 * their content hashes) can be deleted as outdated garbage.
6 * Garbage collection is performed on the granularity of catalog revisions, thus
7 * a complete repository revision is either considered to be outdated or active.
8 * This way, a mountable repository revision stays completely usable (no nested
9 * catalogs or data objects become unavailable). A revision is defined by it's
10 * root catalog; the revision numbers of nested catalogs are irrelevant, since
11 * they might be referenced by newer (preserved) repository revisions.
12 * Thus, garbage objects are those that are _not_ referenced by any of the pre-
13 * served root catalogs or their direct subordinate nested catalog try.
14 *
15 * We use a two-stage approach:
16 *
17 * 1st Stage - Initialization
18 * The GarbageCollector is reading all the catalogs that are meant
19 * to be preserved. It builds up a filter (HashFilterT) containing
20 * all content hashes that are _not_ to be deleted
21 *
22 * 2nd Stage - Sweeping
23 * The initialized HashFilterT is presented with all content
24 * hashes found in condemned catalogs and decides if they are
25 * referenced by the preserved catalog revisions or not.
26 *
27 * The GarbageCollector is templated with CatalogTraversalT mainly for
28 * testability and with HashFilterT as an instance of the Strategy Pattern to
29 * abstract from the actual hash filtering method to be used.
30 */
31
32 #ifndef CVMFS_GARBAGE_COLLECTION_GARBAGE_COLLECTOR_H_
33 #define CVMFS_GARBAGE_COLLECTION_GARBAGE_COLLECTOR_H_
34
35 #include <inttypes.h>
36
37 #include <vector>
38
39 #include "catalog_traversal_parallel.h"
40 #include "garbage_collection/hash_filter.h"
41 #include "path_filters/inclusion_spec.h"
42 #include "statistics.h"
43 #include "upload_facility.h"
44
45 template<class CatalogTraversalT, class HashFilterT>
46 class GarbageCollector {
47 protected:
48 typedef typename CatalogTraversalT::ObjectFetcherTN ObjectFetcherTN;
49 typedef typename ObjectFetcherTN::HistoryTN HistoryTN;
50 typedef typename ObjectFetcherTN::ReflogTN ReflogTN;
51 typedef typename CatalogTraversalT::CatalogTN CatalogTN;
52 typedef typename CatalogTraversalT::CallbackDataTN TraversalCallbackDataTN;
53 typedef typename CatalogTraversalT::Parameters TraversalParameters;
54 typedef std::vector<shash::Any> HashVector;
55
56 public:
57 struct Configuration {
58 static const uint64_t kFullHistory;
59 static const uint64_t kNoHistory;
60 static const time_t kNoTimestamp;
61 static const shash::Any kLatestHistoryDatabase;
62
63 2088 Configuration()
64 2088 : uploader(NULL)
65 2088 , object_fetcher(NULL)
66 2088 , reflog(NULL)
67 2088 , keep_history_depth(kFullHistory)
68 2088 , keep_history_timestamp(kNoTimestamp)
69 2088 , dry_run(false)
70 2088 , verbose(false)
71 2088 , deleted_objects_logfile(NULL)
72 2088 , statistics(NULL)
73 2088 , extended_stats(false)
74 2088 , num_threads(8)
75 2088 , prune_partial_replica(false)
76 2088 , inclusion_spec(NULL) { }
77
78 26448 bool has_deletion_log() const { return deleted_objects_logfile != NULL; }
79
80 upload::AbstractUploader *uploader;
81 ObjectFetcherTN *object_fetcher;
82 ReflogTN *reflog;
83 uint64_t keep_history_depth;
84 time_t keep_history_timestamp;
85 bool dry_run;
86 bool verbose;
87 FILE *deleted_objects_logfile;
88 perf::Statistics *statistics;
89 bool extended_stats;
90 unsigned int num_threads;
91 bool prune_partial_replica;
92 const catalog::InclusionSpec *inclusion_spec;
93 };
94
95 public:
96 explicit GarbageCollector(const Configuration &configuration);
97
98 void UseReflogTimestamps();
99 bool Collect();
100
101 5336 uint64_t preserved_catalog_count() const { return preserved_catalogs_; }
102 1102 uint64_t condemned_catalog_count() const { return condemned_catalogs_; }
103 290 uint64_t condemned_objects_count() const { return condemned_objects_; }
104 ✗ uint64_t duplicate_delete_requests() const {
105 ✗ return duplicate_delete_requests_;
106 }
107 ✗ uint64_t condemned_bytes_count() const { return condemned_bytes_; }
108 1218 uint64_t oldest_trunk_catalog() const { return oldest_trunk_catalog_; }
109
110 protected:
111 TraversalParameters GetTraversalParams(const Configuration &configuration);
112
113 void PreserveDataObjects(const TraversalCallbackDataTN &data);
114 void SweepDataObjects(const TraversalCallbackDataTN &data);
115 void SweepExcludedDataObjects(const TraversalCallbackDataTN &data);
116
117 bool AnalyzePreservedCatalogTree();
118 bool CheckPreservedRevisions();
119 bool SweepReflog();
120 bool SweepExcludedCatalogs();
121
122 void CheckAndSweep(const shash::Any &hash);
123 void Sweep(const shash::Any &hash);
124 bool RemoveCatalogFromReflog(const shash::Any &catalog);
125
126 void PrintCatalogTreeEntry(const unsigned int tree_level,
127 const CatalogTN *catalog) const;
128 void LogDeletion(const shash::Any &hash) const;
129
130 private:
131 class ReflogBasedInfoShim
132 : public swissknife::CatalogTraversalInfoShim<CatalogTN> {
133 public:
134 3132 explicit ReflogBasedInfoShim(ReflogTN *reflog) : reflog_(reflog) {
135 3132 pthread_mutex_init(&reflog_mutex_, NULL);
136 3132 }
137 1566 virtual ~ReflogBasedInfoShim() { pthread_mutex_destroy(&reflog_mutex_); }
138 522 virtual uint64_t GetLastModified(const CatalogTN *catalog) {
139 uint64_t timestamp;
140 1044 MutexLockGuard m(&reflog_mutex_);
141
1/2
✓ Branch 2 taken 522 times.
✗ Branch 3 not taken.
1044 bool retval = reflog_->GetCatalogTimestamp(catalog->hash(), &timestamp);
142
1/2
✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
2088 return retval ? timestamp : catalog->GetLastModified();
143 1044 }
144
145 private:
146 ReflogTN *reflog_;
147 pthread_mutex_t reflog_mutex_;
148 };
149
150 const Configuration configuration_;
151 ReflogBasedInfoShim catalog_info_shim_;
152 CatalogTraversalT traversal_;
153 HashFilterT hash_filter_;
154 HashFilterT hash_map_delete_requests_;
155
156
157 bool use_reflog_timestamps_;
158 /**
159 * A marker for the garbage collection grace period, the time span that is
160 * walked back from the current head catalog. There can be named snapshots
161 * older than this snapshot. The oldest_trunk_catalog_ is used as a marker
162 * for when to remove auxiliary files (meta info, history, ...).
163 */
164 uint64_t oldest_trunk_catalog_;
165 bool oldest_trunk_catalog_found_;
166 uint64_t preserved_catalogs_;
167 /**
168 * Number of catalogs in the reflog that are to be deleted (in fact, some of
169 * them might not exist anymore).
170 */
171 uint64_t unreferenced_trees_;
172 /**
173 * Number of root catalogs garbage collected, count grows as GC progresses
174 */
175 uint64_t condemned_trees_;
176 /**
177 * Number of catalogs garbage collected, count grows as GC progresses
178 */
179 uint64_t condemned_catalogs_;
180 /**
181 * Keeps track if the last status report issued, between 0 and 1
182 */
183 float last_reported_status_;
184
185 uint64_t condemned_objects_;
186 uint64_t condemned_bytes_;
187 uint64_t duplicate_delete_requests_;
188 };
189
190 #include "garbage_collector_impl.h"
191
192 #endif // CVMFS_GARBAGE_COLLECTION_GARBAGE_COLLECTOR_H_
193