GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2025-04-20 02:34:28
Exec Total Coverage
Lines: 454 605 75.0%
Branches: 572 1534 37.3%

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