GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2026-03-22 02:40:38
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 5645 bool CatalogDatabase::CheckSchemaCompatibility() {
92
2/4
✓ Branch 1 taken 5565 times.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
11210 return !((schema_version() >= 2.0 - kSchemaEpsilon)
93
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5565 times.
5565 && (!IsEqualSchema(schema_version(), kLatestSupportedSchema))
94 && (!IsEqualSchema(schema_version(), 2.4)
95
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
5645 || !IsEqualSchema(kLatestSupportedSchema, 2.5)));
96 }
97
98
99 3879 bool CatalogDatabase::LiveSchemaUpgradeIfNecessary() {
100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3879 times.
3879 assert(read_write());
101
102
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3796 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3876 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 0)) {
103
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (0 --> 1)");
104
105 SqlCatalog sql_upgrade(*this, "ALTER TABLE nested_catalogs "
106
2/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
6 "ADD size INTEGER;");
107
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if (!sql_upgrade.Execute()) {
108 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade nested_catalogs");
109 return false;
110 }
111
112 3 set_schema_revision(1);
113
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if (!StoreSchemaRevision()) {
114 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
115 return false;
116 }
117
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 }
118
119
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 3793 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3873 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 1)) {
120
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (1 --> 2)");
121
122
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 SqlCatalog sql_upgrade1(*this, "ALTER TABLE catalog ADD xattr BLOB;");
123 SqlCatalog sql_upgrade2(
124 *this,
125
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "INSERT INTO statistics (counter, value) VALUES ('self_xattr', 0);");
126 SqlCatalog sql_upgrade3(
127 *this,
128
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "INSERT INTO statistics (counter, value) VALUES ('subtree_xattr', 0);");
129
3/7
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
12 if (!sql_upgrade1.Execute() || !sql_upgrade2.Execute()
130
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
12 || !sql_upgrade3.Execute()) {
131 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (1 --> 2)");
132 return false;
133 }
134
135 6 set_schema_revision(2);
136
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!StoreSchemaRevision()) {
137 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
138 return false;
139 }
140
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 }
141
142
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 3793 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3873 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 2)) {
143
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 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 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "('self_external', 0);");
148 SqlCatalog sql_upgrade5(*this,
149 "INSERT INTO statistics (counter, value) VALUES "
150
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "('self_external_file_size', 0);");
151 SqlCatalog sql_upgrade6(*this,
152 "INSERT INTO statistics (counter, value) VALUES "
153
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "('subtree_external', 0);");
154 SqlCatalog sql_upgrade7(*this,
155 "INSERT INTO statistics (counter, value) VALUES "
156
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "('subtree_external_file_size', 0);");
157
3/7
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
12 if (!sql_upgrade4.Execute() || !sql_upgrade5.Execute()
158
6/13
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
12 || !sql_upgrade6.Execute() || !sql_upgrade7.Execute()) {
159 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (2 --> 3)");
160 return false;
161 }
162
163 6 set_schema_revision(3);
164
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!StoreSchemaRevision()) {
165 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
166 return false;
167 }
168
4/8
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
6 }
169
170
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 3793 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3873 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 3)) {
171
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 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 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "CONSTRAINT pk_bind_mountpoints PRIMARY KEY (path));");
177
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!sql_upgrade8.Execute()) {
178 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (3 --> 4)");
179 return false;
180 }
181
182 6 set_schema_revision(4);
183
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!StoreSchemaRevision()) {
184 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
185 return false;
186 }
187
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 }
188
189
190
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 3793 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3873 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 4)) {
191
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 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 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "('self_special', 0);");
196 SqlCatalog sql_upgrade10(*this,
197 "INSERT INTO statistics (counter, value) VALUES "
198
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 "('subtree_special', 0);");
199
5/11
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
6 if (!sql_upgrade9.Execute() || !sql_upgrade10.Execute()) {
200 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (4 --> 5)");
201 return false;
202 }
203
204 6 set_schema_revision(5);
205
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!StoreSchemaRevision()) {
206 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
207 return false;
208 }
209
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 }
210
211
212
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 3793 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3873 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 5)) {
213 6 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (5 --> 6)");
214
215 6 set_schema_revision(6);
216
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (!StoreSchemaRevision()) {
217 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
218 return false;
219 }
220 }
221
222
6/6
✓ Branch 2 taken 3799 times.
✓ Branch 3 taken 80 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 3793 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 3873 times.
3879 if (IsEqualSchema(schema_version(), 2.5) && (schema_revision() == 6)) {
223
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 LogCvmfs(kLogCatalog, kLogDebug, "upgrading schema revision (6 --> 7)");
224
225
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 SqlCatalog sql_upgrade1(*this, "ALTER TABLE catalog ADD mtimens INTEGER;");
226
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!sql_upgrade1.Execute()) {
227 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade catalogs (6 --> 7)");
228 return false;
229 }
230
231 6 set_schema_revision(7);
232
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!StoreSchemaRevision()) {
233 LogCvmfs(kLogCatalog, kLogDebug, "failed to upgrade schema revision");
234 return false;
235 }
236
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 }
237
238 3879 return true;
239 }
240
241
242 3440 bool CatalogDatabase::CreateEmptyDatabase() {
243
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3440 times.
3440 assert(read_write());
244
245 // generate the catalog table and index structure
246 const bool retval =
247
4/16
✓ Branch 1 taken 3440 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3440 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3440 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3440 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.
6880 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 6880 .Execute()
258
5/20
✓ Branch 2 taken 3440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3440 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3440 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3440 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 3440 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.
6880 && SqlCatalog(*this,
259 "CREATE INDEX idx_catalog_parent "
260 "ON catalog (parent_1, parent_2);")
261
2/4
✓ Branch 1 taken 3440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3440 times.
✗ Branch 4 not taken.
3440 .Execute()
262
5/20
✓ Branch 2 taken 3440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3440 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3440 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3440 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 3440 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.
6880 && 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 3440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3440 times.
✗ Branch 4 not taken.
3440 .Execute()
272
5/20
✓ Branch 2 taken 3440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3440 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3440 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3440 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 3440 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.
6880 && 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 3440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3440 times.
✗ Branch 4 not taken.
3440 .Execute()
277
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
6880 &&
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 3440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3440 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3440 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3440 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 3440 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.
6880 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 3440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3440 times.
✗ Branch 4 not taken.
3440 .Execute()
291
7/24
✓ Branch 2 taken 3440 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3440 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3440 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3440 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 3440 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 3440 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 3440 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.
17200 && SqlCatalog(*this,
292 "CREATE TABLE statistics (counter TEXT, value INTEGER, "
293 "CONSTRAINT pk_statistics PRIMARY KEY (counter));")
294
3/6
✓ Branch 1 taken 3440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3440 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3440 times.
✗ Branch 6 not taken.
6880 .Execute();
295
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3440 times.
3440 if (!retval) {
297 PrintSqlError("failed to create catalog database tables.");
298 }
299
300 3440 return retval;
301 }
302
303
304 3437 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 3437 times.
3437 assert(read_write());
309 3437 bool retval = false;
310
311 // Path hashes
312
1/2
✓ Branch 2 taken 3437 times.
✗ Branch 3 not taken.
3437 const shash::Md5 root_path_hash = shash::Md5(shash::AsciiPtr(root_path));
313 3437 const shash::Md5 root_parent_hash = (root_path == "")
314 ? shash::Md5()
315 : shash::Md5(shash::AsciiPtr(
316
7/12
✓ Branch 0 taken 1686 times.
✓ Branch 1 taken 1751 times.
✓ Branch 3 taken 1686 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1751 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1751 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1751 times.
✓ Branch 13 taken 1686 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
3437 GetParentPath(root_path)));
317
318 // Start initial filling transaction
319
1/2
✓ Branch 1 taken 3437 times.
✗ Branch 2 not taken.
3437 retval = BeginTransaction();
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3437 times.
3437 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 3437 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3437 times.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3437 times.
3437 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 3437 times.
3437 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 3437 times.
3437 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 3437 times.
✗ Branch 2 not taken.
3437 catalog::Counters counters;
351
352 // Insert root entry (when given)
353
2/2
✓ Branch 1 taken 2621 times.
✓ Branch 2 taken 816 times.
3437 if (!root_entry.IsNegative()) {
354
1/2
✓ Branch 1 taken 2621 times.
✗ Branch 2 not taken.
2621 SqlDirentInsert sql_insert(*this);
355
1/2
✓ Branch 1 taken 2621 times.
✗ Branch 2 not taken.
2621 retval = sql_insert.BindPathHash(root_path_hash)
356
2/4
✓ Branch 1 taken 2621 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2621 times.
✗ Branch 4 not taken.
2621 && sql_insert.BindParentPathHash(root_parent_hash)
357
5/11
✓ Branch 0 taken 2621 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2621 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2621 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2621 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2621 times.
✗ Branch 11 not taken.
5242 && sql_insert.BindDirent(root_entry) && sql_insert.Execute();
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2621 times.
2621 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 2621 counters.self.directories = 1;
365
1/2
✓ Branch 1 taken 2621 times.
✗ Branch 2 not taken.
2621 }
366
367 // Save initial statistics counters
368
2/4
✓ Branch 1 taken 3437 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3437 times.
3437 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 1751 times.
✓ Branch 2 taken 1686 times.
3437 if (!root_path.empty()) {
375
4/9
✓ Branch 1 taken 1751 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1751 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1751 times.
✗ Branch 9 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1751 times.
1751 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 3437 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3437 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 3437 times.
3437 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 3437 times.
✗ Branch 2 not taken.
3437 retval = CommitTransaction();
390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3437 times.
3437 if (!retval) {
391 PrintSqlError("failed to commit initial filling transaction");
392 return false;
393 }
394
395 3437 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 2106 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 2106 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2106 times.
✗ Branch 6 not taken.
4212 "AS ratio FROM catalog;");
409
1/2
✓ Branch 1 taken 2106 times.
✗ Branch 2 not taken.
2106 const bool retval = rowid_waste_ratio_query.FetchRow();
410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2106 times.
2106 assert(retval);
411
412
1/2
✓ Branch 1 taken 2106 times.
✗ Branch 2 not taken.
4212 return rowid_waste_ratio_query.RetrieveDouble(0);
413 2106 }
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 31311 unsigned SqlDirent::CreateDatabaseFlags(const DirectoryEntry &entry) const {
459 31311 unsigned int database_flags = 0;
460
461
2/2
✓ Branch 1 taken 1575 times.
✓ Branch 2 taken 29736 times.
31311 if (entry.IsNestedCatalogRoot())
462 1575 database_flags |= kFlagDirNestedRoot;
463
2/2
✓ Branch 1 taken 1727 times.
✓ Branch 2 taken 28009 times.
29736 else if (entry.IsNestedCatalogMountpoint())
464 1727 database_flags |= kFlagDirNestedMountpoint;
465
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28009 times.
28009 else if (entry.IsBindMountpoint())
466 database_flags |= kFlagDirBindMountpoint;
467
468
2/2
✓ Branch 1 taken 17954 times.
✓ Branch 2 taken 13357 times.
31311 if (entry.IsDirectory()) {
469 17954 database_flags |= kFlagDir;
470
2/2
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 12820 times.
13357 } else if (entry.IsLink()) {
471 537 database_flags |= kFlagFile | kFlagLink;
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12820 times.
12820 } else if (entry.IsSpecial()) {
473 database_flags |= kFlagFile | kFlagFileSpecial;
474 } else {
475 12820 database_flags |= kFlagFile;
476 12820 database_flags |= entry.compression_algorithm() << kFlagPosCompression;
477
2/2
✓ Branch 1 taken 408 times.
✓ Branch 2 taken 12412 times.
12820 if (entry.IsChunkedFile())
478 408 database_flags |= kFlagFileChunk;
479
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12820 times.
12820 if (entry.IsExternalFile())
480 database_flags |= kFlagFileExternal;
481
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12820 times.
12820 if (entry.IsDirectIo())
482 database_flags |= kFlagDirectIo;
483 }
484
485
5/6
✓ Branch 2 taken 18971 times.
✓ Branch 3 taken 12340 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18971 times.
✓ Branch 7 taken 12340 times.
✓ Branch 8 taken 18971 times.
31311 if (!entry.checksum_ptr()->IsNull() || entry.IsChunkedFile())
486 12340 StoreHashAlgorithm(entry.checksum_ptr()->algorithm, &database_flags);
487
488
2/2
✓ Branch 1 taken 408 times.
✓ Branch 2 taken 30903 times.
31311 if (entry.IsHidden())
489 408 database_flags |= kFlagHidden;
490
491 31311 return database_flags;
492 }
493
494
495 12340 void SqlDirent::StoreHashAlgorithm(const shash::Algorithms algo,
496 unsigned *flags) const {
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12340 times.
12340 assert(algo != shash::kAny);
498 // Md5 unusable for content hashes
499 12340 *flags |= (algo - 1) << kFlagPosHash;
500 12340 }
501
502
503 33204 shash::Algorithms SqlDirent::RetrieveHashAlgorithm(const unsigned flags) const {
504 33204 unsigned in_flags = ((7 << kFlagPosHash) & flags) >> kFlagPosHash;
505 // Skip Md5
506 33204 in_flags++;
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33204 times.
33204 assert(in_flags < shash::kAny);
508 33204 return static_cast<shash::Algorithms>(in_flags);
509 }
510
511
512 32684 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 32684 const unsigned in_flags = ((7 << kFlagPosCompression) & flags)
516 32684 >> kFlagPosCompression;
517 32684 return static_cast<zlib::Algorithms>(in_flags);
518 }
519
520
521 32684 uint32_t SqlDirent::Hardlinks2Linkcount(const uint64_t hardlinks) const {
522 32684 return (hardlinks << 32) >> 32;
523 }
524
525
526 32684 uint32_t SqlDirent::Hardlinks2HardlinkGroup(const uint64_t hardlinks) const {
527 32684 return hardlinks >> 32;
528 }
529
530
531 31311 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 31311 times.
31311 assert(linkcount > 0);
534 31311 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 26953 void SqlDirent::ExpandSymlink(LinkString *raw_symlink) const {
543 26953 const char *c = raw_symlink->GetChars();
544 26953 const char *cEnd = c + raw_symlink->GetLength();
545
2/2
✓ Branch 0 taken 1426 times.
✓ Branch 1 taken 26953 times.
28379 for (; c < cEnd; ++c) {
546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1426 times.
1426 if (*c == '$')
547 goto expand_symlink;
548 }
549 26953 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 31311 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 31311 const uint64_t hardlinks = MakeHardlinks(entry.hardlink_group_,
616 31311 entry.linkcount_);
617
618 31311 bool result = BindHashBlob(hash_idx, entry.checksum_)
619
1/2
✓ Branch 1 taken 31311 times.
✗ Branch 2 not taken.
31311 && BindInt64(hardlinks_idx, hardlinks)
620
1/2
✓ Branch 1 taken 31311 times.
✗ Branch 2 not taken.
31311 && BindInt64(size_idx, entry.size_)
621
1/2
✓ Branch 1 taken 31311 times.
✗ Branch 2 not taken.
31311 && BindInt(mode_idx, entry.mode_)
622
1/2
✓ Branch 1 taken 31311 times.
✗ Branch 2 not taken.
31311 && BindInt64(uid_idx, entry.uid_)
623
1/2
✓ Branch 1 taken 31311 times.
✗ Branch 2 not taken.
31311 && BindInt64(gid_idx, entry.gid_)
624
1/2
✓ Branch 1 taken 31311 times.
✗ Branch 2 not taken.
31311 && BindInt64(mtime_idx, entry.mtime_)
625
1/2
✓ Branch 2 taken 31311 times.
✗ Branch 3 not taken.
31311 && BindInt(flags_idx, CreateDatabaseFlags(entry))
626
1/2
✓ Branch 2 taken 31311 times.
✗ Branch 3 not taken.
31311 && BindText(name_idx, entry.name_.GetChars(),
627 31311 static_cast<int>(entry.name_.GetLength()))
628
2/4
✓ Branch 0 taken 31311 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 31311 times.
✗ Branch 5 not taken.
62622 && BindText(symlink_idx, entry.symlink_.GetChars(),
629 31311 static_cast<int>(entry.symlink_.GetLength()));
630
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31311 times.
31311 if (entry.HasMtimeNs()) {
631 result &= BindInt(mtimens_idx, entry.mtime_ns_);
632 } else {
633 31311 result &= BindNull(mtimens_idx);
634 }
635
636 31311 return result;
637 }
638
639
640 //------------------------------------------------------------------------------
641
642
643 80 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 40 times.
✓ Branch 2 taken 40 times.
80 if (database.schema_version() < 2.4 - CatalogDatabase::kSchemaEpsilon) {
662
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_lt_2_4);
663 } else {
664
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_ge_2_4);
665 }
666 80 }
667
668
669 520 shash::Any SqlListContentHashes::GetHash() const {
670 520 const unsigned int db_flags = RetrieveInt(1);
671 520 const shash::Algorithms hash_algorithm = RetrieveHashAlgorithm(db_flags);
672 520 shash::Any hash = RetrieveHashBlob(0, hash_algorithm);
673
2/2
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 320 times.
520 if (RetrieveInt(2) == 1) {
674 200 hash.suffix = shash::kSuffixPartial;
675 }
676
677 520 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 32684 DirectoryEntry SqlLookup::GetDirent(const Catalog *catalog,
745 const bool expand_symlink) const {
746 32684 DirectoryEntry result;
747
748
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 const unsigned database_flags = RetrieveInt(5);
749 32684 result.is_nested_catalog_root_ = (database_flags & kFlagDirNestedRoot);
750 32684 result.is_nested_catalog_mountpoint_ = (database_flags
751 32684 & kFlagDirNestedMountpoint);
752
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 const char *name = reinterpret_cast<const char *>(RetrieveText(6));
753
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 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 32684 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 32684 times.
32684 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 32684 times.
✗ Branch 2 not taken.
32684 const uint64_t hardlinks = RetrieveInt64(1);
767 32684 result.linkcount_ = Hardlinks2Linkcount(hardlinks);
768 32684 result.hardlink_group_ = Hardlinks2HardlinkGroup(hardlinks);
769
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.inode_ = catalog->GetMangledInode(RetrieveInt64(12),
770
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.hardlink_group_);
771 32684 result.is_bind_mountpoint_ = (database_flags & kFlagDirBindMountpoint);
772 32684 result.is_chunked_file_ = (database_flags & kFlagFileChunk);
773 32684 result.is_hidden_ = (database_flags & kFlagHidden);
774 32684 result.is_direct_io_ = (database_flags & kFlagDirectIo);
775 32684 result.is_external_file_ = (database_flags & kFlagFileExternal);
776
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.has_xattrs_ = RetrieveInt(15) != 0;
777
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.mtime_ns_ = RetrieveNullableInt(16, -1);
778
1/2
✓ Branch 2 taken 32684 times.
✗ Branch 3 not taken.
32684 result.checksum_ = RetrieveHashBlob(0,
779 RetrieveHashAlgorithm(database_flags));
780 32684 result.compression_algorithm_ = RetrieveCompressionAlgorithm(
781 database_flags);
782
783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32684 times.
32684 if (g_claim_ownership) {
784 result.uid_ = g_uid;
785 result.gid_ = g_gid;
786 } else {
787
2/4
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32684 times.
✗ Branch 5 not taken.
32684 result.uid_ = catalog->MapUid(RetrieveInt64(13));
788
2/4
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32684 times.
✗ Branch 5 not taken.
32684 result.gid_ = catalog->MapGid(RetrieveInt64(14));
789 }
790 }
791
792
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.mode_ = RetrieveInt(3);
793
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.size_ = RetrieveInt64(2);
794
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.mtime_ = RetrieveInt64(4);
795
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.name_.Assign(name, strlen(name));
796
1/2
✓ Branch 1 taken 32684 times.
✗ Branch 2 not taken.
32684 result.symlink_.Assign(symlink, strlen(symlink));
797
3/4
✓ Branch 0 taken 26953 times.
✓ Branch 1 taken 5731 times.
✓ Branch 2 taken 26953 times.
✗ Branch 3 not taken.
32684 if (expand_symlink && !g_raw_symlinks)
798
1/2
✓ Branch 1 taken 26953 times.
✗ Branch 2 not taken.
26953 ExpandSymlink(&result.symlink_);
799
800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32684 times.
32684 if (g_world_readable) {
801 if (S_ISDIR(result.mode_)) {
802 result.mode_ |= 0555;
803 } else {
804 result.mode_ |= 0444;
805 }
806 }
807
808 32684 return result;
809 }
810
811
812 //------------------------------------------------------------------------------
813
814
815 5636 SqlListing::SqlListing(const CatalogDatabase &database) {
816
28/62
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 5590 times.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 46 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 46 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 46 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 46 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 28 taken 46 times.
✓ Branch 29 taken 5590 times.
✓ Branch 31 taken 46 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 46 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 46 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 43 taken 46 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 46 times.
✗ Branch 47 not taken.
✓ Branch 56 taken 46 times.
✓ Branch 57 taken 5590 times.
✓ Branch 59 taken 46 times.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✓ Branch 63 taken 46 times.
✗ Branch 64 not taken.
✓ Branch 67 taken 46 times.
✗ Branch 68 not taken.
✓ Branch 71 taken 46 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 46 times.
✗ Branch 75 not taken.
✓ Branch 84 taken 46 times.
✓ Branch 85 taken 5590 times.
✓ Branch 87 taken 46 times.
✗ Branch 88 not taken.
✓ Branch 91 taken 46 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 46 times.
✗ Branch 96 not taken.
✓ Branch 99 taken 46 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 46 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.
5636 MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog "
817 "WHERE (parent_1 = :p_1) AND (parent_2 = :p_2);");
818
8/25
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 5556 times.
✓ Branch 5 taken 80 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 80 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.
5636 DEFERRED_INITS(database);
819 5636 }
820
821
822 4145 bool SqlListing::BindPathHash(const struct shash::Md5 &hash) {
823 4145 return BindMd5(1, 2, hash);
824 }
825
826
827 //------------------------------------------------------------------------------
828
829
830 5636 SqlLookupPathHash::SqlLookupPathHash(const CatalogDatabase &database) {
831
28/62
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 5590 times.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 46 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 46 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 46 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 46 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 28 taken 46 times.
✓ Branch 29 taken 5590 times.
✓ Branch 31 taken 46 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 46 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 46 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 43 taken 46 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 46 times.
✗ Branch 47 not taken.
✓ Branch 56 taken 46 times.
✓ Branch 57 taken 5590 times.
✓ Branch 59 taken 46 times.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✓ Branch 63 taken 46 times.
✗ Branch 64 not taken.
✓ Branch 67 taken 46 times.
✗ Branch 68 not taken.
✓ Branch 71 taken 46 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 46 times.
✗ Branch 75 not taken.
✓ Branch 84 taken 46 times.
✓ Branch 85 taken 5590 times.
✓ Branch 87 taken 46 times.
✗ Branch 88 not taken.
✓ Branch 91 taken 46 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 46 times.
✗ Branch 96 not taken.
✓ Branch 99 taken 46 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 46 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.
5636 MAKE_STATEMENTS("SELECT @DB_FIELDS@ FROM catalog "
832 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
833
8/25
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 5556 times.
✓ Branch 5 taken 80 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 80 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.
5636 DEFERRED_INITS(database);
834 5636 }
835
836 25836 bool SqlLookupPathHash::BindPathHash(const struct shash::Md5 &hash) {
837 25836 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 3870 SqlDirentTouch::SqlDirentTouch(const CatalogDatabase &database) {
878
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 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 3870 }
890
891
892 160 bool SqlDirentTouch::BindDirentBase(const DirectoryEntryBase &entry) {
893
1/2
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
320 bool result = BindHashBlob(1, entry.checksum_) && BindInt64(2, entry.size_)
894
2/4
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 160 times.
✗ Branch 5 not taken.
160 && BindInt(3, entry.mode_) && BindInt64(4, entry.mtime_)
895
1/2
✓ Branch 3 taken 160 times.
✗ Branch 4 not taken.
160 && BindText(5, entry.name_.GetChars(), entry.name_.GetLength())
896
1/2
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
160 && BindText(6, entry.symlink_.GetChars(),
897 160 entry.symlink_.GetLength())
898
3/6
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 160 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 160 times.
✗ Branch 7 not taken.
320 && BindInt64(7, entry.uid_) && BindInt64(8, entry.gid_);
899
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
160 if (entry.HasMtimeNs()) {
900 result &= BindInt(10, entry.mtime_ns_);
901 } else {
902 160 result &= BindNull(10);
903 }
904 160 return result;
905 }
906
907
908 160 bool SqlDirentTouch::BindPathHash(const shash::Md5 &hash) {
909 160 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 160 bool SqlDirentTouch::BindXattrEmpty() { return BindNull(9); }
924
925
926 //------------------------------------------------------------------------------
927
928
929 5636 SqlNestedCatalogLookup::SqlNestedCatalogLookup(
930 5636 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 5636 if (database.IsEqualSchema(database.schema_version(), 2.5)
943
5/6
✓ Branch 0 taken 5556 times.
✓ Branch 1 taken 80 times.
✓ Branch 3 taken 5556 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5556 times.
✓ Branch 6 taken 80 times.
5636 && (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 80 } else if (database.IsEqualSchema(database.schema_version(), 2.5)
946
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 80 times.
80 && (database.schema_revision() >= 1)) {
947 DeferredInit(database.sqlite_db(), stmt_2_5_ge_1_lt_4);
948 } else {
949
2/2
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
80 if (database.IsEqualSchema(database.schema_version(), 0.9)) {
950
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_0_9);
951 } else {
952
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_2_5_lt_1);
953 }
954 }
955 5636 }
956
957
958 2384 bool SqlNestedCatalogLookup::BindSearchPath(const PathString &path) {
959 2384 return BindText(1, path.GetChars(), path.GetLength());
960 }
961
962
963 2305 shash::Any SqlNestedCatalogLookup::GetContentHash() const {
964
2/4
✓ Branch 2 taken 2305 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2305 times.
✗ Branch 6 not taken.
2305 const string hash = string(reinterpret_cast<const char *>(RetrieveText(0)));
965 2305 return (hash.empty())
966 ? shash::Any(shash::kAny)
967
4/6
✓ Branch 0 taken 1226 times.
✓ Branch 1 taken 1079 times.
✓ Branch 3 taken 1226 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1079 times.
✗ Branch 8 not taken.
4610 : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog);
968 2305 }
969
970
971 2305 uint64_t SqlNestedCatalogLookup::GetSize() const { return RetrieveInt64(1); }
972
973
974 //------------------------------------------------------------------------------
975
976
977 5636 SqlNestedCatalogListing::SqlNestedCatalogListing(
978 5636 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 5636 if (database.IsEqualSchema(database.schema_version(), 2.5)
991
5/6
✓ Branch 0 taken 5556 times.
✓ Branch 1 taken 80 times.
✓ Branch 3 taken 5556 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5556 times.
✓ Branch 6 taken 80 times.
5636 && (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 80 } else if (database.IsEqualSchema(database.schema_version(), 2.5)
994
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 80 times.
80 && (database.schema_revision() >= 1)) {
995 DeferredInit(database.sqlite_db(), stmt_2_5_ge_1_lt_4);
996 } else {
997
2/2
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
80 if (database.IsEqualSchema(database.schema_version(), 0.9)) {
998
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_0_9);
999 } else {
1000
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_2_5_lt_1);
1001 }
1002 }
1003 5636 }
1004
1005
1006 2116 PathString SqlNestedCatalogListing::GetPath() const {
1007 2116 const char *path = reinterpret_cast<const char *>(RetrieveText(0));
1008 2116 return PathString(path, strlen(path));
1009 }
1010
1011
1012 2116 shash::Any SqlNestedCatalogListing::GetContentHash() const {
1013
2/4
✓ Branch 2 taken 2116 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2116 times.
✗ Branch 6 not taken.
2116 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
1014 2116 return (hash.empty())
1015 ? shash::Any(shash::kAny)
1016
4/6
✓ Branch 0 taken 534 times.
✓ Branch 1 taken 1582 times.
✓ Branch 3 taken 534 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1582 times.
✗ Branch 8 not taken.
4232 : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog);
1017 2116 }
1018
1019
1020 2116 uint64_t SqlNestedCatalogListing::GetSize() const { return RetrieveInt64(2); }
1021
1022
1023 //------------------------------------------------------------------------------
1024
1025
1026 5636 SqlOwnNestedCatalogListing::SqlOwnNestedCatalogListing(
1027 5636 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 5636 if (database.IsEqualSchema(database.schema_version(), 2.5)
1037
5/6
✓ Branch 0 taken 5556 times.
✓ Branch 1 taken 80 times.
✓ Branch 3 taken 5556 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5556 times.
✓ Branch 6 taken 80 times.
5636 && (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 40 times.
✓ Branch 3 taken 40 times.
80 if (database.IsEqualSchema(database.schema_version(), 0.9)) {
1041
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_0_9);
1042 } else {
1043
2/4
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
40 DeferredInit(database.sqlite_db(), stmt_2_5_lt_1);
1044 }
1045 }
1046 5636 }
1047
1048
1049 188 PathString SqlOwnNestedCatalogListing::GetPath() const {
1050 188 const char *path = reinterpret_cast<const char *>(RetrieveText(0));
1051 188 return PathString(path, strlen(path));
1052 }
1053
1054
1055 188 shash::Any SqlOwnNestedCatalogListing::GetContentHash() const {
1056
2/4
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 188 times.
✗ Branch 6 not taken.
188 const string hash = string(reinterpret_cast<const char *>(RetrieveText(1)));
1057 188 return (hash.empty())
1058 ? shash::Any(shash::kAny)
1059
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 7 taken 188 times.
✗ Branch 8 not taken.
376 : shash::MkFromHexPtr(shash::HexPtr(hash), shash::kSuffixCatalog);
1060 188 }
1061
1062
1063 188 uint64_t SqlOwnNestedCatalogListing::GetSize() const {
1064 188 return RetrieveInt64(2);
1065 }
1066
1067
1068 //------------------------------------------------------------------------------
1069
1070
1071 6491 SqlDirentInsert::SqlDirentInsert(const CatalogDatabase &database) {
1072 12982 DeferredInit(
1073
2/4
✓ Branch 1 taken 6491 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6491 times.
✗ Branch 5 not taken.
6491 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 6491 }
1082
1083
1084 23052 bool SqlDirentInsert::BindPathHash(const shash::Md5 &hash) {
1085 23052 return BindMd5(1, 2, hash);
1086 }
1087
1088
1089 23052 bool SqlDirentInsert::BindParentPathHash(const shash::Md5 &hash) {
1090 23052 return BindMd5(3, 4, hash);
1091 }
1092
1093
1094 23052 bool SqlDirentInsert::BindDirent(const DirectoryEntry &entry) {
1095 23052 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 20431 bool SqlDirentInsert::BindXattrEmpty() { return BindNull(15); }
1110
1111
1112 //------------------------------------------------------------------------------
1113
1114
1115 3870 SqlDirentUpdate::SqlDirentUpdate(const CatalogDatabase &database) {
1116
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 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 3870 }
1128
1129
1130 8259 bool SqlDirentUpdate::BindPathHash(const shash::Md5 &hash) {
1131 8259 return BindMd5(12, 13, hash);
1132 }
1133
1134
1135 8259 bool SqlDirentUpdate::BindDirent(const DirectoryEntry &entry) {
1136 8259 return BindDirentFields(1, 8, 2, 3, 4, 11, 5, 6, 7, 9, 10, entry);
1137 }
1138
1139
1140 //------------------------------------------------------------------------------
1141
1142
1143 3870 SqlDirentUnlink::SqlDirentUnlink(const CatalogDatabase &database) {
1144
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 DeferredInit(database.sqlite_db(),
1145 "DELETE FROM catalog "
1146 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1147 3870 }
1148
1149 5536 bool SqlDirentUnlink::BindPathHash(const shash::Md5 &hash) {
1150 5536 return BindMd5(1, 2, hash);
1151 }
1152
1153
1154 //------------------------------------------------------------------------------
1155
1156
1157 3870 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 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 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 3870 }
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 3870 SqlChunkInsert::SqlChunkInsert(const CatalogDatabase &database) {
1184
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 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 3870 }
1189
1190
1191 408 bool SqlChunkInsert::BindPathHash(const shash::Md5 &hash) {
1192 408 return BindMd5(1, 2, hash);
1193 }
1194
1195
1196 408 bool SqlChunkInsert::BindFileChunk(const FileChunk &chunk) {
1197
1/2
✓ Branch 4 taken 408 times.
✗ Branch 5 not taken.
816 return BindInt64(3, chunk.offset()) && BindInt64(4, chunk.size())
1198
2/4
✓ Branch 0 taken 408 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 408 times.
✗ Branch 5 not taken.
816 && BindHashBlob(5, chunk.content_hash());
1199 }
1200
1201
1202 //------------------------------------------------------------------------------
1203
1204
1205 3870 SqlChunksRemove::SqlChunksRemove(const CatalogDatabase &database) {
1206
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 DeferredInit(database.sqlite_db(),
1207 "DELETE FROM chunks "
1208 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1209 3870 }
1210
1211
1212 bool SqlChunksRemove::BindPathHash(const shash::Md5 &hash) {
1213 return BindMd5(1, 2, hash);
1214 }
1215
1216
1217 //------------------------------------------------------------------------------
1218
1219
1220 5636 SqlChunksListing::SqlChunksListing(const CatalogDatabase &database) {
1221
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
5636 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 5636 }
1228
1229
1230 40 bool SqlChunksListing::BindPathHash(const shash::Md5 &hash) {
1231 40 return BindMd5(1, 2, hash);
1232 }
1233
1234
1235 40 FileChunk SqlChunksListing::GetFileChunk(
1236 const shash::Algorithms interpret_hash_as) const {
1237 return FileChunk(
1238 40 RetrieveHashBlob(2, interpret_hash_as, shash::kSuffixPartial),
1239 40 RetrieveInt64(0),
1240 80 RetrieveInt64(1));
1241 }
1242
1243
1244 //------------------------------------------------------------------------------
1245
1246
1247 3870 SqlChunksCount::SqlChunksCount(const CatalogDatabase &database) {
1248
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 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 3870 }
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 3870 SqlMaxHardlinkGroup::SqlMaxHardlinkGroup(const CatalogDatabase &database) {
1268
2/4
✓ Branch 1 taken 3870 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3870 times.
✗ Branch 5 not taken.
3870 DeferredInit(database.sqlite_db(), "SELECT max(hardlinks) FROM catalog;");
1269 3870 }
1270
1271
1272 123 uint32_t SqlMaxHardlinkGroup::GetMaxGroupId() const {
1273 123 return RetrieveInt64(0) >> 32;
1274 }
1275
1276
1277 //------------------------------------------------------------------------------
1278
1279
1280 9085 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 9005 times.
✓ Branch 2 taken 80 times.
9085 if (database.schema_version() >= 2.4 - CatalogDatabase::kSchemaEpsilon) {
1286 9005 compat_ = false;
1287
2/4
✓ Branch 1 taken 9005 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9005 times.
✗ Branch 5 not taken.
9005 DeferredInit(database.sqlite_db(), stmt_ge_2_4);
1288 } else {
1289 80 compat_ = true;
1290
2/4
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
80 DeferredInit(database.sqlite_db(), stmt_lt_2_4);
1291 }
1292 9085 }
1293
1294
1295 218040 bool SqlGetCounter::BindCounter(const std::string &counter) {
1296
2/2
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 216120 times.
218040 if (compat_)
1297 1920 return true;
1298 216120 return BindText(1, counter);
1299 }
1300
1301
1302 218040 uint64_t SqlGetCounter::GetCounter() const {
1303
2/2
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 216120 times.
218040 if (compat_)
1304 1920 return 0;
1305 216120 return RetrieveInt64(0);
1306 }
1307
1308
1309 //------------------------------------------------------------------------------
1310
1311
1312 3449 SqlUpdateCounter::SqlUpdateCounter(const CatalogDatabase &database) {
1313 6898 DeferredInit(
1314
2/4
✓ Branch 1 taken 3449 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3449 times.
✗ Branch 5 not taken.
3449 database.sqlite_db(),
1315 "UPDATE statistics SET value=value+:val WHERE counter=:counter;");
1316 3449 }
1317
1318
1319 82776 bool SqlUpdateCounter::BindCounter(const std::string &counter) {
1320 82776 return BindText(2, counter);
1321 }
1322
1323
1324 82776 bool SqlUpdateCounter::BindDelta(const int64_t delta) {
1325 82776 return BindInt64(1, delta);
1326 }
1327
1328
1329 //------------------------------------------------------------------------------
1330
1331
1332 3440 SqlCreateCounter::SqlCreateCounter(const CatalogDatabase &database) {
1333
2/4
✓ Branch 1 taken 3440 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3440 times.
✗ Branch 5 not taken.
3440 DeferredInit(database.sqlite_db(),
1334 "INSERT OR REPLACE INTO statistics (counter, value) "
1335 "VALUES (:counter, :value);");
1336 3440 }
1337
1338
1339 82560 bool SqlCreateCounter::BindCounter(const std::string &counter) {
1340 82560 return BindText(1, counter);
1341 }
1342
1343
1344 82560 bool SqlCreateCounter::BindInitialValue(const int64_t value) {
1345 82560 return BindInt64(2, value);
1346 }
1347
1348
1349 //------------------------------------------------------------------------------
1350
1351
1352 5636 SqlAllChunks::SqlAllChunks(const CatalogDatabase &database) {
1353 5636 const int hash_mask = 7 << SqlDirent::kFlagPosHash;
1354
3/6
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5636 times.
✗ Branch 8 not taken.
11272 const string flags2hash = " ((flags&" + StringifyInt(hash_mask) + ") >> "
1355
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
16908 + StringifyInt(SqlDirent::kFlagPosHash)
1356
1/2
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
5636 + ")+1 AS hash_algorithm ";
1357
1358 5636 const int compression_mask = 7 << SqlDirent::kFlagPosCompression;
1359
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
11272 const string flags2compression = " ((flags&" + StringifyInt(compression_mask)
1360
1/2
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
11272 + ") >> "
1361
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
16908 + StringifyInt(
1362 SqlDirent::kFlagPosCompression)
1363
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
11272 + ") " + "AS compression_algorithm ";
1364
1365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5636 times.
5636 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 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5636 times.
✗ Branch 8 not taken.
11272 + StringifyInt(SqlDirent::kFlagFile) + " THEN "
1376
4/8
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5636 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5636 times.
✗ Branch 11 not taken.
22544 + StringifyInt(shash::kSuffixNone) + " " + "WHEN flags & "
1377
3/6
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5636 times.
✗ Branch 8 not taken.
22544 + StringifyInt(SqlDirent::kFlagDir) + " THEN "
1378
3/6
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5636 times.
✗ Branch 8 not taken.
22544 + StringifyInt(shash::kSuffixMicroCatalog) + " END "
1379
4/8
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5636 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 5636 times.
✗ Branch 11 not taken.
11272 + "AS chunk_type, " + flags2hash + "," + flags2compression
1380
1/2
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
11272 + "FROM catalog WHERE (hash IS NOT NULL) AND "
1381 " (flags & "
1382
3/6
✓ Branch 0 taken 5636 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5636 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5636 times.
✗ Branch 7 not taken.
16908 + StringifyInt(SqlDirent::kFlagFileExternal |
1383 (g_ignore_legacy_bulk_hashes
1384 ? SqlDirent::kFlagFileChunk
1385
1/2
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
5636 : 0)) + " = 0)";
1386
2/2
✓ Branch 1 taken 5556 times.
✓ Branch 2 taken 80 times.
5636 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 5636 times.
✗ Branch 2 not taken.
5636 sql += ";";
1398
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
5636 Init(database.sqlite_db(), sql);
1399 5636 }
1400
1401
1402 82 bool SqlAllChunks::Open() { return true; }
1403
1404
1405 408 bool SqlAllChunks::Next(shash::Any *hash, zlib::Algorithms *compression_alg) {
1406
2/2
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 326 times.
408 if (!FetchRow()) {
1407 82 return false;
1408 }
1409
1410 326 *hash = RetrieveHashBlob(0, static_cast<shash::Algorithms>(RetrieveInt(2)),
1411 326 static_cast<shash::Suffix>(RetrieveInt(1)));
1412 326 *compression_alg = static_cast<zlib::Algorithms>(RetrieveInt(3));
1413 326 return true;
1414 }
1415
1416
1417 82 bool SqlAllChunks::Close() { return Reset(); }
1418
1419
1420 //------------------------------------------------------------------------------
1421
1422
1423 5636 SqlLookupXattrs::SqlLookupXattrs(const CatalogDatabase &database) {
1424
2/4
✓ Branch 1 taken 5636 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5636 times.
✗ Branch 5 not taken.
5636 DeferredInit(database.sqlite_db(),
1425 "SELECT xattr FROM catalog "
1426 "WHERE (md5path_1 = :md5_1) AND (md5path_2 = :md5_2);");
1427 5636 }
1428
1429
1430 40 bool SqlLookupXattrs::BindPathHash(const shash::Md5 &hash) {
1431 40 return BindMd5(1, 2, hash);
1432 }
1433
1434
1435 40 XattrList SqlLookupXattrs::GetXattrs() {
1436 const unsigned char *packed_xattrs = reinterpret_cast<const unsigned char *>(
1437
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 RetrieveBlob(0));
1438
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (packed_xattrs == NULL)
1439 40 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