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