GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2025-06-08 02:35:55
Exec Total Coverage
Lines: 449 594 75.6%
Branches: 572 1530 37.4%

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