GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/** |
||
2 |
* This file is part of the CernVM File System. |
||
3 |
*/ |
||
4 |
|||
5 |
#ifndef CVMFS_CATALOG_DIFF_TOOL_IMPL_H_ |
||
6 |
#define CVMFS_CATALOG_DIFF_TOOL_IMPL_H_ |
||
7 |
|||
8 |
#include <algorithm> |
||
9 |
#include <string> |
||
10 |
|||
11 |
#include "catalog.h" |
||
12 |
#include "download.h" |
||
13 |
#include "hash.h" |
||
14 |
#include "logging.h" |
||
15 |
#include "util/posix.h" |
||
16 |
|||
17 |
const uint64_t kLastInode = uint64_t(-1); |
||
18 |
|||
19 |
8 |
inline void AppendFirstEntry(catalog::DirectoryEntryList* entry_list) { |
|
20 |
8 |
catalog::DirectoryEntry empty_entry; |
|
21 |
8 |
entry_list->push_back(empty_entry); |
|
22 |
8 |
} |
|
23 |
|||
24 |
8 |
inline void AppendLastEntry(catalog::DirectoryEntryList* entry_list) { |
|
25 |
✗✓ | 8 |
assert(!entry_list->empty()); |
26 |
8 |
catalog::DirectoryEntry last_entry; |
|
27 |
8 |
last_entry.set_inode(kLastInode); |
|
28 |
8 |
entry_list->push_back(last_entry); |
|
29 |
8 |
} |
|
30 |
|||
31 |
48 |
inline bool IsSmaller(const catalog::DirectoryEntry& a, |
|
32 |
const catalog::DirectoryEntry& b) { |
||
33 |
48 |
bool a_is_first = (a.inode() == catalog::DirectoryEntryBase::kInvalidInode); |
|
34 |
48 |
bool a_is_last = (a.inode() == kLastInode); |
|
35 |
48 |
bool b_is_first = (b.inode() == catalog::DirectoryEntryBase::kInvalidInode); |
|
36 |
48 |
bool b_is_last = (b.inode() == kLastInode); |
|
37 |
|||
38 |
✓✓✓✓ |
48 |
if (a_is_last || b_is_first) return false; |
39 |
✗✓ | 15 |
if (a_is_first) return !b_is_first; |
40 |
✓✓ | 15 |
if (b_is_last) return !a_is_last; |
41 |
12 |
return a.name() < b.name(); |
|
42 |
} |
||
43 |
|||
44 |
template <typename RoCatalogMgr> |
||
45 |
1 |
bool CatalogDiffTool<RoCatalogMgr>::Init() { |
|
46 |
✓✗ | 1 |
if (needs_setup_) { |
47 |
// Create a temp directory |
||
48 |
1 |
old_raii_temp_dir_ = RaiiTempDir::Create(temp_dir_prefix_); |
|
49 |
1 |
new_raii_temp_dir_ = RaiiTempDir::Create(temp_dir_prefix_); |
|
50 |
|||
51 |
// Old catalog from release manager machine (before lease) |
||
52 |
1 |
old_catalog_mgr_ = |
|
53 |
OpenCatalogManager(repo_path_, old_raii_temp_dir_->dir(), |
||
54 |
old_root_hash_, download_manager_, &stats_old_); |
||
55 |
|||
56 |
// New catalog from release manager machine (before lease) |
||
57 |
1 |
new_catalog_mgr_ = |
|
58 |
OpenCatalogManager(repo_path_, new_raii_temp_dir_->dir(), |
||
59 |
new_root_hash_, download_manager_, &stats_new_); |
||
60 |
|||
61 |
✗✓ | 1 |
if (!old_catalog_mgr_.IsValid()) { |
62 |
LogCvmfs(kLogCvmfs, kLogStderr, "Could not open old catalog"); |
||
63 |
return false; |
||
64 |
} |
||
65 |
|||
66 |
✗✓ | 1 |
if (!new_catalog_mgr_.IsValid()) { |
67 |
LogCvmfs(kLogCvmfs, kLogStderr, "Could not open new catalog"); |
||
68 |
return false; |
||
69 |
} |
||
70 |
} |
||
71 |
|||
72 |
1 |
return true; |
|
73 |
} |
||
74 |
|||
75 |
template <typename RoCatalogMgr> |
||
76 |
1 |
bool CatalogDiffTool<RoCatalogMgr>::Run(const PathString& path) { |
|
77 |
1 |
DiffRec(path); |
|
78 |
|||
79 |
1 |
return true; |
|
80 |
} |
||
81 |
|||
82 |
template <typename RoCatalogMgr> |
||
83 |
2 |
RoCatalogMgr* CatalogDiffTool<RoCatalogMgr>::OpenCatalogManager( |
|
84 |
const std::string& repo_path, const std::string& temp_dir, |
||
85 |
const shash::Any& root_hash, download::DownloadManager* download_manager, |
||
86 |
perf::Statistics* stats) { |
||
87 |
RoCatalogMgr* mgr = new RoCatalogMgr(root_hash, repo_path, temp_dir, |
||
88 |
2 |
download_manager, stats, true); |
|
89 |
2 |
mgr->Init(); |
|
90 |
|||
91 |
2 |
return mgr; |
|
92 |
} |
||
93 |
|||
94 |
template <typename RoCatalogMgr> |
||
95 |
4 |
void CatalogDiffTool<RoCatalogMgr>::DiffRec(const PathString& path) { |
|
96 |
4 |
catalog::DirectoryEntryList old_listing; |
|
97 |
4 |
AppendFirstEntry(&old_listing); |
|
98 |
4 |
old_catalog_mgr_->Listing(path, &old_listing); |
|
99 |
4 |
sort(old_listing.begin(), old_listing.end(), IsSmaller); |
|
100 |
4 |
AppendLastEntry(&old_listing); |
|
101 |
|||
102 |
4 |
catalog::DirectoryEntryList new_listing; |
|
103 |
4 |
AppendFirstEntry(&new_listing); |
|
104 |
4 |
new_catalog_mgr_->Listing(path, &new_listing); |
|
105 |
4 |
sort(new_listing.begin(), new_listing.end(), IsSmaller); |
|
106 |
4 |
AppendLastEntry(&new_listing); |
|
107 |
|||
108 |
4 |
unsigned i_from = 0, size_from = old_listing.size(); |
|
109 |
4 |
unsigned i_to = 0, size_to = new_listing.size(); |
|
110 |
✗✓✓✗ ✗✓✓✗ ✓✓✗✓ ✓✗✗✓ ✓✗✓✓ ✓ |
4 |
while ((i_from < size_from) || (i_to < size_to)) { |
111 |
15 |
catalog::DirectoryEntry old_entry = old_listing[i_from]; |
|
112 |
15 |
catalog::DirectoryEntry new_entry = new_listing[i_to]; |
|
113 |
|||
114 |
✗✓ | 15 |
if (old_entry.linkcount() == 0) { |
115 |
LogCvmfs(kLogCvmfs, kLogStderr, |
||
116 |
"CatalogDiffTool - Entry %s in old catalog has linkcount 0. " |
||
117 |
"Aborting.", |
||
118 |
old_entry.name().c_str()); |
||
119 |
abort(); |
||
120 |
} |
||
121 |
✗✓ | 15 |
if (new_entry.linkcount() == 0) { |
122 |
LogCvmfs(kLogCvmfs, kLogStderr, |
||
123 |
"CatalogDiffTool - Entry %s in new catalog has linkcount 0. " |
||
124 |
"Aborting.", |
||
125 |
new_entry.name().c_str()); |
||
126 |
abort(); |
||
127 |
} |
||
128 |
|||
129 |
// Skip .cvmfs hidden directory |
||
130 |
✗✓ | 15 |
while (old_entry.IsHidden()) old_entry = old_listing[++i_from]; |
131 |
✗✓ | 15 |
while (new_entry.IsHidden()) new_entry = new_listing[++i_to]; |
132 |
|||
133 |
15 |
PathString old_path(path); |
|
134 |
15 |
old_path.Append("/", 1); |
|
135 |
15 |
old_path.Append(old_entry.name().GetChars(), old_entry.name().GetLength()); |
|
136 |
15 |
PathString new_path(path); |
|
137 |
15 |
new_path.Append("/", 1); |
|
138 |
15 |
new_path.Append(new_entry.name().GetChars(), new_entry.name().GetLength()); |
|
139 |
|||
140 |
15 |
XattrList xattrs; |
|
141 |
✗✓ | 15 |
if (new_entry.HasXattrs()) { |
142 |
new_catalog_mgr_->LookupXattrs(new_path, &xattrs); |
||
143 |
} |
||
144 |
|||
145 |
✓✓ | 15 |
if (IsSmaller(new_entry, old_entry)) { |
146 |
2 |
i_to++; |
|
147 |
2 |
FileChunkList chunks; |
|
148 |
✗✓ | 2 |
if (new_entry.IsChunkedFile()) { |
149 |
new_catalog_mgr_->ListFileChunks(new_path, new_entry.hash_algorithm(), |
||
150 |
&chunks); |
||
151 |
} |
||
152 |
2 |
ReportAddition(new_path, new_entry, xattrs, chunks); |
|
153 |
✓✓ | 2 |
if (new_entry.IsDirectory()) { |
154 |
1 |
DiffRec(new_path); |
|
155 |
} |
||
156 |
2 |
continue; |
|
157 |
✓✓ | 13 |
} else if (IsSmaller(old_entry, new_entry)) { |
158 |
2 |
i_from++; |
|
159 |
✓✓✓✗ ✓✓ |
2 |
if (old_entry.IsDirectory() && !old_entry.IsNestedCatalogMountpoint()) { |
160 |
1 |
DiffRec(old_path); |
|
161 |
} |
||
162 |
2 |
ReportRemoval(old_path, old_entry); |
|
163 |
2 |
continue; |
|
164 |
} |
||
165 |
|||
166 |
✗✓ | 11 |
assert(old_path == new_path); |
167 |
11 |
i_from++; |
|
168 |
11 |
i_to++; |
|
169 |
|||
170 |
catalog::DirectoryEntryBase::Differences diff = |
||
171 |
11 |
old_entry.CompareTo(new_entry); |
|
172 |
✓✓✗✓ ✗✓ |
11 |
if ((diff == catalog::DirectoryEntryBase::Difference::kIdentical) && |
173 |
old_entry.IsNestedCatalogMountpoint()) { |
||
174 |
// Early recursion stop if nested catalogs are identical |
||
175 |
shash::Any id_nested_from, id_nested_to; |
||
176 |
id_nested_from = old_catalog_mgr_->GetNestedCatalogHash(old_path); |
||
177 |
id_nested_to = new_catalog_mgr_->GetNestedCatalogHash(new_path); |
||
178 |
assert(!id_nested_from.IsNull() && !id_nested_to.IsNull()); |
||
179 |
if (id_nested_from == id_nested_to) continue; |
||
180 |
} |
||
181 |
|||
182 |
✓✓ | 11 |
if (old_entry.CompareTo(new_entry) > 0) { |
183 |
1 |
FileChunkList chunks; |
|
184 |
✗✓ | 1 |
if (new_entry.IsChunkedFile()) { |
185 |
new_catalog_mgr_->ListFileChunks(new_path, new_entry.hash_algorithm(), |
||
186 |
&chunks); |
||
187 |
} |
||
188 |
1 |
ReportModification(old_path, old_entry, new_entry, xattrs, chunks); |
|
189 |
} |
||
190 |
✓✓✗✓ ✓✓ |
11 |
if (!old_entry.IsDirectory() || !new_entry.IsDirectory()) { |
191 |
✗✓ | 10 |
if (old_entry.IsDirectory()) { |
192 |
DiffRec(old_path); |
||
193 |
✗✓ | 10 |
} else if (new_entry.IsDirectory()) { |
194 |
DiffRec(new_path); |
||
195 |
} |
||
196 |
10 |
continue; |
|
197 |
} |
||
198 |
|||
199 |
// Recursion |
||
200 |
1 |
DiffRec(old_path); |
|
201 |
} |
||
202 |
4 |
} |
|
203 |
|||
204 |
#endif // CVMFS_CATALOG_DIFF_TOOL_IMPL_H_ |
Generated by: GCOVR (Version 4.1) |