GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2026-05-03 02:36:16
Exec Total Coverage
Lines: 452 598 75.6%
Branches: 574 1536 37.4%

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