Directory: | cvmfs/ |
---|---|
File: | cvmfs/catalog_sql.cc |
Date: | 2025-06-08 02:35:55 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 449 | 594 | 75.6% |
Branches: | 572 | 1530 | 37.4% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM file system. | ||
3 | */ | ||
4 | |||
5 | |||
6 | #include "catalog_sql.h" | ||
7 | |||
8 | #include <cstdlib> | ||
9 | #include <cstring> | ||
10 | |||
11 | #include "catalog.h" | ||
12 | #include "globals.h" | ||
13 | #include "util/logging.h" | ||
14 | #include "util/posix.h" | ||
15 | #include "xattr.h" | ||
16 | |||
17 | using namespace std; // NOLINT | ||
18 | |||
19 | namespace catalog { | ||
20 | |||
21 | /** | ||
22 | * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE | ||
23 | * Always remember to update the legacy catalog migration classes to produce a | ||
24 | * compatible catalog structure when updating the schema revisions here! | ||
25 | * | ||
26 | * Repository rollbacks to an outdated catalog schema is not supported. Have a | ||
27 | * look into CVM-252 if that becomes necessary at some point. | ||
28 | * | ||
29 | * If the statistics counters get modified, the swissknife migration 'stats' | ||
30 | * tools needs to be modified, too. | ||
31 | * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE | ||
32 | */ | ||
33 | |||
34 | // ChangeLog | ||
35 | // 2.5 (Jun 26 2013 - Git: e79baec22c6abd6ddcdf8f8d7d33921027a052ab) | ||
36 | // * add (backward compatible) schema revision - see below | ||
37 | // * add statistics counters for chunked files | ||
38 | // Note: this was retrofitted and needed a catalog migration step | ||
39 | // | ||
40 | // 2.4 (Aug 15 2012 - Git: 17de8fc782b5b8dc4404dda925627b5ec2b552e1) | ||
41 | // 2.3 (Aug 15 2012 - Git: ab77688cdb2f851af3fe983bf3694dc2465e65be) | ||
42 | // 2.2 (never existed) | ||
43 | // 2.1 (Aug 7 2012 - Git: beba36c12d2b1123ffbb169f865a861e570adc68) | ||
44 | // * add 'chunks' table for file chunks | ||
45 | // * add 'statistics' table for accumulative counters | ||
46 | // * rename 'inode' field to 'hardlinks' | ||
47 | // * containing both hardlink group ID and linkcount | ||
48 | // * .cvmfscatalog files become first-class entries in the catalogs | ||
49 | // | ||
50 | // 2.0 (Aug 6 2012 - Git: c8a81ede603e57fbe4324b6ab6bc8c41e3a2fa5f) | ||
51 | // * beginning of CernVM-FS 2.1.x branch ('modern' era) | ||
52 | // | ||
53 | // 1.x (earlier - code base still in SVN) | ||
54 | // * pre-historic times | ||
55 | // 0.9 (some time 2011, artificial version) | ||
56 | // * 1.0 catalogs that lack the SHA-1 value for nested catalogs | ||
57 | const float CatalogDatabase::kLatestSchema = 2.5; | ||
58 | const float CatalogDatabase::kLatestSupportedSchema = 2.5; // + 1.X (r/o) | ||
59 | |||
60 | // ChangeLog | ||
61 | // 0 --> 1: (Jan 6 2014 - Git: 3667fe7a669d0d65e07275b753a7c6f23fc267df) | ||
62 | // * add size column to nested catalog table, | ||
63 | // * add schema_revision property | ||
64 | // 1 --> 2: (Jan 22 2014 - Git: 85e6680e52cfe56dc1213a5ad74a5cc62fd50ead): | ||
65 | // * add xattr column to catalog table | ||
66 | // * add self_xattr and subtree_xattr statistics counters | ||
67 | // 2 --> 3: (Sep 28 2015 - Git: f4171234b13ea448589820c1524ee52eae141bb4): | ||
68 | // * add kFlagFileExternal to entries in catalog table | ||
69 | // * add self_external and subtree_external statistics counters | ||
70 | // * store compression algorithm in flags | ||
71 | // 3 --> 4: (Nov 11 2016 - Git): | ||
72 | // * add kFlagDirBindMountpoint | ||
73 | // * add kFlagHidden | ||
74 | // * add table bind_mountpoints | ||
75 | // 4 --> 5: (Dec 07 2017): | ||
76 | // * add kFlagFileSpecial (rebranded unused kFlagFileStat) | ||
77 | // * add self_special and subtree_special statistics counters | ||
78 | // 5 --> 6: (Jul 01 2021): | ||
79 | // * Add kFlagDirectIo | ||
80 | // 6 --> 7: (Feb 23 2024): | ||
81 | // * Store nanosecond timestamps (mtimens column) in catalog table. | ||
82 | // The mtimens column has only the nanosecond part of the timestamp | ||
83 | // and may be NULL | ||
84 | const unsigned CatalogDatabase::kLatestSchemaRevision = 7; | ||
85 | |||
86 | 159 | bool CatalogDatabase::CheckSchemaCompatibility() { | |
87 |
2/4✓ Branch 1 taken 157 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
316 | return !((schema_version() >= 2.0 - kSchemaEpsilon) |
88 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 157 times.
|
157 | && (!IsEqualSchema(schema_version(), kLatestSupportedSchema)) |
89 | ✗ | && (!IsEqualSchema(schema_version(), 2.4) | |
90 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
159 | || !IsEqualSchema(kLatestSupportedSchema, 2.5))); |
91 | } | ||
92 | |||
93 | |||
94 | 101 | bool CatalogDatabase::LiveSchemaUpgradeIfNecessary() { | |
95 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
|
101 | assert(read_write()); |
96 | |||
97 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 98 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 100 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 0)) { |
98 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (0 --> 1)"); |
99 | |||
100 | SqlCatalog sql_upgrade(*this, "ALTER TABLE nested_catalogs " | ||
101 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
2 | "ADD size INTEGER;"); |
102 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | if (!sql_upgrade.Execute()) { |
103 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade nested_catalogs"); | |
104 | ✗ | return false; | |
105 | } | ||
106 | |||
107 | 1 | set_schema_revision(1); | |
108 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | if (!StoreSchemaRevision()) { |
109 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
110 | ✗ | return false; | |
111 | } | ||
112 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | } |
113 | |||
114 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 99 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 1)) { |
115 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (1 --> 2)"); |
116 | |||
117 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | SqlCatalog sql_upgrade1(*this, "ALTER TABLE catalog ADD xattr BLOB;"); |
118 | SqlCatalog sql_upgrade2( | ||
119 | *this, | ||
120 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "INSERT INTO statistics (counter, value) VALUES ('self_xattr', 0);"); |
121 | SqlCatalog sql_upgrade3( | ||
122 | *this, | ||
123 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "INSERT INTO statistics (counter, value) VALUES ('subtree_xattr', 0);"); |
124 |
3/7✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
4 | if (!sql_upgrade1.Execute() || !sql_upgrade2.Execute() |
125 |
4/8✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
4 | || !sql_upgrade3.Execute()) { |
126 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (1 --> 2)"); | |
127 | ✗ | return false; | |
128 | } | ||
129 | |||
130 | 2 | set_schema_revision(2); | |
131 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!StoreSchemaRevision()) { |
132 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
133 | ✗ | return false; | |
134 | } | ||
135 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | } |
136 | |||
137 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 99 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 2)) { |
138 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (2 --> 3)"); |
139 | |||
140 | SqlCatalog sql_upgrade4(*this, | ||
141 | "INSERT INTO statistics (counter, value) VALUES " | ||
142 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "('self_external', 0);"); |
143 | SqlCatalog sql_upgrade5(*this, | ||
144 | "INSERT INTO statistics (counter, value) VALUES " | ||
145 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "('self_external_file_size', 0);"); |
146 | SqlCatalog sql_upgrade6(*this, | ||
147 | "INSERT INTO statistics (counter, value) VALUES " | ||
148 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "('subtree_external', 0);"); |
149 | SqlCatalog sql_upgrade7(*this, | ||
150 | "INSERT INTO statistics (counter, value) VALUES " | ||
151 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "('subtree_external_file_size', 0);"); |
152 |
3/7✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
4 | if (!sql_upgrade4.Execute() || !sql_upgrade5.Execute() |
153 |
6/13✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
|
4 | || !sql_upgrade6.Execute() || !sql_upgrade7.Execute()) { |
154 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (2 --> 3)"); | |
155 | ✗ | return false; | |
156 | } | ||
157 | |||
158 | 2 | set_schema_revision(3); | |
159 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!StoreSchemaRevision()) { |
160 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
161 | ✗ | return false; | |
162 | } | ||
163 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
2 | } |
164 | |||
165 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 99 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 3)) { |
166 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (3 --> 4)"); |
167 | |||
168 | SqlCatalog sql_upgrade8( | ||
169 | *this, | ||
170 | "CREATE TABLE bind_mountpoints (path TEXT, sha1 TEXT, size INTEGER, " | ||
171 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));"); |
172 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!sql_upgrade8.Execute()) { |
173 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (3 --> 4)"); | |
174 | ✗ | return false; | |
175 | } | ||
176 | |||
177 | 2 | set_schema_revision(4); | |
178 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!StoreSchemaRevision()) { |
179 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
180 | ✗ | return false; | |
181 | } | ||
182 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | } |
183 | |||
184 | |||
185 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 99 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 4)) { |
186 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (4 --> 5)"); |
187 | |||
188 | SqlCatalog sql_upgrade9(*this, | ||
189 | "INSERT INTO statistics (counter, value) VALUES " | ||
190 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "('self_special', 0);"); |
191 | SqlCatalog sql_upgrade10(*this, | ||
192 | "INSERT INTO statistics (counter, value) VALUES " | ||
193 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | "('subtree_special', 0);"); |
194 |
5/11✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
|
2 | if (!sql_upgrade9.Execute() || !sql_upgrade10.Execute()) { |
195 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (4 --> 5)"); | |
196 | ✗ | return false; | |
197 | } | ||
198 | |||
199 | 2 | set_schema_revision(5); | |
200 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!StoreSchemaRevision()) { |
201 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
202 | ✗ | return false; | |
203 | } | ||
204 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | } |
205 | |||
206 | |||
207 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 99 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 5)) { |
208 | 2 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (5 --> 6)"); | |
209 | |||
210 | 2 | set_schema_revision(6); | |
211 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (!StoreSchemaRevision()) { |
212 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
213 | ✗ | return false; | |
214 | } | ||
215 | } | ||
216 | |||
217 |
6/6✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 99 times.
|
101 | if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 6)) { |
218 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (6 --> 7)"); |
219 | |||
220 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | SqlCatalog sql_upgrade1(*this, "ALTER TABLE catalog ADD mtimens INTEGER;"); |
221 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!sql_upgrade1.Execute()) { |
222 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (6 --> 7)"); | |
223 | ✗ | return false; | |
224 | } | ||
225 | |||
226 | 2 | set_schema_revision(7); | |
227 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!StoreSchemaRevision()) { |
228 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision"); | |
229 | ✗ | return false; | |
230 | } | ||
231 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | } |
232 | |||
233 | 101 | return true; | |
234 | } | ||
235 | |||
236 | |||
237 | 100 | bool CatalogDatabase::CreateEmptyDatabase() { | |
238 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
|
100 | assert(read_write()); |
239 | |||
240 | // generate the catalog table and index structure | ||
241 | const bool retval = | ||
242 |
4/16✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 100 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 100 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
200 | SqlCatalog(*this, |
243 | "CREATE TABLE catalog " | ||
244 | "(md5path_1 INTEGER, md5path_2 INTEGER, parent_1 INTEGER, " | ||
245 | "parent_2 INTEGER," | ||
246 | " hardlinks INTEGER, hash BLOB, size INTEGER, mode INTEGER, " | ||
247 | "mtime INTEGER," | ||
248 | " mtimens INTEGER, flags INTEGER, name TEXT, symlink TEXT, " | ||
249 | "uid INTEGER," | ||
250 | " gid INTEGER, xattr BLOB, " | ||
251 | " CONSTRAINT pk_catalog PRIMARY KEY (md5path_1, md5path_2));") | ||
252 | 200 | .Execute() | |
253 |
5/20✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 100 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
200 | && SqlCatalog(*this, |
254 | "CREATE INDEX idx_catalog_parent " | ||
255 | "ON catalog (parent_1, parent_2);") | ||
256 |
2/4✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
|
100 | .Execute() |
257 |
5/20✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 100 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
200 | && SqlCatalog(*this, |
258 | "CREATE TABLE chunks " | ||
259 | "(md5path_1 INTEGER, md5path_2 INTEGER, offset INTEGER, " | ||
260 | "size INTEGER, " | ||
261 | " hash BLOB, " | ||
262 | " CONSTRAINT pk_chunks PRIMARY KEY (md5path_1, md5path_2, " | ||
263 | "offset, size), " | ||
264 | " FOREIGN KEY (md5path_1, md5path_2) REFERENCES " | ||
265 | " catalog(md5path_1, md5path_2));") | ||
266 |
2/4✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
|
100 | .Execute() |
267 |
5/20✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 100 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
200 | && SqlCatalog(*this, |
268 | "CREATE TABLE nested_catalogs (path TEXT, sha1 TEXT, size " | ||
269 | "INTEGER, " | ||
270 | "CONSTRAINT pk_nested_catalogs PRIMARY KEY (path));") | ||
271 |
2/4✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
|
100 | .Execute() |
272 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
200 | && |
273 | // Bind mountpoints and nested catalogs are almost the same. We put them | ||
274 | // in separate tables to | ||
275 | // - not confuse previous client versions, which would crash on bind | ||
276 | // mountpoints | ||
277 | // - prevent catalogs referenced as bind mountpoints from being | ||
278 | // replicated, | ||
279 | // which would cause exhaustive recursive catalog tree walking | ||
280 | // - don't walk into bind mountpoints in catalog traversal (e.g. GC) | ||
281 |
5/19✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 100 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
200 | SqlCatalog( |
282 | *this, | ||
283 | "CREATE TABLE bind_mountpoints (path TEXT, sha1 TEXT, size INTEGER, " | ||
284 | "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));") | ||
285 |
2/4✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
|
100 | .Execute() |
286 |
7/24✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 100 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 100 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 100 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 100 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 100 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
|
500 | && SqlCatalog(*this, |
287 | "CREATE TABLE statistics (counter TEXT, value INTEGER, " | ||
288 | "CONSTRAINT pk_statistics PRIMARY KEY (counter));") | ||
289 |
3/6✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
✗ Branch 6 not taken.
|
200 | .Execute(); |
290 | |||
291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
|
100 | if (!retval) { |
292 | ✗ | PrintSqlError("failed to create catalog database tables."); | |
293 | } | ||
294 | |||
295 | 100 | return retval; | |
296 | } | ||
297 | |||
298 | |||
299 | 99 | bool CatalogDatabase::InsertInitialValues(const std::string &root_path, | |
300 | const bool volatile_content, | ||
301 | const std::string &voms_authz, | ||
302 | const DirectoryEntry &root_entry) { | ||
303 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
|
99 | assert(read_write()); |
304 | 99 | bool retval = false; | |
305 | |||
306 | // Path hashes | ||
307 |
1/2✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
|
99 | const shash::Md5 root_path_hash = shash::Md5(shash::AsciiPtr(root_path)); |
308 | const shash::Md5 root_parent_hash = | ||
309 | 99 | (root_path == "") ? shash::Md5() | |
310 |
7/12✓ Branch 0 taken 54 times.
✓ Branch 1 taken 45 times.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 45 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 45 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 45 times.
✓ Branch 13 taken 54 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
99 | : shash::Md5(shash::AsciiPtr(GetParentPath(root_path))); |
311 | |||
312 | // Start initial filling transaction | ||
313 |
1/2✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
|
99 | retval = BeginTransaction(); |
314 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
99 | if (!retval) { |
315 | ✗ | PrintSqlError("failed to enter initial filling transaction"); | |
316 | ✗ | return false; | |
317 | } | ||
318 | |||
319 | // Insert initial values to properties | ||
320 |
3/6✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 99 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 99 times.
|
99 | if (!this->SetProperty("revision", 0)) { |
321 | ✗ | PrintSqlError( | |
322 | "failed to insert default initial values into the newly created " | ||
323 | "catalog tables."); | ||
324 | ✗ | return false; | |
325 | } | ||
326 | |||
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
99 | if (volatile_content) { |
328 | ✗ | if (!this->SetProperty("volatile", 1)) { | |
329 | ✗ | PrintSqlError("failed to insert volatile flag into the newly created " | |
330 | "catalog tables."); | ||
331 | ✗ | return false; | |
332 | } | ||
333 | } | ||
334 | |||
335 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
|
99 | if (!voms_authz.empty()) { |
336 | ✗ | if (!SetVOMSAuthz(voms_authz)) { | |
337 | ✗ | PrintSqlError("failed to insert VOMS authz flag into the newly created " | |
338 | "catalog tables."); | ||
339 | ✗ | return false; | |
340 | } | ||
341 | } | ||
342 | |||
343 | // Create initial statistics counters | ||
344 |
1/2✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
|
99 | catalog::Counters counters; |
345 | |||
346 | // Insert root entry (when given) | ||
347 |
2/2✓ Branch 1 taken 79 times.
✓ Branch 2 taken 20 times.
|
99 | if (!root_entry.IsNegative()) { |
348 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | SqlDirentInsert sql_insert(*this); |
349 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | retval = sql_insert.BindPathHash(root_path_hash) |
350 |
2/4✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
✗ Branch 4 not taken.
|
79 | && sql_insert.BindParentPathHash(root_parent_hash) |
351 |
5/11✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 79 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 79 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 79 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 79 times.
✗ Branch 11 not taken.
|
158 | && sql_insert.BindDirent(root_entry) && sql_insert.Execute(); |
352 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | if (!retval) { |
353 | ✗ | PrintSqlError("failed to insert root entry into newly created catalog."); | |
354 | ✗ | return false; | |
355 | } | ||
356 | |||
357 | // account for the created root entry | ||
358 | 79 | counters.self.directories = 1; | |
359 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | } |
360 | |||
361 | // Save initial statistics counters | ||
362 |
2/4✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 99 times.
|
99 | if (!counters.InsertIntoDatabase(*this)) { |
363 | ✗ | PrintSqlError("failed to insert initial catalog statistics counters."); | |
364 | ✗ | return false; | |
365 | } | ||
366 | |||
367 | // Insert root path (when given) | ||
368 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 54 times.
|
99 | if (!root_path.empty()) { |
369 |
4/9✓ Branch 1 taken 45 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 45 times.
✗ Branch 9 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 45 times.
|
45 | if (!this->SetProperty("root_prefix", root_path)) { |
370 | ✗ | PrintSqlError( | |
371 | "failed to store root prefix in the newly created catalog."); | ||
372 | ✗ | return false; | |
373 | } | ||
374 | } | ||
375 | |||
376 | // Set creation timestamp | ||
377 |
3/6✓ Branch 3 taken 99 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 99 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 99 times.
|
99 | if (!this->SetProperty("last_modified", static_cast<uint64_t>(time(NULL)))) { |
378 | ✗ | PrintSqlError("failed to store creation timestamp in the new catalog."); | |
379 | ✗ | return false; | |
380 | } | ||
381 | |||
382 | // Commit initial filling transaction | ||
383 |
1/2✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
|
99 | retval = CommitTransaction(); |
384 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
99 | if (!retval) { |
385 | ✗ | PrintSqlError("failed to commit initial filling transaction"); | |
386 | ✗ | return false; | |
387 | } | ||
388 | |||
389 | 99 | return true; | |
390 | } | ||
391 | |||
392 | |||
393 | ✗ | bool CatalogDatabase::SetVOMSAuthz(const std::string &voms_authz) { | |
394 | ✗ | return this->SetProperty("voms_authz", voms_authz); | |
395 | } | ||
396 | |||
397 | |||
398 | 54 | double CatalogDatabase::GetRowIdWasteRatio() const { | |
399 | SqlCatalog rowid_waste_ratio_query( | ||
400 | *this, | ||
401 | "SELECT 1.0 - CAST(COUNT(*) AS DOUBLE) / MAX(rowid) " | ||
402 |
2/4✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
|
108 | "AS ratio FROM catalog;"); |
403 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 | const bool retval = rowid_waste_ratio_query.FetchRow(); |
404 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | assert(retval); |
405 | |||
406 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
108 | return rowid_waste_ratio_query.RetrieveDouble(0); |
407 | 54 | } | |
408 | |||
409 | /** | ||
410 | * Cleanup unused database space | ||
411 | * | ||
412 | * This copies the entire catalog content into a temporary SQLite table, sweeps | ||
413 | * the original data from the 'catalog' table and reinserts everything from the | ||
414 | * temporary table afterwards. That way the implicit rowid field of 'catalog' is | ||
415 | * defragmented. | ||
416 | * | ||
417 | * Since the 'chunks' table has a foreign key relationship to the 'catalog' we | ||
418 | * need to temporarily switch off the foreign key checks. Otherwise the clearing | ||
419 | * of the 'catalog' table would fail due to foreign key violations. Note that it | ||
420 | * is a NOOP to change the foreign key setting during a transaction! | ||
421 | * | ||
422 | * Note: VACUUM used to have a similar behaviour but it was dropped from SQLite | ||
423 | * at some point. Since we compute client-inodes from the rowIDs, we are | ||
424 | * probably one of the few use cases where a defragmented rowID is indeed | ||
425 | * beneficial. | ||
426 | * | ||
427 | * See: http://www.sqlite.org/lang_vacuum.html | ||
428 | */ | ||
429 | 14 | bool CatalogDatabase::CompactDatabase() const { | |
430 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
14 | assert(read_write()); |
431 | |||
432 |
4/16✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
28 | return SqlCatalog(*this, "PRAGMA foreign_keys = OFF;").Execute() |
433 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
14 | && BeginTransaction() |
434 |
5/20✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 14 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
28 | && SqlCatalog(*this, "CREATE TEMPORARY TABLE duplicate AS " |
435 | " SELECT * FROM catalog " | ||
436 | " ORDER BY rowid ASC;") | ||
437 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
14 | .Execute() |
438 |
7/22✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 14 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
|
28 | && SqlCatalog(*this, "DELETE FROM catalog;").Execute() |
439 |
5/20✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 14 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
28 | && SqlCatalog(*this, "INSERT INTO catalog " |
440 | " SELECT * FROM duplicate " | ||
441 | " ORDER BY rowid") | ||
442 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
14 | .Execute() |
443 |
7/22✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 14 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
|
28 | && SqlCatalog(*this, "DROP TABLE duplicate;").Execute() |
444 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
14 | && CommitTransaction() |
445 |
10/29✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 14 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 14 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 14 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 14 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 14 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
|
56 | && SqlCatalog(*this, "PRAGMA foreign_keys = ON;").Execute(); |
446 | } | ||
447 | |||
448 | |||
449 | //------------------------------------------------------------------------------ | ||
450 | |||
451 | |||
452 | 819 | unsigned SqlDirent::CreateDatabaseFlags(const DirectoryEntry &entry) const { | |
453 | 819 | unsigned int database_flags = 0; | |
454 | |||
455 |
2/2✓ Branch 1 taken 41 times.
✓ Branch 2 taken 778 times.
|
819 | if (entry.IsNestedCatalogRoot()) |
456 | 41 | database_flags |= kFlagDirNestedRoot; | |
457 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 733 times.
|
778 | else if (entry.IsNestedCatalogMountpoint()) |
458 | 45 | database_flags |= kFlagDirNestedMountpoint; | |
459 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 733 times.
|
733 | else if (entry.IsBindMountpoint()) |
460 | ✗ | database_flags |= kFlagDirBindMountpoint; | |
461 | |||
462 |
2/2✓ Branch 1 taken 467 times.
✓ Branch 2 taken 352 times.
|
819 | if (entry.IsDirectory()) { |
463 | 467 | database_flags |= kFlagDir; | |
464 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 339 times.
|
352 | } else if (entry.IsLink()) { |
465 | 13 | database_flags |= kFlagFile | kFlagLink; | |
466 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
|
339 | } else if (entry.IsSpecial()) { |
467 | ✗ | database_flags |= kFlagFile | kFlagFileSpecial; | |
468 | } else { | ||
469 | 339 | database_flags |= kFlagFile; | |
470 | 339 | database_flags |= entry.compression_algorithm() << kFlagPosCompression; | |
471 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 329 times.
|
339 | if (entry.IsChunkedFile()) |
472 | 10 | database_flags |= kFlagFileChunk; | |
473 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
|
339 | if (entry.IsExternalFile()) |
474 | ✗ | database_flags |= kFlagFileExternal; | |
475 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
|
339 | if (entry.IsDirectIo()) |
476 | ✗ | database_flags |= kFlagDirectIo; | |
477 | } | ||
478 | |||
479 |
5/6✓ Branch 2 taken 500 times.
✓ Branch 3 taken 319 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 500 times.
✓ Branch 7 taken 319 times.
✓ Branch 8 taken 500 times.
|
819 | if (!entry.checksum_ptr()->IsNull() || entry.IsChunkedFile()) |
480 | 319 | StoreHashAlgorithm(entry.checksum_ptr()->algorithm, &database_flags); | |
481 | |||
482 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 809 times.
|
819 | if (entry.IsHidden()) |
483 | 10 | database_flags |= kFlagHidden; | |
484 | |||
485 | 819 | return database_flags; | |
486 | } | ||
487 | |||
488 | |||
489 | 319 | void SqlDirent::StoreHashAlgorithm(const shash::Algorithms algo, | |
490 | unsigned *flags) const { | ||
491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 319 times.
|
319 | assert(algo != shash::kAny); |
492 | // Md5 unusable for content hashes | ||
493 | 319 | *flags |= (algo - 1) << kFlagPosHash; | |
494 | 319 | } | |
495 | |||
496 | |||
497 | 856 | shash::Algorithms SqlDirent::RetrieveHashAlgorithm(const unsigned flags) const { | |
498 | 856 | unsigned in_flags = ((7 << kFlagPosHash) & flags) >> kFlagPosHash; | |
499 | // Skip Md5 | ||
500 | 856 | in_flags++; | |
501 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 856 times.
|
856 | assert(in_flags < shash::kAny); |
502 | 856 | return static_cast<shash::Algorithms>(in_flags); | |
503 | } | ||
504 | |||
505 | |||
506 | 843 | zlib::Algorithms SqlDirent::RetrieveCompressionAlgorithm( | |
507 | const unsigned flags) const { | ||
508 | // 3 bits, so use 7 (111) to only pull out the flags we want | ||
509 | 843 | const unsigned in_flags = | |
510 | 843 | ((7 << kFlagPosCompression) & flags) >> kFlagPosCompression; | |
511 | 843 | return static_cast<zlib::Algorithms>(in_flags); | |
512 | } | ||
513 | |||
514 | |||
515 | 843 | uint32_t SqlDirent::Hardlinks2Linkcount(const uint64_t hardlinks) const { | |
516 | 843 | return (hardlinks << 32) >> 32; | |
517 | } | ||
518 | |||
519 | |||
520 | 843 | uint32_t SqlDirent::Hardlinks2HardlinkGroup(const uint64_t hardlinks) const { | |
521 | 843 | return hardlinks >> 32; | |
522 | } | ||
523 | |||
524 | |||
525 | 819 | uint64_t SqlDirent::MakeHardlinks(const uint32_t hardlink_group, | |
526 | const uint32_t linkcount) const { | ||
527 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 819 times.
|
819 | assert(linkcount > 0); |
528 | 819 | return (static_cast<uint64_t>(hardlink_group) << 32) | linkcount; | |
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Expands variant symlinks containing $(VARIABLE) string. Uses the environment | ||
534 | * variables of the current process (cvmfs2) | ||
535 | */ | ||
536 | 693 | void SqlDirent::ExpandSymlink(LinkString *raw_symlink) const { | |
537 | 693 | const char *c = raw_symlink->GetChars(); | |
538 | 693 | const char *cEnd = c + raw_symlink->GetLength(); | |
539 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 693 times.
|
727 | for (; c < cEnd; ++c) { |
540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (*c == '$') |
541 | ✗ | goto expand_symlink; | |
542 | } | ||
543 | 693 | return; | |
544 | |||
545 | ✗ | expand_symlink: | |
546 | ✗ | LinkString result; | |
547 | ✗ | for (c = raw_symlink->GetChars(); c < cEnd; ++c) { | |
548 | ✗ | if ((*c == '$') && (c < cEnd - 2) && (*(c + 1) == '(')) { | |
549 | ✗ | c += 2; | |
550 | ✗ | const char *rpar = c; | |
551 | ✗ | while (rpar < cEnd) { | |
552 | ✗ | if (*rpar == ')') | |
553 | ✗ | goto expand_symlink_getenv; | |
554 | ✗ | rpar++; | |
555 | } | ||
556 | // right parenthesis missing | ||
557 | ✗ | result.Append("$(", 2); | |
558 | ✗ | result.Append(c, 1); | |
559 | ✗ | continue; | |
560 | |||
561 | ✗ | expand_symlink_getenv: | |
562 | // Check for default value | ||
563 | ✗ | const char *default_separator = c; | |
564 | ✗ | const char *default_value = rpar; | |
565 | ✗ | while (default_separator != rpar) { | |
566 | ✗ | if ((*default_separator == ':') && (*(default_separator + 1) == '-')) { | |
567 | ✗ | default_value = default_separator + 2; | |
568 | ✗ | break; | |
569 | } | ||
570 | ✗ | default_separator++; | |
571 | } | ||
572 | |||
573 | ✗ | const unsigned environ_var_length = default_separator - c; | |
574 | ✗ | char environ_var[environ_var_length + 1]; | |
575 | ✗ | environ_var[environ_var_length] = '\0'; | |
576 | ✗ | memcpy(environ_var, c, environ_var_length); | |
577 | ✗ | const char *environ_value = getenv(environ_var); // Don't free! | |
578 | ✗ | if (environ_value) { | |
579 | ✗ | result.Append(environ_value, strlen(environ_value)); | |
580 | } else { | ||
581 | ✗ | const unsigned default_length = rpar - default_value; | |
582 | ✗ | result.Append(default_value, default_length); | |
583 | } | ||
584 | ✗ | c = rpar; | |
585 | ✗ | continue; | |
586 | } | ||
587 | ✗ | result.Append(c, 1); | |
588 | } | ||
589 | ✗ | raw_symlink->Assign(result); | |
590 | ✗ | return; | |
591 | } | ||
592 | |||
593 | |||
594 | //------------------------------------------------------------------------------ | ||
595 | |||
596 | |||
597 | 819 | bool SqlDirentWrite::BindDirentFields(const int hash_idx, | |
598 | const int hardlinks_idx, | ||
599 | const int size_idx, | ||
600 | const int mode_idx, | ||
601 | const int mtime_idx, | ||
602 | const int mtimens_idx, | ||
603 | const int flags_idx, | ||
604 | const int name_idx, | ||
605 | const int symlink_idx, | ||
606 | const int uid_idx, | ||
607 | const int gid_idx, | ||
608 | const DirectoryEntry &entry) { | ||
609 | 819 | const uint64_t hardlinks = MakeHardlinks(entry.hardlink_group_, | |
610 | 819 | entry.linkcount_); | |
611 | |||
612 | 819 | bool result = BindHashBlob(hash_idx, entry.checksum_) | |
613 |
1/2✓ Branch 1 taken 819 times.
✗ Branch 2 not taken.
|
819 | && BindInt64(hardlinks_idx, hardlinks) |
614 |
1/2✓ Branch 1 taken 819 times.
✗ Branch 2 not taken.
|
819 | && BindInt64(size_idx, entry.size_) |
615 |
1/2✓ Branch 1 taken 819 times.
✗ Branch 2 not taken.
|
819 | && BindInt(mode_idx, entry.mode_) |
616 |
1/2✓ Branch 1 taken 819 times.
✗ Branch 2 not taken.
|
819 | && BindInt64(uid_idx, entry.uid_) |
617 |
1/2✓ Branch 1 taken 819 times.
✗ Branch 2 not taken.
|
819 | && BindInt64(gid_idx, entry.gid_) |
618 |
1/2✓ Branch 1 taken 819 times.
✗ Branch 2 not taken.
|
819 | && BindInt64(mtime_idx, entry.mtime_) |
619 |
1/2✓ Branch 2 taken 819 times.
✗ Branch 3 not taken.
|
819 | && BindInt(flags_idx, CreateDatabaseFlags(entry)) |
620 |
1/2✓ Branch 2 taken 819 times.
✗ Branch 3 not taken.
|
819 | && BindText(name_idx, entry.name_.GetChars(), |
621 | 819 | static_cast<int>(entry.name_.GetLength())) | |
622 |
2/4✓ Branch 0 taken 819 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 819 times.
✗ Branch 5 not taken.
|
1638 | && BindText(symlink_idx, entry.symlink_.GetChars(), |
623 | 819 | static_cast<int>(entry.symlink_.GetLength())); | |
624 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 819 times.
|
819 | if (entry.HasMtimeNs()) { |
625 | ✗ | result &= BindInt(mtimens_idx, entry.mtime_ns_); | |
626 | } else { | ||
627 | 819 | result &= BindNull(mtimens_idx); | |
628 | } | ||
629 | |||
630 | 819 | return result; | |
631 | } | ||
632 | |||
633 | |||
634 | //------------------------------------------------------------------------------ | ||
635 | |||
636 | |||
637 | 2 | SqlListContentHashes::SqlListContentHashes(const CatalogDatabase &database) { | |
638 | static const char *stmt_lt_2_4 = "SELECT hash, flags, 0 " | ||
639 | " FROM catalog " | ||
640 | " WHERE length(hash) > 0;"; | ||
641 | |||
642 | static const char | ||
643 | *stmt_ge_2_4 = "SELECT hash, flags, 0 " | ||
644 | " FROM catalog " | ||
645 | " WHERE (length(catalog.hash) > 0) AND " | ||
646 | " ((flags & 128) = 0) " // kFlagFileExternal | ||
647 | "UNION " | ||
648 | "SELECT chunks.hash, catalog.flags, 1 " | ||
649 | " FROM catalog " | ||
650 | " LEFT JOIN chunks " | ||
651 | " ON catalog.md5path_1 = chunks.md5path_1 AND " | ||
652 | " catalog.md5path_2 = chunks.md5path_2 " | ||
653 | " WHERE (catalog.flags & 128) = 0;"; // kFlagFileExternal | ||
654 | |||
655 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
|
2 | if (database.schema_version() < 2.4 - CatalogDatabase::kSchemaEpsilon) { |
656 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_lt_2_4); |
657 | } else { | ||
658 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_ge_2_4); |
659 | } | ||
660 | 2 | } | |
661 | |||
662 | |||
663 | 13 | shash::Any SqlListContentHashes::GetHash() const { | |
664 | 13 | const unsigned int db_flags = RetrieveInt(1); | |
665 | 13 | const shash::Algorithms hash_algorithm = RetrieveHashAlgorithm(db_flags); | |
666 | 13 | shash::Any hash = RetrieveHashBlob(0, hash_algorithm); | |
667 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 8 times.
|
13 | if (RetrieveInt(2) == 1) { |
668 | 5 | hash.suffix = shash::kSuffixPartial; | |
669 | } | ||
670 | |||
671 | 13 | return hash; | |
672 | } | ||
673 | |||
674 | |||
675 | //------------------------------------------------------------------------------ | ||
676 | |||
677 | #define DB_FIELDS_LT_V2_1 \ | ||
678 | "catalog.hash, catalog.inode, catalog.size, " \ | ||
679 | "catalog.mode, catalog.mtime, catalog.flags, " \ | ||
680 | "catalog.name, catalog.symlink, catalog.md5path_1, " \ | ||
681 | "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \ | ||
682 | "catalog.rowid" | ||
683 | #define DB_FIELDS_GE_V2_1_LT_R2 \ | ||
684 | "catalog.hash, catalog.hardlinks, catalog.size, " \ | ||
685 | "catalog.mode, catalog.mtime, catalog.flags, " \ | ||
686 | "catalog.name, catalog.symlink, catalog.md5path_1, " \ | ||
687 | "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \ | ||
688 | "catalog.rowid, catalog.uid, catalog.gid, " \ | ||
689 | "0, NULL" | ||
690 | #define DB_FIELDS_GE_V2_1_LT_R7 \ | ||
691 | "catalog.hash, catalog.hardlinks, catalog.size, " \ | ||
692 | "catalog.mode, catalog.mtime, catalog.flags, " \ | ||
693 | "catalog.name, catalog.symlink, catalog.md5path_1, " \ | ||
694 | "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \ | ||
695 | "catalog.rowid, catalog.uid, catalog.gid, " \ | ||
696 | "catalog.xattr IS NOT NULL, NULL" | ||
697 | #define DB_FIELDS_GE_V2_1_GE_R7 \ | ||
698 | "catalog.hash, catalog.hardlinks, catalog.size, " \ | ||
699 | "catalog.mode, catalog.mtime, catalog.flags, " \ | ||
700 | "catalog.name, catalog.symlink, catalog.md5path_1, " \ | ||
701 | "catalog.md5path_2, catalog.parent_1, catalog.parent_2, " \ | ||
702 | "catalog.rowid, catalog.uid, catalog.gid, " \ | ||
703 | "catalog.xattr IS NOT NULL, catalog.mtimens" | ||
704 | |||
705 | #define MAKE_STATEMENT(STMT_TMPL, REV) \ | ||
706 | static const std::string REV = ReplaceAll(STMT_TMPL, "@DB_FIELDS@", \ | ||
707 | DB_FIELDS_##REV) | ||
708 | |||
709 | #define MAKE_STATEMENTS(STMT_TMPL) \ | ||
710 | MAKE_STATEMENT(STMT_TMPL, LT_V2_1); \ | ||
711 | MAKE_STATEMENT(STMT_TMPL, GE_V2_1_LT_R2); \ | ||
712 | MAKE_STATEMENT(STMT_TMPL, GE_V2_1_LT_R7); \ | ||
713 | MAKE_STATEMENT(STMT_TMPL, GE_V2_1_GE_R7) | ||
714 | |||
715 | #define DEFERRED_INIT(DB, REV) DeferredInit((DB).sqlite_db(), (REV).c_str()) | ||
716 | |||
717 | #define DEFERRED_INITS(DB) \ | ||
718 | if ((DB).schema_version() < 2.1 - CatalogDatabase::kSchemaEpsilon) { \ | ||
719 | DEFERRED_INIT((DB), LT_V2_1); \ | ||
720 | } else if ((DB).schema_revision() < 2) { \ | ||
721 | DEFERRED_INIT((DB), GE_V2_1_LT_R2); \ | ||
722 | } else if ((DB).schema_revision() < 7) { \ | ||
723 | DEFERRED_INIT((DB), GE_V2_1_LT_R7); \ | ||
724 | } else { \ | ||
725 | DEFERRED_INIT((DB), GE_V2_1_GE_R7); \ | ||
726 | } | ||
727 | |||
728 | |||
729 | ✗ | shash::Md5 SqlLookup::GetPathHash() const { return RetrieveMd5(8, 9); } | |
730 | |||
731 | |||
732 | ✗ | shash::Md5 SqlLookup::GetParentPathHash() const { return RetrieveMd5(10, 11); } | |
733 | |||
734 | |||
735 | /** | ||
736 | * This method is a friend of DirectoryEntry. | ||
737 | */ | ||
738 | 843 | DirectoryEntry SqlLookup::GetDirent(const Catalog *catalog, | |
739 | const bool expand_symlink) const { | ||
740 | 843 | DirectoryEntry result; | |
741 | |||
742 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | const unsigned database_flags = RetrieveInt(5); |
743 | 843 | result.is_nested_catalog_root_ = (database_flags & kFlagDirNestedRoot); | |
744 | 843 | result.is_nested_catalog_mountpoint_ = (database_flags | |
745 | 843 | & kFlagDirNestedMountpoint); | |
746 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | const char *name = reinterpret_cast<const char *>(RetrieveText(6)); |
747 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | const char *symlink = reinterpret_cast<const char *>(RetrieveText(7)); |
748 | |||
749 | // Retrieve the hardlink information from the hardlinks database field | ||
750 |
2/4✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 843 times.
|
843 | if (catalog->schema() < 2.1 - CatalogDatabase::kSchemaEpsilon) { |
751 | ✗ | result.linkcount_ = 1; | |
752 | ✗ | result.hardlink_group_ = 0; | |
753 | ✗ | result.inode_ = catalog->GetMangledInode(RetrieveInt64(12), 0); | |
754 | ✗ | result.is_chunked_file_ = false; | |
755 | ✗ | result.has_xattrs_ = false; | |
756 | ✗ | result.checksum_ = RetrieveHashBlob(0, shash::kSha1); | |
757 | ✗ | result.uid_ = g_uid; | |
758 | ✗ | result.gid_ = g_gid; | |
759 | } else { | ||
760 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | const uint64_t hardlinks = RetrieveInt64(1); |
761 | 843 | result.linkcount_ = Hardlinks2Linkcount(hardlinks); | |
762 | 843 | result.hardlink_group_ = Hardlinks2HardlinkGroup(hardlinks); | |
763 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.inode_ = catalog->GetMangledInode(RetrieveInt64(12), |
764 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.hardlink_group_); |
765 | 843 | result.is_bind_mountpoint_ = (database_flags & kFlagDirBindMountpoint); | |
766 | 843 | result.is_chunked_file_ = (database_flags & kFlagFileChunk); | |
767 | 843 | result.is_hidden_ = (database_flags & kFlagHidden); | |
768 | 843 | result.is_direct_io_ = (database_flags & kFlagDirectIo); | |
769 | 843 | result.is_external_file_ = (database_flags & kFlagFileExternal); | |
770 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.has_xattrs_ = RetrieveInt(15) != 0; |
771 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.mtime_ns_ = RetrieveNullableInt(16, -1); |
772 |
1/2✓ Branch 2 taken 843 times.
✗ Branch 3 not taken.
|
843 | result.checksum_ = RetrieveHashBlob(0, |
773 | RetrieveHashAlgorithm(database_flags)); | ||
774 | 843 | result.compression_algorithm_ = RetrieveCompressionAlgorithm( | |
775 | database_flags); | ||
776 | |||
777 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 843 times.
|
843 | if (g_claim_ownership) { |
778 | ✗ | result.uid_ = g_uid; | |
779 | ✗ | result.gid_ = g_gid; | |
780 | } else { | ||
781 |
2/4✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 843 times.
✗ Branch 5 not taken.
|
843 | result.uid_ = catalog->MapUid(RetrieveInt64(13)); |
782 |
2/4✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 843 times.
✗ Branch 5 not taken.
|
843 | result.gid_ = catalog->MapGid(RetrieveInt64(14)); |
783 | } | ||
784 | } | ||
785 | |||
786 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.mode_ = RetrieveInt(3); |
787 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.size_ = RetrieveInt64(2); |
788 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.mtime_ = RetrieveInt64(4); |
789 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.name_.Assign(name, strlen(name)); |
790 |
1/2✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
|
843 | result.symlink_.Assign(symlink, strlen(symlink)); |
791 |
3/4✓ Branch 0 taken 693 times.
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 693 times.
✗ Branch 3 not taken.
|
843 | if (expand_symlink && !g_raw_symlinks) |
792 |
1/2✓ Branch 1 taken 693 times.
✗ Branch 2 not taken.
|
693 | ExpandSymlink(&result.symlink_); |
793 | |||
794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 843 times.
|
843 | if (g_world_readable) { |
795 | ✗ | if (S_ISDIR(result.mode_)) { | |
796 | ✗ | result.mode_ |= 0555; | |
797 | } else { | ||
798 | ✗ | result.mode_ |= 0444; | |
799 | } | ||
800 | } | ||
801 | |||
802 | 843 | return result; | |
803 | } | ||
804 | |||
805 | |||
806 | //------------------------------------------------------------------------------ | ||
807 | |||
808 | |||
809 | 156 | SqlListing::SqlListing(const CatalogDatabase &database) { | |
810 |
28/62✓ Branch 0 taken 1 times.
✓ Branch 1 taken 155 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 28 taken 1 times.
✓ Branch 29 taken 155 times.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 56 taken 1 times.
✓ Branch 57 taken 155 times.
✓ Branch 59 taken 1 times.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✓ Branch 63 taken 1 times.
✗ Branch 64 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 68 not taken.
✓ Branch 71 taken 1 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 1 times.
✗ Branch 75 not taken.
✓ Branch 84 taken 1 times.
✓ Branch 85 taken 155 times.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✓ Branch 91 taken 1 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 1 times.
✗ Branch 96 not taken.
✓ Branch 99 taken 1 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 1 times.
✗ Branch 103 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
|
156 | MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog " |
811 | "WHERE (parent_1 = :p_1) AND (parent_2 = :p_2);"); | ||
812 |
8/25✓ Branch 1 taken 2 times.
✓ Branch 2 taken 154 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 154 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 154 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 32 taken 154 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 154 times.
✗ Branch 36 not taken.
|
156 | DEFERRED_INITS(database); |
813 | 156 | } | |
814 | |||
815 | |||
816 | 103 | bool SqlListing::BindPathHash(const struct shash::Md5 &hash) { | |
817 | 103 | return BindMd5(1, 2, hash); | |
818 | } | ||
819 | |||
820 | |||
821 | //------------------------------------------------------------------------------ | ||
822 | |||
823 | |||
824 | 156 | SqlLookupPathHash::SqlLookupPathHash(const CatalogDatabase &database) { | |
825 |
28/62✓ Branch 0 taken 1 times.
✓ Branch 1 taken 155 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 28 taken 1 times.
✓ Branch 29 taken 155 times.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 56 taken 1 times.
✓ Branch 57 taken 155 times.
✓ Branch 59 taken 1 times.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✓ Branch 63 taken 1 times.
✗ Branch 64 not taken.
✓ Branch 67 taken 1 times.
✗ Branch 68 not taken.
✓ Branch 71 taken 1 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 1 times.
✗ Branch 75 not taken.
✓ Branch 84 taken 1 times.
✓ Branch 85 taken 155 times.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✓ Branch 91 taken 1 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 1 times.
✗ Branch 96 not taken.
✓ Branch 99 taken 1 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 1 times.
✗ Branch 103 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
|
156 | MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog " |
826 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);"); | ||
827 |
8/25✓ Branch 1 taken 2 times.
✓ Branch 2 taken 154 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 154 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 154 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 32 taken 154 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 154 times.
✗ Branch 36 not taken.
|
156 | DEFERRED_INITS(database); |
828 | 156 | } | |
829 | |||
830 | 670 | bool SqlLookupPathHash::BindPathHash(const struct shash::Md5 &hash) { | |
831 | 670 | return BindMd5(1, 2, hash); | |
832 | } | ||
833 | |||
834 | |||
835 | //------------------------------------------------------------------------------ | ||
836 | |||
837 | |||
838 | ✗ | SqlLookupInode::SqlLookupInode(const CatalogDatabase &database) { | |
839 | ✗ | MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog WHERE rowid = :rowid;"); | |
840 | ✗ | DEFERRED_INITS(database); | |
841 | } | ||
842 | |||
843 | |||
844 | ✗ | bool SqlLookupInode::BindRowId(const uint64_t inode) { | |
845 | ✗ | return BindInt64(1, inode); | |
846 | } | ||
847 | |||
848 | |||
849 | //------------------------------------------------------------------------------ | ||
850 | |||
851 | |||
852 | ✗ | SqlLookupDanglingMountpoints::SqlLookupDanglingMountpoints( | |
853 | ✗ | const catalog::CatalogDatabase &database) { | |
854 | ✗ | MAKE_STATEMENTS("SELECT DISTINCT @DB_FIELDS@ FROM catalog " | |
855 | "JOIN catalog AS c2 " | ||
856 | "ON catalog.md5path_1 = c2.parent_1 AND " | ||
857 | " catalog.md5path_2 = c2.parent_2 " | ||
858 | "WHERE catalog.flags & :nested_mountpoint_flag"); | ||
859 | ✗ | DEFERRED_INITS(database); | |
860 | |||
861 | // this pretty much removes the advantage of a deferred init but the statement | ||
862 | // is anyway only used directly. | ||
863 | ✗ | const bool success = BindInt64(1, SqlDirent::kFlagDirNestedMountpoint); | |
864 | ✗ | assert(success); | |
865 | } | ||
866 | |||
867 | |||
868 | //------------------------------------------------------------------------------ | ||
869 | |||
870 | |||
871 | 98 | SqlDirentTouch::SqlDirentTouch(const CatalogDatabase &database) { | |
872 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
873 | "UPDATE catalog " | ||
874 | "SET hash = :hash, size = :size, mode = :mode, mtime = :mtime, " | ||
875 | // 1 2 3 4 | ||
876 | "name = :name, symlink = :symlink, uid = :uid, gid = :gid, " | ||
877 | "xattr = :xattr, " | ||
878 | // 5 6 7 8 9 | ||
879 | "mtimens = :mtimens " | ||
880 | // 10 | ||
881 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);"); | ||
882 | // 11 12 | ||
883 | 98 | } | |
884 | |||
885 | |||
886 | 4 | bool SqlDirentTouch::BindDirentBase(const DirectoryEntryBase &entry) { | |
887 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | bool result = BindHashBlob(1, entry.checksum_) && BindInt64(2, entry.size_) |
888 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | && BindInt(3, entry.mode_) && BindInt64(4, entry.mtime_) |
889 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | && BindText(5, entry.name_.GetChars(), entry.name_.GetLength()) |
890 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | && BindText(6, entry.symlink_.GetChars(), |
891 | 4 | entry.symlink_.GetLength()) | |
892 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
8 | && BindInt64(7, entry.uid_) && BindInt64(8, entry.gid_); |
893 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (entry.HasMtimeNs()) { |
894 | ✗ | result &= BindInt(10, entry.mtime_ns_); | |
895 | } else { | ||
896 | 4 | result &= BindNull(10); | |
897 | } | ||
898 | 4 | return result; | |
899 | } | ||
900 | |||
901 | |||
902 | 4 | bool SqlDirentTouch::BindPathHash(const shash::Md5 &hash) { | |
903 | 4 | return BindMd5(11, 12, hash); | |
904 | } | ||
905 | |||
906 | |||
907 | ✗ | bool SqlDirentTouch::BindXattr(const XattrList &xattrs) { | |
908 | unsigned char *packed_xattrs; | ||
909 | unsigned size; | ||
910 | ✗ | xattrs.Serialize(&packed_xattrs, &size); | |
911 | ✗ | if (packed_xattrs == NULL) | |
912 | ✗ | return BindNull(9); | |
913 | ✗ | return BindBlobTransient(9, packed_xattrs, size); | |
914 | } | ||
915 | |||
916 | |||
917 | 4 | bool SqlDirentTouch::BindXattrEmpty() { return BindNull(9); } | |
918 | |||
919 | |||
920 | //------------------------------------------------------------------------------ | ||
921 | |||
922 | |||
923 | 156 | SqlNestedCatalogLookup::SqlNestedCatalogLookup( | |
924 | 156 | const CatalogDatabase &database) { | |
925 | // We cannot access nested catalogs where the content hash is missing | ||
926 | static const char *stmt_0_9 = "SELECT '', 0 FROM nested_catalogs;"; | ||
927 | static const char *stmt_2_5_ge_4 = | ||
928 | "SELECT sha1, size FROM nested_catalogs WHERE path=:path " | ||
929 | "UNION ALL SELECT sha1, size FROM bind_mountpoints WHERE path=:path;"; | ||
930 | static const char *stmt_2_5_ge_1_lt_4 = "SELECT sha1, size FROM " | ||
931 | "nested_catalogs WHERE path=:path;"; | ||
932 | // Internally converts NULL to 0 for size | ||
933 | static const char | ||
934 | *stmt_2_5_lt_1 = "SELECT sha1, 0 FROM nested_catalogs WHERE path=:path;"; | ||
935 | |||
936 | 156 | if (database.IsEqualSchema(database.schema_version(), 2.5) | |
937 |
5/6✓ Branch 0 taken 154 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 154 times.
✓ Branch 6 taken 2 times.
|
156 | && (database.schema_revision() >= 4)) { |
938 |
2/4✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
|
154 | DeferredInit(database.sqlite_db(), stmt_2_5_ge_4); |
939 | 2 | } else if (database.IsEqualSchema(database.schema_version(), 2.5) | |
940 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
|
2 | && (database.schema_revision() >= 1)) { |
941 | ✗ | DeferredInit(database.sqlite_db(), stmt_2_5_ge_1_lt_4); | |
942 | } else { | ||
943 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if (database.IsEqualSchema(database.schema_version(), 0.9)) { |
944 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_0_9); |
945 | } else { | ||
946 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_2_5_lt_1); |
947 | } | ||
948 | } | ||
949 | 156 | } | |
950 | |||
951 | |||
952 | 62 | bool SqlNestedCatalogLookup::BindSearchPath(const PathString &path) { | |
953 | 62 | return BindText(1, path.GetChars(), path.GetLength()); | |
954 | } | ||
955 | |||
956 | |||
957 | 60 | shash::Any SqlNestedCatalogLookup::GetContentHash() const { | |
958 |
2/4✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 60 times.
✗ Branch 6 not taken.
|
60 | const string hash = string(reinterpret_cast<const char *>(RetrieveText(0))); |
959 | 60 | return (hash.empty()) | |
960 | ? shash::Any(shash::kAny) | ||
961 |
4/6✓ Branch 0 taken 32 times.
✓ Branch 1 taken 28 times.
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
|
120 | : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog); |
962 | 60 | } | |
963 | |||
964 | |||
965 | 60 | uint64_t SqlNestedCatalogLookup::GetSize() const { return RetrieveInt64(1); } | |
966 | |||
967 | |||
968 | //------------------------------------------------------------------------------ | ||
969 | |||
970 | |||
971 | 156 | SqlNestedCatalogListing::SqlNestedCatalogListing( | |
972 | 156 | const CatalogDatabase &database) { | |
973 | // We cannot access nested catalogs where the content hash is missing | ||
974 | static const char *stmt_0_9 = "SELECT '', '', 0 FROM nested_catalogs;"; | ||
975 | static const char *stmt_2_5_ge_4 = | ||
976 | "SELECT path, sha1, size FROM nested_catalogs " | ||
977 | "UNION ALL SELECT path, sha1, size FROM bind_mountpoints;"; | ||
978 | static const char | ||
979 | *stmt_2_5_ge_1_lt_4 = "SELECT path, sha1, size FROM nested_catalogs;"; | ||
980 | // Internally converts NULL to 0 for size | ||
981 | static const char | ||
982 | *stmt_2_5_lt_1 = "SELECT path, sha1, 0 FROM nested_catalogs;"; | ||
983 | |||
984 | 156 | if (database.IsEqualSchema(database.schema_version(), 2.5) | |
985 |
5/6✓ Branch 0 taken 154 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 154 times.
✓ Branch 6 taken 2 times.
|
156 | && (database.schema_revision() >= 4)) { |
986 |
2/4✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
|
154 | DeferredInit(database.sqlite_db(), stmt_2_5_ge_4); |
987 | 2 | } else if (database.IsEqualSchema(database.schema_version(), 2.5) | |
988 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
|
2 | && (database.schema_revision() >= 1)) { |
989 | ✗ | DeferredInit(database.sqlite_db(), stmt_2_5_ge_1_lt_4); | |
990 | } else { | ||
991 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if (database.IsEqualSchema(database.schema_version(), 0.9)) { |
992 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_0_9); |
993 | } else { | ||
994 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_2_5_lt_1); |
995 | } | ||
996 | } | ||
997 | 156 | } | |
998 | |||
999 | |||
1000 | 55 | PathString SqlNestedCatalogListing::GetPath() const { | |
1001 | 55 | const char *path = reinterpret_cast<const char *>(RetrieveText(0)); | |
1002 | 55 | return PathString(path, strlen(path)); | |
1003 | } | ||
1004 | |||
1005 | |||
1006 | 55 | shash::Any SqlNestedCatalogListing::GetContentHash() const { | |
1007 |
2/4✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 55 times.
✗ Branch 6 not taken.
|
55 | const string hash = string(reinterpret_cast<const char *>(RetrieveText(1))); |
1008 | 55 | return (hash.empty()) | |
1009 | ? shash::Any(shash::kAny) | ||
1010 |
4/6✓ Branch 0 taken 14 times.
✓ Branch 1 taken 41 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 41 times.
✗ Branch 8 not taken.
|
110 | : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog); |
1011 | 55 | } | |
1012 | |||
1013 | |||
1014 | 55 | uint64_t SqlNestedCatalogListing::GetSize() const { return RetrieveInt64(2); } | |
1015 | |||
1016 | |||
1017 | //------------------------------------------------------------------------------ | ||
1018 | |||
1019 | |||
1020 | 156 | SqlOwnNestedCatalogListing::SqlOwnNestedCatalogListing( | |
1021 | 156 | const CatalogDatabase &database) { | |
1022 | // We cannot access nested catalogs where the content hash is missing | ||
1023 | static const char *stmt_0_9 = "SELECT '', '', 0 FROM nested_catalogs;"; | ||
1024 | static const char | ||
1025 | *stmt_2_5_ge_1 = "SELECT path, sha1, size FROM nested_catalogs;"; | ||
1026 | // Internally converts NULL to 0 for size | ||
1027 | static const char | ||
1028 | *stmt_2_5_lt_1 = "SELECT path, sha1, 0 FROM nested_catalogs;"; | ||
1029 | |||
1030 | 156 | if (database.IsEqualSchema(database.schema_version(), 2.5) | |
1031 |
5/6✓ Branch 0 taken 154 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 154 times.
✓ Branch 6 taken 2 times.
|
156 | && (database.schema_revision() >= 1)) { |
1032 |
2/4✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
|
154 | DeferredInit(database.sqlite_db(), stmt_2_5_ge_1); |
1033 | } else { | ||
1034 |
2/2✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if (database.IsEqualSchema(database.schema_version(), 0.9)) { |
1035 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_0_9); |
1036 | } else { | ||
1037 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | DeferredInit(database.sqlite_db(), stmt_2_5_lt_1); |
1038 | } | ||
1039 | } | ||
1040 | 156 | } | |
1041 | |||
1042 | |||
1043 | 5 | PathString SqlOwnNestedCatalogListing::GetPath() const { | |
1044 | 5 | const char *path = reinterpret_cast<const char *>(RetrieveText(0)); | |
1045 | 5 | return PathString(path, strlen(path)); | |
1046 | } | ||
1047 | |||
1048 | |||
1049 | 5 | shash::Any SqlOwnNestedCatalogListing::GetContentHash() const { | |
1050 |
2/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
5 | const string hash = string(reinterpret_cast<const char *>(RetrieveText(1))); |
1051 | 5 | return (hash.empty()) | |
1052 | ? shash::Any(shash::kAny) | ||
1053 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
|
10 | : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog); |
1054 | 5 | } | |
1055 | |||
1056 | |||
1057 | 5 | uint64_t SqlOwnNestedCatalogListing::GetSize() const { | |
1058 | 5 | return RetrieveInt64(2); | |
1059 | } | ||
1060 | |||
1061 | |||
1062 | //------------------------------------------------------------------------------ | ||
1063 | |||
1064 | |||
1065 | 177 | SqlDirentInsert::SqlDirentInsert(const CatalogDatabase &database) { | |
1066 | 354 | DeferredInit( | |
1067 |
2/4✓ Branch 1 taken 177 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 177 times.
✗ Branch 5 not taken.
|
177 | database.sqlite_db(), |
1068 | "INSERT INTO catalog " | ||
1069 | "(md5path_1, md5path_2, parent_1, parent_2, hash, hardlinks, size, mode," | ||
1070 | // 1 2 3 4 5 6 7 8 | ||
1071 | "mtime, flags, name, symlink, uid, gid, xattr, mtimens) " | ||
1072 | // 9, 10 11 12 13 14 15 16 | ||
1073 | "VALUES (:md5_1, :md5_2, :p_1, :p_2, :hash, :links, :size, :mode, :mtime," | ||
1074 | " :flags, :name, :symlink, :uid, :gid, :xattr, :mtimens);"); | ||
1075 | 177 | } | |
1076 | |||
1077 | |||
1078 | 605 | bool SqlDirentInsert::BindPathHash(const shash::Md5 &hash) { | |
1079 | 605 | return BindMd5(1, 2, hash); | |
1080 | } | ||
1081 | |||
1082 | |||
1083 | 605 | bool SqlDirentInsert::BindParentPathHash(const shash::Md5 &hash) { | |
1084 | 605 | return BindMd5(3, 4, hash); | |
1085 | } | ||
1086 | |||
1087 | |||
1088 | 605 | bool SqlDirentInsert::BindDirent(const DirectoryEntry &entry) { | |
1089 | 605 | return BindDirentFields(5, 6, 7, 8, 9, 16, 10, 11, 12, 13, 14, entry); | |
1090 | } | ||
1091 | |||
1092 | |||
1093 | ✗ | bool SqlDirentInsert::BindXattr(const XattrList &xattrs) { | |
1094 | unsigned char *packed_xattrs; | ||
1095 | unsigned size; | ||
1096 | ✗ | xattrs.Serialize(&packed_xattrs, &size); | |
1097 | ✗ | if (packed_xattrs == NULL) | |
1098 | ✗ | return BindNull(15); | |
1099 | ✗ | return BindBlobTransient(15, packed_xattrs, size); | |
1100 | } | ||
1101 | |||
1102 | |||
1103 | 526 | bool SqlDirentInsert::BindXattrEmpty() { return BindNull(15); } | |
1104 | |||
1105 | |||
1106 | //------------------------------------------------------------------------------ | ||
1107 | |||
1108 | |||
1109 | 98 | SqlDirentUpdate::SqlDirentUpdate(const CatalogDatabase &database) { | |
1110 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
1111 | "UPDATE catalog " | ||
1112 | "SET hash = :hash, size = :size, mode = :mode, mtime = :mtime, " | ||
1113 | // 1 2 3 4 | ||
1114 | "flags = :flags, name = :name, symlink = :symlink, hardlinks = " | ||
1115 | ":hardlinks, " | ||
1116 | // 5 6 7 8 | ||
1117 | "uid = :uid, gid = :gid, mtimens = :mtimens " | ||
1118 | // 9 10 11 | ||
1119 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);"); | ||
1120 | // 12 13 | ||
1121 | 98 | } | |
1122 | |||
1123 | |||
1124 | 214 | bool SqlDirentUpdate::BindPathHash(const shash::Md5 &hash) { | |
1125 | 214 | return BindMd5(12, 13, hash); | |
1126 | } | ||
1127 | |||
1128 | |||
1129 | 214 | bool SqlDirentUpdate::BindDirent(const DirectoryEntry &entry) { | |
1130 | 214 | return BindDirentFields(1, 8, 2, 3, 4, 11, 5, 6, 7, 9, 10, entry); | |
1131 | } | ||
1132 | |||
1133 | |||
1134 | //------------------------------------------------------------------------------ | ||
1135 | |||
1136 | |||
1137 | 98 | SqlDirentUnlink::SqlDirentUnlink(const CatalogDatabase &database) { | |
1138 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
1139 | "DELETE FROM catalog " | ||
1140 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);"); | ||
1141 | 98 | } | |
1142 | |||
1143 | 144 | bool SqlDirentUnlink::BindPathHash(const shash::Md5 &hash) { | |
1144 | 144 | return BindMd5(1, 2, hash); | |
1145 | } | ||
1146 | |||
1147 | |||
1148 | //------------------------------------------------------------------------------ | ||
1149 | |||
1150 | |||
1151 | 98 | SqlIncLinkcount::SqlIncLinkcount(const CatalogDatabase &database) { | |
1152 | // This command changes the linkcount of a whole hardlink group at once! | ||
1153 | // We can do this, since the 'hardlinks'-field contains the hardlink group ID | ||
1154 | // in the higher 32bit as well as the 'linkcount' in the lower 32bit. | ||
1155 | // This field will be equal for all entries belonging to the same hardlink | ||
1156 | // group while adding/subtracting small values from it will only effect the | ||
1157 | // linkcount in the lower 32bit. | ||
1158 | // Take a deep breath! | ||
1159 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
1160 | "UPDATE catalog SET hardlinks = hardlinks + :delta " | ||
1161 | "WHERE hardlinks = (SELECT hardlinks from catalog " | ||
1162 | "WHERE md5path_1 = :md5_1 AND md5path_2 = :md5_2);"); | ||
1163 | 98 | } | |
1164 | |||
1165 | |||
1166 | ✗ | bool SqlIncLinkcount::BindPathHash(const shash::Md5 &hash) { | |
1167 | ✗ | return BindMd5(2, 3, hash); | |
1168 | } | ||
1169 | |||
1170 | |||
1171 | ✗ | bool SqlIncLinkcount::BindDelta(const int delta) { return BindInt(1, delta); } | |
1172 | |||
1173 | |||
1174 | //------------------------------------------------------------------------------ | ||
1175 | |||
1176 | |||
1177 | 98 | SqlChunkInsert::SqlChunkInsert(const CatalogDatabase &database) { | |
1178 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
1179 | "INSERT INTO chunks (md5path_1, md5path_2, offset, size, hash) " | ||
1180 | // 1 2 3 4 5 | ||
1181 | "VALUES (:md5_1, :md5_2, :offset, :size, :hash);"); | ||
1182 | 98 | } | |
1183 | |||
1184 | |||
1185 | 10 | bool SqlChunkInsert::BindPathHash(const shash::Md5 &hash) { | |
1186 | 10 | return BindMd5(1, 2, hash); | |
1187 | } | ||
1188 | |||
1189 | |||
1190 | 10 | bool SqlChunkInsert::BindFileChunk(const FileChunk &chunk) { | |
1191 |
1/2✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | return BindInt64(3, chunk.offset()) && BindInt64(4, chunk.size()) |
1192 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | && BindHashBlob(5, chunk.content_hash()); |
1193 | } | ||
1194 | |||
1195 | |||
1196 | //------------------------------------------------------------------------------ | ||
1197 | |||
1198 | |||
1199 | 98 | SqlChunksRemove::SqlChunksRemove(const CatalogDatabase &database) { | |
1200 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
1201 | "DELETE FROM chunks " | ||
1202 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);"); | ||
1203 | 98 | } | |
1204 | |||
1205 | |||
1206 | ✗ | bool SqlChunksRemove::BindPathHash(const shash::Md5 &hash) { | |
1207 | ✗ | return BindMd5(1, 2, hash); | |
1208 | } | ||
1209 | |||
1210 | |||
1211 | //------------------------------------------------------------------------------ | ||
1212 | |||
1213 | |||
1214 | 156 | SqlChunksListing::SqlChunksListing(const CatalogDatabase &database) { | |
1215 |
2/4✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
|
156 | DeferredInit(database.sqlite_db(), |
1216 | "SELECT offset, size, hash FROM chunks " | ||
1217 | // 0 1 2 | ||
1218 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2) " | ||
1219 | // 1 2 | ||
1220 | "ORDER BY offset ASC;"); | ||
1221 | 156 | } | |
1222 | |||
1223 | |||
1224 | 1 | bool SqlChunksListing::BindPathHash(const shash::Md5 &hash) { | |
1225 | 1 | return BindMd5(1, 2, hash); | |
1226 | } | ||
1227 | |||
1228 | |||
1229 | 1 | FileChunk SqlChunksListing::GetFileChunk( | |
1230 | const shash::Algorithms interpret_hash_as) const { | ||
1231 | return FileChunk( | ||
1232 | 1 | RetrieveHashBlob(2, interpret_hash_as, shash::kSuffixPartial), | |
1233 | 1 | RetrieveInt64(0), | |
1234 | 2 | RetrieveInt64(1)); | |
1235 | } | ||
1236 | |||
1237 | |||
1238 | //------------------------------------------------------------------------------ | ||
1239 | |||
1240 | |||
1241 | 98 | SqlChunksCount::SqlChunksCount(const CatalogDatabase &database) { | |
1242 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), |
1243 | "SELECT count(*) FROM chunks " | ||
1244 | // 0 | ||
1245 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2)"); | ||
1246 | // 1 2 | ||
1247 | 98 | } | |
1248 | |||
1249 | |||
1250 | ✗ | bool SqlChunksCount::BindPathHash(const shash::Md5 &hash) { | |
1251 | ✗ | return BindMd5(1, 2, hash); | |
1252 | } | ||
1253 | |||
1254 | |||
1255 | ✗ | int SqlChunksCount::GetChunkCount() const { return RetrieveInt64(0); } | |
1256 | |||
1257 | |||
1258 | //------------------------------------------------------------------------------ | ||
1259 | |||
1260 | |||
1261 | 98 | SqlMaxHardlinkGroup::SqlMaxHardlinkGroup(const CatalogDatabase &database) { | |
1262 |
2/4✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
|
98 | DeferredInit(database.sqlite_db(), "SELECT max(hardlinks) FROM catalog;"); |
1263 | 98 | } | |
1264 | |||
1265 | |||
1266 | 3 | uint32_t SqlMaxHardlinkGroup::GetMaxGroupId() const { | |
1267 | 3 | return RetrieveInt64(0) >> 32; | |
1268 | } | ||
1269 | |||
1270 | |||
1271 | //------------------------------------------------------------------------------ | ||
1272 | |||
1273 | |||
1274 | 245 | SqlGetCounter::SqlGetCounter(const CatalogDatabase &database) { | |
1275 | static const char | ||
1276 | *stmt_ge_2_4 = "SELECT value from statistics WHERE counter = :counter;"; | ||
1277 | static const char *stmt_lt_2_4 = "SELECT 0;"; | ||
1278 | |||
1279 |
2/2✓ Branch 1 taken 243 times.
✓ Branch 2 taken 2 times.
|
245 | if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) { |
1280 | 243 | compat_ = false; | |
1281 |
2/4✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 243 times.
✗ Branch 5 not taken.
|
243 | DeferredInit(database.sqlite_db(), stmt_ge_2_4); |
1282 | } else { | ||
1283 | 2 | compat_ = true; | |
1284 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | DeferredInit(database.sqlite_db(), stmt_lt_2_4); |
1285 | } | ||
1286 | 245 | } | |
1287 | |||
1288 | |||
1289 | 5880 | bool SqlGetCounter::BindCounter(const std::string &counter) { | |
1290 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 5832 times.
|
5880 | if (compat_) |
1291 | 48 | return true; | |
1292 | 5832 | return BindText(1, counter); | |
1293 | } | ||
1294 | |||
1295 | |||
1296 | 5880 | uint64_t SqlGetCounter::GetCounter() const { | |
1297 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 5832 times.
|
5880 | if (compat_) |
1298 | 48 | return 0; | |
1299 | 5832 | return RetrieveInt64(0); | |
1300 | } | ||
1301 | |||
1302 | |||
1303 | //------------------------------------------------------------------------------ | ||
1304 | |||
1305 | |||
1306 | 89 | SqlUpdateCounter::SqlUpdateCounter(const CatalogDatabase &database) { | |
1307 | 178 | DeferredInit( | |
1308 |
2/4✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 89 times.
✗ Branch 5 not taken.
|
89 | database.sqlite_db(), |
1309 | "UPDATE statistics SET value=value+:val WHERE counter=:counter;"); | ||
1310 | 89 | } | |
1311 | |||
1312 | |||
1313 | 2136 | bool SqlUpdateCounter::BindCounter(const std::string &counter) { | |
1314 | 2136 | return BindText(2, counter); | |
1315 | } | ||
1316 | |||
1317 | |||
1318 | 2136 | bool SqlUpdateCounter::BindDelta(const int64_t delta) { | |
1319 | 2136 | return BindInt64(1, delta); | |
1320 | } | ||
1321 | |||
1322 | |||
1323 | //------------------------------------------------------------------------------ | ||
1324 | |||
1325 | |||
1326 | 100 | SqlCreateCounter::SqlCreateCounter(const CatalogDatabase &database) { | |
1327 |
2/4✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
|
100 | DeferredInit(database.sqlite_db(), |
1328 | "INSERT OR REPLACE INTO statistics (counter, value) " | ||
1329 | "VALUES (:counter, :value);"); | ||
1330 | 100 | } | |
1331 | |||
1332 | |||
1333 | 2400 | bool SqlCreateCounter::BindCounter(const std::string &counter) { | |
1334 | 2400 | return BindText(1, counter); | |
1335 | } | ||
1336 | |||
1337 | |||
1338 | 2400 | bool SqlCreateCounter::BindInitialValue(const int64_t value) { | |
1339 | 2400 | return BindInt64(2, value); | |
1340 | } | ||
1341 | |||
1342 | |||
1343 | //------------------------------------------------------------------------------ | ||
1344 | |||
1345 | |||
1346 | 156 | SqlAllChunks::SqlAllChunks(const CatalogDatabase &database) { | |
1347 | 156 | const int hash_mask = 7 << SqlDirent::kFlagPosHash; | |
1348 |
4/8✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 156 times.
✗ Branch 11 not taken.
|
312 | const string flags2hash = " ((flags&" + StringifyInt(hash_mask) + ") >> " + |
1349 |
1/2✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
|
156 | StringifyInt(SqlDirent::kFlagPosHash) + |
1350 |
1/2✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
|
156 | ")+1 AS hash_algorithm "; |
1351 | |||
1352 | 156 | const int compression_mask = 7 << SqlDirent::kFlagPosCompression; | |
1353 | const string flags2compression = | ||
1354 |
4/8✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 156 times.
✗ Branch 11 not taken.
|
312 | " ((flags&" + StringifyInt(compression_mask) + ") >> " + |
1355 |
2/4✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
|
468 | StringifyInt(SqlDirent::kFlagPosCompression) + ") " + |
1356 |
1/2✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
|
156 | "AS compression_algorithm "; |
1357 | |||
1358 | // TODO(reneme): this depends on shash::kSuffix* being a char! | ||
1359 | // it should be more generic or replaced entirely | ||
1360 | // TODO(reneme): this is practically the same as SqlListContentHashes and | ||
1361 | // should be consolidated | ||
1362 | string sql = "SELECT DISTINCT hash, " | ||
1363 | "CASE WHEN flags & " | ||
1364 |
3/6✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
|
312 | + StringifyInt(SqlDirent::kFlagFile) + " THEN " |
1365 |
4/8✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 156 times.
✗ Branch 11 not taken.
|
624 | + StringifyInt(shash::kSuffixNone) + " " + "WHEN flags & " |
1366 |
3/6✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
|
624 | + StringifyInt(SqlDirent::kFlagDir) + " THEN " |
1367 |
3/6✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
|
624 | + StringifyInt(shash::kSuffixMicroCatalog) + " END " |
1368 |
4/8✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 156 times.
✗ Branch 11 not taken.
|
312 | + "AS chunk_type, " + flags2hash + "," + flags2compression |
1369 |
1/2✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
|
312 | + "FROM catalog WHERE (hash IS NOT NULL) AND " |
1370 | "(flags & " | ||
1371 |
3/6✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 156 times.
✗ Branch 8 not taken.
|
468 | + StringifyInt(SqlDirent::kFlagFileExternal) + " = 0)"; |
1372 |
2/2✓ Branch 1 taken 154 times.
✓ Branch 2 taken 2 times.
|
156 | if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) { |
1373 | sql += " UNION " | ||
1374 | "SELECT DISTINCT chunks.hash, " | ||
1375 |
5/10✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 154 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 154 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 154 times.
✗ Branch 14 not taken.
|
308 | + StringifyInt(shash::kSuffixPartial) + ", " + flags2hash + "," |
1376 |
1/2✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
|
308 | + flags2compression |
1377 |
1/2✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
|
308 | + "FROM chunks, catalog WHERE " |
1378 | "chunks.md5path_1=catalog.md5path_1 AND " | ||
1379 | "chunks.md5path_2=catalog.md5path_2 AND " | ||
1380 | "(catalog.flags & " | ||
1381 |
4/8✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 154 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 154 times.
✗ Branch 11 not taken.
|
462 | + StringifyInt(SqlDirent::kFlagFileExternal) + " = 0)"; |
1382 | } | ||
1383 |
1/2✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
|
156 | sql += ";"; |
1384 |
2/4✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
|
156 | Init(database.sqlite_db(), sql); |
1385 | 156 | } | |
1386 | |||
1387 | |||
1388 | 2 | bool SqlAllChunks::Open() { return true; } | |
1389 | |||
1390 | |||
1391 | 11 | bool SqlAllChunks::Next(shash::Any *hash, zlib::Algorithms *compression_alg) { | |
1392 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
|
11 | if (!FetchRow()) { |
1393 | 2 | return false; | |
1394 | } | ||
1395 | |||
1396 | 9 | *hash = RetrieveHashBlob(0, static_cast<shash::Algorithms>(RetrieveInt(2)), | |
1397 | 9 | static_cast<shash::Suffix>(RetrieveInt(1))); | |
1398 | 9 | *compression_alg = static_cast<zlib::Algorithms>(RetrieveInt(3)); | |
1399 | 9 | return true; | |
1400 | } | ||
1401 | |||
1402 | |||
1403 | 2 | bool SqlAllChunks::Close() { return Reset(); } | |
1404 | |||
1405 | |||
1406 | //------------------------------------------------------------------------------ | ||
1407 | |||
1408 | |||
1409 | 156 | SqlLookupXattrs::SqlLookupXattrs(const CatalogDatabase &database) { | |
1410 |
2/4✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
|
156 | DeferredInit(database.sqlite_db(), |
1411 | "SELECT xattr FROM catalog " | ||
1412 | "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);"); | ||
1413 | 156 | } | |
1414 | |||
1415 | |||
1416 | 1 | bool SqlLookupXattrs::BindPathHash(const shash::Md5 &hash) { | |
1417 | 1 | return BindMd5(1, 2, hash); | |
1418 | } | ||
1419 | |||
1420 | |||
1421 | 1 | XattrList SqlLookupXattrs::GetXattrs() { | |
1422 | const unsigned char *packed_xattrs = reinterpret_cast<const unsigned char *>( | ||
1423 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | RetrieveBlob(0)); |
1424 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (packed_xattrs == NULL) |
1425 | 1 | return XattrList(); | |
1426 | |||
1427 | ✗ | const int size = RetrieveBytes(0); | |
1428 | ✗ | assert(size >= 0); | |
1429 | const UniquePtr<XattrList> xattrs( | ||
1430 | ✗ | XattrList::Deserialize(packed_xattrs, size)); | |
1431 | ✗ | if (!xattrs.IsValid()) { | |
1432 | ✗ | LogCvmfs(kLogCatalog, kLogDebug, "corrupted xattr data"); | |
1433 | ✗ | return XattrList(); | |
1434 | } | ||
1435 | ✗ | return *xattrs; | |
1436 | } | ||
1437 | |||
1438 | } // namespace catalog | ||
1439 |