GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/sync_mediator.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 13 0.0%
Branches: 0 12 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * The SyncMediator is an intermediate layer between the UnionSync
5 * implementation and the CatalogManager.
6 * It's main responsibility is to unwind file system intrinsics as
7 * deleting all files in a deleted directory. Furthermore newly
8 * created directories are recursed and all included files are
9 * added as a whole (performance improvement).
10 *
11 * Furthermore it keeps track of hard link relations. As we cannot store the
12 * transient inode of the union file system in cvmfs, we just keep track of
13 * hard link relations itself. Inodes will be assigned at run time of the CVMFS
14 * client taking these relations into account.
15 *
16 * Another responsibility of this class is the creation and destruction
17 * of nested catalogs. If a .cvmfscatalog magic file is encountered,
18 * either on delete or add, it will be treated as nested catalog change.
19 *
20 * New and modified files are piped to external processes for hashing and
21 * compression. Results come back in a pipe.
22 */
23
24 #ifndef CVMFS_SYNC_MEDIATOR_H_
25 #define CVMFS_SYNC_MEDIATOR_H_
26
27 #include <pthread.h>
28
29 #include <map>
30 #include <set>
31 #include <stack>
32 #include <string>
33 #include <vector>
34
35 #include "catalog_mgr_rw.h"
36 #include "compression.h"
37 #include "file_chunk.h"
38 #include "publish/repository.h"
39 #include "statistics.h"
40 #include "swissknife_sync.h"
41 #include "sync_item.h"
42 #include "util/platform.h"
43 #include "util/pointer.h"
44 #include "util/shared_ptr.h"
45 #include "xattr.h"
46
47 namespace manifest {
48 class Manifest;
49 }
50
51 namespace publish {
52
53 class SyncDiffReporter : public DiffListener {
54 public:
55 enum PrintAction {
56 kPrintDots,
57 kPrintChanges
58 };
59
60 explicit SyncDiffReporter(PrintAction print_action = kPrintChanges,
61 unsigned int processing_dot_interval = 100)
62 : print_action_(print_action),
63 processing_dot_interval_(processing_dot_interval),
64 changed_items_(0) {}
65
66 virtual void OnInit(const history::History::Tag &from_tag,
67 const history::History::Tag &to_tag);
68 virtual void OnStats(const catalog::DeltaCounters &delta);
69
70 virtual void OnAdd(const std::string &path,
71 const catalog::DirectoryEntry &entry);
72 virtual void OnRemove(const std::string &path,
73 const catalog::DirectoryEntry &entry);
74 virtual void OnModify(const std::string &path,
75 const catalog::DirectoryEntry &entry_from,
76 const catalog::DirectoryEntry &entry_to);
77 void CommitReport();
78
79 private:
80 void PrintDots();
81 void AddImpl(const std::string &path);
82 void RemoveImpl(const std::string &path);
83 void ModifyImpl(const std::string &path);
84
85 PrintAction print_action_;
86 unsigned int processing_dot_interval_;
87 unsigned int changed_items_;
88 };
89
90 /**
91 * If we encounter a file with linkcount > 1 it will be added to a HardlinkGroup
92 * After processing all files, the HardlinkGroups are populated with
93 * related hardlinks
94 * Assertion: linkcount == HardlinkGroup::hardlinks.size() at the end
95 */
96 struct HardlinkGroup {
97 explicit HardlinkGroup(const SharedPtr<SyncItem> &item) : master(item) {
98 hardlinks[master->GetRelativePath()] = item;
99 }
100
101 void AddHardlink(const SharedPtr<SyncItem> &entry) {
102 hardlinks[entry->GetRelativePath()] = entry;
103 }
104
105 SharedPtr<SyncItem> master;
106 SyncItemList hardlinks;
107 FileChunkList file_chunks;
108 };
109
110 class AbstractSyncMediator {
111 public:
112 virtual ~AbstractSyncMediator() = 0;
113
114 virtual void RegisterUnionEngine(SyncUnion *engine) = 0;
115
116 virtual void Add(SharedPtr<SyncItem> entry) = 0;
117 virtual void Touch(SharedPtr<SyncItem> entry) = 0;
118 virtual void Remove(SharedPtr<SyncItem> entry) = 0;
119 virtual void Replace(SharedPtr<SyncItem> entry) = 0;
120 virtual void Clone(const std::string from, const std::string to) = 0;
121
122 virtual void AddUnmaterializedDirectory(SharedPtr<SyncItem> entry) = 0;
123
124 virtual void EnterDirectory(SharedPtr<SyncItem> entry) = 0;
125 virtual void LeaveDirectory(SharedPtr<SyncItem> entry) = 0;
126
127 virtual bool Commit(manifest::Manifest *manifest) = 0;
128
129 virtual bool IsExternalData() const = 0;
130 virtual bool IsDirectIo() const = 0;
131 virtual zlib::Algorithms GetCompressionAlgorithm() const = 0;
132 };
133
134 /**
135 * Mapping of inode number to the related HardlinkGroup.
136 */
137 typedef std::map<uint64_t, HardlinkGroup> HardlinkGroupMap;
138
139 /**
140 * The SyncMediator refines the input received from a concrete UnionSync object.
141 * For example, it resolves the insertion and deletion of complete directories
142 * by recursing them. It works as a mediator between the union file system and
143 * forwards the correct database commands to the catalog handler to sync the
144 * changes into the repository.
145 * Furthermore it sends new and modified files to the spooler for compression
146 * and hashing.
147 */
148 class SyncMediator : public virtual AbstractSyncMediator {
149 public:
150 static const unsigned int processing_dot_interval = 100;
151
152 SyncMediator(catalog::WritableCatalogManager *catalog_manager,
153 const SyncParameters *params,
154 perf::StatisticsTemplate statistics);
155 void RegisterUnionEngine(SyncUnion *engine);
156 // Final class, it is not meant to be derived any further
157 ~SyncMediator();
158
159 void Add(SharedPtr<SyncItem> entry);
160 void Touch(SharedPtr<SyncItem> entry);
161 void Remove(SharedPtr<SyncItem> entry);
162 void Replace(SharedPtr<SyncItem> entry);
163 void Clone(const std::string from, const std::string to);
164
165 void AddUnmaterializedDirectory(SharedPtr<SyncItem> entry);
166
167 void EnterDirectory(SharedPtr<SyncItem> entry);
168 void LeaveDirectory(SharedPtr<SyncItem> entry);
169
170 bool Commit(manifest::Manifest *manifest);
171
172 // The sync union engine uses this information to create properly initialized
173 // sync items
174 bool IsExternalData() const { return params_->external_data; }
175 bool IsDirectIo() const { return params_->direct_io; }
176 zlib::Algorithms GetCompressionAlgorithm() const {
177 return params_->compression_alg;
178 }
179
180 private:
181 typedef std::stack<HardlinkGroupMap> HardlinkGroupMapStack;
182 typedef std::vector<HardlinkGroup> HardlinkGroupList;
183
184 void EnsureAllowed(SharedPtr<SyncItem> entry);
185
186 // Called after figuring out the type of a path (file, symlink, dir)
187 void AddFile(SharedPtr<SyncItem> entry);
188 void RemoveFile(SharedPtr<SyncItem> entry);
189
190 void AddDirectory(SharedPtr<SyncItem> entry);
191 void RemoveDirectory(SharedPtr<SyncItem> entry);
192 void TouchDirectory(SharedPtr<SyncItem> entry);
193
194 void CreateNestedCatalog(SharedPtr<SyncItem> directory);
195 void RemoveNestedCatalog(SharedPtr<SyncItem> directory);
196
197 void TouchDirectoryRecursively(SharedPtr<SyncItem> entry);
198 void TouchingFileCallback(const std::string &parent_dir,
199 const std::string &file_name);
200 void TouchingSymlinkCallback(const std::string &parent_dir,
201 const std::string &link_name);
202 void TouchDirectoryCallback(const std::string &parent_dir,
203 const std::string &dir_name);
204 void RemoveDirectoryRecursively(SharedPtr<SyncItem> entry);
205 void RemoveFileCallback(const std::string &parent_dir,
206 const std::string &file_name);
207 void RemoveSymlinkCallback(const std::string &parent_dir,
208 const std::string &link_name);
209 void RemoveCharacterDeviceCallback(const std::string &parent_dir,
210 const std::string &link_name);
211 void RemoveBlockDeviceCallback(const std::string &parent_dir,
212 const std::string &link_name);
213 void RemoveFifoCallback(const std::string &parent_dir,
214 const std::string &link_name);
215 void RemoveSocketCallback(const std::string &parent_dir,
216 const std::string &link_name);
217 void RemoveDirectoryCallback(const std::string &parent_dir,
218 const std::string &dir_name);
219 bool IgnoreFileCallback(const std::string &parent_dir,
220 const std::string &file_name);
221 // Called by file system traversal
222 void EnterAddedDirectoryCallback(const std::string &parent_dir,
223 const std::string &dir_name);
224 void LeaveAddedDirectoryCallback(const std::string &parent_dir,
225 const std::string &dir_name);
226 void AddDirectoryRecursively(SharedPtr<SyncItem> entry);
227 bool AddDirectoryCallback(const std::string &parent_dir,
228 const std::string &dir_name);
229 void AddFileCallback(const std::string &parent_dir,
230 const std::string &file_name);
231 void AddCharacterDeviceCallback(const std::string &parent_dir,
232 const std::string &file_name);
233 void AddBlockDeviceCallback(const std::string &parent_dir,
234 const std::string &file_name);
235 void AddFifoCallback(const std::string &parent_dir,
236 const std::string &file_name);
237 void AddSocketCallback(const std::string &parent_dir,
238 const std::string &file_name);
239 void AddSymlinkCallback(const std::string &parent_dir,
240 const std::string &link_name);
241 SharedPtr<SyncItem> CreateSyncItem(const std::string &relative_parent_path,
242 const std::string &filename,
243 const SyncItemType entry_type) const;
244
245 // Called by Upload Spooler
246 void PublishFilesCallback(const upload::SpoolerResult &result);
247 void PublishHardlinksCallback(const upload::SpoolerResult &result);
248
249 // Hardlink handling
250 void CompleteHardlinks(SharedPtr<SyncItem> entry);
251 HardlinkGroupMap &GetHardlinkMap() { return hardlink_stack_.top(); }
252 void LegacyRegularHardlinkCallback(const std::string &parent_dir,
253 const std::string &file_name);
254 void LegacySymlinkHardlinkCallback(const std::string &parent_dir,
255 const std::string &file_name);
256 void LegacyCharacterDeviceHardlinkCallback(const std::string &parent_dir,
257 const std::string &file_name);
258 void LegacyBlockDeviceHardlinkCallback(const std::string &parent_dir,
259 const std::string &file_name);
260 void LegacyFifoHardlinkCallback(const std::string &parent_dir,
261 const std::string &file_name);
262 void LegacySocketHardlinkCallback(const std::string &parent_dir,
263 const std::string &file_name);
264 void InsertLegacyHardlink(SharedPtr<SyncItem> entry);
265 uint64_t GetTemporaryHardlinkGroupNumber(SharedPtr<SyncItem> entry) const;
266 void InsertHardlink(SharedPtr<SyncItem> entry);
267
268 void AddLocalHardlinkGroups(const HardlinkGroupMap &hardlinks);
269 void AddHardlinkGroup(const HardlinkGroup &group);
270
271 catalog::WritableCatalogManager *catalog_manager_;
272 SyncUnion *union_engine_;
273
274 bool handle_hardlinks_;
275
276 /**
277 * Hardlinks are supported as long as they all reside in the same directory.
278 * If a recursion enters a directory, we push an empty HardlinkGroupMap to
279 * keep track of the hardlinks of this directory.
280 * When leaving a directory (i.e. it is completely processed) the stack is
281 * popped and the HardlinkGroupMap is processed.
282 */
283 HardlinkGroupMapStack hardlink_stack_;
284
285 /**
286 * New and modified files are sent to an external spooler for hashing and
287 * compression. A spooler callback adds them to the catalogs, once processed.
288 */
289 pthread_mutex_t lock_file_queue_;
290 SyncItemList file_queue_;
291
292 HardlinkGroupList hardlink_queue_;
293
294 const SyncParameters *params_;
295 mutable unsigned int changed_items_;
296
297 /**
298 * By default, files have no extended attributes.
299 */
300 XattrList default_xattrs_;
301 UniquePtr<perf::FsCounters> counters_;
302
303 UniquePtr<SyncDiffReporter> reporter_;
304 }; // class SyncMediator
305
306 } // namespace publish
307
308 #endif // CVMFS_SYNC_MEDIATOR_H_
309