GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2026-10-18 02:40:11
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 4632 bool CatalogDatabase::CheckSchemaCompatibility() {
96
2/4
✓ Branch 1 taken 4606 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
9238 return !((schema_version() >= 2.0 - kSchemaEpsilon)
97
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4606 times.
4606 && (!IsEqualSchema(schema_version(), kLatestSupportedSchema))
98 ✗ && (!IsEqualSchema(schema_version(), 2.4)
99
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
4632 || !IsEqualSchema(kLatestSupportedSchema, 2.5)));
100 }
101
102
103 2807 bool CatalogDatabase::LiveSchemaUpgradeIfNecessary() {
104
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2807 times.
2807 assert(read_write());
105
106
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 44 times.
✓ Branch 6 taken 2737 times.
✓ Branch 7 taken 44 times.
✓ Branch 8 taken 2763 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 0)) {
107
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (0 --> 1)");
108
109 SqlCatalog sql_upgrade(*this, "ALTER TABLE nested_catalogs "
110
2/4
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 44 times.
✗ Branch 6 not taken.
88 "ADD size INTEGER;");
111
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
44 if (!sql_upgrade.Execute()) {
112 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade nested_catalogs");
113 ✗ return false;
114 }
115
116 44 set_schema_revision(1);
117
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
44 if (!StoreSchemaRevision()) {
118 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
119 ✗ return false;
120 }
121
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 }
122
123
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 1)) {
124
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (1 --> 2)");
125
126
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 SqlCatalog sql_upgrade1(*this, "ALTER TABLE catalog ADD xattr BLOB;");
127 SqlCatalog sql_upgrade2(
128 *this,
129
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "INSERT INTO statistics (counter, value) VALUES ('self_xattr', 0);");
130 SqlCatalog sql_upgrade3(
131 *this,
132
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "INSERT INTO statistics (counter, value) VALUES ('subtree_xattr', 0);");
133
3/7
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
176 if (!sql_upgrade1.Execute() || !sql_upgrade2.Execute()
134
4/8
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 88 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 88 times.
176 || !sql_upgrade3.Execute()) {
135 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (1 --> 2)");
136 ✗ return false;
137 }
138
139 88 set_schema_revision(2);
140
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!StoreSchemaRevision()) {
141 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
142 ✗ return false;
143 }
144
3/6
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 88 times.
✗ Branch 8 not taken.
88 }
145
146
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 2)) {
147
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 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 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "('self_external', 0);");
152 SqlCatalog sql_upgrade5(*this,
153 "INSERT INTO statistics (counter, value) VALUES "
154
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "('self_external_file_size', 0);");
155 SqlCatalog sql_upgrade6(*this,
156 "INSERT INTO statistics (counter, value) VALUES "
157
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "('subtree_external', 0);");
158 SqlCatalog sql_upgrade7(*this,
159 "INSERT INTO statistics (counter, value) VALUES "
160
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "('subtree_external_file_size', 0);");
161
3/7
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
176 if (!sql_upgrade4.Execute() || !sql_upgrade5.Execute()
162
6/13
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 88 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 88 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 88 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 88 times.
176 || !sql_upgrade6.Execute() || !sql_upgrade7.Execute()) {
163 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (2 --> 3)");
164 ✗ return false;
165 }
166
167 88 set_schema_revision(3);
168
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!StoreSchemaRevision()) {
169 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
170 ✗ return false;
171 }
172
4/8
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 88 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 88 times.
✗ Branch 11 not taken.
88 }
173
174
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 3)) {
175
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 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 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));");
181
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!sql_upgrade8.Execute()) {
182 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (3 --> 4)");
183 ✗ return false;
184 }
185
186 88 set_schema_revision(4);
187
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!StoreSchemaRevision()) {
188 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
189 ✗ return false;
190 }
191
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 }
192
193
194
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 4)) {
195
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 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 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "('self_special', 0);");
200 SqlCatalog sql_upgrade10(*this,
201 "INSERT INTO statistics (counter, value) VALUES "
202
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 "('subtree_special', 0);");
203
5/11
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 88 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 88 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 88 times.
88 if (!sql_upgrade9.Execute() || !sql_upgrade10.Execute()) {
204 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (4 --> 5)");
205 ✗ return false;
206 }
207
208 88 set_schema_revision(5);
209
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!StoreSchemaRevision()) {
210 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
211 ✗ return false;
212 }
213
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
88 }
214
215
216
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 5)) {
217 88 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (5 --> 6)");
218
219 88 set_schema_revision(6);
220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if (!StoreSchemaRevision()) {
221 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
222 ✗ return false;
223 }
224 }
225
226
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 6)) {
227
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (6 --> 7)");
228
229
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 88 times.
✗ Branch 6 not taken.
176 SqlCatalog sql_upgrade1(*this, "ALTER TABLE catalog ADD mtimens INTEGER;");
230
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!sql_upgrade1.Execute()) {
231 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (6 --> 7)");
232 ✗ return false;
233 }
234
235 88 set_schema_revision(7);
236
2/4
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
88 if (!StoreSchemaRevision()) {
237 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
238 ✗ return false;
239 }
240
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 }
241
242
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 7)) {
243 88 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (7 --> 8)");
244
245 88 set_schema_revision(8);
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if (!StoreSchemaRevision()) {
247 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
248 ✗ return false;
249 }
250 }
251
252
6/6
✓ Branch 2 taken 2781 times.
✓ Branch 3 taken 26 times.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 2693 times.
✓ Branch 7 taken 88 times.
✓ Branch 8 taken 2719 times.
2807 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 8)) {
253 88 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (8 --> 9)");
254
255 // No DDL change: kFlagFileVolatile is encoded in the existing flags column.
256 88 set_schema_revision(9);
257
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
88 if (!StoreSchemaRevision()) {
258 ✗ LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
259 ✗ return false;
260 }
261 }
262
263 2807 return true;
264 }
265
266
267 2580 bool CatalogDatabase::CreateEmptyDatabase() {
268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2580 times.
2580 assert(read_write());
269
270 // generate the catalog table and index structure
271 const bool retval =
272
4/16
✓ Branch 1 taken 2580 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2580 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2580 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2580 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.
5160 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 5160 .Execute()
283
5/20
✓ Branch 2 taken 2580 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2580 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2580 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2580 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2580 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.
5160 && SqlCatalog(*this,
284 "CREATE INDEX idx_catalog_parent "
285 "ON catalog (parent_1, parent_2);")
286
2/4
✓ Branch 1 taken 2580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2580 times.
✗ Branch 4 not taken.
2580 .Execute()
287
5/20
✓ Branch 2 taken 2580 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2580 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2580 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2580 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2580 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.
5160 && 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 2580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2580 times.
✗ Branch 4 not taken.
2580 .Execute()
297
5/20
✓ Branch 2 taken 2580 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2580 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2580 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2580 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2580 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.
5160 && 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 2580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2580 times.
✗ Branch 4 not taken.
2580 .Execute()
302
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
5160 &&
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 2580 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2580 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2580 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2580 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2580 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.
5160 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 2580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2580 times.
✗ Branch 4 not taken.
2580 .Execute()
316
7/24
✓ Branch 2 taken 2580 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2580 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2580 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2580 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2580 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2580 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 2580 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.
12900 && SqlCatalog(*this,
317 "CREATE TABLE statistics (counter TEXT, value INTEGER, "
318 "CONSTRAINT pk_statistics PRIMARY KEY (counter));")
319
3/6
✓ Branch 1 taken 2580 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2580 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2580 times.
✗ Branch 6 not taken.
5160 .Execute();
320
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2580 times.
2580 if (!retval) {
322 ✗ PrintSqlError("failed to create catalog database tables.");
323 }
324
325 2580 return retval;
326 }
327
328
329 2536 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 2536 times.
2536 assert(read_write());
334 2536 bool retval = false;
335
336 // Path hashes
337
1/2
✓ Branch 2 taken 2536 times.
✗ Branch 3 not taken.
2536 const shash::Md5 root_path_hash = shash::Md5(shash::AsciiPtr(root_path));
338 2536 const shash::Md5 root_parent_hash = (root_path == "")
339 ? shash::Md5()
340 : shash::Md5(shash::AsciiPtr(
341
7/12
✓ Branch 0 taken 1658 times.
✓ Branch 1 taken 878 times.
✓ Branch 3 taken 1658 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 878 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 878 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 878 times.
✓ Branch 13 taken 1658 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
2536 GetParentPath(root_path)));
342
343 // Start initial filling transaction
344
1/2
✓ Branch 1 taken 2536 times.
✗ Branch 2 not taken.
2536 retval = BeginTransaction();
345
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2536 times.
2536 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 2536 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2536 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 2536 times.
2536 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 2536 times.
2536 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 2536 times.
2536 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 2536 times.
✗ Branch 2 not taken.
2536 catalog::Counters counters;
376
377 // Insert root entry (when given)
378
2/2
✓ Branch 1 taken 2224 times.
✓ Branch 2 taken 312 times.
2536 if (!root_entry.IsNegative()) {
379
1/2
✓ Branch 1 taken 2224 times.
✗ Branch 2 not taken.
2224 SqlDirentInsert sql_insert(*this);
380
1/2
✓ Branch 1 taken 2224 times.
✗ Branch 2 not taken.
2224 retval = sql_insert.BindPathHash(root_path_hash)
381
2/4
✓ Branch 1 taken 2224 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2224 times.
✗ Branch 4 not taken.
2224 && sql_insert.BindParentPathHash(root_parent_hash)
382
5/11
✓ Branch 0 taken 2224 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2224 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2224 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2224 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2224 times.
✗ Branch 11 not taken.
4448 && sql_insert.BindDirent(root_entry) && sql_insert.Execute();
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2224 times.
2224 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 2224 counters.self.directories = 1;
390
1/2
✓ Branch 1 taken 2224 times.
✗ Branch 2 not taken.
2224 }
391
392 // Save initial statistics counters
393
2/4
✓ Branch 1 taken 2536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2536 times.
2536 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 878 times.
✓ Branch 2 taken 1658 times.
2536 if (!root_path.empty()) {
400
4/9
✓ Branch 1 taken 878 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 878 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 878 times.
✗ Branch 9 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 878 times.
878 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 2536 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2536 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2536 times.
2536 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 2536 times.
✗ Branch 2 not taken.
2536 retval = CommitTransaction();
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2536 times.
2536 if (!retval) {
416 ✗ PrintSqlError("failed to commit initial filling transaction");
417 ✗ return false;
418 }
419
420 2536 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 1723 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 1723 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1723 times.
✗ Branch 6 not taken.
3446 "AS ratio FROM catalog;");
434
1/2
✓ Branch 1 taken 1723 times.
✗ Branch 2 not taken.
1723 const bool retval = rowid_waste_ratio_query.FetchRow();
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1723 times.
1723 assert(retval);
436
437
1/2
✓ Branch 1 taken 1723 times.
✗ Branch 2 not taken.
3446 return rowid_waste_ratio_query.RetrieveDouble(0);
438 1723 }
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 359 bool CatalogDatabase::CompactDatabase() const {
461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 359 times.
359 assert(read_write());
462
463
4/16
✓ Branch 1 taken 359 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 359 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 359 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 359 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.
718 return SqlCatalog(*this, "PRAGMA foreign_keys = OFF;").Execute()
464
2/4
✓ Branch 1 taken 359 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 359 times.
✗ Branch 4 not taken.
359 && BeginTransaction()
465
5/20
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 359 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 359 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 359 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 359 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.
718 && SqlCatalog(*this, "CREATE TEMPORARY TABLE duplicate AS "
466 " SELECT * FROM catalog "
467 " ORDER BY rowid ASC;")
468
2/4
✓ Branch 1 taken 359 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 359 times.
✗ Branch 4 not taken.
359 .Execute()
469
7/22
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 359 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 359 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 359 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 359 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 359 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 359 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.
718 && SqlCatalog(*this, "DELETE FROM catalog;").Execute()
470
5/20
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 359 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 359 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 359 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 359 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.
718 && SqlCatalog(*this, "INSERT INTO catalog "
471 " SELECT * FROM duplicate "
472 " ORDER BY rowid")
473
2/4
✓ Branch 1 taken 359 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 359 times.
✗ Branch 4 not taken.
359 .Execute()
474
7/22
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 359 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 359 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 359 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 359 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 359 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 359 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.
718 && SqlCatalog(*this, "DROP TABLE duplicate;").Execute()
475
2/4
✓ Branch 1 taken 359 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 359 times.
✗ Branch 4 not taken.
359 && CommitTransaction()
476
10/29
✓ Branch 2 taken 359 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 359 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 359 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 359 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 359 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 359 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 359 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 359 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 359 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 359 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.
1436 && SqlCatalog(*this, "PRAGMA foreign_keys = ON;").Execute();
477 }
478
479
480 //------------------------------------------------------------------------------
481
482
483 19727 unsigned SqlDirent::CreateDatabaseFlags(const DirectoryEntry &entry) const {
484 19727 unsigned int database_flags = 0;
485
486
2/2
✓ Branch 1 taken 776 times.
✓ Branch 2 taken 18951 times.
19727 if (entry.IsNestedCatalogRoot())
487 776 database_flags |= kFlagDirNestedRoot;
488
2/2
✓ Branch 1 taken 825 times.
✓ Branch 2 taken 18126 times.
18951 else if (entry.IsNestedCatalogMountpoint())
489 825 database_flags |= kFlagDirNestedMountpoint;
490
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18126 times.
18126 else if (entry.IsBindMountpoint())
491 ✗ database_flags |= kFlagDirBindMountpoint;
492
493
2/2
✓ Branch 1 taken 11695 times.
✓ Branch 2 taken 8032 times.
19727 if (entry.IsDirectory()) {
494 11695 database_flags |= kFlagDir;
495
2/2
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 7755 times.
8032 } else if (entry.IsLink()) {
496 277 database_flags |= kFlagFile | kFlagLink;
497
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7755 times.
7755 } else if (entry.IsSpecial()) {
498 ✗ database_flags |= kFlagFile | kFlagFileSpecial;
499 } else {
500 7755 database_flags |= kFlagFile;
501 7755 database_flags |= entry.compression_algorithm() << kFlagPosCompression;
502
2/2
✓ Branch 1 taken 156 times.
✓ Branch 2 taken 7599 times.
7755 if (entry.IsChunkedFile())
503 156 database_flags |= kFlagFileChunk;
504
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7755 times.
7755 if (entry.IsExternalFile())
505 ✗ database_flags |= kFlagFileExternal;
506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7755 times.
7755 if (entry.IsDirectIo())
507 ✗ database_flags |= kFlagDirectIo;
508
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7755 times.
7755 if (entry.IsBundleTrigger())
509 ✗ database_flags |= kFlagBundleTrigger;
510
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7755 times.
7755 if (entry.IsVolatile())
511 ✗ database_flags |= kFlagFileVolatile;
512 }
513
514
5/6
✓ Branch 2 taken 12632 times.
✓ Branch 3 taken 7095 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12632 times.
✓ Branch 7 taken 7095 times.
✓ Branch 8 taken 12632 times.
19727 if (!entry.checksum_ptr()->IsNull() || entry.IsChunkedFile())
515 7095 StoreHashAlgorithm(entry.checksum_ptr()->algorithm, &database_flags);
516
517
2/2
✓ Branch 1 taken 143 times.
✓ Branch 2 taken 19584 times.
19727 if (entry.IsHidden())
518 143 database_flags |= kFlagHidden;
519
520 19727 return database_flags;
521 }
522
523
524 7095 void SqlDirent::StoreHashAlgorithm(const shash::Algorithms algo,
525 unsigned *flags) const {
526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7095 times.
7095 assert(algo != shash::kAny);
527 // Md5 unusable for content hashes
528 7095 *flags |= (algo - 1) << kFlagPosHash;
529 7095 }
530
531
532 20702 shash::Algorithms SqlDirent::RetrieveHashAlgorithm(const unsigned flags) const {
533 20702 unsigned in_flags = ((7 << kFlagPosHash) & flags) >> kFlagPosHash;
534 // Skip Md5
535 20702 in_flags++;
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20702 times.
20702 assert(in_flags < shash::kAny);
537 20702 return static_cast<shash::Algorithms>(in_flags);
538 }
539
540
541 20533 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 20533 const unsigned in_flags = ((7 << kFlagPosCompression) & flags)
545 20533 >> kFlagPosCompression;
546 20533 return static_cast<zlib::Algorithms>(in_flags);
547 }
548
549
550 20533 uint32_t SqlDirent::Hardlinks2Linkcount(const uint64_t hardlinks) const {
551 20533 return (hardlinks << 32) >> 32;
552 }
553
554
555 20533 uint32_t SqlDirent::Hardlinks2HardlinkGroup(const uint64_t hardlinks) const {
556 20533 return hardlinks >> 32;
557 }
558
559
560 19727 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 19727 times.
19727 assert(linkcount > 0);
563 19727 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 17694 void SqlDirent::ExpandSymlink(LinkString *raw_symlink) const {
572 17694 const char *c = raw_symlink->GetChars();
573 17694 const char *cEnd = c + raw_symlink->GetLength();
574
2/2
✓ Branch 0 taken 1222 times.
✓ Branch 1 taken 17694 times.
18916 for (; c < cEnd; ++c) {
575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1222 times.
1222 if (*c == '$')
576 ✗ goto expand_symlink;
577 }
578 17694 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 19727 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 19727 const uint64_t hardlinks = MakeHardlinks(entry.hardlink_group_,
645 19727 entry.linkcount_);
646
647 19727 bool result = BindHashBlob(hash_idx, entry.checksum_)
648
1/2
✓ Branch 1 taken 19727 times.
✗ Branch 2 not taken.
19727 && BindInt64(hardlinks_idx, hardlinks)
649
1/2
✓ Branch 1 taken 19727 times.
✗ Branch 2 not taken.
19727 && BindInt64(size_idx, entry.size_)
650
1/2
✓ Branch 1 taken 19727 times.
✗ Branch 2 not taken.
19727 && BindInt(mode_idx, entry.mode_)
651
1/2
✓ Branch 1 taken 19727 times.
✗ Branch 2 not taken.
19727 && BindInt64(uid_idx, entry.uid_)
652
1/2
✓ Branch 1 taken 19727 times.
✗ Branch 2 not taken.
19727 && BindInt64(gid_idx, entry.gid_)
653
1/2
✓ Branch 1 taken 19727 times.
✗ Branch 2 not taken.
19727 && BindInt64(mtime_idx, entry.mtime_)
654
1/2
✓ Branch 2 taken 19727 times.
✗ Branch 3 not taken.
19727 && BindInt(flags_idx, CreateDatabaseFlags(entry))
655
1/2
✓ Branch 2 taken 19727 times.
✗ Branch 3 not taken.
19727 && BindText(name_idx, entry.name_.GetChars(),
656 19727 static_cast<int>(entry.name_.GetLength()))
657
2/4
✓ Branch 0 taken 19727 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 19727 times.
✗ Branch 5 not taken.
39454 && BindText(symlink_idx, entry.symlink_.GetChars(),
658 19727 static_cast<int>(entry.symlink_.GetLength()));
659
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19727 times.
19727 if (entry.HasMtimeNs()) {
660 ✗ result &= BindInt(mtimens_idx, entry.mtime_ns_);
661 } else {
662 19727 result &= BindNull(mtimens_idx);
663 }
664
665 19727 return result;
666 }
667
668
669 //------------------------------------------------------------------------------
670
671
672 26 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 13 times.
✓ Branch 2 taken 13 times.
26 if (database.schema_version() < 2.4 - CatalogDatabase::kSchemaEpsilon) {
691
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_lt_2_4);
692 } else {
693
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_ge_2_4);
694 }
695 26 }
696
697
698 169 shash::Any SqlListContentHashes::GetHash() const {
699 169 const unsigned int db_flags = RetrieveInt(1);
700 169 const shash::Algorithms hash_algorithm = RetrieveHashAlgorithm(db_flags);
701 169 shash::Any hash = RetrieveHashBlob(0, hash_algorithm);
702
2/2
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 104 times.
169 if (RetrieveInt(2) == 1) {
703 65 hash.suffix = shash::kSuffixPartial;
704 }
705
706 169 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 20533 DirectoryEntry SqlLookup::GetDirent(const Catalog *catalog,
774 const bool expand_symlink) const {
775 20533 DirectoryEntry result;
776
777
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 const unsigned database_flags = RetrieveInt(5);
778 20533 result.is_nested_catalog_root_ = (database_flags & kFlagDirNestedRoot);
779 20533 result.is_nested_catalog_mountpoint_ = (database_flags
780 20533 & kFlagDirNestedMountpoint);
781
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 const char *name = reinterpret_cast<const char *>(RetrieveText(6));
782
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 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 20533 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 20533 times.
20533 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 20533 times.
✗ Branch 2 not taken.
20533 const uint64_t hardlinks = RetrieveInt64(1);
796 20533 result.linkcount_ = Hardlinks2Linkcount(hardlinks);
797 20533 result.hardlink_group_ = Hardlinks2HardlinkGroup(hardlinks);
798
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.inode_ = catalog->GetMangledInode(RetrieveInt64(12),
799
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.hardlink_group_);
800 20533 result.is_bind_mountpoint_ = (database_flags & kFlagDirBindMountpoint);
801 20533 result.is_chunked_file_ = (database_flags & kFlagFileChunk);
802 20533 result.is_hidden_ = (database_flags & kFlagHidden);
803 20533 result.is_direct_io_ = (database_flags & kFlagDirectIo);
804 20533 result.is_volatile_ = (database_flags & kFlagFileVolatile);
805 20533 result.is_external_file_ = (database_flags & kFlagFileExternal);
806 20533 result.is_bundle_trigger_ = (database_flags & kFlagBundleTrigger);
807
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.has_xattrs_ = RetrieveInt(15) != 0;
808
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.mtime_ns_ = RetrieveNullableInt(16, -1);
809
1/2
✓ Branch 2 taken 20533 times.
✗ Branch 3 not taken.
20533 result.checksum_ = RetrieveHashBlob(0,
810 RetrieveHashAlgorithm(database_flags));
811 20533 result.compression_algorithm_ = RetrieveCompressionAlgorithm(
812 database_flags);
813
814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20533 times.
20533 if (g_claim_ownership) {
815 ✗ result.uid_ = g_uid;
816 ✗ result.gid_ = g_gid;
817 } else {
818
2/4
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20533 times.
✗ Branch 5 not taken.
20533 result.uid_ = catalog->MapUid(RetrieveInt64(13));
819
2/4
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20533 times.
✗ Branch 5 not taken.
20533 result.gid_ = catalog->MapGid(RetrieveInt64(14));
820 }
821 }
822
823
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.mode_ = RetrieveInt(3);
824
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.size_ = RetrieveInt64(2);
825
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.mtime_ = RetrieveInt64(4);
826
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.name_.Assign(name, strlen(name));
827
1/2
✓ Branch 1 taken 20533 times.
✗ Branch 2 not taken.
20533 result.symlink_.Assign(symlink, strlen(symlink));
828
3/4
✓ Branch 0 taken 17694 times.
✓ Branch 1 taken 2839 times.
✓ Branch 2 taken 17694 times.
✗ Branch 3 not taken.
20533 if (expand_symlink && !g_raw_symlinks)
829
1/2
✓ Branch 1 taken 17694 times.
✗ Branch 2 not taken.
17694 ExpandSymlink(&result.symlink_);
830
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20533 times.
20533 if (g_world_readable) {
832 ✗ if (S_ISDIR(result.mode_)) {
833 ✗ result.mode_ |= 0555;
834 } else {
835 ✗ result.mode_ |= 0444;
836 }
837 }
838
839 20533 return result;
840 }
841
842
843 //------------------------------------------------------------------------------
844
845
846 4500 SqlListing::SqlListing(const CatalogDatabase &database) {
847
28/62
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 4456 times.
✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 44 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 44 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 44 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 28 taken 44 times.
✓ Branch 29 taken 4456 times.
✓ Branch 31 taken 44 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 44 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 44 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 43 taken 44 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 44 times.
✗ Branch 47 not taken.
✓ Branch 56 taken 44 times.
✓ Branch 57 taken 4456 times.
✓ Branch 59 taken 44 times.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✓ Branch 63 taken 44 times.
✗ Branch 64 not taken.
✓ Branch 67 taken 44 times.
✗ Branch 68 not taken.
✓ Branch 71 taken 44 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 44 times.
✗ Branch 75 not taken.
✓ Branch 84 taken 44 times.
✓ Branch 85 taken 4456 times.
✓ Branch 87 taken 44 times.
✗ Branch 88 not taken.
✓ Branch 91 taken 44 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 44 times.
✗ Branch 96 not taken.
✓ Branch 99 taken 44 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 44 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.
4500 MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog "
848 "WHERE (parent_1 = :p_1) AND (parent_2 = :p_2);");
849
8/25
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 4474 times.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 26 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 4474 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 4474 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 32 taken 4474 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 4474 times.
✗ Branch 36 not taken.
4500 DEFERRED_INITS(database);
850 4500 }
851
852
853 3653 bool SqlListing::BindPathHash(const struct shash::Md5 &hash) {
854 3653 return BindMd5(1, 2, hash);
855 }
856
857
858 //------------------------------------------------------------------------------
859
860
861 4500 SqlLookupPathHash::SqlLookupPathHash(const CatalogDatabase &database) {
862
28/62
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 4456 times.
✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 44 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 44 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 44 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 44 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 28 taken 44 times.
✓ Branch 29 taken 4456 times.
✓ Branch 31 taken 44 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 44 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 44 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 43 taken 44 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 44 times.
✗ Branch 47 not taken.
✓ Branch 56 taken 44 times.
✓ Branch 57 taken 4456 times.
✓ Branch 59 taken 44 times.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✓ Branch 63 taken 44 times.
✗ Branch 64 not taken.
✓ Branch 67 taken 44 times.
✗ Branch 68 not taken.
✓ Branch 71 taken 44 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 44 times.
✗ Branch 75 not taken.
✓ Branch 84 taken 44 times.
✓ Branch 85 taken 4456 times.
✓ Branch 87 taken 44 times.
✗ Branch 88 not taken.
✓ Branch 91 taken 44 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 44 times.
✗ Branch 96 not taken.
✓ Branch 99 taken 44 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 44 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.
4500 MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog "
863 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
864
8/25
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 4474 times.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 26 times.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 4474 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 4474 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 32 taken 4474 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 4474 times.
✗ Branch 36 not taken.
4500 DEFERRED_INITS(database);
865 4500 }
866
867 15682 bool SqlLookupPathHash::BindPathHash(const struct shash::Md5 &hash) {
868 15682 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 2675 SqlDirentTouch::SqlDirentTouch(const CatalogDatabase &database) {
909
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 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 2675 }
921
922
923 71 bool SqlDirentTouch::BindDirentBase(const DirectoryEntryBase &entry) {
924
1/2
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
142 bool result = BindHashBlob(1, entry.checksum_) && BindInt64(2, entry.size_)
925
2/4
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
71 && BindInt(3, entry.mode_) && BindInt64(4, entry.mtime_)
926
1/2
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
71 && BindText(5, entry.name_.GetChars(), entry.name_.GetLength())
927
1/2
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
71 && BindText(6, entry.symlink_.GetChars(),
928 71 entry.symlink_.GetLength())
929
3/6
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 71 times.
✗ Branch 7 not taken.
142 && BindInt64(7, entry.uid_) && BindInt64(8, entry.gid_);
930
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
71 if (entry.HasMtimeNs()) {
931 ✗ result &= BindInt(10, entry.mtime_ns_);
932 } else {
933 71 result &= BindNull(10);
934 }
935 71 return result;
936 }
937
938
939 71 bool SqlDirentTouch::BindPathHash(const shash::Md5 &hash) {
940 71 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 71 bool SqlDirentTouch::BindXattrEmpty() { return BindNull(9); }
955
956
957 //------------------------------------------------------------------------------
958
959
960 4500 SqlNestedCatalogLookup::SqlNestedCatalogLookup(
961 4500 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 4500 if (database.IsEqualSchema(database.schema_version(), 2.5)
974
5/6
✓ Branch 0 taken 4474 times.
✓ Branch 1 taken 26 times.
✓ Branch 3 taken 4474 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4474 times.
✓ Branch 6 taken 26 times.
4500 && (database.schema_revision() >= 4)) {
975
2/4
✓ Branch 1 taken 4474 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4474 times.
✗ Branch 5 not taken.
4474 DeferredInit(database.sqlite_db(), stmt_2_5_ge_4);
976 26 } else if (database.IsEqualSchema(database.schema_version(), 2.5)
977
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 26 times.
26 && (database.schema_revision() >= 1)) {
978 ✗ DeferredInit(database.sqlite_db(), stmt_2_5_ge_1_lt_4);
979 } else {
980
2/2
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 13 times.
26 if (database.IsEqualSchema(database.schema_version(), 0.9)) {
981
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_0_9);
982 } else {
983
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_2_5_lt_1);
984 }
985 }
986 4500 }
987
988
989 1223 bool SqlNestedCatalogLookup::BindSearchPath(const PathString &path) {
990 1223 return BindText(1, path.GetChars(), path.GetLength());
991 }
992
993
994 1201 shash::Any SqlNestedCatalogLookup::GetContentHash() const {
995
2/4
✓ Branch 2 taken 1201 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1201 times.
✗ Branch 6 not taken.
1201 const string hash = string(reinterpret_cast<const char *>(RetrieveText(0)));
996 1201 return (hash.empty())
997 ? shash::Any(shash::kAny)
998
4/6
✓ Branch 0 taken 695 times.
✓ Branch 1 taken 506 times.
✓ Branch 3 taken 695 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 506 times.
✗ Branch 8 not taken.
2402 : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog);
999 1201 }
1000
1001
1002 1201 uint64_t SqlNestedCatalogLookup::GetSize() const { return RetrieveInt64(1); }
1003
1004
1005 //------------------------------------------------------------------------------
1006
1007
1008 4500 SqlNestedCatalogListing::SqlNestedCatalogListing(
1009 4500 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 4500 if (database.IsEqualSchema(database.schema_version(), 2.5)
1022
5/6
✓ Branch 0 taken 4474 times.
✓ Branch 1 taken 26 times.
✓ Branch 3 taken 4474 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4474 times.
✓ Branch 6 taken 26 times.
4500 && (database.schema_revision() >= 4)) {
1023
2/4
✓ Branch 1 taken 4474 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4474 times.
✗ Branch 5 not taken.
4474 DeferredInit(database.sqlite_db(), stmt_2_5_ge_4);
1024 26 } else if (database.IsEqualSchema(database.schema_version(), 2.5)
1025
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 26 times.
26 && (database.schema_revision() >= 1)) {
1026 ✗ DeferredInit(database.sqlite_db(), stmt_2_5_ge_1_lt_4);
1027 } else {
1028
2/2
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 13 times.
26 if (database.IsEqualSchema(database.schema_version(), 0.9)) {
1029
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_0_9);
1030 } else {
1031
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_2_5_lt_1);
1032 }
1033 }
1034 4500 }
1035
1036
1037 963 PathString SqlNestedCatalogListing::GetPath() const {
1038 963 const char *path = reinterpret_cast<const char *>(RetrieveText(0));
1039 963 return PathString(path, strlen(path));
1040 }
1041
1042
1043 963 shash::Any SqlNestedCatalogListing::GetContentHash() const {
1044
2/4
✓ Branch 2 taken 963 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 963 times.
✗ Branch 6 not taken.
963 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
1045 963 return (hash.empty())
1046 ? shash::Any(shash::kAny)
1047
4/6
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 663 times.
✓ Branch 3 taken 300 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 663 times.
✗ Branch 8 not taken.
1926 : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog);
1048 963 }
1049
1050
1051 963 uint64_t SqlNestedCatalogListing::GetSize() const { return RetrieveInt64(2); }
1052
1053
1054 //------------------------------------------------------------------------------
1055
1056
1057 4500 SqlOwnNestedCatalogListing::SqlOwnNestedCatalogListing(
1058 4500 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 4500 if (database.IsEqualSchema(database.schema_version(), 2.5)
1068
5/6
✓ Branch 0 taken 4474 times.
✓ Branch 1 taken 26 times.
✓ Branch 3 taken 4474 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4474 times.
✓ Branch 6 taken 26 times.
4500 && (database.schema_revision() >= 1)) {
1069
2/4
✓ Branch 1 taken 4474 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4474 times.
✗ Branch 5 not taken.
4474 DeferredInit(database.sqlite_db(), stmt_2_5_ge_1);
1070 } else {
1071
2/2
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 13 times.
26 if (database.IsEqualSchema(database.schema_version(), 0.9)) {
1072
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_0_9);
1073 } else {
1074
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 DeferredInit(database.sqlite_db(), stmt_2_5_lt_1);
1075 }
1076 }
1077 4500 }
1078
1079
1080 145 PathString SqlOwnNestedCatalogListing::GetPath() const {
1081 145 const char *path = reinterpret_cast<const char *>(RetrieveText(0));
1082 145 return PathString(path, strlen(path));
1083 }
1084
1085
1086 145 shash::Any SqlOwnNestedCatalogListing::GetContentHash() const {
1087
2/4
✓ Branch 2 taken 145 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 145 times.
✗ Branch 6 not taken.
145 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
1088 145 return (hash.empty())
1089 ? shash::Any(shash::kAny)
1090
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 145 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 7 taken 145 times.
✗ Branch 8 not taken.
290 : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog);
1091 145 }
1092
1093
1094 145 uint64_t SqlOwnNestedCatalogListing::GetSize() const {
1095 145 return RetrieveInt64(2);
1096 }
1097
1098
1099 //------------------------------------------------------------------------------
1100
1101
1102 4899 SqlDirentInsert::SqlDirentInsert(const CatalogDatabase &database) {
1103 9798 DeferredInit(
1104
2/4
✓ Branch 1 taken 4899 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4899 times.
✗ Branch 5 not taken.
4899 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 4899 }
1113
1114
1115 14339 bool SqlDirentInsert::BindPathHash(const shash::Md5 &hash) {
1116 14339 return BindMd5(1, 2, hash);
1117 }
1118
1119
1120 14339 bool SqlDirentInsert::BindParentPathHash(const shash::Md5 &hash) {
1121 14339 return BindMd5(3, 4, hash);
1122 }
1123
1124
1125 14339 bool SqlDirentInsert::BindDirent(const DirectoryEntry &entry) {
1126 14339 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 12115 bool SqlDirentInsert::BindXattrEmpty() { return BindNull(15); }
1141
1142
1143 //------------------------------------------------------------------------------
1144
1145
1146 2675 SqlDirentUpdate::SqlDirentUpdate(const CatalogDatabase &database) {
1147
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 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 2675 }
1159
1160
1161 5388 bool SqlDirentUpdate::BindPathHash(const shash::Md5 &hash) {
1162 5388 return BindMd5(12, 13, hash);
1163 }
1164
1165
1166 5388 bool SqlDirentUpdate::BindDirent(const DirectoryEntry &entry) {
1167 5388 return BindDirentFields(1, 8, 2, 3, 4, 11, 5, 6, 7, 9, 10, entry);
1168 }
1169
1170
1171 //------------------------------------------------------------------------------
1172
1173
1174 2675 SqlDirentUnlink::SqlDirentUnlink(const CatalogDatabase &database) {
1175
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 DeferredInit(database.sqlite_db(),
1176 "DELETE FROM catalog "
1177 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1178 2675 }
1179
1180 3006 bool SqlDirentUnlink::BindPathHash(const shash::Md5 &hash) {
1181 3006 return BindMd5(1, 2, hash);
1182 }
1183
1184
1185 //------------------------------------------------------------------------------
1186
1187
1188 2675 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 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 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 2675 }
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 2675 SqlChunkInsert::SqlChunkInsert(const CatalogDatabase &database) {
1215
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 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 2675 }
1220
1221
1222 156 bool SqlChunkInsert::BindPathHash(const shash::Md5 &hash) {
1223 156 return BindMd5(1, 2, hash);
1224 }
1225
1226
1227 156 bool SqlChunkInsert::BindFileChunk(const FileChunk &chunk) {
1228
1/2
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
312 return BindInt64(3, chunk.offset()) && BindInt64(4, chunk.size())
1229
2/4
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 156 times.
✗ Branch 5 not taken.
312 && BindHashBlob(5, chunk.content_hash());
1230 }
1231
1232
1233 //------------------------------------------------------------------------------
1234
1235
1236 2675 SqlChunksRemove::SqlChunksRemove(const CatalogDatabase &database) {
1237
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 DeferredInit(database.sqlite_db(),
1238 "DELETE FROM chunks "
1239 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1240 2675 }
1241
1242
1243 ✗ bool SqlChunksRemove::BindPathHash(const shash::Md5 &hash) {
1244 ✗ return BindMd5(1, 2, hash);
1245 }
1246
1247
1248 //------------------------------------------------------------------------------
1249
1250
1251 4500 SqlChunksListing::SqlChunksListing(const CatalogDatabase &database) {
1252
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
4500 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 4500 }
1259
1260
1261 26 bool SqlChunksListing::BindPathHash(const shash::Md5 &hash) {
1262 26 return BindMd5(1, 2, hash);
1263 }
1264
1265
1266 26 FileChunk SqlChunksListing::GetFileChunk(
1267 const shash::Algorithms interpret_hash_as) const {
1268 return FileChunk(
1269 26 RetrieveHashBlob(2, interpret_hash_as, shash::kSuffixPartial),
1270 26 RetrieveInt64(0),
1271 52 RetrieveInt64(1));
1272 }
1273
1274
1275 //------------------------------------------------------------------------------
1276
1277
1278 2675 SqlChunksCount::SqlChunksCount(const CatalogDatabase &database) {
1279
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 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 2675 }
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 2675 SqlMaxHardlinkGroup::SqlMaxHardlinkGroup(const CatalogDatabase &database) {
1299
2/4
✓ Branch 1 taken 2675 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2675 times.
✗ Branch 5 not taken.
2675 DeferredInit(database.sqlite_db(), "SELECT max(hardlinks) FROM catalog;");
1300 2675 }
1301
1302
1303 75 uint32_t SqlMaxHardlinkGroup::GetMaxGroupId() const {
1304 75 return RetrieveInt64(0) >> 32;
1305 }
1306
1307
1308 //------------------------------------------------------------------------------
1309
1310
1311 6945 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 6919 times.
✓ Branch 2 taken 26 times.
6945 if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1317 6919 compat_ = false;
1318
2/4
✓ Branch 1 taken 6919 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6919 times.
✗ Branch 5 not taken.
6919 DeferredInit(database.sqlite_db(), stmt_ge_2_4);
1319 } else {
1320 26 compat_ = true;
1321
2/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 DeferredInit(database.sqlite_db(), stmt_lt_2_4);
1322 }
1323 6945 }
1324
1325
1326 166680 bool SqlGetCounter::BindCounter(const std::string &counter) {
1327
2/2
✓ Branch 0 taken 624 times.
✓ Branch 1 taken 166056 times.
166680 if (compat_)
1328 624 return true;
1329 166056 return BindText(1, counter);
1330 }
1331
1332
1333 166680 uint64_t SqlGetCounter::GetCounter() const {
1334
2/2
✓ Branch 0 taken 624 times.
✓ Branch 1 taken 166056 times.
166680 if (compat_)
1335 624 return 0;
1336 166056 return RetrieveInt64(0);
1337 }
1338
1339
1340 //------------------------------------------------------------------------------
1341
1342
1343 2445 SqlUpdateCounter::SqlUpdateCounter(const CatalogDatabase &database) {
1344 4890 DeferredInit(
1345
2/4
✓ Branch 1 taken 2445 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2445 times.
✗ Branch 5 not taken.
2445 database.sqlite_db(),
1346 "UPDATE statistics SET value=value+:val WHERE counter=:counter;");
1347 2445 }
1348
1349
1350 58680 bool SqlUpdateCounter::BindCounter(const std::string &counter) {
1351 58680 return BindText(2, counter);
1352 }
1353
1354
1355 58680 bool SqlUpdateCounter::BindDelta(const int64_t delta) {
1356 58680 return BindInt64(1, delta);
1357 }
1358
1359
1360 //------------------------------------------------------------------------------
1361
1362
1363 2580 SqlCreateCounter::SqlCreateCounter(const CatalogDatabase &database) {
1364
2/4
✓ Branch 1 taken 2580 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2580 times.
✗ Branch 5 not taken.
2580 DeferredInit(database.sqlite_db(),
1365 "INSERT OR REPLACE INTO statistics (counter, value) "
1366 "VALUES (:counter, :value);");
1367 2580 }
1368
1369
1370 61920 bool SqlCreateCounter::BindCounter(const std::string &counter) {
1371 61920 return BindText(1, counter);
1372 }
1373
1374
1375 61920 bool SqlCreateCounter::BindInitialValue(const int64_t value) {
1376 61920 return BindInt64(2, value);
1377 }
1378
1379
1380 //------------------------------------------------------------------------------
1381
1382
1383 4500 SqlAllChunks::SqlAllChunks(const CatalogDatabase &database) {
1384 4500 const int hash_mask = 7 << SqlDirent::kFlagPosHash;
1385
3/6
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4500 times.
✗ Branch 8 not taken.
9000 const string flags2hash = " ((flags&" + StringifyInt(hash_mask) + ") >> "
1386
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
13500 + StringifyInt(SqlDirent::kFlagPosHash)
1387
1/2
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
4500 + ")+1 AS hash_algorithm ";
1388
1389 4500 const int compression_mask = 7 << SqlDirent::kFlagPosCompression;
1390
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
9000 const string flags2compression = " ((flags&" + StringifyInt(compression_mask)
1391
1/2
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
9000 + ") >> "
1392
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
13500 + StringifyInt(
1393 SqlDirent::kFlagPosCompression)
1394
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
9000 + ") " + "AS compression_algorithm ";
1395
1396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4500 times.
4500 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 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4500 times.
✗ Branch 8 not taken.
9000 + StringifyInt(SqlDirent::kFlagFile) + " THEN "
1408
4/8
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4500 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4500 times.
✗ Branch 11 not taken.
18000 + StringifyInt(shash::kSuffixNone) + " " + "WHEN flags & "
1409
3/6
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4500 times.
✗ Branch 8 not taken.
18000 + StringifyInt(SqlDirent::kFlagDir) + " THEN "
1410
3/6
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4500 times.
✗ Branch 8 not taken.
18000 + StringifyInt(shash::kSuffixMicroCatalog) + " END "
1411
4/8
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4500 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4500 times.
✗ Branch 11 not taken.
9000 + "AS chunk_type, " + flags2hash + "," + flags2compression
1412
1/2
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
9000 + "FROM catalog WHERE (hash IS NOT NULL) AND "
1413 " (flags & "
1414
3/6
✓ Branch 0 taken 4500 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4500 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4500 times.
✗ Branch 7 not taken.
13500 + StringifyInt(SqlDirent::kFlagFileExternal
1415 | (g_ignore_legacy_bulk_hashes
1416 ? SqlDirent::kFlagFileChunk
1417 : 0))
1418
1/2
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
4500 + " = 0)";
1419
2/2
✓ Branch 1 taken 4474 times.
✓ Branch 2 taken 26 times.
4500 if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1420 sql += " UNION "
1421 "SELECT DISTINCT chunks.hash, "
1422
5/10
✓ Branch 1 taken 4474 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4474 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4474 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4474 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4474 times.
✗ Branch 14 not taken.
8948 + StringifyInt(shash::kSuffixPartial) + ", " + flags2hash + ","
1423
1/2
✓ Branch 1 taken 4474 times.
✗ Branch 2 not taken.
8948 + flags2compression
1424
1/2
✓ Branch 1 taken 4474 times.
✗ Branch 2 not taken.
8948 + "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 4474 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4474 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4474 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4474 times.
✗ Branch 11 not taken.
13422 + StringifyInt(SqlDirent::kFlagFileExternal) + " = 0)";
1429 }
1430
1/2
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
4500 sql += ";";
1431
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
4500 Init(database.sqlite_db(), sql);
1432 4500 }
1433
1434
1435 26 bool SqlAllChunks::Open() { return true; }
1436
1437
1438 130 bool SqlAllChunks::Next(shash::Any *hash, zlib::Algorithms *compression_alg) {
1439
2/2
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 104 times.
130 if (!FetchRow()) {
1440 26 return false;
1441 }
1442
1443 104 *hash = RetrieveHashBlob(0, static_cast<shash::Algorithms>(RetrieveInt(2)),
1444 104 static_cast<shash::Suffix>(RetrieveInt(1)));
1445 104 *compression_alg = static_cast<zlib::Algorithms>(RetrieveInt(3));
1446 104 return true;
1447 }
1448
1449
1450 26 bool SqlAllChunks::Close() { return Reset(); }
1451
1452
1453 //------------------------------------------------------------------------------
1454
1455
1456 4500 SqlLookupXattrs::SqlLookupXattrs(const CatalogDatabase &database) {
1457
2/4
✓ Branch 1 taken 4500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4500 times.
✗ Branch 5 not taken.
4500 DeferredInit(database.sqlite_db(),
1458 "SELECT xattr FROM catalog "
1459 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1460 4500 }
1461
1462
1463 11 bool SqlLookupXattrs::BindPathHash(const shash::Md5 &hash) {
1464 11 return BindMd5(1, 2, hash);
1465 }
1466
1467
1468 11 XattrList SqlLookupXattrs::GetXattrs() {
1469 const unsigned char *packed_xattrs = reinterpret_cast<const unsigned char *>(
1470
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 RetrieveBlob(0));
1471
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (packed_xattrs == NULL)
1472 11 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