GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2026-09-06 02:40:30
Exec Total Coverage
Lines: 464 616 75.3%
Branches: 590 1554 38.0%

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