GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2025-02-09 02:34:19
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 147 bool CatalogDatabase::CheckSchemaCompatibility() {
87
3/6
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 145 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
292 return !( (schema_version() >= 2.0-kSchemaEpsilon) &&
88 145 (!IsEqualSchema(schema_version(), kLatestSupportedSchema)) &&
89 (!IsEqualSchema(schema_version(), 2.4) ||
90 147 !IsEqualSchema(kLatestSupportedSchema, 2.5)) );
91 }
92
93
94 92 bool CatalogDatabase::LiveSchemaUpgradeIfNecessary() {
95
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 92 times.
92 assert(read_write());
96
97
6/6
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 89 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 91 times.
92 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 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 90 times.
92 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 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 90 times.
92 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 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 90 times.
92 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 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 90 times.
92 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 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 90 times.
92 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 90 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 88 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 90 times.
92 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 92 return true;
233 }
234
235
236 92 bool CatalogDatabase::CreateEmptyDatabase() {
237
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 92 times.
92 assert(read_write());
238
239 // generate the catalog table and index structure
240 const bool retval =
241
4/16
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 92 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 92 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.
184 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.
368 " CONSTRAINT pk_catalog PRIMARY KEY (md5path_1, md5path_2));").Execute() &&
248
5/19
✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 92 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 92 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 92 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.
184 SqlCatalog(*this,
249 "CREATE INDEX idx_catalog_parent "
250
2/4
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 "ON catalog (parent_1, parent_2);") .Execute() &&
251
5/19
✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 92 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 92 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 92 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.
184 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 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 " catalog(md5path_1, md5path_2));") .Execute() &&
258
5/19
✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 92 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 92 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 92 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.
184 SqlCatalog(*this,
259 "CREATE TABLE nested_catalogs (path TEXT, sha1 TEXT, size INTEGER, "
260
2/4
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
92 "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 92 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 92 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 92 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 92 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.
184 SqlCatalog(*this,
269 "CREATE TABLE bind_mountpoints (path TEXT, sha1 TEXT, size INTEGER, "
270
4/9
✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 92 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 92 times.
✗ Branch 10 not taken.
368 "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));") .Execute() &&
271
5/19
✓ Branch 2 taken 92 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 92 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 92 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 92 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.
184 SqlCatalog(*this,
272 "CREATE TABLE statistics (counter TEXT, value INTEGER, "
273
3/6
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 92 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✗ Branch 6 not taken.
184 "CONSTRAINT pk_statistics PRIMARY KEY (counter));") .Execute();
274
275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
92 if (!retval) {
276 PrintSqlError("failed to create catalog database tables.");
277 }
278
279 92 return retval;
280 }
281
282
283 91 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 91 times.
91 assert(read_write());
290 91 bool retval = false;
291
292 // Path hashes
293
1/2
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
91 shash::Md5 root_path_hash = shash::Md5(shash::AsciiPtr(root_path));
294 91 shash::Md5 root_parent_hash = (root_path == "")
295 ? shash::Md5()
296
7/12
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 39 times.
✓ Branch 3 taken 52 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 39 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 39 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 39 times.
✓ Branch 13 taken 52 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
91 : shash::Md5(shash::AsciiPtr(GetParentPath(root_path)));
297
298 // Start initial filling transaction
299
1/2
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
91 retval = BeginTransaction();
300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 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 91 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 91 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 91 times.
91 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 91 times.
91 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 91 times.
91 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 91 times.
✗ Branch 2 not taken.
91 catalog::Counters counters;
331
332 // Insert root entry (when given)
333
2/2
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 20 times.
91 if (!root_entry.IsNegative()) {
334
1/2
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
71 SqlDirentInsert sql_insert(*this);
335
1/2
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
71 retval = sql_insert.BindPathHash(root_path_hash) &&
336
2/4
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
71 sql_insert.BindParentPathHash(root_parent_hash) &&
337
3/6
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 71 times.
✗ Branch 6 not taken.
213 sql_insert.BindDirent(root_entry) &&
338
2/4
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
71 sql_insert.Execute();
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 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 71 counters.self.directories = 1;
346
1/2
✓ Branch 1 taken 71 times.
✗ Branch 2 not taken.
71 }
347
348 // Save initial statistics counters
349
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
91 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 39 times.
✓ Branch 2 taken 52 times.
91 if (!root_path.empty()) {
356
4/9
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 39 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 39 times.
✗ Branch 9 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 39 times.
39 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 91 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 91 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 91 times.
91 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 91 times.
✗ Branch 2 not taken.
91 retval = CommitTransaction();
371
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 if (!retval) {
372 PrintSqlError("failed to commit initial filling transaction");
373 return false;
374 }
375
376 91 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 46 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 46 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 46 times.
✗ Branch 6 not taken.
92 "AS ratio FROM catalog;");
390
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 const bool retval = rowid_waste_ratio_query.FetchRow();
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 assert(retval);
392
393
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
92 return rowid_waste_ratio_query.RetrieveDouble(0);
394 46 }
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 12 bool CatalogDatabase::CompactDatabase() const {
417
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 assert(read_write());
418
419
4/17
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 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.
24 return SqlCatalog(*this, "PRAGMA foreign_keys = OFF;").Execute() &&
420
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 BeginTransaction() &&
421
5/19
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 12 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.
24 SqlCatalog(*this, "CREATE TEMPORARY TABLE duplicate AS "
422 " SELECT * FROM catalog "
423
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 " ORDER BY rowid ASC;").Execute() &&
424
7/22
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 12 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.
24 SqlCatalog(*this, "DELETE FROM catalog;").Execute() &&
425
5/19
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 12 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.
24 SqlCatalog(*this, "INSERT INTO catalog "
426 " SELECT * FROM duplicate "
427
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 " ORDER BY rowid").Execute() &&
428
7/22
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 12 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.
24 SqlCatalog(*this, "DROP TABLE duplicate;").Execute() &&
429
4/9
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
48 CommitTransaction() &&
430
8/25
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 12 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 12 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.
36 SqlCatalog(*this, "PRAGMA foreign_keys = ON;").Execute();
431 }
432
433
434 //------------------------------------------------------------------------------
435
436
437 709 unsigned SqlDirent::CreateDatabaseFlags(const DirectoryEntry &entry) const {
438 709 unsigned int database_flags = 0;
439
440
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 677 times.
709 if (entry.IsNestedCatalogRoot())
441 32 database_flags |= kFlagDirNestedRoot;
442
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 642 times.
677 else if (entry.IsNestedCatalogMountpoint())
443 35 database_flags |= kFlagDirNestedMountpoint;
444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 642 times.
642 else if (entry.IsBindMountpoint())
445 database_flags |= kFlagDirBindMountpoint;
446
447
2/2
✓ Branch 1 taken 399 times.
✓ Branch 2 taken 310 times.
709 if (entry.IsDirectory()) {
448 399 database_flags |= kFlagDir;
449
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 297 times.
310 } else if (entry.IsLink()) {
450 13 database_flags |= kFlagFile | kFlagLink;
451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 297 times.
297 } else if (entry.IsSpecial()) {
452 database_flags |= kFlagFile | kFlagFileSpecial;
453 } else {
454 297 database_flags |= kFlagFile;
455 297 database_flags |= entry.compression_algorithm() << kFlagPosCompression;
456
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 287 times.
297 if (entry.IsChunkedFile())
457 10 database_flags |= kFlagFileChunk;
458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 297 times.
297 if (entry.IsExternalFile())
459 database_flags |= kFlagFileExternal;
460
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 297 times.
297 if (entry.IsDirectIo())
461 database_flags |= kFlagDirectIo;
462 }
463
464
5/6
✓ Branch 2 taken 432 times.
✓ Branch 3 taken 277 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 432 times.
✓ Branch 7 taken 277 times.
✓ Branch 8 taken 432 times.
709 if (!entry.checksum_ptr()->IsNull() || entry.IsChunkedFile())
465 277 StoreHashAlgorithm(entry.checksum_ptr()->algorithm, &database_flags);
466
467
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 699 times.
709 if (entry.IsHidden())
468 10 database_flags |= kFlagHidden;
469
470 709 return database_flags;
471 }
472
473
474 277 void SqlDirent::StoreHashAlgorithm(const shash::Algorithms algo,
475 unsigned *flags) const
476 {
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 277 times.
277 assert(algo != shash::kAny);
478 // Md5 unusable for content hashes
479 277 *flags |= (algo - 1) << kFlagPosHash;
480 277 }
481
482
483 723 shash::Algorithms SqlDirent::RetrieveHashAlgorithm(const unsigned flags) const {
484 723 unsigned in_flags = ((7 << kFlagPosHash) & flags) >> kFlagPosHash;
485 // Skip Md5
486 723 in_flags++;
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 723 times.
723 assert(in_flags < shash::kAny);
488 723 return static_cast<shash::Algorithms>(in_flags);
489 }
490
491
492 710 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 710 unsigned in_flags =
497 710 ((7 << kFlagPosCompression) & flags) >> kFlagPosCompression;
498 710 return static_cast<zlib::Algorithms>(in_flags);
499 }
500
501
502 710 uint32_t SqlDirent::Hardlinks2Linkcount(const uint64_t hardlinks) const {
503 710 return (hardlinks << 32) >> 32;
504 }
505
506
507 710 uint32_t SqlDirent::Hardlinks2HardlinkGroup(const uint64_t hardlinks) const {
508 710 return hardlinks >> 32;
509 }
510
511
512 709 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 709 times.
709 assert(linkcount > 0);
516 709 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 586 void SqlDirent::ExpandSymlink(LinkString *raw_symlink) const {
525 586 const char *c = raw_symlink->GetChars();
526 586 const char *cEnd = c+raw_symlink->GetLength();
527
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 586 times.
620 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 586 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 709 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 709 MakeHardlinks(entry.hardlink_group_,
600 709 entry.linkcount_);
601
602 bool result =
603
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
709 BindHashBlob(hash_idx, entry.checksum_) &&
604
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 BindInt64(hardlinks_idx, hardlinks) &&
605
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 BindInt64(size_idx, entry.size_) &&
606
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 BindInt(mode_idx, entry.mode_) &&
607
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 BindInt64(uid_idx, entry.uid_) &&
608
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 BindInt64(gid_idx, entry.gid_) &&
609
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
709 BindInt64(mtime_idx, entry.mtime_) &&
610
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 BindInt(flags_idx, CreateDatabaseFlags(entry)) &&
611
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 BindText(name_idx, entry.name_.GetChars(),
612
1/4
✓ Branch 0 taken 709 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2127 static_cast<int>(entry.name_.GetLength())) &&
613
1/2
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
709 BindText(symlink_idx, entry.symlink_.GetChars(),
614 709 static_cast<int>(entry.symlink_.GetLength()));
615
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 709 times.
709 if (entry.HasMtimeNs()) {
616 result &= BindInt(mtimens_idx, entry.mtime_ns_);
617 } else {
618 709 result &= BindNull(mtimens_idx);
619 }
620
621 709 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 710 DirectoryEntry SqlLookup::GetDirent(const Catalog *catalog,
736 const bool expand_symlink) const
737 {
738 710 DirectoryEntry result;
739
740
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 const unsigned database_flags = RetrieveInt(5);
741 710 result.is_nested_catalog_root_ = (database_flags & kFlagDirNestedRoot);
742 710 result.is_nested_catalog_mountpoint_ =
743 710 (database_flags & kFlagDirNestedMountpoint);
744
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 const char *name = reinterpret_cast<const char *>(RetrieveText(6));
745
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 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 710 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 710 times.
710 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 710 times.
✗ Branch 2 not taken.
710 const uint64_t hardlinks = RetrieveInt64(1);
759 710 result.linkcount_ = Hardlinks2Linkcount(hardlinks);
760 710 result.hardlink_group_ = Hardlinks2HardlinkGroup(hardlinks);
761 710 result.inode_ =
762
2/4
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 710 times.
✗ Branch 5 not taken.
710 catalog->GetMangledInode(RetrieveInt64(12), result.hardlink_group_);
763 710 result.is_bind_mountpoint_ = (database_flags & kFlagDirBindMountpoint);
764 710 result.is_chunked_file_ = (database_flags & kFlagFileChunk);
765 710 result.is_hidden_ = (database_flags & kFlagHidden);
766 710 result.is_direct_io_ = (database_flags & kFlagDirectIo);
767 710 result.is_external_file_ = (database_flags & kFlagFileExternal);
768
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.has_xattrs_ = RetrieveInt(15) != 0;
769
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.mtime_ns_ = RetrieveNullableInt(16, -1);
770 710 result.checksum_ =
771
1/2
✓ Branch 2 taken 710 times.
✗ Branch 3 not taken.
710 RetrieveHashBlob(0, RetrieveHashAlgorithm(database_flags));
772 710 result.compression_algorithm_ =
773 710 RetrieveCompressionAlgorithm(database_flags);
774
775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 710 times.
710 if (g_claim_ownership) {
776 result.uid_ = g_uid;
777 result.gid_ = g_gid;
778 } else {
779
2/4
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 710 times.
✗ Branch 5 not taken.
710 result.uid_ = catalog->MapUid(RetrieveInt64(13));
780
2/4
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 710 times.
✗ Branch 5 not taken.
710 result.gid_ = catalog->MapGid(RetrieveInt64(14));
781 }
782 }
783
784
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.mode_ = RetrieveInt(3);
785
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.size_ = RetrieveInt64(2);
786
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.mtime_ = RetrieveInt64(4);
787
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.name_.Assign(name, strlen(name));
788
1/2
✓ Branch 1 taken 710 times.
✗ Branch 2 not taken.
710 result.symlink_.Assign(symlink, strlen(symlink));
789
3/4
✓ Branch 0 taken 586 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 586 times.
✗ Branch 3 not taken.
710 if (expand_symlink && !g_raw_symlinks)
790
1/2
✓ Branch 1 taken 586 times.
✗ Branch 2 not taken.
586 ExpandSymlink(&result.symlink_);
791
792
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 710 times.
710 if (g_world_readable) {
793 if (S_ISDIR(result.mode_)) {
794 result.mode_ |= 0555;
795 } else {
796 result.mode_ |= 0444;
797 }
798 }
799
800 710 return result;
801 }
802
803
804 //------------------------------------------------------------------------------
805
806
807 144 SqlListing::SqlListing(const CatalogDatabase &database) {
808
28/62
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 143 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 143 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 143 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 143 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.
144 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 142 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 142 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 142 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 32 taken 142 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 142 times.
✗ Branch 36 not taken.
144 DEFERRED_INITS(database);
811 144 }
812
813
814 91 bool SqlListing::BindPathHash(const struct shash::Md5 &hash) {
815 91 return BindMd5(1, 2, hash);
816 }
817
818
819 //------------------------------------------------------------------------------
820
821
822 144 SqlLookupPathHash::SqlLookupPathHash(const CatalogDatabase &database) {
823
28/62
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 143 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 143 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 143 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 143 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.
144 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 142 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 142 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 142 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 32 taken 142 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 142 times.
✗ Branch 36 not taken.
144 DEFERRED_INITS(database);
826 144 }
827
828 561 bool SqlLookupPathHash::BindPathHash(const struct shash::Md5 &hash) {
829 561 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 89 SqlDirentTouch::SqlDirentTouch(const CatalogDatabase &database) {
870
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(),
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 89 }
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 144 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 142 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 142 times.
✓ Branch 7 taken 2 times.
286 if (database.IsEqualSchema(database.schema_version(), 2.5) &&
940 142 (database.schema_revision() >= 4))
941 {
942
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
142 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 144 }
955
956
957 50 bool SqlNestedCatalogLookup::BindSearchPath(const PathString &path) {
958 50 return BindText(1, path.GetChars(), path.GetLength());
959 }
960
961
962 48 shash::Any SqlNestedCatalogLookup::GetContentHash() const {
963
2/4
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
48 const string hash = string(reinterpret_cast<const char *>(RetrieveText(0)));
964 48 return (hash.empty()) ? shash::Any(shash::kAny) :
965
1/2
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
22 shash::MkFromHexPtr(shash::HexPtr(hash),
966
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 22 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
96 shash::kSuffixCatalog);
967 48 }
968
969
970 48 uint64_t SqlNestedCatalogLookup::GetSize() const {
971 48 return RetrieveInt64(1);
972 }
973
974
975 //------------------------------------------------------------------------------
976
977
978 144 SqlNestedCatalogListing::SqlNestedCatalogListing(
979 144 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 142 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 142 times.
✓ Branch 7 taken 2 times.
286 if (database.IsEqualSchema(database.schema_version(), 2.5) &&
994 142 (database.schema_revision() >= 4))
995 {
996
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
142 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 144 }
1009
1010
1011 46 PathString SqlNestedCatalogListing::GetPath() const {
1012 46 const char *path = reinterpret_cast<const char *>(RetrieveText(0));
1013 46 return PathString(path, strlen(path));
1014 }
1015
1016
1017 46 shash::Any SqlNestedCatalogListing::GetContentHash() const {
1018
2/4
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 46 times.
✗ Branch 6 not taken.
46 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
1019 46 return (hash.empty()) ? shash::Any(shash::kAny) :
1020
1/2
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 shash::MkFromHexPtr(shash::HexPtr(hash),
1021
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 34 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
92 shash::kSuffixCatalog);
1022 46 }
1023
1024
1025 46 uint64_t SqlNestedCatalogListing::GetSize() const {
1026 46 return RetrieveInt64(2);
1027 }
1028
1029
1030 //------------------------------------------------------------------------------
1031
1032
1033 144 SqlOwnNestedCatalogListing::SqlOwnNestedCatalogListing(
1034 144 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 142 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 142 times.
✓ Branch 7 taken 2 times.
286 if (database.IsEqualSchema(database.schema_version(), 2.5) &&
1046 142 (database.schema_revision() >= 1))
1047 {
1048
2/4
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
142 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 144 }
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 160 SqlDirentInsert::SqlDirentInsert(const CatalogDatabase &database) {
1082
2/4
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 160 times.
✗ Branch 5 not taken.
160 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 160 }
1091
1092
1093 532 bool SqlDirentInsert::BindPathHash(const shash::Md5 &hash) {
1094 532 return BindMd5(1, 2, hash);
1095 }
1096
1097
1098 532 bool SqlDirentInsert::BindParentPathHash(const shash::Md5 &hash) {
1099 532 return BindMd5(3, 4, hash);
1100 }
1101
1102
1103 532 bool SqlDirentInsert::BindDirent(const DirectoryEntry &entry) {
1104 532 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 461 bool SqlDirentInsert::BindXattrEmpty() {
1119 461 return BindNull(15);
1120 }
1121
1122
1123 //------------------------------------------------------------------------------
1124
1125
1126 89 SqlDirentUpdate::SqlDirentUpdate(const CatalogDatabase &database) {
1127
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(),
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 89 }
1138
1139
1140 177 bool SqlDirentUpdate::BindPathHash(const shash::Md5 &hash) {
1141 177 return BindMd5(12, 13, hash);
1142 }
1143
1144
1145 177 bool SqlDirentUpdate::BindDirent(const DirectoryEntry &entry) {
1146 177 return BindDirentFields(1, 8, 2, 3, 4, 11, 5, 6, 7, 9, 10, entry);
1147 }
1148
1149
1150 //------------------------------------------------------------------------------
1151
1152
1153 89 SqlDirentUnlink::SqlDirentUnlink(const CatalogDatabase &database) {
1154
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(),
1155 "DELETE FROM catalog "
1156 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1157 89 }
1158
1159 113 bool SqlDirentUnlink::BindPathHash(const shash::Md5 &hash) {
1160 113 return BindMd5(1, 2, hash);
1161 }
1162
1163
1164 //------------------------------------------------------------------------------
1165
1166
1167 89 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 89 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 89 times.
✗ Branch 5 not taken.
89 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 89 }
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 89 SqlChunkInsert::SqlChunkInsert(const CatalogDatabase &database) {
1196
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(),
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 89 }
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 89 SqlChunksRemove::SqlChunksRemove(const CatalogDatabase &database) {
1220
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(),
1221 "DELETE FROM chunks "
1222 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1223 89 }
1224
1225
1226 bool SqlChunksRemove::BindPathHash(const shash::Md5 &hash) {
1227 return BindMd5(1, 2, hash);
1228 }
1229
1230
1231 //------------------------------------------------------------------------------
1232
1233
1234 144 SqlChunksListing::SqlChunksListing(const CatalogDatabase &database) {
1235
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
144 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 144 }
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 89 SqlChunksCount::SqlChunksCount(const CatalogDatabase &database) {
1263
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(),
1264 "SELECT count(*) FROM chunks "
1265 // 0
1266 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2)");
1267 // 1 2
1268 89 }
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 89 SqlMaxHardlinkGroup::SqlMaxHardlinkGroup(const CatalogDatabase &database) {
1285
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(), "SELECT max(hardlinks) FROM catalog;");
1286 89 }
1287
1288
1289 1 uint32_t SqlMaxHardlinkGroup::GetMaxGroupId() const {
1290 1 return RetrieveInt64(0) >> 32;
1291 }
1292
1293
1294 //------------------------------------------------------------------------------
1295
1296
1297 219 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 217 times.
✓ Branch 2 taken 2 times.
219 if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1304 217 compat_ = false;
1305
2/4
✓ Branch 1 taken 217 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 217 times.
✗ Branch 5 not taken.
217 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 219 }
1311
1312
1313 5256 bool SqlGetCounter::BindCounter(const std::string &counter) {
1314
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 5208 times.
5256 if (compat_) return true;
1315 5208 return BindText(1, counter);
1316 }
1317
1318
1319 5256 uint64_t SqlGetCounter::GetCounter() const {
1320
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 5208 times.
5256 if (compat_) return 0;
1321 5208 return RetrieveInt64(0);
1322 }
1323
1324
1325 //------------------------------------------------------------------------------
1326
1327
1328 75 SqlUpdateCounter::SqlUpdateCounter(const CatalogDatabase &database) {
1329
2/4
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75 times.
✗ Branch 5 not taken.
75 DeferredInit(database.sqlite_db(),
1330 "UPDATE statistics SET value=value+:val WHERE counter=:counter;");
1331 75 }
1332
1333
1334 1800 bool SqlUpdateCounter::BindCounter(const std::string &counter) {
1335 1800 return BindText(2, counter);
1336 }
1337
1338
1339 1800 bool SqlUpdateCounter::BindDelta(const int64_t delta) {
1340 1800 return BindInt64(1, delta);
1341 }
1342
1343
1344 //------------------------------------------------------------------------------
1345
1346
1347 92 SqlCreateCounter::SqlCreateCounter(const CatalogDatabase &database) {
1348
2/4
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 92 times.
✗ Branch 5 not taken.
92 DeferredInit(database.sqlite_db(),
1349 "INSERT OR REPLACE INTO statistics (counter, value) "
1350 "VALUES (:counter, :value);");
1351 92 }
1352
1353
1354 2208 bool SqlCreateCounter::BindCounter(const std::string &counter) {
1355 2208 return BindText(1, counter);
1356 }
1357
1358
1359 2208 bool SqlCreateCounter::BindInitialValue(const int64_t value) {
1360 2208 return BindInt64(2, value);
1361 }
1362
1363
1364 //------------------------------------------------------------------------------
1365
1366
1367 144 SqlAllChunks::SqlAllChunks(const CatalogDatabase &database) {
1368 144 int hash_mask = 7 << SqlDirent::kFlagPosHash;
1369 string flags2hash =
1370
4/8
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 144 times.
✗ Branch 11 not taken.
288 " ((flags&" + StringifyInt(hash_mask) + ") >> " +
1371
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
288 StringifyInt(SqlDirent::kFlagPosHash) + ")+1 AS hash_algorithm ";
1372
1373 144 int compression_mask = 7 << SqlDirent::kFlagPosCompression;
1374 string flags2compression =
1375
4/8
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 144 times.
✗ Branch 11 not taken.
288 " ((flags&" + StringifyInt(compression_mask) + ") >> " +
1376
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
432 StringifyInt(SqlDirent::kFlagPosCompression) + ") " +
1377
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 "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 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 144 times.
✗ Branch 11 not taken.
288 "CASE WHEN flags & " + StringifyInt(SqlDirent::kFlagFile) + " THEN " +
1385
3/6
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
576 StringifyInt(shash::kSuffixNone) + " " +
1386
4/8
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 144 times.
✗ Branch 11 not taken.
576 "WHEN flags & " + StringifyInt(SqlDirent::kFlagDir) + " THEN " +
1387
3/6
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
576 StringifyInt(shash::kSuffixMicroCatalog) + " END " +
1388
4/8
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 144 times.
✗ Branch 11 not taken.
288 "AS chunk_type, " + flags2hash + "," + flags2compression +
1389 "FROM catalog WHERE (hash IS NOT NULL) AND "
1390
3/6
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 8 not taken.
432 "(flags & " + StringifyInt(SqlDirent::kFlagFileExternal) + " = 0)";
1391
2/2
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 2 times.
144 if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1392 sql +=
1393 " UNION "
1394
3/6
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
284 "SELECT DISTINCT chunks.hash, " + StringifyInt(shash::kSuffixPartial) +
1395
4/8
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 142 times.
✗ Branch 11 not taken.
284 ", " + 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 142 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 142 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 142 times.
✗ Branch 8 not taken.
568 "(catalog.flags & " + StringifyInt(SqlDirent::kFlagFileExternal) +
1400
1/2
✓ Branch 1 taken 142 times.
✗ Branch 2 not taken.
142 " = 0)";
1401 }
1402
1/2
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
144 sql += ";";
1403
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
144 Init(database.sqlite_db(), sql);
1404 144 }
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 144 SqlLookupXattrs::SqlLookupXattrs(const CatalogDatabase &database) {
1433
2/4
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
144 DeferredInit(database.sqlite_db(),
1434 "SELECT xattr FROM catalog "
1435 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1436 144 }
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