GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/catalog_sql.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 439 584 75.2%
Branches: 539 1408 38.3%

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