GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2026-06-21 02:37:04
Exec Total Coverage
Lines: 458 607 75.5%
Branches: 582 1546 37.6%

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