GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2025-06-29 02:35:41
Exec Total Coverage
Lines: 450 595 75.6%
Branches: 572 1530 37.4%

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