├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── benches ├── my_benchmark.rs └── sizes.rs └── src ├── content.rs ├── content_address.rs ├── database.rs ├── datum_size.rs ├── error.rs ├── freemap.rs ├── index.rs ├── index_item.rs ├── lib.rs ├── metadata.rs ├── safe_database.rs ├── table.rs └── types.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.10" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" 8 | dependencies = [ 9 | "memchr", 10 | ] 11 | 12 | [[package]] 13 | name = "arrayref" 14 | version = "0.3.6" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" 17 | 18 | [[package]] 19 | name = "arrayvec" 20 | version = "0.4.12" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" 23 | dependencies = [ 24 | "nodrop", 25 | ] 26 | 27 | [[package]] 28 | name = "arrayvec" 29 | version = "0.5.1" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" 32 | 33 | [[package]] 34 | name = "atty" 35 | version = "0.2.14" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 38 | dependencies = [ 39 | "hermit-abi", 40 | "libc", 41 | "winapi", 42 | ] 43 | 44 | [[package]] 45 | name = "autocfg" 46 | version = "1.0.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 49 | 50 | [[package]] 51 | name = "base64" 52 | version = "0.11.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" 55 | 56 | [[package]] 57 | name = "bitflags" 58 | version = "1.2.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 61 | 62 | [[package]] 63 | name = "bitvec" 64 | version = "0.17.4" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" 67 | dependencies = [ 68 | "either", 69 | "radium", 70 | ] 71 | 72 | [[package]] 73 | name = "blake2-rfc" 74 | version = "0.2.18" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" 77 | dependencies = [ 78 | "arrayvec 0.4.12", 79 | "constant_time_eq", 80 | ] 81 | 82 | [[package]] 83 | name = "blake2b_simd" 84 | version = "0.5.10" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" 87 | dependencies = [ 88 | "arrayref", 89 | "arrayvec 0.5.1", 90 | "constant_time_eq", 91 | ] 92 | 93 | [[package]] 94 | name = "bstr" 95 | version = "0.2.12" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" 98 | dependencies = [ 99 | "lazy_static", 100 | "memchr", 101 | "regex-automata", 102 | "serde", 103 | ] 104 | 105 | [[package]] 106 | name = "bumpalo" 107 | version = "3.2.1" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" 110 | 111 | [[package]] 112 | name = "byte-slice-cast" 113 | version = "0.3.5" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" 116 | 117 | [[package]] 118 | name = "byteorder" 119 | version = "1.3.4" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 122 | 123 | [[package]] 124 | name = "cast" 125 | version = "0.2.3" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" 128 | dependencies = [ 129 | "rustc_version", 130 | ] 131 | 132 | [[package]] 133 | name = "cfg-if" 134 | version = "0.1.10" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 137 | 138 | [[package]] 139 | name = "chrono" 140 | version = "0.4.11" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" 143 | dependencies = [ 144 | "num-integer", 145 | "num-traits", 146 | "time", 147 | ] 148 | 149 | [[package]] 150 | name = "clap" 151 | version = "2.33.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 154 | dependencies = [ 155 | "bitflags", 156 | "textwrap", 157 | "unicode-width", 158 | ] 159 | 160 | [[package]] 161 | name = "cloudabi" 162 | version = "0.0.3" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 165 | dependencies = [ 166 | "bitflags", 167 | ] 168 | 169 | [[package]] 170 | name = "constant_time_eq" 171 | version = "0.1.5" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" 174 | 175 | [[package]] 176 | name = "criterion" 177 | version = "0.3.1" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" 180 | dependencies = [ 181 | "atty", 182 | "cast", 183 | "clap", 184 | "criterion-plot", 185 | "csv", 186 | "itertools", 187 | "lazy_static", 188 | "num-traits", 189 | "oorandom", 190 | "plotters", 191 | "rayon", 192 | "regex", 193 | "serde", 194 | "serde_derive", 195 | "serde_json", 196 | "tinytemplate", 197 | "walkdir", 198 | ] 199 | 200 | [[package]] 201 | name = "criterion-plot" 202 | version = "0.4.1" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" 205 | dependencies = [ 206 | "cast", 207 | "itertools", 208 | ] 209 | 210 | [[package]] 211 | name = "crossbeam-deque" 212 | version = "0.7.3" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" 215 | dependencies = [ 216 | "crossbeam-epoch", 217 | "crossbeam-utils", 218 | "maybe-uninit", 219 | ] 220 | 221 | [[package]] 222 | name = "crossbeam-epoch" 223 | version = "0.8.2" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" 226 | dependencies = [ 227 | "autocfg", 228 | "cfg-if", 229 | "crossbeam-utils", 230 | "lazy_static", 231 | "maybe-uninit", 232 | "memoffset", 233 | "scopeguard", 234 | ] 235 | 236 | [[package]] 237 | name = "crossbeam-queue" 238 | version = "0.2.1" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" 241 | dependencies = [ 242 | "cfg-if", 243 | "crossbeam-utils", 244 | ] 245 | 246 | [[package]] 247 | name = "crossbeam-utils" 248 | version = "0.7.2" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" 251 | dependencies = [ 252 | "autocfg", 253 | "cfg-if", 254 | "lazy_static", 255 | ] 256 | 257 | [[package]] 258 | name = "csv" 259 | version = "1.1.3" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" 262 | dependencies = [ 263 | "bstr", 264 | "csv-core", 265 | "itoa", 266 | "ryu", 267 | "serde", 268 | ] 269 | 270 | [[package]] 271 | name = "csv-core" 272 | version = "0.1.10" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" 275 | dependencies = [ 276 | "memchr", 277 | ] 278 | 279 | [[package]] 280 | name = "derive_more" 281 | version = "0.99.5" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "e2323f3f47db9a0e77ce7a300605d8d2098597fc451ed1a97bb1f6411bb550a7" 284 | dependencies = [ 285 | "proc-macro2", 286 | "quote", 287 | "syn", 288 | ] 289 | 290 | [[package]] 291 | name = "dirs" 292 | version = "2.0.2" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" 295 | dependencies = [ 296 | "cfg-if", 297 | "dirs-sys", 298 | ] 299 | 300 | [[package]] 301 | name = "dirs-sys" 302 | version = "0.3.4" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" 305 | dependencies = [ 306 | "cfg-if", 307 | "libc", 308 | "redox_users", 309 | "winapi", 310 | ] 311 | 312 | [[package]] 313 | name = "either" 314 | version = "1.5.3" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" 317 | 318 | [[package]] 319 | name = "env_logger" 320 | version = "0.7.1" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 323 | dependencies = [ 324 | "atty", 325 | "humantime", 326 | "log", 327 | "regex", 328 | "termcolor", 329 | ] 330 | 331 | [[package]] 332 | name = "getrandom" 333 | version = "0.1.14" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" 336 | dependencies = [ 337 | "cfg-if", 338 | "libc", 339 | "wasi", 340 | ] 341 | 342 | [[package]] 343 | name = "hash-db" 344 | version = "0.15.2" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" 347 | 348 | [[package]] 349 | name = "hermit-abi" 350 | version = "0.1.10" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" 353 | dependencies = [ 354 | "libc", 355 | ] 356 | 357 | [[package]] 358 | name = "hex" 359 | version = "0.4.2" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" 362 | 363 | [[package]] 364 | name = "humantime" 365 | version = "1.3.0" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" 368 | dependencies = [ 369 | "quick-error", 370 | ] 371 | 372 | [[package]] 373 | name = "impl-trait-for-tuples" 374 | version = "0.1.3" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" 377 | dependencies = [ 378 | "proc-macro2", 379 | "quote", 380 | "syn", 381 | ] 382 | 383 | [[package]] 384 | name = "itertools" 385 | version = "0.8.2" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" 388 | dependencies = [ 389 | "either", 390 | ] 391 | 392 | [[package]] 393 | name = "itoa" 394 | version = "0.4.5" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 397 | 398 | [[package]] 399 | name = "js-sys" 400 | version = "0.3.37" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" 403 | dependencies = [ 404 | "wasm-bindgen", 405 | ] 406 | 407 | [[package]] 408 | name = "kvdb" 409 | version = "0.5.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "cad096c6849b2ef027fabe35c4aed356d0e3d3f586d0a8361e5e17f1e50a7ce5" 412 | dependencies = [ 413 | "parity-util-mem", 414 | "smallvec", 415 | ] 416 | 417 | [[package]] 418 | name = "lazy_static" 419 | version = "1.4.0" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 422 | 423 | [[package]] 424 | name = "libc" 425 | version = "0.2.68" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" 428 | 429 | [[package]] 430 | name = "lock_api" 431 | version = "0.3.3" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" 434 | dependencies = [ 435 | "scopeguard", 436 | ] 437 | 438 | [[package]] 439 | name = "log" 440 | version = "0.4.8" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 443 | dependencies = [ 444 | "cfg-if", 445 | ] 446 | 447 | [[package]] 448 | name = "maybe-uninit" 449 | version = "2.0.0" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 452 | 453 | [[package]] 454 | name = "memchr" 455 | version = "2.3.3" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" 458 | 459 | [[package]] 460 | name = "memmap" 461 | version = "0.7.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" 464 | dependencies = [ 465 | "libc", 466 | "winapi", 467 | ] 468 | 469 | [[package]] 470 | name = "memoffset" 471 | version = "0.5.4" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" 474 | dependencies = [ 475 | "autocfg", 476 | ] 477 | 478 | [[package]] 479 | name = "nodrop" 480 | version = "0.1.14" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" 483 | 484 | [[package]] 485 | name = "num-integer" 486 | version = "0.1.42" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" 489 | dependencies = [ 490 | "autocfg", 491 | "num-traits", 492 | ] 493 | 494 | [[package]] 495 | name = "num-traits" 496 | version = "0.2.11" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" 499 | dependencies = [ 500 | "autocfg", 501 | ] 502 | 503 | [[package]] 504 | name = "num_cpus" 505 | version = "1.12.0" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" 508 | dependencies = [ 509 | "hermit-abi", 510 | "libc", 511 | ] 512 | 513 | [[package]] 514 | name = "oorandom" 515 | version = "11.1.0" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" 518 | 519 | [[package]] 520 | name = "parity-scale-codec" 521 | version = "1.3.0" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "329c8f7f4244ddb5c37c103641027a76c530e65e8e4b8240b29f81ea40508b17" 524 | dependencies = [ 525 | "arrayvec 0.5.1", 526 | "bitvec", 527 | "byte-slice-cast", 528 | "parity-scale-codec-derive", 529 | "serde", 530 | ] 531 | 532 | [[package]] 533 | name = "parity-scale-codec-derive" 534 | version = "1.2.0" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "5a0ec292e92e8ec7c58e576adacc1e3f399c597c8f263c42f18420abe58e7245" 537 | dependencies = [ 538 | "proc-macro-crate", 539 | "proc-macro2", 540 | "quote", 541 | "syn", 542 | ] 543 | 544 | [[package]] 545 | name = "parity-util-mem" 546 | version = "0.6.0" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "6e42755f26e5ea21a6a819d9e63cbd70713e9867a2b767ec2cc65ca7659532c5" 549 | dependencies = [ 550 | "cfg-if", 551 | "impl-trait-for-tuples", 552 | "parity-util-mem-derive", 553 | "winapi", 554 | ] 555 | 556 | [[package]] 557 | name = "parity-util-mem-derive" 558 | version = "0.1.0" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" 561 | dependencies = [ 562 | "proc-macro2", 563 | "syn", 564 | "synstructure", 565 | ] 566 | 567 | [[package]] 568 | name = "parking_lot" 569 | version = "0.10.0" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" 572 | dependencies = [ 573 | "lock_api", 574 | "parking_lot_core", 575 | ] 576 | 577 | [[package]] 578 | name = "parking_lot_core" 579 | version = "0.7.0" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" 582 | dependencies = [ 583 | "cfg-if", 584 | "cloudabi", 585 | "libc", 586 | "redox_syscall", 587 | "smallvec", 588 | "winapi", 589 | ] 590 | 591 | [[package]] 592 | name = "plotters" 593 | version = "0.2.12" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" 596 | dependencies = [ 597 | "js-sys", 598 | "num-traits", 599 | "wasm-bindgen", 600 | "web-sys", 601 | ] 602 | 603 | [[package]] 604 | name = "ppv-lite86" 605 | version = "0.2.6" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" 608 | 609 | [[package]] 610 | name = "pretty_env_logger" 611 | version = "0.4.0" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" 614 | dependencies = [ 615 | "env_logger", 616 | "log", 617 | ] 618 | 619 | [[package]] 620 | name = "proc-macro-crate" 621 | version = "0.1.4" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" 624 | dependencies = [ 625 | "toml", 626 | ] 627 | 628 | [[package]] 629 | name = "proc-macro2" 630 | version = "1.0.9" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" 633 | dependencies = [ 634 | "unicode-xid", 635 | ] 636 | 637 | [[package]] 638 | name = "quick-error" 639 | version = "1.2.3" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 642 | 643 | [[package]] 644 | name = "quote" 645 | version = "1.0.3" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" 648 | dependencies = [ 649 | "proc-macro2", 650 | ] 651 | 652 | [[package]] 653 | name = "radium" 654 | version = "0.3.0" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" 657 | 658 | [[package]] 659 | name = "rand" 660 | version = "0.7.3" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 663 | dependencies = [ 664 | "getrandom", 665 | "libc", 666 | "rand_chacha", 667 | "rand_core", 668 | "rand_hc", 669 | ] 670 | 671 | [[package]] 672 | name = "rand_chacha" 673 | version = "0.2.2" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 676 | dependencies = [ 677 | "ppv-lite86", 678 | "rand_core", 679 | ] 680 | 681 | [[package]] 682 | name = "rand_core" 683 | version = "0.5.1" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 686 | dependencies = [ 687 | "getrandom", 688 | ] 689 | 690 | [[package]] 691 | name = "rand_hc" 692 | version = "0.2.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 695 | dependencies = [ 696 | "rand_core", 697 | ] 698 | 699 | [[package]] 700 | name = "rayon" 701 | version = "1.3.0" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" 704 | dependencies = [ 705 | "crossbeam-deque", 706 | "either", 707 | "rayon-core", 708 | ] 709 | 710 | [[package]] 711 | name = "rayon-core" 712 | version = "1.7.0" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" 715 | dependencies = [ 716 | "crossbeam-deque", 717 | "crossbeam-queue", 718 | "crossbeam-utils", 719 | "lazy_static", 720 | "num_cpus", 721 | ] 722 | 723 | [[package]] 724 | name = "redox_syscall" 725 | version = "0.1.56" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 728 | 729 | [[package]] 730 | name = "redox_users" 731 | version = "0.3.4" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" 734 | dependencies = [ 735 | "getrandom", 736 | "redox_syscall", 737 | "rust-argon2", 738 | ] 739 | 740 | [[package]] 741 | name = "regex" 742 | version = "1.3.6" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" 745 | dependencies = [ 746 | "aho-corasick", 747 | "memchr", 748 | "regex-syntax", 749 | "thread_local", 750 | ] 751 | 752 | [[package]] 753 | name = "regex-automata" 754 | version = "0.1.9" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" 757 | dependencies = [ 758 | "byteorder", 759 | ] 760 | 761 | [[package]] 762 | name = "regex-syntax" 763 | version = "0.6.17" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" 766 | 767 | [[package]] 768 | name = "remove_dir_all" 769 | version = "0.5.2" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" 772 | dependencies = [ 773 | "winapi", 774 | ] 775 | 776 | [[package]] 777 | name = "rust-argon2" 778 | version = "0.7.0" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" 781 | dependencies = [ 782 | "base64", 783 | "blake2b_simd", 784 | "constant_time_eq", 785 | "crossbeam-utils", 786 | ] 787 | 788 | [[package]] 789 | name = "rustc_version" 790 | version = "0.2.3" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 793 | dependencies = [ 794 | "semver", 795 | ] 796 | 797 | [[package]] 798 | name = "ryu" 799 | version = "1.0.3" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" 802 | 803 | [[package]] 804 | name = "same-file" 805 | version = "1.0.6" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 808 | dependencies = [ 809 | "winapi-util", 810 | ] 811 | 812 | [[package]] 813 | name = "scopeguard" 814 | version = "1.1.0" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 817 | 818 | [[package]] 819 | name = "semver" 820 | version = "0.9.0" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 823 | dependencies = [ 824 | "semver-parser", 825 | ] 826 | 827 | [[package]] 828 | name = "semver-parser" 829 | version = "0.7.0" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 832 | 833 | [[package]] 834 | name = "serde" 835 | version = "1.0.105" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" 838 | 839 | [[package]] 840 | name = "serde_derive" 841 | version = "1.0.105" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" 844 | dependencies = [ 845 | "proc-macro2", 846 | "quote", 847 | "syn", 848 | ] 849 | 850 | [[package]] 851 | name = "serde_json" 852 | version = "1.0.50" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" 855 | dependencies = [ 856 | "itoa", 857 | "ryu", 858 | "serde", 859 | ] 860 | 861 | [[package]] 862 | name = "simplelog" 863 | version = "0.7.5" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "bcacac97349a890d437921dfb23cbec52ab5b4752551cb637df2721371acd467" 866 | dependencies = [ 867 | "chrono", 868 | "log", 869 | "term", 870 | ] 871 | 872 | [[package]] 873 | name = "smallvec" 874 | version = "1.2.0" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" 877 | 878 | [[package]] 879 | name = "sp-database" 880 | version = "2.0.0-alpha.5" 881 | source = "git+https://github.com/paritytech/substrate?branch=gav-db-trait#ad4b0107357454075e39a829ac719c9f858f1c08" 882 | dependencies = [ 883 | "kvdb", 884 | "parking_lot", 885 | ] 886 | 887 | [[package]] 888 | name = "subdb" 889 | version = "0.1.0" 890 | dependencies = [ 891 | "blake2-rfc", 892 | "criterion", 893 | "derive_more", 894 | "hash-db", 895 | "hex", 896 | "log", 897 | "memmap", 898 | "parity-scale-codec", 899 | "parking_lot", 900 | "pretty_env_logger", 901 | "simplelog", 902 | "smallvec", 903 | "sp-database", 904 | "tempfile", 905 | "twox-hash", 906 | ] 907 | 908 | [[package]] 909 | name = "syn" 910 | version = "1.0.17" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" 913 | dependencies = [ 914 | "proc-macro2", 915 | "quote", 916 | "unicode-xid", 917 | ] 918 | 919 | [[package]] 920 | name = "synstructure" 921 | version = "0.12.3" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" 924 | dependencies = [ 925 | "proc-macro2", 926 | "quote", 927 | "syn", 928 | "unicode-xid", 929 | ] 930 | 931 | [[package]] 932 | name = "tempfile" 933 | version = "3.1.0" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" 936 | dependencies = [ 937 | "cfg-if", 938 | "libc", 939 | "rand", 940 | "redox_syscall", 941 | "remove_dir_all", 942 | "winapi", 943 | ] 944 | 945 | [[package]] 946 | name = "term" 947 | version = "0.6.1" 948 | source = "registry+https://github.com/rust-lang/crates.io-index" 949 | checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" 950 | dependencies = [ 951 | "dirs", 952 | "winapi", 953 | ] 954 | 955 | [[package]] 956 | name = "termcolor" 957 | version = "1.1.0" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" 960 | dependencies = [ 961 | "winapi-util", 962 | ] 963 | 964 | [[package]] 965 | name = "textwrap" 966 | version = "0.11.0" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 969 | dependencies = [ 970 | "unicode-width", 971 | ] 972 | 973 | [[package]] 974 | name = "thread_local" 975 | version = "1.0.1" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" 978 | dependencies = [ 979 | "lazy_static", 980 | ] 981 | 982 | [[package]] 983 | name = "time" 984 | version = "0.1.42" 985 | source = "registry+https://github.com/rust-lang/crates.io-index" 986 | checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 987 | dependencies = [ 988 | "libc", 989 | "redox_syscall", 990 | "winapi", 991 | ] 992 | 993 | [[package]] 994 | name = "tinytemplate" 995 | version = "1.0.3" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" 998 | dependencies = [ 999 | "serde", 1000 | "serde_json", 1001 | ] 1002 | 1003 | [[package]] 1004 | name = "toml" 1005 | version = "0.5.6" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" 1008 | dependencies = [ 1009 | "serde", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "twox-hash" 1014 | version = "1.5.0" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" 1017 | dependencies = [ 1018 | "rand", 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "unicode-width" 1023 | version = "0.1.7" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" 1026 | 1027 | [[package]] 1028 | name = "unicode-xid" 1029 | version = "0.2.0" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 1032 | 1033 | [[package]] 1034 | name = "walkdir" 1035 | version = "2.3.1" 1036 | source = "registry+https://github.com/rust-lang/crates.io-index" 1037 | checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" 1038 | dependencies = [ 1039 | "same-file", 1040 | "winapi", 1041 | "winapi-util", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "wasi" 1046 | version = "0.9.0+wasi-snapshot-preview1" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 1049 | 1050 | [[package]] 1051 | name = "wasm-bindgen" 1052 | version = "0.2.60" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" 1055 | dependencies = [ 1056 | "cfg-if", 1057 | "wasm-bindgen-macro", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "wasm-bindgen-backend" 1062 | version = "0.2.60" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" 1065 | dependencies = [ 1066 | "bumpalo", 1067 | "lazy_static", 1068 | "log", 1069 | "proc-macro2", 1070 | "quote", 1071 | "syn", 1072 | "wasm-bindgen-shared", 1073 | ] 1074 | 1075 | [[package]] 1076 | name = "wasm-bindgen-macro" 1077 | version = "0.2.60" 1078 | source = "registry+https://github.com/rust-lang/crates.io-index" 1079 | checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" 1080 | dependencies = [ 1081 | "quote", 1082 | "wasm-bindgen-macro-support", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "wasm-bindgen-macro-support" 1087 | version = "0.2.60" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" 1090 | dependencies = [ 1091 | "proc-macro2", 1092 | "quote", 1093 | "syn", 1094 | "wasm-bindgen-backend", 1095 | "wasm-bindgen-shared", 1096 | ] 1097 | 1098 | [[package]] 1099 | name = "wasm-bindgen-shared" 1100 | version = "0.2.60" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" 1103 | 1104 | [[package]] 1105 | name = "web-sys" 1106 | version = "0.3.37" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" 1109 | dependencies = [ 1110 | "js-sys", 1111 | "wasm-bindgen", 1112 | ] 1113 | 1114 | [[package]] 1115 | name = "winapi" 1116 | version = "0.3.8" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 1119 | dependencies = [ 1120 | "winapi-i686-pc-windows-gnu", 1121 | "winapi-x86_64-pc-windows-gnu", 1122 | ] 1123 | 1124 | [[package]] 1125 | name = "winapi-i686-pc-windows-gnu" 1126 | version = "0.4.0" 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" 1128 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1129 | 1130 | [[package]] 1131 | name = "winapi-util" 1132 | version = "0.1.3" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" 1135 | dependencies = [ 1136 | "winapi", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "winapi-x86_64-pc-windows-gnu" 1141 | version = "0.4.0" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1144 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "subdb" 3 | version = "0.1.0" 4 | authors = ["Gav Wood "] 5 | edition = "2018" 6 | license = "Apache-2.0" 7 | homepage = "https://substrate.dev" 8 | repository = "https://github.com/paritytech/subdb/" 9 | description = "Experimental database for cryptographic structures." 10 | documentation = "https://docs.rs/subdb" 11 | 12 | [dependencies] 13 | memmap = "0.7.0" 14 | parity-scale-codec = { version = "1.3.0", features = [ "derive" ] } 15 | blake2-rfc = "0.2.18" 16 | smallvec = "1.2.0" 17 | hex = "0.4.2" 18 | log = "0.4.8" 19 | pretty_env_logger = "0.4.0" 20 | derive_more = "0.99.5" 21 | simplelog = "^0.7.4" 22 | twox-hash = "1.5.0" 23 | hash-db = "0.15.2" 24 | parking_lot = "0.10.0" 25 | sp-database = { version = "2.0.0-alpha.5", git = "https://github.com/paritytech/substrate", branch = "gav-db-trait" } 26 | 27 | [dev-dependencies] 28 | criterion = "0.3.1" 29 | tempfile = "3" 30 | 31 | [[bench]] 32 | name = "my_benchmark" 33 | harness = false -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `subdb` - Substrate Database 2 | ### An experimental domain-specific database for Substrate 3 | 4 | ## Domain 5 | 6 | `subdb` is a database designed for use with the Substrate Modified Merkle Patricia Tree ("trie"). Rather than a "normal" flat key/value database, `subdb` makes two requirements on keys: 7 | 8 | - Uniform entropy distribution. 9 | - Same size. 10 | 11 | This is fine if you know your keys are the output of a cryptographic hasher, but otherwise perhaps not super useful. 12 | 13 | Furthermore the design is made to be optimal over certain distribution of sizes of values: 14 | 15 | - At least 32 bytes. 16 | - Majority of values of size 32 bytes to around 512-544 bytes, with many sharing the same size. 17 | - Minority of values up to 1MB, with clusters sharing roughly the same size exponentially more likely at the lower end. 18 | - Small numbers of values occasionally found beyond 1MB in size. 19 | 20 | In addition, it supports reference counting on the datagrams stored (allowing each item to be interested and removed multiple times with subsequent insertions and their corresponding removals being fast). 21 | 22 | Eventually, it aims to support value links, allowing for each value to have a number of "friend" values, which are stored with it and may be looked-up faster than by using just their hash. This is particularly useful for cryptographic-hash-linked structures such as a Merkle trees and DAGs. 23 | 24 | The minimum working size for a `subdb` database instance is currently 400-500 MB (though there are plans to reduce this), and this can be used to store up to around 1 million key/values if the size distribution is optimal. After this the database will grow as needed. No compression is used, but it is designed to be a fairly compact layout with minimal overhead per key/value pair; it should typically be only 11 additional bytes storage footprint per item stored. It is assumed that hosts will have a sufficient amount of free physical memory to keep the database in memory at once and the disk backing is used only for persistence. 25 | 26 | It is designed to be fairly fast to fetch keys by hash and to insert and remove values. In almost all cases, finding, insertion and removal will require just two random access operations; one of them into a 128MB memory-mapped index file and the other into a 2MB mem-mapped content file. Furthermore, it is designed to be twice as fast to fetch data if the address is already known (e.g. because it is stored alongside a referencing entry) as the first 128MB index lookup can be avoided, reducing it to a single access. Insertion and removal requires a third fixed-location access also, however since it is likely held in processor cache when under load, it's unlikely to affect performance. 27 | 28 | ## Architecture 29 | 30 | Sub-DB is formed as a database with only two component types: A single index table and a set of storage tables. 31 | 32 | ### Index Table 33 | 34 | The index table is used exclusively as a means of looking up a key to get an address. It is implemented as a giant hash table, using the first bits of the key as an index. Entries store some additional key material to minimise the chance of inappropriate accidental content-lookup; usually this is 1 or 2 bytes. 35 | 36 | They also store an 8-bit `skipped_count` which tracks the total number of times the item has been skipped over (if non-zero, then lookups must assume a collision happened on the entry and continue onto the next entry in their search), an `occupied` flag (the MSB of the very first byte) and a 15-bit `index_correction` which offsets the entry's index to give the primary index point (this is only non-zero if there was a collision and the non-primary slot had to be used). 37 | 38 | In addition to this, a 32-byte *content address* is stored which pinpoints the actual data (the database currently has a hard limit of around 4 billion individual items that it can store). This has three components: the *datum size*, the *storage table index* and the *storage table entry index*. 39 | 40 | Of this 32-bit value, the first 6 bits is the value's *datum size*, encoded in a special logarithmic `DatumSize` format allowing for size precision to be distributed in an optimal way. 41 | 42 | The other 26-bits are split between *storage table index* (a unique storage table can be found by combining the `DatumSize` and the this) and the *storage table entry index* (which can identify a specific datum within a storage table). These are split depending on *datum size*, with smaller sizes having more bits dedicated to the *entry index*. The highest sizes have no bits dedicated to the *entry index* at all as their tables have only single entry. 43 | 44 | Overall, assuming a 4 byte total key size and at least 24 bits of those used for the index, then entries will be 8 bytes. 45 | 46 | ### Storage Tables 47 | 48 | The storage tables come in two flavours: fixed size and oversize. Currently, data items over around 100 KB are considered oversize. Oversize tables are just a file containing a reference count, and a key (in full) as well as its corresponding value. 49 | 50 | Fixed size tables are really just heap slabs with a bump allocator. A simple free list linked-list is maintained for allocated items that have since been freed. Each allocated item has a reference count, as well as its key in full and its value. Since items are fixed size, and since tables are held in memory as a reference, knowing an item's address is enough to get a reference to it without any further I/O. 51 | -------------------------------------------------------------------------------- /benches/my_benchmark.rs: -------------------------------------------------------------------------------- 1 | use std::hash::Hasher; 2 | use parity_scale_codec::{Encode, Decode}; 3 | use criterion::{Criterion, criterion_group, criterion_main, BatchSize}; 4 | use subdb::{Options, KeyType}; 5 | use twox_hash::XxHash64; 6 | 7 | mod sizes; 8 | 9 | #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode, Debug)] 10 | struct Xx256([u8; 32]); 11 | 12 | impl KeyType for Xx256 { 13 | const SIZE: usize = 32; 14 | fn from_data(data: &[u8]) -> Self { 15 | let mut key = [0u8; 32]; 16 | let mut h = XxHash64::with_seed(0); 17 | h.write(data); 18 | let r = h.finish(); 19 | key[..8].copy_from_slice(&r.to_le_bytes()); 20 | key[8..16].copy_from_slice(&r.to_le_bytes()); 21 | key[16..24].copy_from_slice(&r.to_le_bytes()); 22 | key[24..].copy_from_slice(&r.to_le_bytes()); 23 | Self(key) 24 | } 25 | } 26 | impl AsRef<[u8]> for Xx256 { 27 | fn as_ref(&self) -> &[u8] { &self.0 } 28 | } 29 | impl AsMut<[u8]> for Xx256 { 30 | fn as_mut(&mut self) -> &mut [u8] { &mut self.0 } 31 | } 32 | 33 | fn criterion_benchmark(c: &mut Criterion) { 34 | let keys = (0..1_000).map(|i| { 35 | let data = format!("This is a fairly long string with a unique value at the end of {}", i); 36 | let key = <[u8; 32]>::from_data(data.as_bytes()); 37 | (data.into_bytes(), key) 38 | }).collect::>(); 39 | 40 | let new_db_with_index = |index_bits| { 41 | let path = tempfile::TempDir::new().unwrap(); 42 | let db = Options::new() 43 | .key_bytes(4) 44 | .index_bits(index_bits) 45 | .path(path.as_ref().to_path_buf()) 46 | .open::<[u8; 32]>() 47 | .unwrap(); 48 | (path, db) 49 | }; 50 | let new_db = || new_db_with_index(24); 51 | 52 | c.bench_function("insert-1k", |b| { 53 | b.iter_batched(|| new_db(), |(_, mut db)| { 54 | for (ref data, ref k) in keys.iter() { 55 | db.insert(data.as_ref(), Some(k.clone())); 56 | } 57 | }, BatchSize::LargeInput) 58 | }); 59 | 60 | c.bench_function("insert-1k-12bit", |b| { 61 | b.iter_batched(|| new_db_with_index(12), |(_, mut db)| { 62 | for (ref data, ref k) in keys.iter() { 63 | db.insert(data.as_ref(), Some(k.clone())); 64 | } 65 | }, BatchSize::LargeInput) 66 | }); 67 | 68 | c.bench_function("insert-1k-13bit", |b| { 69 | b.iter_batched(|| new_db_with_index(13), |(_, mut db)| { 70 | for (ref data, ref k) in keys.iter() { 71 | db.insert(data.as_ref(), Some(k.clone())); 72 | } 73 | }, BatchSize::LargeInput) 74 | }); 75 | 76 | c.bench_function("insert-1k-14bit", |b| { 77 | b.iter_batched(|| new_db_with_index(14), |(_, mut db)| { 78 | for (ref data, ref k) in keys.iter() { 79 | db.insert(data.as_ref(), Some(k.clone())); 80 | } 81 | }, BatchSize::LargeInput) 82 | }); 83 | 84 | c.bench_function("insert-1k-16bit", |b| { 85 | b.iter_batched(|| new_db_with_index(16), |(_, mut db)| { 86 | for (ref data, ref k) in keys.iter() { 87 | db.insert(data.as_ref(), Some(k.clone())); 88 | } 89 | }, BatchSize::LargeInput) 90 | }); 91 | 92 | c.bench_function("insert-1k-18bit", |b| { 93 | b.iter_batched(|| new_db_with_index(18), |(_, mut db)| { 94 | for (ref data, ref k) in keys.iter() { 95 | db.insert(data.as_ref(), Some(k.clone())); 96 | } 97 | }, BatchSize::LargeInput) 98 | }); 99 | 100 | c.bench_function("insert-1k-20bit", |b| { 101 | b.iter_batched(|| new_db_with_index(20), |(_, mut db)| { 102 | for (ref data, ref k) in keys.iter() { 103 | db.insert(data.as_ref(), Some(k.clone())); 104 | } 105 | }, BatchSize::LargeInput) 106 | }); 107 | 108 | c.bench_function("insert-1k-21bit", |b| { 109 | b.iter_batched(|| new_db_with_index(21), |(_, mut db)| { 110 | for (ref data, ref k) in keys.iter() { 111 | db.insert(data.as_ref(), Some(k.clone())); 112 | } 113 | }, BatchSize::LargeInput) 114 | }); 115 | 116 | c.bench_function("insert-1k-22bit", |b| { 117 | b.iter_batched(|| new_db_with_index(22), |(_, mut db)| { 118 | for (ref data, ref k) in keys.iter() { 119 | db.insert(data.as_ref(), Some(k.clone())); 120 | } 121 | }, BatchSize::LargeInput) 122 | }); 123 | 124 | c.bench_function("remove-1k", |b| { 125 | b.iter_batched(|| { 126 | let (path, mut db) = new_db(); 127 | for (ref data, ref k) in keys.iter() { 128 | db.insert(data.as_ref(), Some(k.clone())); 129 | } 130 | (path, db) 131 | }, |(_, mut db)| { 132 | for (_, ref k) in keys.iter() { 133 | db.remove(k).unwrap(); 134 | } 135 | }, BatchSize::LargeInput) 136 | }); 137 | 138 | c.bench_function("bump-1k", |b| { 139 | b.iter_batched(|| { 140 | let (path, mut db) = new_db(); 141 | for (ref data, ref k) in keys.iter() { 142 | db.insert(data.as_ref(), Some(k.clone())); 143 | } 144 | (path, db) 145 | }, |(_, mut db)| { 146 | for (ref data, ref k) in keys.iter() { 147 | db.insert(data.as_ref(), Some(k.clone())); 148 | } 149 | }, BatchSize::LargeInput) 150 | }); 151 | 152 | c.bench_function("unbump-1k", |b| { 153 | b.iter_batched(|| { 154 | let (path, mut db) = new_db(); 155 | for (ref data, ref k) in keys.iter() { 156 | db.insert(data.as_ref(), Some(k.clone())); 157 | db.insert(data.as_ref(), Some(k.clone())); 158 | } 159 | (path, db) 160 | }, |(_, mut db)| { 161 | for (_, ref k) in keys.iter() { 162 | db.remove(k).unwrap(); 163 | } 164 | }, BatchSize::LargeInput) 165 | }); 166 | } 167 | 168 | criterion_group!{ 169 | name = benches; 170 | config = Criterion::default().sample_size(10); 171 | targets = criterion_benchmark 172 | } 173 | criterion_main!(benches); -------------------------------------------------------------------------------- /benches/sizes.rs: -------------------------------------------------------------------------------- 1 | /// Kusama value size distribution 2 | pub const KUSAMA_SIZES: &'static[(u32, u32)] = &[ 3 | (32, 35), 4 | (33, 20035), 5 | (34, 5369), 6 | (35, 184), 7 | (36, 54599), 8 | (37, 1515056), 9 | (38, 885), 10 | (39, 69965), 11 | (41, 210754), 12 | (42, 467), 13 | (43, 3241), 14 | (44, 32660), 15 | (45, 231141), 16 | (46, 220016), 17 | (47, 248931), 18 | (48, 157232), 19 | (49, 143236), 20 | (50, 2428), 21 | (51, 1476159), 22 | (52, 31), 23 | (53, 112), 24 | (54, 711), 25 | (55, 1934), 26 | (56, 39), 27 | (57, 407), 28 | (58, 6929), 29 | (59, 6568), 30 | (60, 26), 31 | (61, 268673), 32 | (62, 118137), 33 | (63, 84640), 34 | (64, 193232), 35 | (65, 2584210), 36 | (66, 1002), 37 | (67, 2993), 38 | (68, 4266), 39 | (69, 5633381), 40 | (70, 277369), 41 | (71, 5106), 42 | (72, 722), 43 | (73, 1882), 44 | (74, 8178), 45 | (75, 4045), 46 | (76, 1596), 47 | (77, 5335), 48 | (78, 14591), 49 | (79, 9645), 50 | (80, 44171), 51 | (81, 13474), 52 | (82, 51090), 53 | (83, 2595), 54 | (84, 6276), 55 | (85, 382195), 56 | (86, 1062), 57 | (87, 3846), 58 | (88, 5663), 59 | (89, 3811), 60 | (90, 1580), 61 | (91, 5729), 62 | (92, 19144), 63 | (93, 197), 64 | (94, 235), 65 | (95, 545), 66 | (96, 54914), 67 | (97, 3858), 68 | (98, 1610), 69 | (99, 635), 70 | (100, 2481), 71 | (101, 6457), 72 | (102, 3753951), 73 | (103, 11821), 74 | (104, 11114), 75 | (105, 2601), 76 | (106, 2518), 77 | (107, 521925), 78 | (108, 297), 79 | (109, 411), 80 | (110, 668), 81 | (111, 4500), 82 | (112, 704), 83 | (113, 316), 84 | (114, 59), 85 | (115, 291), 86 | (116, 1727), 87 | (117, 6010), 88 | (118, 51874), 89 | (119, 13969), 90 | (120, 9496), 91 | (121, 274), 92 | (122, 810), 93 | (123, 643), 94 | (124, 69), 95 | (125, 41), 96 | (126, 329), 97 | (127, 175435), 98 | (128, 2641), 99 | (129, 2658), 100 | (130, 415277), 101 | (131, 2705), 102 | (132, 2314), 103 | (133, 4290), 104 | (134, 693), 105 | (135, 1957478), 106 | (136, 1111), 107 | (137, 1474503), 108 | (138, 3656), 109 | (139, 940), 110 | (140, 1755692), 111 | (141, 61), 112 | (142, 4140), 113 | (143, 47), 114 | (144, 6725), 115 | (145, 610), 116 | (146, 250), 117 | (147, 48), 118 | (148, 28), 119 | (149, 132), 120 | (150, 123489), 121 | (151, 7476), 122 | (152, 55), 123 | (153, 68), 124 | (154, 170), 125 | (155, 566), 126 | (156, 8110), 127 | (157, 1243), 128 | (158, 1445), 129 | (159, 2569), 130 | (160, 1096), 131 | (161, 865), 132 | (162, 634), 133 | (163, 372411), 134 | (164, 685), 135 | (165, 3481), 136 | (166, 1467), 137 | (167, 2146), 138 | (168, 556539), 139 | (169, 566), 140 | (170, 5080), 141 | (171, 202), 142 | (172, 123), 143 | (173, 100750), 144 | (174, 667), 145 | (175, 433), 146 | (176, 737), 147 | (177, 315), 148 | (178, 317), 149 | (179, 656), 150 | (180, 2522), 151 | (181, 315), 152 | (182, 406), 153 | (183, 4680), 154 | (184, 4941), 155 | (185, 828), 156 | (186, 782), 157 | (187, 565), 158 | (188, 584), 159 | (189, 376), 160 | (190, 321), 161 | (191, 418), 162 | (192, 167), 163 | (193, 362), 164 | (194, 2198), 165 | (195, 180), 166 | (196, 787), 167 | (197, 2680), 168 | (198, 501), 169 | (199, 843), 170 | (200, 287), 171 | (201, 608362), 172 | (202, 1157), 173 | (203, 959), 174 | (204, 1683623), 175 | (205, 440), 176 | (206, 756), 177 | (207, 812), 178 | (208, 1147), 179 | (209, 723), 180 | (210, 856), 181 | (211, 496), 182 | (212, 916), 183 | (213, 615), 184 | (214, 488), 185 | (215, 522), 186 | (216, 8265), 187 | (217, 32574), 188 | (218, 417), 189 | (219, 247), 190 | (220, 579), 191 | (221, 68), 192 | (222, 126), 193 | (223, 306), 194 | (224, 310), 195 | (225, 24), 196 | (226, 37), 197 | (227, 160), 198 | (228, 11), 199 | (229, 3288), 200 | (230, 349), 201 | (231, 23), 202 | (232, 14), 203 | (233, 45), 204 | (234, 452840), 205 | (235, 118), 206 | (236, 741), 207 | (237, 390), 208 | (238, 517), 209 | (239, 694), 210 | (240, 765), 211 | (241, 542), 212 | (242, 417), 213 | (243, 617), 214 | (244, 1307), 215 | (245, 583), 216 | (246, 1640), 217 | (247, 735), 218 | (248, 478), 219 | (249, 4312), 220 | (250, 5426), 221 | (251, 1067), 222 | (252, 435), 223 | (253, 202), 224 | (254, 122), 225 | (255, 486), 226 | (256, 180), 227 | (257, 279), 228 | (258, 406), 229 | (259, 160), 230 | (260, 2759), 231 | (261, 2600), 232 | (262, 686), 233 | (263, 95), 234 | (264, 164), 235 | (265, 150), 236 | (266, 1013), 237 | (267, 552618), 238 | (268, 217), 239 | (269, 188), 240 | (270, 284), 241 | (271, 416), 242 | (272, 453), 243 | (273, 95), 244 | (274, 42), 245 | (275, 68), 246 | (276, 90), 247 | (277, 123), 248 | (278, 340), 249 | (279, 98), 250 | (280, 2795), 251 | (281, 261), 252 | (282, 7370), 253 | (283, 5768), 254 | (284, 3285), 255 | (285, 461), 256 | (286, 363), 257 | (287, 456), 258 | (288, 1475), 259 | (289, 211), 260 | (290, 153), 261 | (291, 282), 262 | (292, 241), 263 | (293, 2924), 264 | (294, 261), 265 | (295, 1070), 266 | (296, 1301), 267 | (297, 688), 268 | (298, 592), 269 | (299, 95), 270 | (300, 686447), 271 | (301, 42), 272 | (302, 385), 273 | (303, 24), 274 | (304, 931), 275 | (305, 49), 276 | (306, 23), 277 | (307, 67), 278 | (308, 32), 279 | (309, 38), 280 | (310, 2), 281 | (311, 7), 282 | (312, 198), 283 | (313, 11), 284 | (314, 38), 285 | (315, 3704), 286 | (316, 7406), 287 | (317, 116), 288 | (318, 229), 289 | (319, 100), 290 | (320, 437), 291 | (321, 244), 292 | (322, 285), 293 | (323, 433), 294 | (324, 382), 295 | (325, 3171), 296 | (326, 761), 297 | (327, 324), 298 | (328, 2264), 299 | (329, 340), 300 | (330, 353), 301 | (331, 110), 302 | (332, 403), 303 | (333, 731366), 304 | (334, 223), 305 | (335, 350), 306 | (336, 600), 307 | (337, 219), 308 | (338, 112), 309 | (339, 10), 310 | (340, 761), 311 | (341, 35), 312 | (342, 99), 313 | (343, 83), 314 | (344, 136), 315 | (345, 7), 316 | (346, 836), 317 | (347, 11), 318 | (348, 10832), 319 | (349, 8931), 320 | (350, 33), 321 | (351, 64), 322 | (352, 66), 323 | (353, 54), 324 | (354, 78), 325 | (355, 198), 326 | (356, 722), 327 | (357, 2647), 328 | (358, 64), 329 | (359, 71), 330 | (360, 2242), 331 | (361, 1462), 332 | (362, 505), 333 | (363, 444), 334 | (364, 597), 335 | (365, 372), 336 | (366, 664852), 337 | (367, 464), 338 | (368, 605), 339 | (369, 123), 340 | (370, 64), 341 | (371, 117), 342 | (372, 328), 343 | (373, 123), 344 | (374, 227), 345 | (375, 151), 346 | (376, 881), 347 | (377, 111), 348 | (378, 30), 349 | (379, 73), 350 | (380, 2126), 351 | (381, 3662), 352 | (382, 9107), 353 | (383, 18), 354 | (384, 294), 355 | (385, 12), 356 | (386, 262), 357 | (387, 127), 358 | (388, 269), 359 | (389, 2566), 360 | (390, 14), 361 | (391, 17), 362 | (392, 80), 363 | (393, 67), 364 | (394, 1470), 365 | (395, 25), 366 | (396, 220), 367 | (397, 131), 368 | (398, 225), 369 | (399, 484755), 370 | (400, 597), 371 | (401, 300), 372 | (402, 253), 373 | (403, 359), 374 | (404, 523), 375 | (405, 311), 376 | (406, 238), 377 | (407, 999), 378 | (408, 424), 379 | (409, 165), 380 | (410, 96), 381 | (411, 248), 382 | (412, 1771), 383 | (413, 139), 384 | (414, 7374), 385 | (415, 11186), 386 | (416, 1355), 387 | (417, 1283666), 388 | (418, 9), 389 | (419, 116), 390 | (420, 3897), 391 | (421, 2554), 392 | (422, 1), 393 | (423, 1), 394 | (424, 16878), 395 | (425, 3198212), 396 | (426, 335), 397 | (427, 1676), 398 | (428, 80), 399 | (429, 19), 400 | (430, 47), 401 | (431, 495), 402 | (432, 421946), 403 | (433, 73), 404 | (434, 95), 405 | (435, 105), 406 | (436, 184), 407 | (437, 56903), 408 | (438, 132), 409 | (439, 87), 410 | (440, 207411), 411 | (441, 230), 412 | (442, 372), 413 | (443, 361), 414 | (444, 387), 415 | (445, 299), 416 | (446, 175), 417 | (447, 7487), 418 | (448, 16346), 419 | (449, 37), 420 | (450, 98313), 421 | (451, 307), 422 | (452, 304), 423 | (453, 2675), 424 | (454, 229), 425 | (455, 130), 426 | (456, 134), 427 | (457, 50), 428 | (458, 238), 429 | (459, 2), 430 | (460, 2267), 431 | (461, 7), 432 | (462, 1), 433 | (463, 8), 434 | (464, 395), 435 | (465, 1279781), 436 | (466, 9), 437 | (467, 12), 438 | (468, 633), 439 | (469, 37), 440 | (470, 13), 441 | (471, 54), 442 | (472, 247), 443 | (473, 82), 444 | (474, 119), 445 | (475, 114), 446 | (476, 332), 447 | (477, 79), 448 | (478, 116), 449 | (479, 128), 450 | (480, 4206), 451 | (481, 20732), 452 | (482, 311), 453 | (483, 343), 454 | (484, 527), 455 | (485, 2750), 456 | (486, 76), 457 | (487, 152), 458 | (488, 510), 459 | (489, 63), 460 | (490, 257), 461 | (491, 79), 462 | (492, 825), 463 | (493, 4198), 464 | (494, 389), 465 | (495, 72), 466 | (496, 1547), 467 | (497, 34), 468 | (498, 631996), 469 | (499, 5), 470 | (500, 2334), 471 | (501, 34), 472 | (502, 7), 473 | (503, 7), 474 | (504, 7682), 475 | (505, 6), 476 | (506, 26), 477 | (507, 22), 478 | (508, 461), 479 | (509, 95), 480 | (510, 36), 481 | (511, 46), 482 | (512, 2741), 483 | (513, 38455), 484 | (514, 29678), 485 | (515, 179), 486 | (516, 1637), 487 | (517, 2597), 488 | (518, 166), 489 | (519, 230), 490 | (520, 2736), 491 | (521, 187), 492 | (522, 361), 493 | (523, 310), 494 | (524, 3327), 495 | (525, 76), 496 | (526, 8070), 497 | (527, 35), 498 | (528, 3310), 499 | (529, 118), 500 | (530, 167), 501 | (531, 214180), 502 | (532, 4597), 503 | (533, 153), 504 | (534, 126), 505 | (535, 23), 506 | (536, 13920), 507 | (537, 10), 508 | (538, 11), 509 | (539, 50), 510 | (540, 50739), 511 | (541, 8), 512 | (542, 347), 513 | (543, 77), 514 | (544, 451575), 515 | (545, 16), 516 | (546, 218814), 517 | (547, 1859026), 518 | (548, 303), 519 | (549, 2511), 520 | (550, 27), 521 | (551, 28), 522 | (552, 188), 523 | (553, 46), 524 | (554, 216), 525 | (555, 63), 526 | (556, 202), 527 | (557, 192), 528 | (558, 257), 529 | (559, 170377), 530 | (560, 902), 531 | (561, 424), 532 | (562, 186), 533 | (563, 145), 534 | (564, 342), 535 | (565, 76), 536 | (566, 41), 537 | (567, 26), 538 | (568, 136), 539 | (569, 1336), 540 | (570, 988), 541 | (571, 131), 542 | (572, 766), 543 | (573, 95), 544 | (574, 57), 545 | (575, 16), 546 | (576, 47), 547 | (577, 63), 548 | (578, 5), 549 | (579, 140), 550 | (580, 1263808), 551 | (581, 2498), 552 | (583, 2), 553 | (584, 706), 554 | (585, 49), 555 | (586, 502), 556 | (587, 16), 557 | (588, 115), 558 | (589, 25), 559 | (590, 31), 560 | (591, 34), 561 | (592, 818), 562 | (593, 60), 563 | (594, 84), 564 | (595, 116), 565 | (596, 446), 566 | (597, 111), 567 | (598, 151), 568 | (599, 153), 569 | (600, 1408), 570 | (601, 165), 571 | (602, 575), 572 | (603, 163), 573 | (604, 309), 574 | (605, 52), 575 | (606, 40), 576 | (607, 116), 577 | (608, 749), 578 | (609, 231), 579 | (610, 171), 580 | (611, 218), 581 | (612, 1145), 582 | (613, 2572), 583 | (614, 27), 584 | (615, 26), 585 | (616, 2060), 586 | (617, 173), 587 | (618, 1094), 588 | (619, 66), 589 | (620, 14235), 590 | (622, 294), 591 | (623, 2), 592 | (624, 79374), 593 | (625, 1), 594 | (626, 3), 595 | (627, 7), 596 | (628, 335), 597 | (629, 27), 598 | (630, 47), 599 | (631, 113), 600 | (632, 589), 601 | (633, 56), 602 | (634, 75), 603 | (635, 85), 604 | (636, 740), 605 | (637, 118), 606 | (638, 180), 607 | (639, 149), 608 | (640, 1169), 609 | (641, 135), 610 | (642, 169), 611 | (643, 170), 612 | (644, 1802), 613 | (645, 2481), 614 | (646, 28), 615 | (647, 78), 616 | (648, 5585), 617 | (649, 173), 618 | (650, 135), 619 | (651, 177), 620 | (652, 6553), 621 | (653, 129), 622 | (654, 55), 623 | (655, 6), 624 | (656, 13250), 625 | (657, 5), 626 | (658, 15), 627 | (659, 3), 628 | (660, 39892), 629 | (661, 28), 630 | (663, 1), 631 | (664, 575061), 632 | (665, 1), 633 | (666, 5), 634 | (667, 73), 635 | (668, 39), 636 | (669, 62), 637 | (670, 50), 638 | (671, 27), 639 | (672, 33), 640 | (673, 48), 641 | (674, 44), 642 | (675, 151), 643 | (676, 70), 644 | (677, 2540), 645 | (678, 150), 646 | (679, 109), 647 | (680, 117), 648 | (681, 95), 649 | (682, 80), 650 | (683, 44), 651 | (684, 34), 652 | (685, 31), 653 | (686, 125), 654 | (687, 146), 655 | (688, 423), 656 | (689, 142), 657 | (690, 154), 658 | (691, 135), 659 | (692, 194), 660 | (693, 48), 661 | (694, 6), 662 | (695, 141), 663 | (696, 47), 664 | (697, 9), 665 | (699, 1), 666 | (701, 1), 667 | (702, 2), 668 | (703, 81), 669 | (704, 3), 670 | (705, 4), 671 | (706, 23), 672 | (707, 131), 673 | (708, 31), 674 | (709, 2458), 675 | (710, 346), 676 | (711, 43), 677 | (712, 46), 678 | (713, 48), 679 | (714, 85), 680 | (715, 119), 681 | (716, 89), 682 | (717, 97), 683 | (718, 95), 684 | (719, 137), 685 | (720, 437), 686 | (721, 64), 687 | (722, 28), 688 | (723, 29), 689 | (724, 121), 690 | (725, 162), 691 | (726, 241), 692 | (727, 219), 693 | (728, 143), 694 | (729, 92), 695 | (730, 100), 696 | (731, 42), 697 | (732, 38), 698 | (733, 60), 699 | (734, 2), 700 | (735, 71), 701 | (736, 12), 702 | (737, 9), 703 | (738, 7), 704 | (739, 193), 705 | (740, 2), 706 | (741, 2404), 707 | (742, 3), 708 | (743, 11), 709 | (744, 5), 710 | (745, 5), 711 | (746, 9), 712 | (747, 16), 713 | (748, 27), 714 | (749, 32), 715 | (750, 57), 716 | (751, 54), 717 | (752, 383), 718 | (753, 61), 719 | (754, 48), 720 | (755, 84), 721 | (756, 108), 722 | (757, 134), 723 | (758, 121), 724 | (759, 160), 725 | (760, 80), 726 | (761, 68), 727 | (762, 192), 728 | (763, 107), 729 | (764, 270), 730 | (765, 58), 731 | (766, 125), 732 | (767, 151), 733 | (768, 75), 734 | (769, 94), 735 | (770, 91), 736 | (771, 187), 737 | (772, 57), 738 | (773, 2371), 739 | (774, 8), 740 | (775, 93), 741 | (776, 107), 742 | (777, 20), 743 | (779, 1), 744 | (780, 22), 745 | (781, 1), 746 | (783, 6), 747 | (784, 318), 748 | (785, 25), 749 | (786, 31), 750 | (787, 23), 751 | (788, 28), 752 | (789, 62), 753 | (790, 53), 754 | (791, 41), 755 | (792, 68), 756 | (793, 60), 757 | (794, 88), 758 | (795, 108), 759 | (796, 63), 760 | (797, 100), 761 | (798, 68), 762 | (799, 72), 763 | (800, 83), 764 | (801, 46), 765 | (802, 36), 766 | (803, 157), 767 | (804, 139), 768 | (805, 2439), 769 | (806, 73), 770 | (807, 81), 771 | (808, 99), 772 | (809, 66), 773 | (810, 45), 774 | (811, 98), 775 | (812, 1), 776 | (814, 31), 777 | (815, 1), 778 | (816, 312), 779 | (818, 155), 780 | (819, 2), 781 | (820, 12), 782 | (821, 27), 783 | (822, 97), 784 | (823, 23), 785 | (824, 7), 786 | (825, 15), 787 | (826, 37), 788 | (827, 39), 789 | (828, 28), 790 | (829, 33), 791 | (830, 53), 792 | (831, 101), 793 | (832, 189), 794 | (833, 94), 795 | (834, 66), 796 | (835, 173), 797 | (836, 74), 798 | (837, 2402), 799 | (838, 64), 800 | (839, 28), 801 | (840, 20), 802 | (841, 13), 803 | (842, 32), 804 | (843, 72), 805 | (844, 68), 806 | (845, 50), 807 | (846, 41), 808 | (847, 114), 809 | (848, 345), 810 | (849, 33), 811 | (850, 17), 812 | (851, 6), 813 | (852, 61), 814 | (853, 101), 815 | (854, 123), 816 | (855, 28), 817 | (856, 3), 818 | (857, 3), 819 | (858, 30), 820 | (859, 12), 821 | (860, 28), 822 | (861, 16), 823 | (862, 20), 824 | (863, 7), 825 | (864, 23), 826 | (865, 28), 827 | (866, 40), 828 | (867, 159), 829 | (868, 40), 830 | (869, 2361), 831 | (870, 92), 832 | (871, 88), 833 | (872, 193), 834 | (873, 61), 835 | (874, 58), 836 | (875, 67), 837 | (876, 65), 838 | (877, 46), 839 | (878, 55), 840 | (879, 30), 841 | (880, 334), 842 | (881, 74), 843 | (882, 121), 844 | (883, 107), 845 | (884, 36), 846 | (885, 66), 847 | (886, 22), 848 | (887, 25), 849 | (888, 24), 850 | (889, 10), 851 | (890, 44), 852 | (891, 5), 853 | (892, 84), 854 | (893, 4), 855 | (894, 1), 856 | (895, 7), 857 | (896, 3), 858 | (897, 8), 859 | (898, 3), 860 | (899, 126), 861 | (900, 13), 862 | (901, 2280), 863 | (902, 74), 864 | (903, 36), 865 | (904, 46), 866 | (905, 52), 867 | (906, 24), 868 | (907, 23), 869 | (908, 43), 870 | (909, 31), 871 | (910, 66), 872 | (911, 65), 873 | (912, 376), 874 | (913, 77), 875 | (914, 85), 876 | (915, 60), 877 | (916, 29), 878 | (917, 64), 879 | (918, 48), 880 | (919, 135), 881 | (920, 21), 882 | (921, 34), 883 | (922, 26), 884 | (923, 22), 885 | (924, 52), 886 | (925, 28), 887 | (926, 142), 888 | (927, 18), 889 | (928, 14), 890 | (929, 30), 891 | (930, 56), 892 | (931, 113), 893 | (933, 2264), 894 | (934, 14), 895 | (935, 4), 896 | (936, 10), 897 | (937, 18), 898 | (938, 2), 899 | (939, 30), 900 | (940, 9), 901 | (941, 29), 902 | (942, 10), 903 | (943, 17), 904 | (944, 296), 905 | (945, 31), 906 | (946, 40), 907 | (947, 26), 908 | (948, 70), 909 | (949, 66), 910 | (950, 44), 911 | (951, 57), 912 | (952, 55), 913 | (953, 56), 914 | (954, 51), 915 | (955, 133), 916 | (956, 39), 917 | (957, 49), 918 | (958, 45), 919 | (959, 26), 920 | (960, 30), 921 | (961, 35), 922 | (962, 40), 923 | (963, 148), 924 | (964, 34), 925 | (965, 2264), 926 | (966, 50), 927 | (967, 21), 928 | (968, 2), 929 | (970, 24), 930 | (972, 45), 931 | (973, 8), 932 | (974, 11), 933 | (975, 20), 934 | (976, 287), 935 | (977, 20), 936 | (978, 6), 937 | (979, 9), 938 | (980, 99), 939 | (981, 32), 940 | (982, 10), 941 | (983, 13), 942 | (984, 26), 943 | (985, 30), 944 | (986, 31), 945 | (987, 38), 946 | (988, 25), 947 | (989, 32), 948 | (990, 44), 949 | (991, 125), 950 | (992, 58), 951 | (993, 44), 952 | (994, 25), 953 | (995, 140), 954 | (996, 25), 955 | (997, 2222), 956 | (998, 16), 957 | (999, 25), 958 | (1000, 38), 959 | (1001, 66), 960 | (1002, 31), 961 | (1003, 38), 962 | (1004, 38), 963 | (1005, 10), 964 | (1006, 7), 965 | (1008, 283), 966 | (1009, 3), 967 | (1010, 1), 968 | (1011, 17), 969 | (1012, 4), 970 | (1013, 51), 971 | (1014, 1), 972 | (1015, 1), 973 | (1016, 3), 974 | (1017, 12), 975 | (1018, 11), 976 | (1019, 21), 977 | (1020, 31), 978 | (1021, 14), 979 | (1022, 14), 980 | (1023, 23), 981 | (1024, 25), 982 | (1025, 42), 983 | (1026, 39), 984 | (1027, 220), 985 | (1028, 33), 986 | (1029, 2206), 987 | (1030, 24), 988 | (1031, 64), 989 | (1032, 36), 990 | (1033, 61), 991 | (1034, 123), 992 | (1035, 32), 993 | (1036, 20), 994 | (1037, 15), 995 | (1038, 11), 996 | (1039, 33), 997 | (1040, 311), 998 | (1041, 58), 999 | (1042, 80), 1000 | (1043, 29), 1001 | (1044, 10), 1002 | (1045, 48), 1003 | (1046, 18), 1004 | (1047, 22), 1005 | (1048, 3), 1006 | (1049, 17), 1007 | (1050, 1), 1008 | (1051, 2), 1009 | (1052, 5), 1010 | (1053, 4), 1011 | (1054, 4), 1012 | (1055, 1), 1013 | (1056, 4), 1014 | (1057, 15), 1015 | (1058, 11), 1016 | (1059, 135), 1017 | (1060, 59), 1018 | (1061, 2132), 1019 | (1062, 32), 1020 | (1063, 116), 1021 | (1064, 37), 1022 | (1065, 44), 1023 | (1066, 42), 1024 | (1067, 28), 1025 | (1068, 10), 1026 | (1069, 36), 1027 | (1070, 59), 1028 | (1071, 48), 1029 | (1072, 332), 1030 | (1073, 59), 1031 | (1074, 43), 1032 | (1075, 19), 1033 | (1076, 19), 1034 | (1077, 31), 1035 | (1078, 31), 1036 | (1079, 20), 1037 | (1080, 38), 1038 | (1081, 58), 1039 | (1082, 37), 1040 | (1083, 47), 1041 | (1084, 19), 1042 | (1085, 24), 1043 | (1086, 12), 1044 | (1087, 26), 1045 | (1088, 89), 1046 | (1089, 3), 1047 | (1091, 108), 1048 | (1093, 2112), 1049 | (1094, 13), 1050 | (1095, 4), 1051 | (1096, 4), 1052 | (1097, 17), 1053 | (1098, 7), 1054 | (1099, 105), 1055 | (1100, 12), 1056 | (1101, 10), 1057 | (1102, 17), 1058 | (1103, 19), 1059 | (1104, 329), 1060 | (1105, 28), 1061 | (1106, 58), 1062 | (1107, 21), 1063 | (1108, 22), 1064 | (1109, 63), 1065 | (1110, 29), 1066 | (1111, 53), 1067 | (1112, 84), 1068 | (1113, 28), 1069 | (1114, 30), 1070 | (1115, 22), 1071 | (1116, 40), 1072 | (1117, 16), 1073 | (1118, 20), 1074 | (1119, 75), 1075 | (1120, 43), 1076 | (1121, 49), 1077 | (1122, 25), 1078 | (1123, 118), 1079 | (1124, 8), 1080 | (1125, 2083), 1081 | (1126, 21), 1082 | (1127, 3), 1083 | (1128, 43), 1084 | (1129, 1), 1085 | (1130, 1), 1086 | (1132, 3), 1087 | (1133, 1), 1088 | (1134, 3), 1089 | (1135, 83), 1090 | (1136, 266), 1091 | (1137, 7), 1092 | (1138, 22), 1093 | (1139, 14), 1094 | (1140, 30), 1095 | (1141, 54), 1096 | (1142, 125), 1097 | (1143, 44), 1098 | (1144, 34), 1099 | (1145, 19), 1100 | (1146, 21), 1101 | (1147, 19), 1102 | (1148, 46), 1103 | (1149, 45), 1104 | (1150, 54), 1105 | (1151, 22), 1106 | (1152, 30), 1107 | (1153, 20), 1108 | (1154, 7), 1109 | (1155, 143), 1110 | (1156, 23), 1111 | (1157, 2078), 1112 | (1158, 30), 1113 | (1159, 23), 1114 | (1160, 12), 1115 | (1161, 18), 1116 | (1162, 6), 1117 | (1164, 5), 1118 | (1165, 1), 1119 | (1168, 254), 1120 | (1169, 1), 1121 | (1170, 3), 1122 | (1171, 95), 1123 | (1172, 37), 1124 | (1173, 23), 1125 | (1174, 7), 1126 | (1175, 11), 1127 | (1176, 5), 1128 | (1177, 14), 1129 | (1178, 15), 1130 | (1179, 19), 1131 | (1180, 10), 1132 | (1181, 28), 1133 | (1182, 87), 1134 | (1183, 35), 1135 | (1184, 30), 1136 | (1185, 30), 1137 | (1186, 38), 1138 | (1187, 148), 1139 | (1188, 49), 1140 | (1189, 2056), 1141 | (1190, 42), 1142 | (1191, 41), 1143 | (1192, 14), 1144 | (1193, 36), 1145 | (1194, 37), 1146 | (1195, 22), 1147 | (1196, 108), 1148 | (1197, 62), 1149 | (1198, 55), 1150 | (1199, 43), 1151 | (1200, 261), 1152 | (1201, 16), 1153 | (1202, 1), 1154 | (1203, 9), 1155 | (1204, 3), 1156 | (1205, 32), 1157 | (1207, 81), 1158 | (1208, 3), 1159 | (1210, 3), 1160 | (1212, 4), 1161 | (1213, 9), 1162 | (1214, 5), 1163 | (1215, 6), 1164 | (1216, 4), 1165 | (1217, 8), 1166 | (1218, 13), 1167 | (1219, 120), 1168 | (1220, 11), 1169 | (1221, 1989), 1170 | (1222, 11), 1171 | (1223, 20), 1172 | (1224, 15), 1173 | (1225, 21), 1174 | (1226, 23), 1175 | (1227, 50), 1176 | (1228, 37), 1177 | (1229, 51), 1178 | (1230, 37), 1179 | (1231, 21), 1180 | (1232, 256), 1181 | (1233, 26), 1182 | (1234, 25), 1183 | (1235, 21), 1184 | (1236, 79), 1185 | (1237, 50), 1186 | (1238, 21), 1187 | (1239, 2), 1188 | (1240, 6), 1189 | (1241, 8), 1190 | (1243, 95), 1191 | (1244, 1), 1192 | (1247, 1), 1193 | (1248, 1), 1194 | (1249, 1), 1195 | (1250, 96), 1196 | (1251, 112), 1197 | (1252, 43), 1198 | (1253, 1960), 1199 | (1254, 7), 1200 | (1255, 13), 1201 | (1256, 16), 1202 | (1257, 20), 1203 | (1258, 19), 1204 | (1259, 17), 1205 | (1260, 12), 1206 | (1261, 5), 1207 | (1262, 12), 1208 | (1263, 29), 1209 | (1264, 272), 1210 | (1265, 63), 1211 | (1266, 37), 1212 | (1267, 36), 1213 | (1268, 25), 1214 | (1269, 55), 1215 | (1270, 38), 1216 | (1271, 7), 1217 | (1272, 37), 1218 | (1273, 10), 1219 | (1274, 16), 1220 | (1275, 28), 1221 | (1276, 18), 1222 | (1277, 11), 1223 | (1278, 8), 1224 | (1279, 91), 1225 | (1280, 1), 1226 | (1282, 1), 1227 | (1283, 110), 1228 | (1284, 20), 1229 | (1285, 1923), 1230 | (1287, 3), 1231 | (1288, 1), 1232 | (1290, 23), 1233 | (1291, 4), 1234 | (1292, 4), 1235 | (1293, 12), 1236 | (1294, 19), 1237 | (1295, 8), 1238 | (1296, 248), 1239 | (1297, 21), 1240 | (1298, 12), 1241 | (1299, 31), 1242 | (1300, 10), 1243 | (1301, 60), 1244 | (1302, 1), 1245 | (1303, 8), 1246 | (1304, 99), 1247 | (1305, 29), 1248 | (1306, 29), 1249 | (1307, 28), 1250 | (1308, 33), 1251 | (1309, 19), 1252 | (1310, 8), 1253 | (1311, 1), 1254 | (1313, 11), 1255 | (1314, 12), 1256 | (1315, 236), 1257 | (1316, 18), 1258 | (1317, 1891), 1259 | (1318, 2), 1260 | (1322, 21), 1261 | (1324, 1), 1262 | (1326, 8), 1263 | (1327, 3), 1264 | (1328, 235), 1265 | (1329, 4), 1266 | (1330, 1), 1267 | (1331, 2), 1268 | (1332, 5), 1269 | (1333, 38), 1270 | (1334, 2), 1271 | (1335, 30), 1272 | (1336, 18), 1273 | (1337, 31), 1274 | (1338, 8), 1275 | (1339, 5), 1276 | (1340, 11), 1277 | (1341, 9), 1278 | (1342, 12), 1279 | (1343, 11), 1280 | (1344, 79), 1281 | (1345, 37), 1282 | (1346, 19), 1283 | (1347, 136), 1284 | (1348, 9), 1285 | (1349, 1861), 1286 | (1350, 8), 1287 | (1351, 112), 1288 | (1352, 10), 1289 | (1353, 3), 1290 | (1354, 16), 1291 | (1355, 4), 1292 | (1356, 12), 1293 | (1357, 18), 1294 | (1358, 67), 1295 | (1359, 6), 1296 | (1360, 229), 1297 | (1361, 1), 1298 | (1362, 1), 1299 | (1364, 1), 1300 | (1365, 27), 1301 | (1366, 6), 1302 | (1368, 14), 1303 | (1370, 8), 1304 | (1371, 29), 1305 | (1372, 3), 1306 | (1373, 21), 1307 | (1374, 8), 1308 | (1375, 6), 1309 | (1376, 3), 1310 | (1377, 9), 1311 | (1378, 9), 1312 | (1379, 120), 1313 | (1380, 5), 1314 | (1381, 1833), 1315 | (1382, 45), 1316 | (1383, 35), 1317 | (1384, 23), 1318 | (1385, 25), 1319 | (1386, 26), 1320 | (1387, 159), 1321 | (1388, 24), 1322 | (1389, 16), 1323 | (1390, 16), 1324 | (1391, 14), 1325 | (1392, 273), 1326 | (1393, 17), 1327 | (1394, 9), 1328 | (1395, 5), 1329 | (1396, 14), 1330 | (1397, 24), 1331 | (1398, 27), 1332 | (1400, 2), 1333 | (1404, 5), 1334 | (1405, 8), 1335 | (1406, 3), 1336 | (1407, 25), 1337 | (1408, 2), 1338 | (1409, 22), 1339 | (1410, 10), 1340 | (1411, 111), 1341 | (1412, 89), 1342 | (1413, 1793), 1343 | (1414, 4), 1344 | (1415, 9), 1345 | (1416, 16), 1346 | (1417, 13), 1347 | (1418, 13), 1348 | (1419, 13), 1349 | (1420, 15), 1350 | (1421, 19), 1351 | (1422, 26), 1352 | (1423, 110), 1353 | (1424, 229), 1354 | (1425, 11), 1355 | (1426, 10), 1356 | (1427, 7), 1357 | (1428, 7), 1358 | (1429, 28), 1359 | (1430, 12), 1360 | (1431, 11), 1361 | (1432, 14), 1362 | (1433, 2), 1363 | (1434, 2), 1364 | (1436, 1), 1365 | (1437, 1), 1366 | (1438, 13), 1367 | (1439, 1), 1368 | (1440, 1), 1369 | (1441, 1), 1370 | (1442, 2), 1371 | (1443, 132), 1372 | (1444, 5), 1373 | (1445, 1795), 1374 | (1448, 11), 1375 | (1449, 10), 1376 | (1450, 11), 1377 | (1451, 8), 1378 | (1452, 47), 1379 | (1453, 6), 1380 | (1454, 8), 1381 | (1455, 12), 1382 | (1456, 229), 1383 | (1457, 15), 1384 | (1458, 12), 1385 | (1459, 121), 1386 | (1460, 15), 1387 | (1461, 48), 1388 | (1462, 49), 1389 | (1463, 22), 1390 | (1464, 11), 1391 | (1465, 9), 1392 | (1466, 81), 1393 | (1467, 1), 1394 | (1468, 1), 1395 | (1469, 6), 1396 | (1470, 6), 1397 | (1471, 6), 1398 | (1472, 9), 1399 | (1473, 12), 1400 | (1474, 2), 1401 | (1475, 109), 1402 | (1476, 5), 1403 | (1477, 1721), 1404 | (1478, 1), 1405 | (1479, 28), 1406 | (1480, 7), 1407 | (1481, 23), 1408 | (1482, 2), 1409 | (1483, 12), 1410 | (1484, 5), 1411 | (1485, 3), 1412 | (1486, 2), 1413 | (1487, 4), 1414 | (1488, 219), 1415 | (1489, 7), 1416 | (1490, 8), 1417 | (1491, 10), 1418 | (1492, 16), 1419 | (1493, 32), 1420 | (1494, 25), 1421 | (1495, 96), 1422 | (1496, 13), 1423 | (1497, 15), 1424 | (1498, 16), 1425 | (1499, 12), 1426 | (1500, 14), 1427 | (1501, 19), 1428 | (1502, 7), 1429 | (1503, 11), 1430 | (1504, 3), 1431 | (1505, 8), 1432 | (1506, 41), 1433 | (1507, 108), 1434 | (1508, 25), 1435 | (1509, 1719), 1436 | (1510, 8), 1437 | (1511, 10), 1438 | (1514, 2), 1439 | (1515, 25), 1440 | (1516, 2), 1441 | (1517, 32), 1442 | (1518, 6), 1443 | (1519, 7), 1444 | (1520, 273), 1445 | (1521, 2), 1446 | (1522, 6), 1447 | (1523, 5), 1448 | (1524, 6), 1449 | (1525, 36), 1450 | (1526, 3), 1451 | (1527, 12), 1452 | (1528, 7), 1453 | (1529, 9), 1454 | (1530, 12), 1455 | (1531, 107), 1456 | (1532, 44), 1457 | (1533, 17), 1458 | (1534, 12), 1459 | (1535, 18), 1460 | (1536, 12), 1461 | (1537, 26), 1462 | (1538, 35), 1463 | (1539, 131), 1464 | (1540, 15), 1465 | (1541, 1693), 1466 | (1542, 11), 1467 | (1543, 7), 1468 | (1544, 2), 1469 | (1545, 6), 1470 | (1546, 14), 1471 | (1547, 6), 1472 | (1548, 2), 1473 | (1549, 24), 1474 | (1550, 2), 1475 | (1551, 33), 1476 | (1552, 206), 1477 | (1553, 18), 1478 | (1555, 1), 1479 | (1556, 7), 1480 | (1557, 38), 1481 | (1558, 6), 1482 | (1559, 3), 1483 | (1560, 21), 1484 | (1562, 2), 1485 | (1563, 5), 1486 | (1564, 7), 1487 | (1565, 5), 1488 | (1566, 6), 1489 | (1567, 110), 1490 | (1568, 9), 1491 | (1569, 16), 1492 | (1570, 13), 1493 | (1571, 109), 1494 | (1572, 6), 1495 | (1573, 1664), 1496 | (1574, 53), 1497 | (1575, 14), 1498 | (1576, 21), 1499 | (1577, 31), 1500 | (1578, 42), 1501 | (1579, 13), 1502 | (1580, 10), 1503 | (1581, 12), 1504 | (1582, 11), 1505 | (1583, 85), 1506 | (1584, 202), 1507 | (1585, 7), 1508 | (1586, 6), 1509 | (1587, 25), 1510 | (1588, 5), 1511 | (1589, 41), 1512 | (1590, 4), 1513 | (1591, 5), 1514 | (1593, 1), 1515 | (1595, 5), 1516 | (1596, 11), 1517 | (1598, 1), 1518 | (1599, 1), 1519 | (1600, 1), 1520 | (1601, 4), 1521 | (1602, 19), 1522 | (1603, 200), 1523 | (1604, 10), 1524 | (1605, 1640), 1525 | (1606, 15), 1526 | (1607, 14), 1527 | (1608, 7), 1528 | (1609, 12), 1529 | (1610, 5), 1530 | (1611, 2), 1531 | (1612, 3), 1532 | (1613, 7), 1533 | (1614, 37), 1534 | (1615, 4), 1535 | (1616, 203), 1536 | (1617, 13), 1537 | (1618, 3), 1538 | (1619, 12), 1539 | (1620, 38), 1540 | (1621, 22), 1541 | (1622, 12), 1542 | (1623, 43), 1543 | (1624, 19), 1544 | (1625, 35), 1545 | (1626, 15), 1546 | (1627, 26), 1547 | (1628, 43), 1548 | (1629, 2), 1549 | (1630, 10), 1550 | (1631, 1), 1551 | (1633, 1), 1552 | (1634, 1), 1553 | (1635, 110), 1554 | (1637, 1612), 1555 | (1638, 1), 1556 | (1639, 107), 1557 | (1640, 1), 1558 | (1641, 2), 1559 | (1643, 7), 1560 | (1644, 9), 1561 | (1645, 8), 1562 | (1646, 3), 1563 | (1647, 19), 1564 | (1648, 206), 1565 | (1649, 2), 1566 | (1650, 9), 1567 | (1651, 8), 1568 | (1652, 19), 1569 | (1653, 22), 1570 | (1654, 4), 1571 | (1655, 13), 1572 | (1656, 3), 1573 | (1657, 5), 1574 | (1658, 5), 1575 | (1659, 35), 1576 | (1660, 10), 1577 | (1661, 26), 1578 | (1662, 8), 1579 | (1663, 10), 1580 | (1664, 7), 1581 | (1665, 4), 1582 | (1666, 2), 1583 | (1667, 110), 1584 | (1668, 12), 1585 | (1669, 1594), 1586 | (1670, 1), 1587 | (1671, 2), 1588 | (1672, 15), 1589 | (1673, 4), 1590 | (1674, 2), 1591 | (1675, 303), 1592 | (1676, 12), 1593 | (1678, 1), 1594 | (1680, 194), 1595 | (1681, 1), 1596 | (1682, 40), 1597 | (1683, 2), 1598 | (1684, 2), 1599 | (1685, 19), 1600 | (1686, 16), 1601 | (1687, 2), 1602 | (1688, 6), 1603 | (1689, 9), 1604 | (1690, 18), 1605 | (1691, 15), 1606 | (1692, 5), 1607 | (1693, 7), 1608 | (1694, 6), 1609 | (1695, 32), 1610 | (1696, 4), 1611 | (1697, 34), 1612 | (1698, 1), 1613 | (1699, 117), 1614 | (1700, 5), 1615 | (1701, 1590), 1616 | (1702, 20), 1617 | (1703, 4), 1618 | (1704, 6), 1619 | (1705, 20), 1620 | (1707, 2), 1621 | (1710, 3), 1622 | (1711, 89), 1623 | (1712, 195), 1624 | (1713, 4), 1625 | (1714, 2), 1626 | (1715, 1), 1627 | (1716, 3), 1628 | (1717, 16), 1629 | (1718, 9), 1630 | (1719, 2), 1631 | (1720, 3), 1632 | (1723, 18), 1633 | (1724, 1), 1634 | (1725, 2), 1635 | (1726, 3), 1636 | (1727, 3), 1637 | (1728, 9), 1638 | (1729, 5), 1639 | (1730, 7), 1640 | (1731, 132), 1641 | (1732, 28), 1642 | (1733, 1585), 1643 | (1734, 5), 1644 | (1735, 3), 1645 | (1736, 5), 1646 | (1737, 27), 1647 | (1738, 4), 1648 | (1739, 19), 1649 | (1740, 15), 1650 | (1741, 4), 1651 | (1742, 15), 1652 | (1743, 9), 1653 | (1744, 183), 1654 | (1745, 12), 1655 | (1747, 119), 1656 | (1748, 1), 1657 | (1749, 15), 1658 | (1750, 5), 1659 | (1754, 1), 1660 | (1757, 2), 1661 | (1758, 8), 1662 | (1759, 7), 1663 | (1760, 7), 1664 | (1761, 2), 1665 | (1762, 13), 1666 | (1763, 113), 1667 | (1764, 8), 1668 | (1765, 1547), 1669 | (1766, 7), 1670 | (1767, 21), 1671 | (1768, 3), 1672 | (1769, 34), 1673 | (1770, 5), 1674 | (1772, 6), 1675 | (1773, 7), 1676 | (1774, 12), 1677 | (1775, 9), 1678 | (1776, 189), 1679 | (1777, 25), 1680 | (1778, 10), 1681 | (1779, 4), 1682 | (1780, 1), 1683 | (1781, 21), 1684 | (1782, 3), 1685 | (1783, 186), 1686 | (1784, 2), 1687 | (1787, 1), 1688 | (1788, 10), 1689 | (1789, 8), 1690 | (1790, 1), 1691 | (1791, 34), 1692 | (1792, 1), 1693 | (1793, 1), 1694 | (1794, 1), 1695 | (1795, 108), 1696 | (1796, 4), 1697 | (1797, 1519), 1698 | (1798, 9), 1699 | (1799, 9), 1700 | (1800, 3), 1701 | (1801, 6), 1702 | (1802, 4), 1703 | (1803, 35), 1704 | (1804, 15), 1705 | (1805, 30), 1706 | (1806, 5), 1707 | (1807, 7), 1708 | (1808, 192), 1709 | (1809, 8), 1710 | (1811, 4), 1711 | (1812, 24), 1712 | (1813, 36), 1713 | (1814, 4), 1714 | (1815, 14), 1715 | (1816, 2), 1716 | (1817, 2), 1717 | (1818, 4), 1718 | (1819, 72), 1719 | (1820, 3), 1720 | (1822, 1), 1721 | (1823, 4), 1722 | (1825, 1), 1723 | (1826, 5), 1724 | (1827, 104), 1725 | (1828, 1), 1726 | (1829, 1494), 1727 | (1830, 11), 1728 | (1831, 5), 1729 | (1832, 2), 1730 | (1833, 2), 1731 | (1834, 2), 1732 | (1835, 4), 1733 | (1836, 9), 1734 | (1837, 1), 1735 | (1838, 14), 1736 | (1839, 33), 1737 | (1840, 188), 1738 | (1841, 27), 1739 | (1842, 13), 1740 | (1843, 10), 1741 | (1844, 28), 1742 | (1845, 52), 1743 | (1846, 17), 1744 | (1847, 40), 1745 | (1848, 35), 1746 | (1849, 6), 1747 | (1850, 6), 1748 | (1851, 2), 1749 | (1853, 4), 1750 | (1854, 6), 1751 | (1855, 77), 1752 | (1856, 1), 1753 | (1859, 106), 1754 | (1860, 2), 1755 | (1861, 1466), 1756 | (1863, 2), 1757 | (1866, 1), 1758 | (1869, 1), 1759 | (1870, 2), 1760 | (1872, 179), 1761 | (1873, 1), 1762 | (1874, 9), 1763 | (1875, 29), 1764 | (1876, 15), 1765 | (1877, 43), 1766 | (1878, 2), 1767 | (1880, 8), 1768 | (1881, 13), 1769 | (1882, 18), 1770 | (1883, 12), 1771 | (1884, 14), 1772 | (1885, 18), 1773 | (1886, 16), 1774 | (1887, 6), 1775 | (1888, 2), 1776 | (1889, 3), 1777 | (1890, 9), 1778 | (1891, 196), 1779 | (1892, 13), 1780 | (1893, 1456), 1781 | (1894, 14), 1782 | (1895, 8), 1783 | (1896, 2), 1784 | (1898, 1), 1785 | (1899, 17), 1786 | (1900, 5), 1787 | (1901, 1), 1788 | (1904, 175), 1789 | (1905, 1), 1790 | (1906, 2), 1791 | (1907, 3), 1792 | (1908, 6), 1793 | (1909, 10), 1794 | (1910, 3), 1795 | (1911, 22), 1796 | (1912, 6), 1797 | (1913, 22), 1798 | (1914, 6), 1799 | (1915, 10), 1800 | (1916, 5), 1801 | (1917, 2), 1802 | (1918, 6), 1803 | (1919, 4), 1804 | (1920, 7), 1805 | (1921, 14), 1806 | (1922, 4), 1807 | (1923, 107), 1808 | (1924, 10), 1809 | (1925, 1434), 1810 | (1926, 7), 1811 | (1927, 76), 1812 | (1928, 4), 1813 | (1929, 7), 1814 | (1930, 10), 1815 | (1931, 14), 1816 | (1932, 6), 1817 | (1933, 15), 1818 | (1934, 4), 1819 | (1935, 2), 1820 | (1936, 182), 1821 | (1937, 2), 1822 | (1939, 11), 1823 | (1940, 1), 1824 | (1941, 4), 1825 | (1942, 2), 1826 | (1943, 9), 1827 | (1944, 1), 1828 | (1947, 24), 1829 | (1949, 22), 1830 | (1952, 15), 1831 | (1953, 14), 1832 | (1954, 5), 1833 | (1955, 111), 1834 | (1956, 11), 1835 | (1957, 1435), 1836 | (1958, 5), 1837 | (1959, 5), 1838 | (1960, 10), 1839 | (1961, 6), 1840 | (1962, 11), 1841 | (1963, 95), 1842 | (1964, 11), 1843 | (1965, 7), 1844 | (1966, 7), 1845 | (1967, 2), 1846 | (1968, 182), 1847 | (1969, 6), 1848 | (1970, 15), 1849 | (1972, 7), 1850 | (1973, 11), 1851 | (1974, 6), 1852 | (1975, 2), 1853 | (1976, 6), 1854 | (1977, 3), 1855 | (1978, 2), 1856 | (1983, 24), 1857 | (1985, 26), 1858 | (1986, 3), 1859 | (1987, 109), 1860 | (1988, 3), 1861 | (1989, 1421), 1862 | (1990, 1), 1863 | (1991, 3), 1864 | (1992, 8), 1865 | (1993, 4), 1866 | (1994, 6), 1867 | (1995, 5), 1868 | (1996, 13), 1869 | (1997, 6), 1870 | (1998, 10), 1871 | (1999, 92), 1872 | (2000, 181), 1873 | (2001, 5), 1874 | (2002, 5), 1875 | (2003, 1), 1876 | (2004, 1), 1877 | (2005, 14), 1878 | (2006, 12), 1879 | (2007, 10), 1880 | (2008, 7), 1881 | (2009, 9), 1882 | (2010, 6), 1883 | (2011, 8), 1884 | (2012, 13), 1885 | (2013, 2), 1886 | (2014, 2), 1887 | (2018, 1), 1888 | (2019, 128), 1889 | (2021, 1429), 1890 | (2022, 4), 1891 | (2026, 2), 1892 | (2027, 2), 1893 | (2030, 7), 1894 | (2032, 175), 1895 | (2033, 1), 1896 | (2035, 90), 1897 | (2036, 3), 1898 | (2037, 11), 1899 | (2038, 2), 1900 | (2039, 4), 1901 | (2040, 3), 1902 | (2041, 2), 1903 | (2042, 1), 1904 | (2043, 2), 1905 | (2044, 5), 1906 | (2045, 1), 1907 | (2046, 3), 1908 | (2047, 21), 1909 | (2048, 5), 1910 | (2050, 16), 1911 | (2051, 120), 1912 | (2053, 1403), 1913 | (2054, 4), 1914 | (2055, 29), 1915 | (2057, 26), 1916 | (2058, 3), 1917 | (2059, 4), 1918 | (2060, 4), 1919 | (2061, 7), 1920 | (2063, 1), 1921 | (2065, 170), 1922 | (2066, 3), 1923 | (2067, 2), 1924 | (2068, 7), 1925 | (2069, 13), 1926 | (2071, 77), 1927 | (2072, 1), 1928 | (2075, 4), 1929 | (2077, 1), 1930 | (2078, 2), 1931 | (2079, 5), 1932 | (2080, 4), 1933 | (2081, 3), 1934 | (2082, 3), 1935 | (2083, 2), 1936 | (2084, 293), 1937 | (2085, 6), 1938 | (2086, 1395), 1939 | (2087, 2), 1940 | (2089, 4), 1941 | (2090, 10), 1942 | (2091, 26), 1943 | (2092, 14), 1944 | (2093, 25), 1945 | (2097, 170), 1946 | (2099, 2), 1947 | (2100, 1), 1948 | (2101, 8), 1949 | (2102, 5), 1950 | (2104, 2), 1951 | (2105, 2), 1952 | (2107, 90), 1953 | (2108, 1), 1954 | (2110, 15), 1955 | (2112, 1), 1956 | (2113, 1), 1957 | (2114, 3), 1958 | (2115, 8), 1959 | (2116, 3), 1960 | (2117, 5), 1961 | (2118, 1380), 1962 | (2119, 4), 1963 | (2120, 1), 1964 | (2121, 3), 1965 | (2122, 1), 1966 | (2123, 6), 1967 | (2124, 24), 1968 | (2125, 1), 1969 | (2127, 33), 1970 | (2128, 4), 1971 | (2129, 197), 1972 | (2132, 1), 1973 | (2133, 3), 1974 | (2134, 8), 1975 | (2141, 1), 1976 | (2143, 95), 1977 | (2144, 6), 1978 | (2146, 1), 1979 | (2147, 1), 1980 | (2148, 3), 1981 | (2150, 1369), 1982 | (2152, 1), 1983 | (2153, 1), 1984 | (2155, 5), 1985 | (2156, 7), 1986 | (2157, 12), 1987 | (2158, 2), 1988 | (2159, 6), 1989 | (2160, 7), 1990 | (2161, 174), 1991 | (2162, 22), 1992 | (2163, 27), 1993 | (2164, 5), 1994 | (2165, 24), 1995 | (2166, 6), 1996 | (2169, 8), 1997 | (2170, 2), 1998 | (2171, 1), 1999 | (2172, 1), 2000 | (2174, 8), 2001 | (2175, 10), 2002 | (2176, 2), 2003 | (2177, 3), 2004 | (2179, 72), 2005 | (2180, 4), 2006 | (2181, 1), 2007 | (2182, 1366), 2008 | (2183, 2), 2009 | (2184, 5), 2010 | (2185, 4), 2011 | (2188, 3), 2012 | (2191, 1), 2013 | (2192, 2), 2014 | (2193, 169), 2015 | (2198, 7), 2016 | (2199, 27), 2017 | (2201, 28), 2018 | (2205, 2), 2019 | (2206, 2), 2020 | (2209, 9), 2021 | (2213, 8), 2022 | (2214, 1364), 2023 | (2215, 95), 2024 | (2216, 1), 2025 | (2217, 2), 2026 | (2218, 1), 2027 | (2219, 1), 2028 | (2220, 3), 2029 | (2221, 2), 2030 | (2222, 3), 2031 | (2223, 41), 2032 | (2225, 168), 2033 | (2228, 1), 2034 | (2229, 6), 2035 | (2230, 8), 2036 | (2231, 1), 2037 | (2232, 2), 2038 | (2233, 6), 2039 | (2234, 1), 2040 | (2235, 41), 2041 | (2236, 2), 2042 | (2237, 17), 2043 | (2240, 7), 2044 | (2242, 6), 2045 | (2244, 1), 2046 | (2246, 1350), 2047 | (2249, 2), 2048 | (2250, 4), 2049 | (2251, 89), 2050 | (2252, 1), 2051 | (2257, 167), 2052 | (2260, 4), 2053 | (2261, 3), 2054 | (2262, 6), 2055 | (2265, 1), 2056 | (2269, 2), 2057 | (2270, 4), 2058 | (2271, 32), 2059 | (2273, 21), 2060 | (2274, 1), 2061 | (2275, 3), 2062 | (2276, 1), 2063 | (2277, 2), 2064 | (2278, 1344), 2065 | (2279, 2), 2066 | (2280, 1), 2067 | (2281, 1), 2068 | (2284, 1), 2069 | (2287, 98), 2070 | (2288, 2), 2071 | (2289, 168), 2072 | (2292, 3), 2073 | (2293, 3), 2074 | (2294, 4), 2075 | (2298, 3), 2076 | (2303, 9), 2077 | (2307, 26), 2078 | (2308, 1), 2079 | (2309, 30), 2080 | (2310, 1344), 2081 | (2314, 1), 2082 | (2318, 1), 2083 | (2321, 164), 2084 | (2323, 1), 2085 | (2324, 82), 2086 | (2325, 1), 2087 | (2326, 5), 2088 | (2327, 1), 2089 | (2334, 6), 2090 | (2338, 1), 2091 | (2339, 1), 2092 | (2340, 1), 2093 | (2342, 1337), 2094 | (2343, 55), 2095 | (2344, 27), 2096 | (2345, 6), 2097 | (2346, 25), 2098 | (2347, 1), 2099 | (2348, 18), 2100 | (2350, 1), 2101 | (2351, 3), 2102 | (2352, 2), 2103 | (2353, 166), 2104 | (2358, 6), 2105 | (2360, 87), 2106 | (2361, 3), 2107 | (2362, 1), 2108 | (2373, 9), 2109 | (2374, 1330), 2110 | (2376, 1), 2111 | (2377, 1), 2112 | (2378, 11), 2113 | (2379, 4), 2114 | (2380, 28), 2115 | (2382, 29), 2116 | (2383, 2), 2117 | (2384, 8), 2118 | (2385, 169), 2119 | (2386, 4), 2120 | (2387, 9), 2121 | (2388, 8), 2122 | (2389, 4), 2123 | (2390, 15), 2124 | (2392, 1), 2125 | (2396, 117), 2126 | (2397, 4), 2127 | (2399, 1), 2128 | (2406, 1330), 2129 | (2410, 1), 2130 | (2414, 1), 2131 | (2415, 4), 2132 | (2416, 26), 2133 | (2417, 164), 2134 | (2418, 31), 2135 | (2421, 3), 2136 | (2422, 4), 2137 | (2424, 6), 2138 | (2425, 3), 2139 | (2426, 3), 2140 | (2427, 5), 2141 | (2428, 1), 2142 | (2429, 2), 2143 | (2432, 100), 2144 | (2433, 1), 2145 | (2435, 1), 2146 | (2436, 1), 2147 | (2438, 1328), 2148 | (2441, 10), 2149 | (2443, 11), 2150 | (2448, 2), 2151 | (2449, 163), 2152 | (2451, 1), 2153 | (2452, 27), 2154 | (2453, 8), 2155 | (2454, 24), 2156 | (2455, 1), 2157 | (2456, 2), 2158 | (2457, 2), 2159 | (2460, 4), 2160 | (2465, 5), 2161 | (2466, 3), 2162 | (2468, 95), 2163 | (2469, 6), 2164 | (2470, 1324), 2165 | (2471, 1), 2166 | (2472, 1), 2167 | (2476, 2), 2168 | (2477, 2), 2169 | (2478, 2), 2170 | (2479, 4), 2171 | (2481, 163), 2172 | (2484, 2), 2173 | (2485, 6), 2174 | (2486, 2), 2175 | (2488, 23), 2176 | (2489, 1), 2177 | (2490, 26), 2178 | (2491, 1), 2179 | (2493, 1), 2180 | (2494, 1), 2181 | (2495, 3), 2182 | (2496, 1), 2183 | (2500, 3), 2184 | (2502, 1327), 2185 | (2503, 1), 2186 | (2504, 93), 2187 | (2505, 2), 2188 | (2506, 1), 2189 | (2511, 4), 2190 | (2513, 166), 2191 | (2516, 3), 2192 | (2517, 5), 2193 | (2518, 8), 2194 | (2519, 2), 2195 | (2521, 1), 2196 | (2524, 27), 2197 | (2526, 20), 2198 | (2532, 1), 2199 | (2534, 1320), 2200 | (2535, 1), 2201 | (2540, 114), 2202 | (2541, 1), 2203 | (2543, 1), 2204 | (2545, 163), 2205 | (2550, 3), 2206 | (2555, 3), 2207 | (2557, 4), 2208 | (2558, 3), 2209 | (2559, 2), 2210 | (2560, 26), 2211 | (2561, 6), 2212 | (2562, 26), 2213 | (2564, 5), 2214 | (2565, 1), 2215 | (2566, 1325), 2216 | (2567, 5), 2217 | (2568, 9), 2218 | (2569, 10), 2219 | (2570, 2), 2220 | (2571, 1), 2221 | (2576, 97), 2222 | (2577, 165), 2223 | (2582, 3), 2224 | (2583, 5), 2225 | (2593, 2), 2226 | (2596, 42), 2227 | (2597, 1), 2228 | (2598, 1336), 2229 | (2602, 1), 2230 | (2609, 163), 2231 | (2612, 97), 2232 | (2613, 1), 2233 | (2614, 2), 2234 | (2619, 1), 2235 | (2621, 2), 2236 | (2624, 2), 2237 | (2628, 2), 2238 | (2630, 1684946), 2239 | (2632, 27), 2240 | (2633, 2), 2241 | (2634, 25), 2242 | (2635, 1), 2243 | (2637, 4), 2244 | (2639, 1), 2245 | (2640, 1), 2246 | (2641, 163), 2247 | (2644, 1), 2248 | (2645, 3), 2249 | (2646, 2), 2250 | (2648, 112), 2251 | (2649, 1), 2252 | (2653, 5), 2253 | (2659, 3), 2254 | (2660, 1), 2255 | (2661, 1), 2256 | (2662, 1315), 2257 | (2664, 1), 2258 | (2668, 30), 2259 | (2669, 1), 2260 | (2670, 26), 2261 | (2673, 163), 2262 | (2674, 2), 2263 | (2675, 1), 2264 | (2678, 7), 2265 | (2679, 1), 2266 | (2680, 1), 2267 | (2684, 90), 2268 | (2685, 1), 2269 | (2686, 1), 2270 | (2694, 1315), 2271 | (2699, 1), 2272 | (2701, 1), 2273 | (2704, 30), 2274 | (2705, 163), 2275 | (2706, 27), 2276 | (2710, 2), 2277 | (2712, 1), 2278 | (2720, 112), 2279 | (2721, 2), 2280 | (2723, 5), 2281 | (2726, 1316), 2282 | (2736, 1), 2283 | (2737, 165), 2284 | (2738, 2), 2285 | (2740, 25), 2286 | (2742, 33), 2287 | (2745, 1), 2288 | (2756, 97), 2289 | (2757, 1), 2290 | (2758, 1315), 2291 | (2769, 163), 2292 | (2774, 3), 2293 | (2776, 32), 2294 | (2778, 34), 2295 | (2781, 1), 2296 | (2782, 1), 2297 | (2784, 1), 2298 | (2790, 1313), 2299 | (2792, 94), 2300 | (2793, 12), 2301 | (2796, 1), 2302 | (2800, 1), 2303 | (2801, 163), 2304 | (2804, 2), 2305 | (2805, 6), 2306 | (2806, 2), 2307 | (2807, 2), 2308 | (2809, 1), 2309 | (2810, 1), 2310 | (2812, 23), 2311 | (2814, 33), 2312 | (2815, 3), 2313 | (2816, 1), 2314 | (2820, 2), 2315 | (2821, 1), 2316 | (2822, 1314), 2317 | (2824, 1), 2318 | (2828, 104), 2319 | (2829, 1), 2320 | (2833, 163), 2321 | (2837, 6), 2322 | (2838, 4), 2323 | (2839, 1), 2324 | (2848, 32), 2325 | (2849, 4), 2326 | (2850, 32), 2327 | (2852, 4), 2328 | (2853, 1), 2329 | (2854, 1312), 2330 | (2861, 1), 2331 | (2863, 52), 2332 | (2864, 111), 2333 | (2865, 164), 2334 | (2868, 2), 2335 | (2869, 15), 2336 | (2870, 2), 2337 | (2871, 1), 2338 | (2884, 30), 2339 | (2886, 1333), 2340 | (2890, 2), 2341 | (2891, 2), 2342 | (2892, 3), 2343 | (2893, 4), 2344 | (2894, 2), 2345 | (2897, 163), 2346 | (2899, 3), 2347 | (2900, 230), 2348 | (2901, 1), 2349 | (2902, 2), 2350 | (2908, 2), 2351 | (2911, 1), 2352 | (2918, 1312), 2353 | (2920, 42), 2354 | (2922, 25), 2355 | (2923, 1), 2356 | (2925, 1), 2357 | (2929, 165), 2358 | (2930, 2), 2359 | (2931, 5), 2360 | (2932, 4), 2361 | (2933, 8), 2362 | (2934, 2), 2363 | (2936, 110), 2364 | (2937, 1), 2365 | (2938, 1), 2366 | (2939, 1), 2367 | (2948, 1), 2368 | (2950, 1313), 2369 | (2956, 38), 2370 | (2958, 32), 2371 | (2961, 163), 2372 | (2964, 1), 2373 | (2966, 4), 2374 | (2967, 2), 2375 | (2969, 1), 2376 | (2971, 1), 2377 | (2972, 151), 2378 | (2973, 1), 2379 | (2975, 3), 2380 | (2976, 4), 2381 | (2977, 3), 2382 | (2978, 1), 2383 | (2979, 1), 2384 | (2980, 1), 2385 | (2982, 1312), 2386 | (2992, 28), 2387 | (2993, 163), 2388 | (2994, 29), 2389 | (2998, 2), 2390 | (3006, 1), 2391 | (3007, 2), 2392 | (3008, 188), 2393 | (3009, 2), 2394 | (3014, 1311), 2395 | (3015, 5), 2396 | (3016, 9), 2397 | (3017, 1), 2398 | (3020, 1), 2399 | (3025, 164), 2400 | (3028, 27), 2401 | (3030, 31), 2402 | (3044, 223), 2403 | (3045, 1), 2404 | (3046, 1311), 2405 | (3048, 1), 2406 | (3057, 163), 2407 | (3061, 2), 2408 | (3062, 4), 2409 | (3064, 41), 2410 | (3066, 35), 2411 | (3076, 2), 2412 | (3078, 1310), 2413 | (3080, 151), 2414 | (3081, 2), 2415 | (3089, 163), 2416 | (3094, 2), 2417 | (3100, 35), 2418 | (3101, 2), 2419 | (3102, 38), 2420 | (3104, 2), 2421 | (3110, 1310), 2422 | (3116, 106), 2423 | (3117, 2), 2424 | (3121, 163), 2425 | (3125, 5), 2426 | (3126, 2), 2427 | (3132, 2), 2428 | (3136, 36), 2429 | (3138, 39), 2430 | (3140, 2), 2431 | (3141, 1), 2432 | (3142, 1309), 2433 | (3143, 1), 2434 | (3144, 1), 2435 | (3152, 120), 2436 | (3153, 164), 2437 | (3155, 1), 2438 | (3157, 1), 2439 | (3158, 2), 2440 | (3163, 1), 2441 | (3164, 1), 2442 | (3172, 34), 2443 | (3174, 1343), 2444 | (3185, 163), 2445 | (3188, 136), 2446 | (3189, 1), 2447 | (3190, 2), 2448 | (3203, 1), 2449 | (3204, 1), 2450 | (3206, 1308), 2451 | (3208, 53), 2452 | (3210, 52), 2453 | (3217, 163), 2454 | (3220, 38), 2455 | (3221, 114), 2456 | (3222, 2), 2457 | (3224, 141), 2458 | (3225, 5), 2459 | (3230, 1), 2460 | (3236, 38), 2461 | (3238, 1308), 2462 | (3244, 35), 2463 | (3246, 46), 2464 | (3249, 163), 2465 | (3254, 2), 2466 | (3260, 105), 2467 | (3261, 4), 2468 | (3263, 1), 2469 | (3270, 1308), 2470 | (3280, 38), 2471 | (3281, 163), 2472 | (3282, 28), 2473 | (3286, 3), 2474 | (3292, 1), 2475 | (3296, 138), 2476 | (3297, 1), 2477 | (3301, 1), 2478 | (3302, 1308), 2479 | (3304, 1), 2480 | (3313, 163), 2481 | (3316, 33), 2482 | (3318, 34), 2483 | (3329, 1), 2484 | (3331, 1), 2485 | (3332, 120), 2486 | (3333, 1), 2487 | (3334, 1309), 2488 | (3345, 163), 2489 | (3350, 3), 2490 | (3352, 34), 2491 | (3354, 31), 2492 | (3357, 1), 2493 | (3366, 1307), 2494 | (3368, 230), 2495 | (3369, 6), 2496 | (3377, 163), 2497 | (3382, 2), 2498 | (3388, 37), 2499 | (3390, 45), 2500 | (3398, 1307), 2501 | (3404, 3128), 2502 | (3405, 2), 2503 | (3409, 163), 2504 | (3414, 2), 2505 | (3424, 40), 2506 | (3426, 23), 2507 | (3430, 1307), 2508 | (3440, 117), 2509 | (3441, 164), 2510 | (3446, 2), 2511 | (3460, 30), 2512 | (3462, 1344), 2513 | (3469, 1), 2514 | (3473, 163), 2515 | (3476, 116), 2516 | (3477, 1), 2517 | (3478, 3), 2518 | (3494, 1305), 2519 | (3496, 36), 2520 | (3498, 38), 2521 | (3501, 2), 2522 | (3504, 2), 2523 | (3505, 163), 2524 | (3510, 2), 2525 | (3512, 124), 2526 | (3513, 4), 2527 | (3515, 1), 2528 | (3525, 1), 2529 | (3526, 1305), 2530 | (3532, 27), 2531 | (3534, 33), 2532 | (3537, 165), 2533 | (3541, 2), 2534 | (3542, 2), 2535 | (3544, 2), 2536 | (3548, 119), 2537 | (3549, 1), 2538 | (3558, 1305), 2539 | (3568, 29), 2540 | (3569, 163), 2541 | (3570, 53), 2542 | (3574, 2), 2543 | (3581, 6), 2544 | (3584, 115), 2545 | (3585, 2), 2546 | (3590, 1306), 2547 | (3601, 163), 2548 | (3604, 39), 2549 | (3606, 45), 2550 | (3620, 107), 2551 | (3621, 1), 2552 | (3622, 1304), 2553 | (3633, 163), 2554 | (3634, 1), 2555 | (3637, 1), 2556 | (3638, 2), 2557 | (3640, 43), 2558 | (3642, 35), 2559 | (3654, 1305), 2560 | (3656, 126), 2561 | (3657, 2), 2562 | (3661, 1), 2563 | (3664, 1), 2564 | (3665, 163), 2565 | (3670, 3), 2566 | (3676, 32), 2567 | (3678, 48), 2568 | (3679, 1), 2569 | (3686, 1303), 2570 | (3692, 128), 2571 | (3693, 2), 2572 | (3697, 163), 2573 | (3702, 3), 2574 | (3712, 33), 2575 | (3714, 28), 2576 | (3718, 1302), 2577 | (3728, 137), 2578 | (3729, 165), 2579 | (3734, 2), 2580 | (3748, 54), 2581 | (3749, 1), 2582 | (3750, 1333), 2583 | (3758, 1), 2584 | (3761, 163), 2585 | (3764, 125), 2586 | (3765, 2), 2587 | (3766, 3), 2588 | (3782, 1301), 2589 | (3784, 32), 2590 | (3786, 50), 2591 | (3793, 163), 2592 | (3798, 2), 2593 | (3800, 123), 2594 | (3801, 3), 2595 | (3805, 1), 2596 | (3814, 1301), 2597 | (3820, 53), 2598 | (3822, 30), 2599 | (3825, 163), 2600 | (3830, 2), 2601 | (3833, 1), 2602 | (3836, 109), 2603 | (3837, 3), 2604 | (3846, 1301), 2605 | (3856, 35), 2606 | (3857, 163), 2607 | (3858, 54), 2608 | (3860, 20), 2609 | (3861, 51), 2610 | (3862, 2), 2611 | (3872, 124), 2612 | (3873, 2), 2613 | (3876, 17), 2614 | (3878, 1302), 2615 | (3882, 1), 2616 | (3889, 163), 2617 | (3892, 45), 2618 | (3894, 47), 2619 | (3901, 2), 2620 | (3903, 1), 2621 | (3904, 2), 2622 | (3908, 138), 2623 | (3909, 2), 2624 | (3910, 1300), 2625 | (3917, 2), 2626 | (3921, 163), 2627 | (3926, 2), 2628 | (3928, 38), 2629 | (3930, 37), 2630 | (3942, 1300), 2631 | (3944, 137), 2632 | (3945, 2), 2633 | (3953, 163), 2634 | (3958, 2), 2635 | (3964, 66), 2636 | (3966, 37), 2637 | (3971, 1), 2638 | (3974, 1300), 2639 | (3980, 166), 2640 | (3981, 1), 2641 | (3985, 163), 2642 | (3990, 2), 2643 | (4000, 35), 2644 | (4002, 54), 2645 | (4006, 1300), 2646 | (4016, 150), 2647 | (4017, 164), 2648 | (4021, 38), 2649 | (4022, 2), 2650 | (4024, 38), 2651 | (4036, 47), 2652 | (4038, 1347), 2653 | (4049, 163), 2654 | (4052, 134), 2655 | (4053, 10), 2656 | (4054, 2), 2657 | (4068, 1), 2658 | (4070, 1300), 2659 | (4072, 52), 2660 | (4074, 40), 2661 | (4075, 1), 2662 | (4081, 163), 2663 | (4085, 7), 2664 | (4086, 2), 2665 | (4088, 123), 2666 | (4089, 4), 2667 | (4100, 2), 2668 | (4102, 1300), 2669 | (4108, 38), 2670 | (4110, 43), 2671 | (4113, 163), 2672 | (4118, 2), 2673 | (4119, 2), 2674 | (4124, 159), 2675 | (4125, 3), 2676 | (4128, 1), 2677 | (4134, 1299), 2678 | (4141, 1), 2679 | (4144, 51), 2680 | (4145, 163), 2681 | (4146, 41), 2682 | (4150, 2), 2683 | (4152, 30), 2684 | (4160, 153), 2685 | (4161, 1), 2686 | (4164, 2), 2687 | (4166, 1299), 2688 | (4177, 163), 2689 | (4180, 225), 2690 | (4181, 596), 2691 | (4182, 50), 2692 | (4187, 1), 2693 | (4196, 373), 2694 | (4197, 3), 2695 | (4198, 1299), 2696 | (4209, 163), 2697 | (4214, 2), 2698 | (4216, 66), 2699 | (4217, 3), 2700 | (4218, 69), 2701 | (4221, 1), 2702 | (4230, 1299), 2703 | (4232, 158), 2704 | (4233, 2), 2705 | (4241, 163), 2706 | (4246, 2), 2707 | (4252, 45), 2708 | (4253, 1), 2709 | (4254, 48), 2710 | (4262, 1300), 2711 | (4267, 2), 2712 | (4268, 145), 2713 | (4269, 3), 2714 | (4270, 1), 2715 | (4271, 1), 2716 | (4273, 163), 2717 | (4278, 3), 2718 | (4288, 75), 2719 | (4290, 36), 2720 | (4294, 1298), 2721 | (4301, 1), 2722 | (4304, 173), 2723 | (4305, 166), 2724 | (4309, 2), 2725 | (4310, 2), 2726 | (4324, 52), 2727 | (4326, 1359), 2728 | (4337, 163), 2729 | (4340, 195), 2730 | (4341, 2), 2731 | (4342, 3), 2732 | (4358, 1297), 2733 | (4360, 76), 2734 | (4362, 56), 2735 | (4365, 2), 2736 | (4369, 163), 2737 | (4374, 2), 2738 | (4376, 171), 2739 | (4377, 1), 2740 | (4390, 1298), 2741 | (4396, 52), 2742 | (4398, 49), 2743 | (4401, 163), 2744 | (4406, 3), 2745 | (4407, 2), 2746 | (4412, 170), 2747 | (4413, 2), 2748 | (4421, 1), 2749 | (4422, 1296), 2750 | (4432, 57), 2751 | (4433, 163), 2752 | (4434, 51), 2753 | (4436, 1), 2754 | (4438, 2), 2755 | (4448, 481), 2756 | (4449, 2), 2757 | (4451, 1), 2758 | (4454, 1295), 2759 | (4463, 1), 2760 | (4465, 163), 2761 | (4468, 74), 2762 | (4470, 92), 2763 | (4484, 448), 2764 | (4485, 3), 2765 | (4486, 1295), 2766 | (4487, 1), 2767 | (4497, 163), 2768 | (4502, 2), 2769 | (4504, 52), 2770 | (4506, 65), 2771 | (4518, 1295), 2772 | (4519, 2), 2773 | (4520, 631), 2774 | (4521, 3), 2775 | (4529, 164), 2776 | (4530, 1), 2777 | (4532, 1), 2778 | (4533, 3), 2779 | (4534, 2), 2780 | (4540, 55), 2781 | (4542, 48), 2782 | (4550, 1294), 2783 | (4556, 2358), 2784 | (4557, 3), 2785 | (4561, 163), 2786 | (4562, 1), 2787 | (4566, 2), 2788 | (4576, 58), 2789 | (4578, 74), 2790 | (4582, 1294), 2791 | (4592, 193), 2792 | (4593, 167), 2793 | (4598, 2), 2794 | (4612, 66), 2795 | (4614, 1363), 2796 | (4621, 2), 2797 | (4625, 163), 2798 | (4628, 218), 2799 | (4629, 3), 2800 | (4630, 2), 2801 | (4635, 3), 2802 | (4640, 1), 2803 | (4645, 1), 2804 | (4646, 1295), 2805 | (4648, 57), 2806 | (4650, 90), 2807 | (4657, 163), 2808 | (4662, 3), 2809 | (4664, 194), 2810 | (4665, 1), 2811 | (4678, 1295), 2812 | (4684, 49), 2813 | (4685, 1), 2814 | (4686, 85), 2815 | (4689, 163), 2816 | (4694, 4), 2817 | (4700, 183), 2818 | (4701, 3), 2819 | (4710, 1291), 2820 | (4720, 61), 2821 | (4721, 163), 2822 | (4722, 75), 2823 | (4726, 3), 2824 | (4736, 175), 2825 | (4737, 4), 2826 | (4742, 1291), 2827 | (4753, 163), 2828 | (4756, 84), 2829 | (4758, 53), 2830 | (4772, 210), 2831 | (4773, 4), 2832 | (4774, 1291), 2833 | (4785, 163), 2834 | (4790, 2), 2835 | (4792, 54), 2836 | (4794, 66), 2837 | (4799, 2), 2838 | (4806, 1292), 2839 | (4808, 180), 2840 | (4809, 6), 2841 | (4817, 164), 2842 | (4820, 32), 2843 | (4821, 132), 2844 | (4822, 3), 2845 | (4824, 17), 2846 | (4828, 70), 2847 | (4830, 62), 2848 | (4836, 42), 2849 | (4838, 1290), 2850 | (4844, 199), 2851 | (4845, 3), 2852 | (4849, 163), 2853 | (4854, 2), 2854 | (4864, 104), 2855 | (4866, 98), 2856 | (4870, 1290), 2857 | (4873, 1), 2858 | (4880, 184), 2859 | (4881, 164), 2860 | (4886, 2), 2861 | (4900, 88), 2862 | (4902, 1387), 2863 | (4909, 1), 2864 | (4913, 163), 2865 | (4916, 187), 2866 | (4917, 6), 2867 | (4918, 2), 2868 | (4934, 1290), 2869 | (4936, 65), 2870 | (4938, 59), 2871 | (4945, 163), 2872 | (4948, 1), 2873 | (4950, 2), 2874 | (4952, 198), 2875 | (4953, 3), 2876 | (4966, 1290), 2877 | (4972, 64), 2878 | (4974, 108), 2879 | (4977, 163), 2880 | (4982, 2), 2881 | (4988, 199), 2882 | (4989, 8), 2883 | (4998, 1290), 2884 | (5008, 82), 2885 | (5009, 163), 2886 | (5010, 113), 2887 | (5012, 3), 2888 | (5013, 9), 2889 | (5014, 2), 2890 | (5017, 1), 2891 | (5024, 228), 2892 | (5025, 2), 2893 | (5028, 4), 2894 | (5030, 1290), 2895 | (5041, 162), 2896 | (5044, 96), 2897 | (5046, 71), 2898 | (5060, 275), 2899 | (5061, 6), 2900 | (5062, 1291), 2901 | (5064, 1), 2902 | (5070, 1), 2903 | (5073, 162), 2904 | (5078, 3), 2905 | (5080, 66), 2906 | (5082, 153), 2907 | (5094, 1289), 2908 | (5096, 272), 2909 | (5097, 10), 2910 | (5101, 2), 2911 | (5104, 2), 2912 | (5105, 162), 2913 | (5110, 2), 2914 | (5116, 87), 2915 | (5118, 80), 2916 | (5126, 1289), 2917 | (5132, 266), 2918 | (5133, 5), 2919 | (5135, 1), 2920 | (5137, 162), 2921 | (5140, 190), 2922 | (5141, 681), 2923 | (5142, 2), 2924 | (5152, 104), 2925 | (5154, 184), 2926 | (5156, 238), 2927 | (5158, 1289), 2928 | (5168, 257), 2929 | (5169, 165), 2930 | (5174, 2), 2931 | (5188, 99), 2932 | (5190, 1435), 2933 | (5201, 162), 2934 | (5204, 228), 2935 | (5205, 6), 2936 | (5206, 2), 2937 | (5221, 206), 2938 | (5222, 1289), 2939 | (5224, 312), 2940 | (5226, 110), 2941 | (5231, 1), 2942 | (5233, 162), 2943 | (5238, 2), 2944 | (5240, 266), 2945 | (5241, 7), 2946 | (5254, 1289), 2947 | (5260, 87), 2948 | (5262, 243), 2949 | (5265, 162), 2950 | (5270, 2), 2951 | (5274, 8), 2952 | (5276, 318), 2953 | (5277, 7), 2954 | (5286, 1289), 2955 | (5288, 86), 2956 | (5296, 88), 2957 | (5297, 162), 2958 | (5298, 123), 2959 | (5302, 3), 2960 | (5312, 351), 2961 | (5313, 1), 2962 | (5318, 1289), 2963 | (5329, 162), 2964 | (5332, 115), 2965 | (5334, 173), 2966 | (5339, 6), 2967 | (5344, 1), 2968 | (5348, 313), 2969 | (5349, 3), 2970 | (5350, 1289), 2971 | (5352, 24), 2972 | (5353, 14), 2973 | (5361, 162), 2974 | (5366, 3), 2975 | (5368, 157), 2976 | (5370, 107), 2977 | (5374, 1), 2978 | (5382, 1289), 2979 | (5384, 293), 2980 | (5385, 4), 2981 | (5388, 4), 2982 | (5393, 162), 2983 | (5396, 1), 2984 | (5398, 2), 2985 | (5404, 142), 2986 | (5406, 201), 2987 | (5407, 1), 2988 | (5414, 1289), 2989 | (5417, 3), 2990 | (5420, 285), 2991 | (5421, 5), 2992 | (5423, 1), 2993 | (5425, 162), 2994 | (5430, 2), 2995 | (5436, 1), 2996 | (5440, 142), 2997 | (5442, 210), 2998 | (5444, 1), 2999 | (5446, 1294), 3000 | (5456, 318), 3001 | (5457, 166), 3002 | (5462, 3), 3003 | (5476, 123), 3004 | (5478, 1608), 3005 | (5482, 2), 3006 | (5489, 162), 3007 | (5492, 329), 3008 | (5493, 2), 3009 | (5494, 2), 3010 | (5504, 1), 3011 | (5506, 1), 3012 | (5510, 1289), 3013 | (5511, 1), 3014 | (5512, 165), 3015 | (5514, 167), 3016 | (5521, 163), 3017 | (5522, 1), 3018 | (5526, 2), 3019 | (5528, 367), 3020 | (5529, 8), 3021 | (5542, 1289), 3022 | (5548, 192), 3023 | (5550, 291), 3024 | (5553, 162), 3025 | (5558, 2), 3026 | (5564, 399), 3027 | (5565, 13), 3028 | (5574, 1289), 3029 | (5584, 188), 3030 | (5585, 163), 3031 | (5586, 356), 3032 | (5590, 2), 3033 | (5592, 1), 3034 | (5599, 1), 3035 | (5600, 375), 3036 | (5601, 3), 3037 | (5606, 1290), 3038 | (5608, 1), 3039 | (5617, 162), 3040 | (5618, 1), 3041 | (5620, 261), 3042 | (5622, 667), 3043 | (5623, 1), 3044 | (5626, 1), 3045 | (5633, 1), 3046 | (5636, 406), 3047 | (5637, 4), 3048 | (5638, 1289), 3049 | (5639, 1), 3050 | (5649, 162), 3051 | (5654, 2), 3052 | (5656, 468), 3053 | (5658, 1159), 3054 | (5662, 1), 3055 | (5670, 1289), 3056 | (5671, 1), 3057 | (5672, 349), 3058 | (5673, 8), 3059 | (5675, 1), 3060 | (5681, 162), 3061 | (5686, 2), 3062 | (5692, 321), 3063 | (5694, 3067), 3064 | (5702, 1289), 3065 | (5706, 1), 3066 | (5708, 443), 3067 | (5709, 7), 3068 | (5713, 162), 3069 | (5718, 2), 3070 | (5728, 496), 3071 | (5730, 4577), 3072 | (5734, 1289), 3073 | (5744, 383), 3074 | (5745, 165), 3075 | (5750, 3), 3076 | (5756, 1), 3077 | (5758, 1), 3078 | (5764, 5847), 3079 | (5766, 8966), 3080 | (5775, 1), 3081 | (5777, 162), 3082 | (5780, 616), 3083 | (5781, 240), 3084 | (5782, 2), 3085 | (5784, 1), 3086 | (5788, 1), 3087 | (5796, 81), 3088 | (5798, 1289), 3089 | (5799, 1), 3090 | (5800, 5543), 3091 | (5802, 13287), 3092 | (5809, 162), 3093 | (5814, 2), 3094 | (5816, 409), 3095 | (5817, 3), 3096 | (5830, 1289), 3097 | (5833, 1), 3098 | (5836, 123), 3099 | (5838, 59), 3100 | (5841, 162), 3101 | (5846, 2), 3102 | (5852, 480), 3103 | (5853, 10), 3104 | (5862, 1289), 3105 | (5872, 191), 3106 | (5873, 162), 3107 | (5874, 38), 3108 | (5878, 2), 3109 | (5888, 616), 3110 | (5889, 12), 3111 | (5894, 1289), 3112 | (5905, 162), 3113 | (5908, 139), 3114 | (5910, 54), 3115 | (5922, 1), 3116 | (5924, 675), 3117 | (5925, 9), 3118 | (5926, 1289), 3119 | (5937, 162), 3120 | (5942, 2), 3121 | (5944, 153), 3122 | (5946, 48), 3123 | (5958, 1289), 3124 | (5960, 614), 3125 | (5961, 33), 3126 | (5969, 162), 3127 | (5974, 2), 3128 | (5980, 140), 3129 | (5982, 95), 3130 | (5990, 1289), 3131 | (5996, 628), 3132 | (5997, 10), 3133 | (6001, 162), 3134 | (6006, 2), 3135 | (6016, 155), 3136 | (6018, 67), 3137 | (6021, 42), 3138 | (6022, 1289), 3139 | (6024, 42), 3140 | (6032, 772), 3141 | (6033, 177), 3142 | (6038, 2), 3143 | (6049, 1), 3144 | (6052, 109), 3145 | (6054, 1340), 3146 | (6065, 162), 3147 | (6068, 749), 3148 | (6069, 11), 3149 | (6070, 2), 3150 | (6086, 1289), 3151 | (6088, 364), 3152 | (6090, 49), 3153 | (6096, 1), 3154 | (6097, 162), 3155 | (6102, 2), 3156 | (6104, 975), 3157 | (6105, 4), 3158 | (6106, 1), 3159 | (6118, 1289), 3160 | (6124, 273), 3161 | (6126, 58), 3162 | (6129, 162), 3163 | (6134, 2), 3164 | (6138, 1), 3165 | (6140, 1053), 3166 | (6141, 13), 3167 | (6150, 1289), 3168 | (6152, 1), 3169 | (6153, 2), 3170 | (6160, 372), 3171 | (6161, 162), 3172 | (6162, 70), 3173 | (6164, 1), 3174 | (6166, 2), 3175 | (6172, 1), 3176 | (6176, 1088), 3177 | (6177, 96), 3178 | (6178, 1), 3179 | (6182, 1290), 3180 | (6188, 4), 3181 | (6193, 162), 3182 | (6194, 1), 3183 | (6196, 346), 3184 | (6198, 101), 3185 | (6206, 1), 3186 | (6212, 1352), 3187 | (6213, 4), 3188 | (6214, 1290), 3189 | (6219, 2), 3190 | (6223, 1), 3191 | (6225, 162), 3192 | (6230, 1), 3193 | (6232, 321), 3194 | (6234, 170), 3195 | (6246, 1290), 3196 | (6248, 1755), 3197 | (6249, 4), 3198 | (6257, 162), 3199 | (6261, 4), 3200 | (6262, 1), 3201 | (6264, 4), 3202 | (6268, 616), 3203 | (6270, 141), 3204 | (6275, 1), 3205 | (6278, 1289), 3206 | (6280, 1), 3207 | (6281, 1), 3208 | (6284, 2516), 3209 | (6285, 73), 3210 | (6289, 162), 3211 | (6294, 1), 3212 | (6304, 409), 3213 | (6306, 163), 3214 | (6310, 1289), 3215 | (6314, 2), 3216 | (6320, 2276), 3217 | (6321, 210), 3218 | (6326, 1), 3219 | (6340, 445), 3220 | (6342, 1437), 3221 | (6353, 162), 3222 | (6356, 4090), 3223 | (6357, 55), 3224 | (6358, 1), 3225 | (6364, 1), 3226 | (6374, 1290), 3227 | (6376, 929), 3228 | (6378, 270), 3229 | (6385, 162), 3230 | (6390, 1), 3231 | (6392, 6135), 3232 | (6393, 16), 3233 | (6400, 1), 3234 | (6406, 1289), 3235 | (6412, 607), 3236 | (6414, 386), 3237 | (6417, 162), 3238 | (6420, 1), 3239 | (6421, 238), 3240 | (6422, 1), 3241 | (6424, 238), 3242 | (6428, 15189), 3243 | (6429, 227), 3244 | (6438, 1289), 3245 | (6443, 1), 3246 | (6448, 1211), 3247 | (6449, 162), 3248 | (6450, 1135), 3249 | (6453, 2), 3250 | (6454, 1), 3251 | (6464, 66588), 3252 | (6465, 77), 3253 | (6470, 1289), 3254 | (6474, 31), 3255 | (6481, 162), 3256 | (6484, 21001), 3257 | (6486, 9926), 3258 | (6488, 95), 3259 | (6498, 1), 3260 | (6500, 51017), 3261 | (6501, 2547), 3262 | (6502, 1289), 3263 | (6513, 162), 3264 | (6518, 1), 3265 | (6520, 11978), 3266 | (6522, 2546), 3267 | (6534, 1289), 3268 | (6536, 1), 3269 | (6537, 4), 3270 | (6539, 7), 3271 | (6545, 162), 3272 | (6546, 1), 3273 | (6550, 1), 3274 | (6553, 27), 3275 | (6566, 1289), 3276 | (6572, 1), 3277 | (6573, 2), 3278 | (6574, 1), 3279 | (6577, 163), 3280 | (6582, 2), 3281 | (6587, 1), 3282 | (6588, 17), 3283 | (6598, 1289), 3284 | (6600, 1), 3285 | (6603, 1), 3286 | (6605, 1), 3287 | (6606, 2), 3288 | (6608, 1), 3289 | (6609, 163), 3290 | (6610, 1), 3291 | (6614, 1), 3292 | (6623, 4), 3293 | (6630, 1289), 3294 | (6631, 1), 3295 | (6633, 1), 3296 | (6635, 1), 3297 | (6640, 1), 3298 | (6641, 162), 3299 | (6644, 1), 3300 | (6645, 2), 3301 | (6646, 2), 3302 | (6662, 1289), 3303 | (6666, 1), 3304 | (6670, 1), 3305 | (6673, 162), 3306 | (6678, 1), 3307 | (6679, 1), 3308 | (6680, 1), 3309 | (6681, 5), 3310 | (6686, 1), 3311 | (6694, 1289), 3312 | (6705, 162), 3313 | (6710, 1), 3314 | (6711, 1), 3315 | (6714, 1), 3316 | (6716, 1), 3317 | (6717, 10), 3318 | (6726, 1289), 3319 | (6734, 1), 3320 | (6737, 163), 3321 | (6738, 1), 3322 | (6740, 2), 3323 | (6742, 1), 3324 | (6752, 1), 3325 | (6753, 1), 3326 | (6757, 1), 3327 | (6758, 1289), 3328 | (6769, 162), 3329 | (6770, 1), 3330 | (6774, 1), 3331 | (6775, 1), 3332 | (6788, 1), 3333 | (6789, 3), 3334 | (6790, 1289), 3335 | (6797, 1), 3336 | (6801, 162), 3337 | (6802, 1), 3338 | (6803, 1), 3339 | (6806, 1), 3340 | (6818, 1), 3341 | (6819, 1), 3342 | (6822, 1289), 3343 | (6824, 1), 3344 | (6825, 5), 3345 | (6833, 162), 3346 | (6834, 1), 3347 | (6837, 1), 3348 | (6838, 1), 3349 | (6844, 2), 3350 | (6854, 1289), 3351 | (6860, 1), 3352 | (6861, 5), 3353 | (6865, 163), 3354 | (6869, 1), 3355 | (6870, 1), 3356 | (6872, 1), 3357 | (6875, 1), 3358 | (6881, 3), 3359 | (6886, 1289), 3360 | (6896, 1), 3361 | (6897, 166), 3362 | (6902, 1), 3363 | (6915, 1), 3364 | (6918, 1289), 3365 | (6929, 162), 3366 | (6932, 2), 3367 | (6933, 1), 3368 | (6934, 1), 3369 | (6947, 1), 3370 | (6950, 1290), 3371 | (6961, 162), 3372 | (6966, 1), 3373 | (6969, 2), 3374 | (6982, 1289), 3375 | (6993, 162), 3376 | (6998, 1), 3377 | (7004, 1), 3378 | (7005, 1), 3379 | (7014, 1289), 3380 | (7025, 162), 3381 | (7030, 1), 3382 | (7032, 1), 3383 | (7034, 1), 3384 | (7040, 1), 3385 | (7041, 1), 3386 | (7046, 1289), 3387 | (7057, 162), 3388 | (7058, 1), 3389 | (7059, 1), 3390 | (7062, 1), 3391 | (7070, 1), 3392 | (7076, 1), 3393 | (7077, 3), 3394 | (7078, 1289), 3395 | (7084, 1), 3396 | (7089, 162), 3397 | (7094, 1), 3398 | (7110, 1289), 3399 | (7112, 1), 3400 | (7113, 5), 3401 | (7121, 162), 3402 | (7124, 1), 3403 | (7126, 1), 3404 | (7133, 1), 3405 | (7142, 1289), 3406 | (7148, 1), 3407 | (7149, 12), 3408 | (7153, 162), 3409 | (7158, 1), 3410 | (7174, 1289), 3411 | (7184, 1), 3412 | (7185, 170), 3413 | (7190, 1), 3414 | (7206, 1289), 3415 | (7217, 162), 3416 | (7220, 1), 3417 | (7221, 82), 3418 | (7222, 1), 3419 | (7224, 81), 3420 | (7229, 1), 3421 | (7237, 1), 3422 | (7238, 1289), 3423 | (7242, 1), 3424 | (7243, 1), 3425 | (7248, 1), 3426 | (7249, 162), 3427 | (7254, 1), 3428 | (7256, 1), 3429 | (7257, 1), 3430 | (7266, 4), 3431 | (7270, 1289), 3432 | (7274, 13), 3433 | (7280, 20), 3434 | (7281, 162), 3435 | (7286, 1), 3436 | (7288, 12), 3437 | (7292, 1), 3438 | (7293, 5), 3439 | (7296, 1), 3440 | (7302, 1289), 3441 | (7308, 1), 3442 | (7313, 162), 3443 | (7315, 1), 3444 | (7318, 1), 3445 | (7328, 1), 3446 | (7329, 1), 3447 | (7334, 1290), 3448 | (7345, 162), 3449 | (7349, 1), 3450 | (7350, 1), 3451 | (7353, 1), 3452 | (7364, 1), 3453 | (7365, 1), 3454 | (7366, 1290), 3455 | (7377, 162), 3456 | (7382, 1), 3457 | (7392, 1), 3458 | (7398, 1289), 3459 | (7400, 1), 3460 | (7401, 4), 3461 | (7406, 1), 3462 | (7409, 162), 3463 | (7411, 1), 3464 | (7414, 1), 3465 | (7430, 1289), 3466 | (7431, 3), 3467 | (7436, 1), 3468 | (7437, 2), 3469 | (7441, 162), 3470 | (7445, 5), 3471 | (7446, 1), 3472 | (7448, 1), 3473 | (7460, 1), 3474 | (7462, 1289), 3475 | (7472, 1), 3476 | (7473, 166), 3477 | (7474, 1), 3478 | (7478, 1), 3479 | (7494, 1289), 3480 | (7505, 162), 3481 | (7508, 3), 3482 | (7509, 2), 3483 | (7510, 2), 3484 | (7525, 1), 3485 | (7526, 1289), 3486 | (7532, 1), 3487 | (7537, 162), 3488 | (7542, 1), 3489 | (7544, 1), 3490 | (7545, 9), 3491 | (7546, 1), 3492 | (7558, 1289), 3493 | (7569, 162), 3494 | (7574, 1), 3495 | (7580, 1), 3496 | (7581, 6), 3497 | (7590, 1289), 3498 | (7601, 162), 3499 | (7606, 1), 3500 | (7616, 1), 3501 | (7617, 6), 3502 | (7622, 1289), 3503 | (7623, 1), 3504 | (7625, 1), 3505 | (7633, 162), 3506 | (7638, 1), 3507 | (7652, 1), 3508 | (7653, 11), 3509 | (7654, 1289), 3510 | (7657, 1), 3511 | (7665, 162), 3512 | (7670, 1), 3513 | (7686, 1289), 3514 | (7688, 1), 3515 | (7689, 1), 3516 | (7697, 162), 3517 | (7702, 1), 3518 | (7708, 1), 3519 | (7715, 1), 3520 | (7717, 2), 3521 | (7718, 1289), 3522 | (7724, 1), 3523 | (7725, 3), 3524 | (7729, 162), 3525 | (7734, 1), 3526 | (7746, 1), 3527 | (7750, 1289), 3528 | (7760, 1), 3529 | (7761, 167), 3530 | (7766, 1), 3531 | (7782, 1289), 3532 | (7793, 162), 3533 | (7794, 1), 3534 | (7796, 1), 3535 | (7797, 1), 3536 | (7798, 1), 3537 | (7814, 1289), 3538 | (7820, 1), 3539 | (7825, 162), 3540 | (7826, 1), 3541 | (7830, 1), 3542 | (7832, 1), 3543 | (7833, 14), 3544 | (7842, 1), 3545 | (7846, 1289), 3546 | (7857, 162), 3547 | (7862, 1), 3548 | (7863, 1), 3549 | (7868, 1), 3550 | (7869, 4), 3551 | (7878, 1289), 3552 | (7885, 1), 3553 | (7889, 162), 3554 | (7894, 1), 3555 | (7904, 1), 3556 | (7905, 2), 3557 | (7910, 1289), 3558 | (7921, 162), 3559 | (7926, 1), 3560 | (7929, 1), 3561 | (7940, 1), 3562 | (7941, 2), 3563 | (7942, 1289), 3564 | (7953, 162), 3565 | (7958, 1), 3566 | (7963, 1), 3567 | (7973, 1), 3568 | (7974, 1289), 3569 | (7976, 1), 3570 | (7977, 16), 3571 | (7985, 162), 3572 | (7989, 1), 3573 | (7990, 1), 3574 | (7991, 1), 3575 | (7997, 1), 3576 | (8000, 1), 3577 | (8006, 1289), 3578 | (8012, 1), 3579 | (8013, 14), 3580 | (8017, 162), 3581 | (8022, 1), 3582 | (8038, 1289), 3583 | (8048, 1), 3584 | (8049, 185), 3585 | (8054, 2), 3586 | (8070, 1289), 3587 | (8081, 162), 3588 | (8084, 1), 3589 | (8085, 24), 3590 | (8086, 1), 3591 | (8102, 1289), 3592 | (8113, 162), 3593 | (8118, 1), 3594 | (8119, 1), 3595 | (8120, 1), 3596 | (8121, 1), 3597 | (8126, 1), 3598 | (8134, 1289), 3599 | (8140, 1), 3600 | (8145, 162), 3601 | (8150, 1), 3602 | (8157, 20), 3603 | (8166, 1289), 3604 | (8177, 162), 3605 | (8182, 1), 3606 | (8192, 1), 3607 | (8193, 1), 3608 | (8198, 1289), 3609 | (8209, 162), 3610 | (8214, 1), 3611 | (8228, 1), 3612 | (8229, 32), 3613 | (8230, 1290), 3614 | (8246, 1), 3615 | (8264, 1), 3616 | (8265, 27), 3617 | (8269, 1), 3618 | (8276, 1), 3619 | (8282, 1), 3620 | (8300, 1), 3621 | (8301, 133), 3622 | (8336, 2), 3623 | (8337, 60), 3624 | (8348, 3), 3625 | (8356, 1), 3626 | (8358, 1), 3627 | (8372, 1), 3628 | (8373, 196), 3629 | (8408, 1), 3630 | (8444, 1), 3631 | (8468, 1), 3632 | (8480, 1), 3633 | (8499, 1), 3634 | (8516, 1), 3635 | (8552, 1), 3636 | (8555, 1), 3637 | (8588, 1), 3638 | (8624, 1), 3639 | (8660, 3), 3640 | (8675, 1), 3641 | (8696, 1), 3642 | (8704, 1), 3643 | (8724, 1), 3644 | (8732, 1), 3645 | (8768, 1), 3646 | (8779, 1), 3647 | (8804, 1), 3648 | (8840, 1), 3649 | (8852, 2), 3650 | (8876, 1), 3651 | (8912, 1), 3652 | (8948, 1), 3653 | (8984, 1), 3654 | (9020, 1), 3655 | (9128, 1), 3656 | (9164, 1), 3657 | (9192, 1), 3658 | (9200, 2), 3659 | (9236, 1), 3660 | (9272, 1), 3661 | (9308, 1), 3662 | (9344, 1), 3663 | (9380, 1), 3664 | (9416, 1), 3665 | (9452, 1), 3666 | (9524, 1), 3667 | (9560, 1), 3668 | (9589, 1), 3669 | (9632, 1), 3670 | (9642, 1), 3671 | (9704, 1), 3672 | (9776, 1), 3673 | (9848, 1), 3674 | (9992, 1), 3675 | (10064, 1), 3676 | (10100, 1), 3677 | (10136, 1), 3678 | (10172, 1), 3679 | (10208, 1), 3680 | (10244, 1), 3681 | (10280, 1), 3682 | (10316, 1), 3683 | (10388, 1), 3684 | (10532, 1), 3685 | (10572, 1), 3686 | (10620, 1), 3687 | (10640, 1), 3688 | (10669, 1), 3689 | (10748, 1), 3690 | (10856, 1), 3691 | (10964, 1), 3692 | (11067, 1), 3693 | (11072, 1), 3694 | (11180, 1), 3695 | (11216, 1), 3696 | (11252, 1), 3697 | (11288, 1), 3698 | (11324, 1), 3699 | (11348, 2), 3700 | (11360, 1), 3701 | (11396, 1), 3702 | (11432, 1), 3703 | (11468, 1), 3704 | (11504, 1), 3705 | (11540, 1), 3706 | (11576, 1), 3707 | (11612, 1), 3708 | (11648, 1), 3709 | (11756, 1), 3710 | (11792, 1), 3711 | (11828, 1), 3712 | (11864, 1), 3713 | (11936, 1), 3714 | (12008, 1), 3715 | (12080, 1), 3716 | (12152, 1), 3717 | (12188, 1), 3718 | (12224, 1), 3719 | (12260, 1), 3720 | (12296, 1), 3721 | (12332, 1), 3722 | (12360, 1), 3723 | (12368, 1), 3724 | (12404, 1), 3725 | (12440, 1), 3726 | (12476, 1), 3727 | (12501, 2), 3728 | (12512, 1), 3729 | (12548, 1), 3730 | (12584, 1), 3731 | (12620, 1), 3732 | (12656, 1), 3733 | (12693, 1), 3734 | (12728, 1), 3735 | (12885, 1), 3736 | (13123, 1), 3737 | (13269, 1), 3738 | (13461, 1), 3739 | (13653, 1), 3740 | (13664, 1), 3741 | (13740, 1), 3742 | (13872, 1), 3743 | (13946, 1), 3744 | (14109, 1), 3745 | (14613, 2), 3746 | (14805, 2), 3747 | (14945, 1), 3748 | (14997, 1), 3749 | (15176, 1), 3750 | (15276, 1), 3751 | (15384, 1), 3752 | (15492, 1), 3753 | (15600, 1), 3754 | (15708, 1), 3755 | (15716, 1), 3756 | (15765, 1), 3757 | (15816, 1), 3758 | (15924, 1), 3759 | (16068, 1), 3760 | (16104, 1), 3761 | (16140, 1), 3762 | (16176, 1), 3763 | (16212, 1), 3764 | (16248, 1), 3765 | (16284, 1), 3766 | (16320, 1), 3767 | (16356, 1), 3768 | (16392, 1), 3769 | (16430, 1), 3770 | (16468, 1), 3771 | (16504, 1), 3772 | (16540, 1), 3773 | (16727, 2), 3774 | (16728, 1), 3775 | (16919, 2), 3776 | (16921, 1), 3777 | (16938, 1), 3778 | (17111, 6), 3779 | (17413, 1), 3780 | (17430, 1), 3781 | (17495, 1), 3782 | (17880, 1), 3783 | (18647, 2), 3784 | (18672, 1), 3785 | (19223, 38), 3786 | (19680, 1), 3787 | (20436, 1), 3788 | (21156, 1), 3789 | (21732, 1), 3790 | (22380, 1), 3791 | (22992, 1), 3792 | (23063, 17), 3793 | (23244, 1), 3794 | (23532, 1), 3795 | (23892, 1), 3796 | (24108, 1), 3797 | (24215, 1), 3798 | (24324, 1), 3799 | (24407, 2), 3800 | (24504, 1), 3801 | (24720, 1), 3802 | (24900, 1), 3803 | (24983, 205), 3804 | (25440, 1), 3805 | (25620, 1), 3806 | (26088, 1), 3807 | (26268, 1), 3808 | (26448, 1), 3809 | (26664, 1), 3810 | (26988, 1), 3811 | (27276, 1), 3812 | (27492, 1), 3813 | (27744, 1), 3814 | (28032, 1), 3815 | (28284, 1), 3816 | (28536, 1), 3817 | (28823, 42), 3818 | (28896, 1), 3819 | (29184, 1), 3820 | (29292, 1), 3821 | (29400, 1), 3822 | (29796, 1), 3823 | (29975, 4), 3824 | (30156, 1), 3825 | (30228, 1), 3826 | (30743, 238), 3827 | (30768, 1), 3828 | (31056, 1), 3829 | (31092, 1), 3830 | (31416, 1), 3831 | (32100, 1), 3832 | (32712, 1), 3833 | (33144, 1), 3834 | (33324, 1), 3835 | (33792, 1), 3836 | (34008, 1), 3837 | (34440, 1), 3838 | (34583, 81), 3839 | (34656, 1), 3840 | (34872, 1), 3841 | (34944, 1), 3842 | (35160, 1), 3843 | (35304, 1), 3844 | (35376, 1), 3845 | (35412, 1), 3846 | (35556, 1), 3847 | (35628, 1), 3848 | (35664, 1), 3849 | (35808, 1), 3850 | (36204, 1), 3851 | (36744, 1), 3852 | (37788, 1), 3853 | (39372, 1), 3854 | (40956, 1), 3855 | (41640, 1), 3856 | (41892, 1), 3857 | (42144, 1), 3858 | (42576, 1), 3859 | (42936, 1), 3860 | (43476, 1), 3861 | (45096, 1), 3862 | (47256, 1), 3863 | (47760, 1), 3864 | (47796, 1), 3865 | (47868, 1), 3866 | (48228, 1), 3867 | (48948, 1), 3868 | (49128, 1), 3869 | (49452, 1), 3870 | (49560, 1), 3871 | (49668, 1), 3872 | (49776, 1), 3873 | (50352, 1), 3874 | (50964, 1), 3875 | (52008, 1), 3876 | (53880, 1), 3877 | (55284, 1), 3878 | (55860, 1), 3879 | (56040, 1), 3880 | (56400, 1), 3881 | (56904, 1), 3882 | (57444, 1), 3883 | (59424, 1), 3884 | (60156, 1), 3885 | (60626, 1), 3886 | (60641, 1), 3887 | (61260, 1), 3888 | (62520, 1), 3889 | (64392, 1), 3890 | (65976, 1), 3891 | (67308, 1), 3892 | (68064, 1), 3893 | (68748, 1), 3894 | (69216, 1), 3895 | (69504, 1), 3896 | (69648, 1), 3897 | (69684, 1), 3898 | (69720, 1), 3899 | (69756, 1), 3900 | (69792, 1), 3901 | (69828, 1), 3902 | (70224, 1), 3903 | (70620, 1), 3904 | (71016, 1), 3905 | (71412, 1), 3906 | (71772, 1), 3907 | (71952, 1), 3908 | (72024, 1), 3909 | (72096, 1), 3910 | (72168, 1), 3911 | (72240, 1), 3912 | (72312, 1), 3913 | (72348, 1), 3914 | (72420, 1), 3915 | (72492, 1), 3916 | (72600, 1), 3917 | (72672, 1), 3918 | (72780, 1), 3919 | (72996, 1), 3920 | (73320, 1), 3921 | (73356, 1), 3922 | (73500, 1), 3923 | (73536, 1), 3924 | (73572, 1), 3925 | (73608, 1), 3926 | (73680, 1), 3927 | (73716, 1), 3928 | (73788, 1), 3929 | (73896, 1), 3930 | (74040, 1), 3931 | (74112, 1), 3932 | (74170, 1), 3933 | (74184, 1), 3934 | (74185, 1), 3935 | (74220, 1), 3936 | (74256, 1), 3937 | (74292, 1), 3938 | (74328, 1), 3939 | (74364, 1), 3940 | (74400, 1), 3941 | (74436, 1), 3942 | (74472, 1), 3943 | (74616, 1), 3944 | (74976, 1), 3945 | (75156, 1), 3946 | (75228, 1), 3947 | (75336, 1), 3948 | (75408, 1), 3949 | (75588, 1), 3950 | (75696, 1), 3951 | (75804, 1), 3952 | (75984, 1), 3953 | (76056, 1), 3954 | (76164, 1), 3955 | (76308, 1), 3956 | (76452, 1), 3957 | (76560, 1), 3958 | (76776, 1), 3959 | (76920, 1), 3960 | (77064, 1), 3961 | (77208, 1), 3962 | (77316, 1), 3963 | (77532, 1), 3964 | (77676, 1), 3965 | (77748, 1), 3966 | (77820, 1), 3967 | (77928, 1), 3968 | (78000, 1), 3969 | (78036, 1), 3970 | (78072, 1), 3971 | (78108, 1), 3972 | (78180, 1), 3973 | (78324, 1), 3974 | (78396, 1), 3975 | (78576, 1), 3976 | (78684, 1), 3977 | (78828, 1), 3978 | (78864, 1), 3979 | (78900, 1), 3980 | (78972, 1), 3981 | (79080, 1), 3982 | (79116, 1), 3983 | (79152, 1), 3984 | (79512, 1), 3985 | (79872, 1), 3986 | (80268, 1), 3987 | (80592, 1), 3988 | (80700, 1), 3989 | (80916, 1), 3990 | (81168, 1), 3991 | (81276, 1), 3992 | (81528, 1), 3993 | (81708, 1), 3994 | (81816, 1), 3995 | (81888, 1), 3996 | (82068, 1), 3997 | (82176, 1), 3998 | (82284, 1), 3999 | (82356, 1), 4000 | (82716, 1), 4001 | (83004, 1), 4002 | (83312, 1), 4003 | (83436, 1), 4004 | (83688, 1), 4005 | (83904, 1), 4006 | (84012, 1), 4007 | (84408, 1), 4008 | (84660, 1), 4009 | (85056, 1), 4010 | (85488, 1), 4011 | (85776, 1), 4012 | (85992, 1), 4013 | (86172, 1), 4014 | (86424, 1), 4015 | (86615, 1), 4016 | (86640, 1), 4017 | (86928, 1), 4018 | (87072, 1), 4019 | (87288, 1), 4020 | (87576, 1), 4021 | (87684, 1), 4022 | (87756, 1), 4023 | (87972, 1), 4024 | (88044, 1), 4025 | (88152, 1), 4026 | (88368, 1), 4027 | (88728, 1), 4028 | (88836, 1), 4029 | (88944, 1), 4030 | (89088, 1), 4031 | (89448, 1), 4032 | (89592, 1), 4033 | (89700, 1), 4034 | (89808, 1), 4035 | (89952, 1), 4036 | (90060, 1), 4037 | (90204, 1), 4038 | (90348, 1), 4039 | (90528, 1), 4040 | (90636, 1), 4041 | (90744, 1), 4042 | (90816, 1), 4043 | (91032, 1), 4044 | (91068, 1), 4045 | (91140, 1), 4046 | (91212, 1), 4047 | (91284, 1), 4048 | (91860, 1), 4049 | (92112, 1), 4050 | (92292, 1), 4051 | (92400, 1), 4052 | (92544, 1), 4053 | (92652, 1), 4054 | (92796, 1), 4055 | (92904, 1), 4056 | (92976, 1), 4057 | (93192, 1), 4058 | (93300, 1), 4059 | (93444, 1), 4060 | (93516, 1), 4061 | (93624, 1), 4062 | (93696, 1), 4063 | (93840, 1), 4064 | (93984, 1), 4065 | (94056, 1), 4066 | (94128, 1), 4067 | (94164, 1), 4068 | (94200, 1), 4069 | (94236, 1), 4070 | (94272, 1), 4071 | (94344, 1), 4072 | (94452, 1), 4073 | (94524, 1), 4074 | (94596, 1), 4075 | (94704, 1), 4076 | (94776, 1), 4077 | (94884, 1), 4078 | (94956, 1), 4079 | (95172, 1), 4080 | (95244, 1), 4081 | (95280, 1), 4082 | (95316, 1), 4083 | (95352, 1), 4084 | (95388, 1), 4085 | (95424, 1), 4086 | (95460, 1), 4087 | (95496, 1), 4088 | (95604, 1), 4089 | (95676, 1), 4090 | (95784, 1), 4091 | (95856, 1), 4092 | (95928, 1), 4093 | (96000, 1), 4094 | (96036, 1), 4095 | (96072, 1), 4096 | (96108, 1), 4097 | (96144, 1), 4098 | (96180, 1), 4099 | (96216, 1), 4100 | (96288, 1), 4101 | (96576, 1), 4102 | (98029, 1), 4103 | (98304, 1), 4104 | (98527, 1), 4105 | (98628, 1), 4106 | (99276, 1), 4107 | (99528, 1), 4108 | (99780, 1), 4109 | (99996, 1), 4110 | (100212, 1), 4111 | (100428, 1), 4112 | (100680, 1), 4113 | (100752, 1), 4114 | (100788, 1), 4115 | (100860, 1), 4116 | (100932, 1), 4117 | (101004, 1), 4118 | (101076, 1), 4119 | (101148, 1), 4120 | (101220, 1), 4121 | (101256, 1), 4122 | (101328, 1), 4123 | (101364, 1), 4124 | (101400, 1), 4125 | (101436, 1), 4126 | (101472, 1), 4127 | (101508, 1), 4128 | (101544, 1), 4129 | (101616, 1), 4130 | (101652, 1), 4131 | (101724, 1), 4132 | (101832, 1), 4133 | (101904, 1), 4134 | (101940, 1), 4135 | (101976, 1), 4136 | (102012, 1), 4137 | (102048, 1), 4138 | (102084, 1), 4139 | (102120, 1), 4140 | (102264, 1), 4141 | (102516, 1), 4142 | (102588, 1), 4143 | (102624, 1), 4144 | (102660, 1), 4145 | (102696, 1), 4146 | (102732, 1), 4147 | (102768, 1), 4148 | (102804, 1), 4149 | (102840, 1), 4150 | (102876, 1), 4151 | (102912, 1), 4152 | (102948, 1), 4153 | (102984, 1), 4154 | (103056, 1), 4155 | (103092, 1), 4156 | (103128, 1), 4157 | (103164, 1), 4158 | (103200, 1), 4159 | (103236, 1), 4160 | (103272, 1), 4161 | (103308, 1), 4162 | (103344, 1), 4163 | (103380, 1), 4164 | (103452, 1), 4165 | (103560, 1), 4166 | (103596, 1), 4167 | (103632, 1), 4168 | (103668, 1), 4169 | (103704, 1), 4170 | (103740, 1), 4171 | (103776, 1), 4172 | (103848, 1), 4173 | (103920, 1), 4174 | (103956, 1), 4175 | (104028, 1), 4176 | (104100, 1), 4177 | (104136, 1), 4178 | (104208, 1), 4179 | (104244, 1), 4180 | (104316, 1), 4181 | (104352, 1), 4182 | (104388, 1), 4183 | (104424, 1), 4184 | (104460, 1), 4185 | (104496, 1), 4186 | (104532, 1), 4187 | (104568, 1), 4188 | (104604, 1), 4189 | (104676, 1), 4190 | (104712, 1), 4191 | (104748, 1), 4192 | (104784, 1), 4193 | (104820, 1), 4194 | (104856, 1), 4195 | (104892, 1), 4196 | (104928, 1), 4197 | (104964, 1), 4198 | (105000, 1), 4199 | (105036, 1), 4200 | (105072, 1), 4201 | (105108, 1), 4202 | (105216, 1), 4203 | (105324, 1), 4204 | (105360, 1), 4205 | (105396, 1), 4206 | (105432, 1), 4207 | (105468, 1), 4208 | (105504, 1), 4209 | (105540, 1), 4210 | (105576, 1), 4211 | (105612, 1), 4212 | (105648, 1), 4213 | (105684, 1), 4214 | (105720, 1), 4215 | (105756, 1), 4216 | (105792, 1), 4217 | (105828, 1), 4218 | (105864, 1), 4219 | (105900, 1), 4220 | (105936, 1), 4221 | (110580, 1), 4222 | (115224, 1), 4223 | (118788, 1), 4224 | (121056, 1), 4225 | (121452, 1), 4226 | (121848, 1), 4227 | (122244, 1), 4228 | (122604, 1), 4229 | (122928, 1), 4230 | (123252, 1), 4231 | (123288, 1), 4232 | (123360, 1), 4233 | (123432, 1), 4234 | (123468, 1), 4235 | (123504, 1), 4236 | (123540, 1), 4237 | (123612, 1), 4238 | (123684, 1), 4239 | (123756, 1), 4240 | (123828, 1), 4241 | (123900, 1), 4242 | (123972, 1), 4243 | (124080, 1), 4244 | (124188, 1), 4245 | (124296, 1), 4246 | (124404, 1), 4247 | (124548, 1), 4248 | (124764, 1), 4249 | (124872, 1), 4250 | (124980, 1), 4251 | (125088, 1), 4252 | (125196, 1), 4253 | (125304, 1), 4254 | (125412, 1), 4255 | (125448, 1), 4256 | (125520, 1), 4257 | (125628, 1), 4258 | (125700, 1), 4259 | (125772, 1), 4260 | (125844, 1), 4261 | (125880, 1), 4262 | (125916, 1), 4263 | (125952, 1), 4264 | (125988, 1), 4265 | (126024, 1), 4266 | (126060, 1), 4267 | (126096, 1), 4268 | (126168, 1), 4269 | (126276, 1), 4270 | (126312, 1), 4271 | (126348, 1), 4272 | (126420, 1), 4273 | (126492, 1), 4274 | (126564, 1), 4275 | (126636, 1), 4276 | (126708, 1), 4277 | (126780, 1), 4278 | (126852, 1), 4279 | (126960, 1), 4280 | (127068, 1), 4281 | (127176, 1), 4282 | (127212, 1), 4283 | (127248, 1), 4284 | (127284, 1), 4285 | (127320, 1), 4286 | (127356, 1), 4287 | (127392, 1), 4288 | (127464, 1), 4289 | (127536, 1), 4290 | (127608, 1), 4291 | (127644, 1), 4292 | (127680, 1), 4293 | (127716, 1), 4294 | (127788, 1), 4295 | (127860, 1), 4296 | (127932, 1), 4297 | (128004, 1), 4298 | (128076, 1), 4299 | (128148, 1), 4300 | (128220, 1), 4301 | (128256, 1), 4302 | (128292, 1), 4303 | (128328, 1), 4304 | (128364, 1), 4305 | (128400, 1), 4306 | (128436, 1), 4307 | (128472, 1), 4308 | (128508, 1), 4309 | (128544, 1), 4310 | (128580, 1), 4311 | (128616, 1), 4312 | (128652, 1), 4313 | (128688, 1), 4314 | (128724, 1), 4315 | (128760, 1), 4316 | (128832, 1), 4317 | (128904, 1), 4318 | (128976, 1), 4319 | (129048, 1), 4320 | (129120, 1), 4321 | (129192, 1), 4322 | (129228, 1), 4323 | (129264, 1), 4324 | (129300, 1), 4325 | (129372, 1), 4326 | (129408, 1), 4327 | (129444, 1), 4328 | (129480, 1), 4329 | (129516, 1), 4330 | (129552, 1), 4331 | (129588, 1), 4332 | (129660, 1), 4333 | (129732, 1), 4334 | (129768, 1), 4335 | (129804, 1), 4336 | (129840, 1), 4337 | (129876, 1), 4338 | (129912, 1), 4339 | (129948, 1), 4340 | (129984, 1), 4341 | (130020, 1), 4342 | (130056, 1), 4343 | (130128, 1), 4344 | (130200, 1), 4345 | (130236, 1), 4346 | (130272, 1), 4347 | (130308, 1), 4348 | (130380, 1), 4349 | (130452, 1), 4350 | (130524, 1), 4351 | (130560, 1), 4352 | (130596, 1), 4353 | (130632, 1), 4354 | (130668, 1), 4355 | (130704, 1), 4356 | (130776, 1), 4357 | (130812, 1), 4358 | (130848, 1), 4359 | (130920, 1), 4360 | (130992, 1), 4361 | (131064, 1), 4362 | (131136, 1), 4363 | (131172, 1), 4364 | (131208, 1), 4365 | (131244, 1), 4366 | (131316, 1), 4367 | (131388, 1), 4368 | (131424, 1), 4369 | (131532, 1), 4370 | (131640, 1), 4371 | (131784, 1), 4372 | (131892, 1), 4373 | (131964, 1), 4374 | (132036, 1), 4375 | (132108, 1), 4376 | (132180, 1), 4377 | (132252, 1), 4378 | (132324, 1), 4379 | (132360, 1), 4380 | (132432, 1), 4381 | (132504, 1), 4382 | (132576, 1), 4383 | (132684, 1), 4384 | (132792, 1), 4385 | (132900, 1), 4386 | (132972, 1), 4387 | (133044, 1), 4388 | (133116, 1), 4389 | (133188, 1), 4390 | (133260, 1), 4391 | (133332, 1), 4392 | (133368, 1), 4393 | (133404, 1), 4394 | (133440, 1), 4395 | (133476, 1), 4396 | (133512, 1), 4397 | (133548, 1), 4398 | (133620, 1), 4399 | (133692, 1), 4400 | (133764, 1), 4401 | (133836, 1), 4402 | (133908, 1), 4403 | (133980, 1), 4404 | (134016, 1), 4405 | (134052, 1), 4406 | (134088, 1), 4407 | (134124, 1), 4408 | (134160, 1), 4409 | (134196, 1), 4410 | (134232, 1), 4411 | (134268, 1), 4412 | (134304, 1), 4413 | (134340, 1), 4414 | (134376, 1), 4415 | (134412, 1), 4416 | (134484, 1), 4417 | (134592, 1), 4418 | (134700, 1), 4419 | (134808, 1), 4420 | (134916, 1), 4421 | (134988, 1), 4422 | (135024, 1), 4423 | (135060, 1), 4424 | (135096, 1), 4425 | (135132, 1), 4426 | (135168, 1), 4427 | (135204, 1), 4428 | (135240, 1), 4429 | (135276, 1), 4430 | (135312, 1), 4431 | (135348, 1), 4432 | (135384, 1), 4433 | (135456, 1), 4434 | (135492, 1), 4435 | (135528, 1), 4436 | (135564, 1), 4437 | (135600, 1), 4438 | (135636, 1), 4439 | (135672, 1), 4440 | (135708, 1), 4441 | (135744, 1), 4442 | (135780, 1), 4443 | (135816, 1), 4444 | (135852, 1), 4445 | (135888, 1), 4446 | (135924, 1), 4447 | (135960, 1), 4448 | (135996, 1), 4449 | (136032, 1), 4450 | (136068, 1), 4451 | (136140, 1), 4452 | (136212, 1), 4453 | (136284, 1), 4454 | (136356, 1), 4455 | (136428, 1), 4456 | (136500, 1), 4457 | (136572, 1), 4458 | (136608, 1), 4459 | (136644, 1), 4460 | (136680, 1), 4461 | (136716, 1), 4462 | (136752, 1), 4463 | (136788, 1), 4464 | (136824, 1), 4465 | (136860, 1), 4466 | (136896, 1), 4467 | (136932, 1), 4468 | (136968, 1), 4469 | (137004, 1), 4470 | (137040, 1), 4471 | (137076, 1), 4472 | (137112, 1), 4473 | (137148, 1), 4474 | (137184, 1), 4475 | (137256, 1), 4476 | (137328, 1), 4477 | (137400, 1), 4478 | (137472, 1), 4479 | (137544, 1), 4480 | (137580, 1), 4481 | (137616, 1), 4482 | (137652, 1), 4483 | (137688, 1), 4484 | (137724, 1), 4485 | (137796, 1), 4486 | (137832, 1), 4487 | (137868, 1), 4488 | (137904, 1), 4489 | (137940, 1), 4490 | (137976, 1), 4491 | (138012, 1), 4492 | (138048, 1), 4493 | (138084, 1), 4494 | (138120, 1), 4495 | (138228, 1), 4496 | (138300, 1), 4497 | (138336, 1), 4498 | (138372, 1), 4499 | (138408, 1), 4500 | (138444, 1), 4501 | (138480, 1), 4502 | (138516, 1), 4503 | (138552, 1), 4504 | (138588, 1), 4505 | (138624, 1), 4506 | (138696, 1), 4507 | (138768, 1), 4508 | (138840, 1), 4509 | (138912, 1), 4510 | (138948, 1), 4511 | (138984, 1), 4512 | (139020, 1), 4513 | (139056, 1), 4514 | (139092, 1), 4515 | (139128, 1), 4516 | (139164, 1), 4517 | (139200, 1), 4518 | (139272, 1), 4519 | (139308, 1), 4520 | (139380, 1), 4521 | (139452, 1), 4522 | (139488, 1), 4523 | (139524, 1), 4524 | (139596, 1), 4525 | (139632, 1), 4526 | (139668, 1), 4527 | (139704, 1), 4528 | (139740, 1), 4529 | (139776, 1), 4530 | (139848, 1), 4531 | (139884, 1), 4532 | (139920, 1), 4533 | (139956, 1), 4534 | (139992, 1), 4535 | (140028, 1), 4536 | (140064, 1), 4537 | (140136, 1), 4538 | (140172, 1), 4539 | (140208, 1), 4540 | (140244, 1), 4541 | (140280, 1), 4542 | (140316, 1), 4543 | (140352, 1), 4544 | (140424, 1), 4545 | (140460, 1), 4546 | (140496, 1), 4547 | (140532, 1), 4548 | (140604, 1), 4549 | (140640, 1), 4550 | (140676, 1), 4551 | (140712, 1), 4552 | (140748, 1), 4553 | (140784, 1), 4554 | (140820, 1), 4555 | (140856, 1), 4556 | (140928, 1), 4557 | (141036, 1), 4558 | (141072, 1), 4559 | (141108, 1), 4560 | (141144, 1), 4561 | (141180, 1), 4562 | (141216, 1), 4563 | (141252, 1), 4564 | (141324, 1), 4565 | (141396, 1), 4566 | (141432, 1), 4567 | (141468, 1), 4568 | (141504, 1), 4569 | (141612, 1), 4570 | (142152, 1), 4571 | (142188, 1), 4572 | (142260, 1), 4573 | (142296, 1), 4574 | (142800, 1), 4575 | (143304, 1), 4576 | (143376, 1), 4577 | (143448, 1), 4578 | (143520, 1), 4579 | (143592, 1), 4580 | (143664, 1), 4581 | (143700, 1), 4582 | (143736, 1), 4583 | (143772, 1), 4584 | (143808, 1), 4585 | (143844, 1), 4586 | (143880, 1), 4587 | (143952, 1), 4588 | (144096, 1), 4589 | (144240, 1), 4590 | (144348, 1), 4591 | (144456, 1), 4592 | (144564, 1), 4593 | (144672, 1), 4594 | (144708, 1), 4595 | (144744, 1), 4596 | (144780, 1), 4597 | (144816, 1), 4598 | (144852, 1), 4599 | (144888, 1), 4600 | (144924, 1), 4601 | (144960, 1), 4602 | (144996, 1), 4603 | (145032, 1), 4604 | (145068, 1), 4605 | (145104, 1), 4606 | (145140, 1), 4607 | (145176, 1), 4608 | (145212, 1), 4609 | (145248, 1), 4610 | (145284, 1), 4611 | (145320, 1), 4612 | (145356, 1), 4613 | (145392, 1), 4614 | (145464, 1), 4615 | (145500, 1), 4616 | (145536, 1), 4617 | (145572, 1), 4618 | (145644, 1), 4619 | (145716, 1), 4620 | (145752, 1), 4621 | (145788, 1), 4622 | (145824, 1), 4623 | (145860, 1), 4624 | (145896, 1), 4625 | (145932, 1), 4626 | (145968, 1), 4627 | (146004, 1), 4628 | (146040, 1), 4629 | (146076, 1), 4630 | (146112, 1), 4631 | (146148, 1), 4632 | (146184, 1), 4633 | (146220, 1), 4634 | (146256, 1), 4635 | (146292, 1), 4636 | (146328, 1), 4637 | (146364, 1), 4638 | (146400, 1), 4639 | (146436, 1), 4640 | (146472, 1), 4641 | (146508, 1), 4642 | (146544, 1), 4643 | (146580, 1), 4644 | (146616, 1), 4645 | (146652, 1), 4646 | (146688, 1), 4647 | (146724, 1), 4648 | (146760, 1), 4649 | (146796, 1), 4650 | (146832, 1), 4651 | (146868, 1), 4652 | (146940, 1), 4653 | (146976, 1), 4654 | (147012, 1), 4655 | (147048, 1), 4656 | (147084, 1), 4657 | (147120, 1), 4658 | (147156, 1), 4659 | (147192, 1), 4660 | (147228, 1), 4661 | (147264, 1), 4662 | (147300, 1), 4663 | (147336, 1), 4664 | (147372, 1), 4665 | (147408, 1), 4666 | (147444, 1), 4667 | (147480, 1), 4668 | (147516, 1), 4669 | (147552, 1), 4670 | (147588, 1), 4671 | (147624, 1), 4672 | (147660, 1), 4673 | (147732, 1), 4674 | (147768, 1), 4675 | (147804, 1), 4676 | (147840, 1), 4677 | (147876, 1), 4678 | (147912, 1), 4679 | (147948, 1), 4680 | (147984, 1), 4681 | (148020, 1), 4682 | (148056, 1), 4683 | (148092, 1), 4684 | (148128, 1), 4685 | (148164, 1), 4686 | (148200, 1), 4687 | (148236, 1), 4688 | (148272, 1), 4689 | (1070556, 1), 4690 | (1079378, 1), 4691 | (1085421, 1), 4692 | (1086835, 1), 4693 | (1121118, 1), 4694 | (1121208, 1), 4695 | (1124515, 1), 4696 | (1128287, 1), 4697 | (1128379, 1), 4698 | (1153308, 1), 4699 | (1153342, 4), 4700 | (1153344, 5), 4701 | (1153398, 1), 4702 | (1153571, 1), 4703 | (1153663, 1), 4704 | (1153670, 1), 4705 | (1153672, 3), 4706 | (1153688, 3), 4707 | (1154504, 1), 4708 | (1154538, 5), 4709 | (1154540, 6), 4710 | (1154596, 1), 4711 | (1164963, 1), 4712 | (1165053, 1), 4713 | (1166494, 1), 4714 | (1166586, 1), 4715 | (1175528, 1), 4716 | (1175636, 1), 4717 | (1177016, 1), 4718 | (1193653, 1), 4719 | (1193743, 1), 4720 | (1205060, 1), 4721 | (1205152, 1), 4722 | (1323322, 1), 4723 | (1323414, 1), 4724 | (1336354, 1), 4725 | (1336444, 1), 4726 | (1348925, 1), 4727 | (1349015, 1), 4728 | (1353326, 1), 4729 | (1353418, 1), 4730 | (1426757, 1), 4731 | (1426845, 1), 4732 | (1426847, 1), 4733 | (1426937, 1), 4734 | (1476463, 1), 4735 | (1476553, 1), 4736 | (1516580, 1), 4737 | (1516670, 1), 4738 | (1605731, 1), 4739 | (1605821, 1), 4740 | ]; -------------------------------------------------------------------------------- /src/content.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use parking_lot::MappedRwLockReadGuard; 3 | 4 | use crate::datum_size::DatumSize; 5 | use crate::types::{KeyType, EntryIndex, TableIndex}; 6 | use crate::content_address::ContentAddress; 7 | use crate::table::{Table, TableItemIndex, RefCount, TableItemCount}; 8 | use crate::Error; 9 | 10 | pub struct Content { 11 | path: PathBuf, 12 | tables: Vec>>, 13 | min_items_backed: TableItemCount, 14 | trigger_oversize_mapped: usize, 15 | shrink_oversize_mapped: usize, 16 | _dummy: std::marker::PhantomData, 17 | } 18 | 19 | impl Content { 20 | /// Creates a new content table of `datum_size`. 21 | fn new_table(&mut self, datum_size: DatumSize) -> (TableIndex, &mut Table) { 22 | let s = ::from(datum_size); 23 | let table_index = self.tables[s as usize].len(); 24 | let table_path = self.table_path(s, table_index); 25 | self.tables[s as usize].push(Table::open(table_path, datum_size, self.min_items_backed)); 26 | (table_index, &mut self.tables[s as usize][table_index]) 27 | } 28 | 29 | /// Generates the file name of a content table with `size_class` and `table_index`. 30 | fn table_name(size_class: u8, table_index: TableIndex) -> String { 31 | format!("{}-{}.content", size_class, table_index) 32 | } 33 | 34 | /// Generates the path for a content table with `size_class` and `table_index`. 35 | fn table_path(&self, size_class: u8, table_index: TableIndex) -> PathBuf { 36 | let mut table_path = self.path.clone(); 37 | table_path.push(&Self::table_name(size_class, table_index)); 38 | table_path 39 | } 40 | 41 | pub fn commit(&mut self) { 42 | for tables in self.tables.iter_mut() { 43 | for table in tables.iter_mut() { 44 | table.commit(); 45 | } 46 | } 47 | } 48 | 49 | /// Get the raw reference to an item's content value, optionally checking its hash to ensure 50 | /// it's the right item. 51 | pub fn item_ref(&self, address: &ContentAddress, check_hash: Option<&K>) -> Result, ()> { 52 | let s = u8::from(address.datum_size) as usize; 53 | self.tables[s as usize][address.content_table] 54 | .item_ref(address.entry_index as TableItemIndex, check_hash) 55 | } 56 | 57 | /// Get the reference count for an item, optionally checking its hash to ensure 58 | /// it's the right item. 59 | pub fn item_ref_count(&self, address: &ContentAddress, check_hash: Option<&K>) -> Result { 60 | let s = u8::from(address.datum_size) as usize; 61 | self.tables[s as usize][address.content_table] 62 | .item_ref_count(address.entry_index as TableItemIndex, check_hash) 63 | } 64 | 65 | /// Get the reference count for an item, optionally checking its hash to ensure 66 | /// it's the right item. 67 | #[allow(dead_code)] 68 | pub fn item_hash(&self, address: &ContentAddress) -> Result { 69 | let s = u8::from(address.datum_size) as usize; 70 | self.tables[s as usize][address.content_table] 71 | .item_hash(address.entry_index as TableItemIndex) 72 | } 73 | 74 | /// Allocate space to store an item's contents and return its content address. 75 | /// 76 | /// - `datum_size` is the size class of the item. 77 | /// - `key` is the hash key of the item. 78 | /// - `actual_size` is its real size, never more than `datum_size.size()`. 79 | fn allocate(&mut self, key: &K, actual_size: usize) -> ContentAddress { 80 | let datum_size = DatumSize::nearest(actual_size); 81 | let s = u8::from(datum_size) as usize; 82 | for (content_table, table) in self.tables[s as usize].iter_mut().enumerate() { 83 | if let Some(entry_index) = table.allocate(key, actual_size) { 84 | return ContentAddress { datum_size, content_table, entry_index: entry_index as EntryIndex }; 85 | } 86 | } 87 | // Out of space - would create a new table 88 | let (content_table, table) = self.new_table(datum_size); 89 | let entry_index = table.allocate(key, actual_size).expect("Freshly created"); 90 | ContentAddress { datum_size, content_table, entry_index: entry_index as EntryIndex } 91 | } 92 | 93 | /// Allocate space to store an item's contents, fill with data and return its content address. 94 | /// 95 | /// - `datum_size` is the size class of the item. 96 | /// - `key` is the hash key of the item. 97 | /// - `data` is its data, whose length is never more than `datum_size.size()`. 98 | pub fn emplace(&mut self, key: &K, data: &[u8]) -> ContentAddress { 99 | let address = self.allocate(key, data.len()); 100 | let s = u8::from(address.datum_size) as usize; 101 | self.tables[s as usize][address.content_table] 102 | .set_item(address.entry_index as TableItemIndex, data) 103 | .expect("Unexpected error setting item"); 104 | self.idle(); 105 | address 106 | } 107 | 108 | /// Increment the references for an item given its content `address` and optionally checking 109 | /// that its key hash is the expected `check_hash`. 110 | pub fn bump(&mut self, address: &ContentAddress, check_hash: Option<&K>) -> Result { 111 | let s = u8::from(address.datum_size) as usize; 112 | let r = self.tables[s as usize][address.content_table] 113 | .bump(address.entry_index as TableItemIndex, check_hash); 114 | self.idle(); 115 | r 116 | } 117 | 118 | /// Decrement the references for an item given its content `address` and optionally checking 119 | /// that its key hash is the expected `check_hash`. If they are decremented to zero then the 120 | /// storage used for the item will be freed. 121 | pub fn free(&mut self, address: &ContentAddress, check_hash: Option<&K>) -> Result { 122 | let s = u8::from(address.datum_size) as usize; 123 | let r = self.tables[s as usize][address.content_table] 124 | .free(address.entry_index as TableItemIndex, check_hash); 125 | self.idle(); 126 | r 127 | } 128 | 129 | /// Reduce the amount we have mapped in our oversize tables, if above the trigger amount. 130 | pub fn idle(&mut self) { 131 | for t in self.tables[63].iter_mut() { 132 | t.shrink_to(self.trigger_oversize_mapped, self.shrink_oversize_mapped); 133 | } 134 | } 135 | 136 | pub fn open( 137 | path: PathBuf, 138 | trigger_oversize_mapped: usize, 139 | shrink_oversize_mapped: usize, 140 | min_items_backed: TableItemCount, 141 | ) -> Result { 142 | let tables = (0u8..64).map(|size| (0usize..) 143 | .map(|table_index| { 144 | let mut table_path = path.clone(); 145 | table_path.push(&Self::table_name(size, table_index)); 146 | table_path 147 | }) 148 | .take_while(|table_path| table_path.is_file()) 149 | .map(|table_path| Table::open(table_path, DatumSize::from(size), min_items_backed)) 150 | .collect() 151 | ).collect(); 152 | 153 | Ok(Self { path, tables, min_items_backed, trigger_oversize_mapped, shrink_oversize_mapped, _dummy: Default::default() }) 154 | } 155 | 156 | pub fn info(&self) -> Vec<((DatumSize, usize), (TableItemCount, TableItemCount, usize, usize))> { 157 | self.tables.iter() 158 | .enumerate() 159 | .map(|(z, tables)| (DatumSize::from(z as u8), tables)) 160 | .flat_map(|(datum_size, tables)| tables.iter() 161 | .enumerate() 162 | .map(|(index, table)| ((datum_size, index), (table.available(), table.used(), table.bytes_used(), table.bytes_mapped()))) 163 | .collect::>() 164 | ) 165 | .collect() 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/content_address.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use parity_scale_codec::{self as codec, Encode, Decode}; 3 | use crate::types::{TableIndex, EntryIndex, EncodedSize}; 4 | use crate::datum_size::DatumSize; 5 | 6 | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode)] 7 | pub struct CompactContentAddress(u32); 8 | 9 | impl fmt::Debug for CompactContentAddress { 10 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 11 | write!(f, "{:x?} ({:?})", self.0, ContentAddress::from(*self)) 12 | } 13 | } 14 | 15 | impl EncodedSize for CompactContentAddress { 16 | fn encoded_size() -> usize { 4 } 17 | } 18 | 19 | #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] 20 | pub struct ContentAddress { 21 | /// The size, or possibly unsized. 22 | pub datum_size: DatumSize, 23 | /// The instance of the content table that the data is stored in. 24 | pub content_table: TableIndex, 25 | /// The index of the entry within the content table that is the data. 26 | pub entry_index: EntryIndex, 27 | } 28 | 29 | impl<'a> From<&'a ContentAddress> for CompactContentAddress { 30 | fn from(x: &'a ContentAddress) -> Self { 31 | let a = u8::from(x.datum_size) as u32; 32 | let b = (x.entry_index + x.datum_size.contents_entries() * x.content_table) as u32; 33 | Self(a | (b << 6)) 34 | } 35 | } 36 | 37 | impl From for CompactContentAddress { 38 | fn from(x: ContentAddress) -> Self { 39 | From::from(&x) 40 | } 41 | } 42 | 43 | impl From for ContentAddress { 44 | fn from(x: CompactContentAddress) -> Self { 45 | let datum_size = DatumSize::from((x.0 % 64) as u8); 46 | let entries = datum_size.contents_entries(); 47 | let rest = (x.0 >> 6) as usize; 48 | let content_table = rest / entries; 49 | let entry_index = rest % entries; 50 | Self { datum_size, content_table, entry_index } 51 | } 52 | } 53 | 54 | impl EncodedSize for ContentAddress { 55 | fn encoded_size() -> usize { 4 } 56 | } 57 | 58 | impl Encode for ContentAddress { 59 | fn encode_to(&self, output: &mut O) { 60 | CompactContentAddress::from(self).encode_to(output) 61 | } 62 | } 63 | 64 | impl Decode for ContentAddress { 65 | fn decode(input: &mut I) -> Result { 66 | Ok(CompactContentAddress::decode(input)?.into()) 67 | } 68 | } 69 | 70 | #[test] 71 | fn content_addresses_encode_encode_ok() { 72 | let a = ContentAddress { datum_size: DatumSize::Size(0), content_table: 1, entry_index: 2 }; 73 | assert_eq!(a.datum_size.size(), Some(32)); 74 | assert_eq!(a.datum_size.contents_entries(), 65536); 75 | let b = CompactContentAddress::from(&a); 76 | assert_eq!(b, CompactContentAddress(65538 * 64)); 77 | let a2 = ContentAddress::from(b); 78 | assert_eq!(a, a2); 79 | } 80 | -------------------------------------------------------------------------------- /src/database.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use log::{info, trace, warn}; 3 | use parking_lot::MappedRwLockReadGuard; 4 | 5 | use crate::datum_size::DatumSize; 6 | use crate::types::{KeyType, HashOutput}; 7 | use crate::content::Content; 8 | use crate::content_address::ContentAddress; 9 | use crate::table::{RefCount, TableItemCount}; 10 | use crate::index::Index; 11 | use crate::metadata::{Metadata, MetadataV1}; 12 | use crate::Error; 13 | 14 | /// The options builder. 15 | pub struct Options { 16 | pub(crate) path: PathBuf, 17 | pub(crate) key_bytes: usize, 18 | pub(crate) index_bits: usize, 19 | pub(crate) skipped_count_trigger: u8, 20 | pub(crate) key_correction_trigger: usize, 21 | pub(crate) oversize_trigger_mapped: usize, 22 | pub(crate) oversize_shrink_mapped: usize, 23 | pub(crate) min_items_backed: TableItemCount, 24 | } 25 | 26 | impl Options { 27 | /// Create a new instance. 28 | pub fn new() -> Self { 29 | Self { 30 | key_bytes: 4, 31 | index_bits: 16, 32 | skipped_count_trigger: 240, 33 | key_correction_trigger: 32, 34 | oversize_trigger_mapped: 256 * 1024 * 1024, 35 | oversize_shrink_mapped: 64 * 1024 * 1024, 36 | min_items_backed: 8, 37 | path: Default::default(), 38 | } 39 | } 40 | 41 | /// Create a new instance, providing a path. 42 | pub fn from_path(path: PathBuf) -> Self { 43 | Self::new().path(path) 44 | } 45 | 46 | /// Set the number of bytes to use for the index key (default: 4). 47 | pub fn key_bytes(mut self, key_bytes: usize) -> Self { 48 | self.key_bytes = key_bytes; 49 | self.index_bits = self.index_bits.min(key_bytes * 8); 50 | self 51 | } 52 | 53 | /// Set the number of bits to use for the index (default: 24). 54 | pub fn index_bits(mut self, index_bits: usize) -> Self { 55 | self.index_bits = index_bits; 56 | self.key_bytes = self.key_bytes.max(index_bits / 8); 57 | self 58 | } 59 | 60 | /// Set the path in which the database should be opened. 61 | pub fn path(mut self, path: PathBuf) -> Self { 62 | self.path = path; 63 | self 64 | } 65 | 66 | /// Set the oversize tables' mapping management properties. Whereas sized tables keep everything 67 | /// mapped all the time, oversize tables (owing to the fact they are essentially unbounded in 68 | /// how much they might be mapping) regularly prune the items that are mapped. This is done as a 69 | /// simple LRU scheme where items accessed least recently will be prioritised for removal. 70 | /// 71 | /// The system has two parameters: a `trigger` size, which is how many bytes much be mapped in 72 | /// total before a "shrinking" (unmapping) happens; and a `shrink` size which is how many bytes, 73 | /// at most, may continue to be mapped at the "shrinking" is completed. 74 | pub fn oversize_shrink(mut self, trigger: usize, shrink: usize) -> Self { 75 | self.oversize_trigger_mapped = trigger; 76 | self.oversize_shrink_mapped = shrink; 77 | self 78 | } 79 | 80 | /// Set the minimum number of items that will be backed on disk. This basically sets the 81 | /// minimum disk space that will be used by a table with a single element in it. 82 | pub fn min_items_backed(mut self, min_items_backed: TableItemCount) -> Self { 83 | self.min_items_backed = min_items_backed; 84 | self 85 | } 86 | 87 | /// Ensure that the disk files never need to extend by always requiring any tables to use their 88 | /// full amount. 89 | pub fn all_items_backed(mut self) -> Self { 90 | self.min_items_backed = 65536; 91 | self 92 | } 93 | 94 | /// Open the database or create one with the configured options if it doesn't yet exist. 95 | pub fn open(self) -> Result, Error> { 96 | Database::open(self) 97 | } 98 | } 99 | 100 | pub struct Database { 101 | options: Options, 102 | index: Index, 103 | content: Content, 104 | _dummy: std::marker::PhantomData, 105 | } 106 | 107 | impl Drop for Database { 108 | fn drop(&mut self) { 109 | self.commit(); 110 | } 111 | } 112 | 113 | impl Database { 114 | /// Open a database if it already exists and create a new one if not. 115 | pub fn open(options: Options) -> Result { 116 | assert!(!options.path.is_file(), "Path must be a directory or not exist."); 117 | if !options.path.is_dir() { 118 | std::fs::create_dir_all(options.path.clone())?; 119 | } 120 | 121 | // Sort out metadata. 122 | let metadata = if let Some(metadata) = MetadataV1::try_read(&options.path)? { 123 | info!("Opening existing SubDB [{} bytes/{}-bit]", metadata.key_bytes, metadata.index_bits); 124 | metadata 125 | } else { 126 | let metadata = MetadataV1::from(&options); 127 | metadata.write(&options.path)?; 128 | info!("Creating new SubDB [{} bytes/{}-bit]", metadata.key_bytes, metadata.index_bits); 129 | metadata 130 | }; 131 | 132 | let mut index_filename = options.path.clone(); 133 | index_filename.push("index.subdb"); 134 | let index = Index::open( 135 | index_filename, 136 | metadata.key_bytes, 137 | metadata.index_bits 138 | )?; 139 | 140 | let content = Content::open( 141 | options.path.clone(), 142 | options.oversize_trigger_mapped, 143 | options.oversize_shrink_mapped, 144 | options.min_items_backed, 145 | )?; 146 | 147 | Ok(Self { 148 | options, index, content, _dummy: Default::default() 149 | }) 150 | } 151 | 152 | pub fn reindex(&mut self, key_bytes: usize, index_bits: usize) -> Result<(), Error> { 153 | let mut temp_filename = self.options.path.clone(); 154 | temp_filename.push("new-index.subdb"); 155 | 156 | let mut index_filename = self.options.path.clone(); 157 | index_filename.push("index.subdb"); 158 | 159 | // First we create the new index. 160 | // We don't want to keep it around as we'll be renaming it and need it to be closed. 161 | Index::from_existing(temp_filename.clone(), &mut self.index, key_bytes, index_bits)?; 162 | 163 | // Then, we cunningly close `self.index` by replacing it with a dummy. 164 | self.index = Index::anonymous(1, 1)?; 165 | 166 | // Then, we remove the old version and rename the new version. 167 | std::fs::remove_file(index_filename.clone())?; 168 | std::fs::rename(temp_filename, index_filename.clone())?; 169 | // ...and reset the metadata. 170 | MetadataV1 { key_bytes, index_bits }.write(&self.options.path)?; 171 | info!("Creating new SubDB [{} bytes/{}-bit]", key_bytes, index_bits); 172 | 173 | 174 | // Finally, we reopen it replacing the dummy. 175 | self.index = Index::open(index_filename, key_bytes, index_bits)?; 176 | 177 | Ok(()) 178 | } 179 | 180 | pub fn commit(&mut self) { 181 | self.index.commit(); 182 | self.content.commit(); 183 | } 184 | 185 | pub fn bytes_mapped(&self) -> usize { 186 | self.info().into_iter().map(|x| (x.1).3).sum() 187 | } 188 | 189 | pub fn info(&self) -> Vec<((DatumSize, usize), (TableItemCount, TableItemCount, usize, usize))> { 190 | self.content.info() 191 | } 192 | 193 | pub fn get(&self, hash: &K) -> Option> { 194 | self.get_ref(hash).map(|d| d.to_vec()) 195 | } 196 | 197 | pub fn get_ref(&self, hash: &K) -> Option> { 198 | self.index.with_item_try(hash, |entry| 199 | self.content.item_ref(&entry.address, Some(hash)) 200 | ) 201 | } 202 | 203 | pub fn contains_key(&self, hash: &K) -> bool { 204 | self.index.with_item_try(hash, |entry| 205 | if &self.content.item_hash(&entry.address)? == hash { Ok(true) } else { Err(()) } 206 | ).is_some() 207 | } 208 | 209 | pub fn get_ref_count(&self, hash: &K) -> RefCount { 210 | self.index.with_item_try(hash, |entry| 211 | self.content.item_ref_count(&entry.address, Some(hash)) 212 | ).unwrap_or(0) 213 | } 214 | 215 | pub fn store(&mut self, data: &[u8]) -> (RefCount, K) where K: HashOutput { 216 | let hash = K::from_data(data); 217 | let rc = self.insert(data, &hash); 218 | (rc, hash) 219 | } 220 | 221 | pub fn insert(&mut self, data: &[u8], hash: &K) -> RefCount { 222 | trace!(target: "index", "Inserting data {:?}", 223 | std::str::from_utf8(data).map_or_else(|_| hex::encode(data), |s| s.to_owned()) 224 | ); 225 | let r = loop { 226 | match { 227 | let content = &mut self.content; 228 | self.index.edit_in( 229 | hash, 230 | |maybe_entry: Option<&ContentAddress>| -> Result<(Option, RefCount), ()> { 231 | if let Some(address) = maybe_entry { 232 | // Same item (almost certainly) - just need to bump the ref count on the 233 | // data. 234 | // We check that this is actually the right item, though. 235 | content.bump(address, Some(hash)) 236 | .map(|r| { 237 | trace!(target: "index", "Bumped."); 238 | (None, r) 239 | }) 240 | } else { 241 | // Nothing there - insert the new item. 242 | Ok((Some(content.emplace(hash, data)), 1)) 243 | } 244 | }, 245 | ) 246 | } { 247 | Ok(r) => break r, 248 | Err(Error::IndexFull) => { 249 | let (key_bytes, index_bits) = self.index.next_size(); 250 | self.reindex(key_bytes, index_bits).expect("Fatal error"); 251 | } 252 | Err(_) => unreachable!(), 253 | } 254 | }; 255 | 256 | let watermarks = self.index.take_watermarks(); 257 | if watermarks.0 > self.options.skipped_count_trigger 258 | || watermarks.1 >= self.options.key_correction_trigger 259 | { 260 | let (key_bytes, index_bits) = self.index.next_size(); 261 | info!(target: "database", "Watermark triggered. Reindexing to [{} bytes/{} bits]", key_bytes, index_bits); 262 | if self.reindex(key_bytes, index_bits).is_err() { 263 | warn!("Error while reindexing. Things will probably go badly wrong now."); 264 | }; 265 | } 266 | 267 | r 268 | } 269 | 270 | pub fn remove(&mut self, hash: &K) -> Result { 271 | let content = &mut self.content; 272 | self.index.edit_out(hash, |address| { 273 | content.free(&address, Some(hash)).map(|refs_left| { 274 | if refs_left == 0 { 275 | // Remove entry (`Some` change to `None` entry) 276 | (Some(None), 0) 277 | } else { 278 | // Ignore (`None` change) 279 | (None, refs_left) 280 | } 281 | }) 282 | }) 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /src/datum_size.rs: -------------------------------------------------------------------------------- 1 | use std::mem::size_of; 2 | use std::fmt; 3 | 4 | const MAX_SIZE: u8 = 63; 5 | 6 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 7 | pub enum DatumSize { 8 | Oversize, 9 | Size(u8), 10 | } 11 | 12 | impl fmt::Debug for DatumSize { 13 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 14 | match self { 15 | DatumSize::Oversize => write!(f, "Oversize"), 16 | DatumSize::Size(z) => write!(f, "Size(#{} = {} bytes)", z, self.size().unwrap()), 17 | } 18 | } 19 | } 20 | 21 | impl DatumSize { 22 | /// The size of a datum, or `None` if the datum is oversized. 23 | pub fn size(&self) -> Option { 24 | match *self { 25 | DatumSize::Oversize => None, 26 | DatumSize::Size(size_class) => { 27 | assert!(size_class < MAX_SIZE); 28 | if size_class < 32 { 29 | let exp = size_class as usize / 8; 30 | let tweak = size_class as usize % 8; 31 | let base = 32usize << exp; 32 | Some(base + base / 8 * tweak) 33 | } else { 34 | let exp = size_class as usize / 4 - 4; 35 | let tweak = size_class as usize % 4; 36 | let base = 32usize << exp; 37 | Some(base + base / 4 * tweak) 38 | } 39 | } 40 | } 41 | } 42 | 43 | /// The nearest datum size for `s`. 44 | pub fn nearest(s: usize) -> Self { 45 | if s <= 32 { 46 | return DatumSize::Size(0) 47 | } 48 | let exp = size_of::() as usize * 8 - s.leading_zeros() as usize - 6; 49 | let base = 32usize << exp; 50 | let rem = s - base; 51 | 52 | let result = if exp < 4 { 53 | // incr of 1/8 54 | let incr = base / 8; 55 | let incrs = (rem + incr - 1) / incr; 56 | exp * 8 + incrs 57 | } else { 58 | // incr of 1/4 59 | let incr = base / 4; 60 | let incrs = (rem + incr - 1) / incr; 61 | 32 + ((exp - 4) * 4) + incrs 62 | }; 63 | 64 | if result < MAX_SIZE as usize { 65 | DatumSize::Size(result as u8) 66 | } else { 67 | DatumSize::Oversize 68 | } 69 | } 70 | 71 | /// How many entries should be in a contents table whose items are this size? 72 | pub fn contents_entries(&self) -> usize { 73 | // max total size per contents table = 2MB 74 | // max number of items in contents table = 65536 75 | if let Some(size) = self.size() { 76 | (2048 * 1024 / size).min(65536).max(1) 77 | } else { 78 | 65536 79 | } 80 | } 81 | 82 | /// Total number of different sizes that are served by this. Only sensible for Sized. 83 | pub fn size_range(&self) -> Option { 84 | match *self { 85 | DatumSize::Oversize => None, 86 | DatumSize::Size(size_class) => { 87 | assert!(size_class < MAX_SIZE); 88 | Some(if size_class == 0 { 89 | 33 90 | } else { 91 | if size_class <= 32 { 92 | let exp = size_class as usize / 8; 93 | let tweak = size_class as usize % 8; 94 | let base = 32usize << exp; 95 | if tweak == 0 { 96 | base / 8 / 2 97 | } else { 98 | base / 8 99 | } 100 | } else { 101 | let exp = size_class as usize / 4 - 4; 102 | let tweak = size_class as usize % 4; 103 | let base = 32usize << exp; 104 | if tweak == 0 { 105 | base / 4 / 2 106 | } else { 107 | base / 4 108 | } 109 | } 110 | }) 111 | } 112 | } 113 | } 114 | } 115 | 116 | impl From for DatumSize { 117 | fn from(x: u8) -> Self { 118 | if x < MAX_SIZE { 119 | DatumSize::Size(x) 120 | } else { 121 | DatumSize::Oversize 122 | } 123 | } 124 | } 125 | 126 | impl From for u8 { 127 | fn from(x: DatumSize) -> u8 { 128 | match x { 129 | DatumSize::Oversize => MAX_SIZE, 130 | DatumSize::Size(x) => x, 131 | } 132 | } 133 | } 134 | 135 | #[test] 136 | fn datum_size_works() { 137 | assert_eq!(DatumSize::from(0).size().unwrap(), 32); 138 | assert_eq!(DatumSize::from(1).size().unwrap(), 36); 139 | assert_eq!(DatumSize::from(2).size().unwrap(), 40); 140 | assert_eq!(DatumSize::from(7).size().unwrap(), 60); 141 | assert_eq!(DatumSize::from(8).size().unwrap(), 64); 142 | assert_eq!(DatumSize::from(9).size().unwrap(), 72); 143 | assert_eq!(DatumSize::from(15).size().unwrap(), 120); 144 | assert_eq!(DatumSize::from(16).size().unwrap(), 128); 145 | assert_eq!(DatumSize::from(17).size().unwrap(), 144); 146 | assert_eq!(DatumSize::from(24).size().unwrap(), 256); 147 | assert_eq!(DatumSize::from(31).size().unwrap(), 480); 148 | assert_eq!(DatumSize::from(32).size().unwrap(), 512); 149 | assert_eq!(DatumSize::from(33).size().unwrap(), 640); 150 | assert_eq!(DatumSize::from(34).size().unwrap(), 768); 151 | assert_eq!(DatumSize::from(35).size().unwrap(), 896); 152 | assert_eq!(DatumSize::from(36).size().unwrap(), 1_024); 153 | assert_eq!(DatumSize::from(37).size().unwrap(), 1_280); 154 | assert_eq!(DatumSize::from(38).size().unwrap(), 1_536); 155 | assert_eq!(DatumSize::from(39).size().unwrap(), 1_792); 156 | assert_eq!(DatumSize::from(40).size().unwrap(), 2_048); 157 | assert_eq!(DatumSize::from(44).size().unwrap(), 4_096); 158 | assert_eq!(DatumSize::from(48).size().unwrap(), 8_192); 159 | assert_eq!(DatumSize::from(52).size().unwrap(), 16_384); 160 | assert_eq!(DatumSize::from(56).size().unwrap(), 32_768); 161 | assert_eq!(DatumSize::from(60).size().unwrap(), 65_536); 162 | assert_eq!(DatumSize::from(62).size().unwrap(), 98_304); 163 | assert_eq!(DatumSize::from(63).size(), None); 164 | 165 | assert_eq!(DatumSize::nearest(0).size().unwrap(), 32); 166 | assert_eq!(DatumSize::nearest(29).size().unwrap(), 32); 167 | assert_eq!(DatumSize::nearest(30).size().unwrap(), 32); 168 | assert_eq!(DatumSize::nearest(31).size().unwrap(), 32); 169 | assert_eq!(DatumSize::nearest(32).size().unwrap(), 32); 170 | assert_eq!(DatumSize::nearest(33).size().unwrap(), 36); 171 | assert_eq!(DatumSize::nearest(34).size().unwrap(), 36); 172 | assert_eq!(DatumSize::nearest(35).size().unwrap(), 36); 173 | assert_eq!(DatumSize::nearest(36).size().unwrap(), 36); 174 | assert_eq!(DatumSize::nearest(37).size().unwrap(), 40); 175 | assert_eq!(DatumSize::nearest(38).size().unwrap(), 40); 176 | assert_eq!(DatumSize::nearest(39).size().unwrap(), 40); 177 | assert_eq!(DatumSize::nearest(40).size().unwrap(), 40); 178 | assert_eq!(DatumSize::nearest(62).size().unwrap(), 64); 179 | assert_eq!(DatumSize::nearest(63).size().unwrap(), 64); 180 | assert_eq!(DatumSize::nearest(64).size().unwrap(), 64); 181 | assert_eq!(DatumSize::nearest(65).size().unwrap(), 72); 182 | assert_eq!(DatumSize::nearest(66).size().unwrap(), 72); 183 | assert_eq!(DatumSize::nearest(67).size().unwrap(), 72); 184 | assert_eq!(DatumSize::nearest(68).size().unwrap(), 72); 185 | assert_eq!(DatumSize::nearest(69).size().unwrap(), 72); 186 | assert_eq!(DatumSize::nearest(70).size().unwrap(), 72); 187 | assert_eq!(DatumSize::nearest(71).size().unwrap(), 72); 188 | assert_eq!(DatumSize::nearest(72).size().unwrap(), 72); 189 | assert_eq!(DatumSize::nearest(73).size().unwrap(), 80); 190 | 191 | assert_eq!(DatumSize::nearest(480).size().unwrap(), 480); 192 | assert_eq!(DatumSize::nearest(481).size().unwrap(), 512); 193 | assert_eq!(DatumSize::nearest(512).size().unwrap(), 512); 194 | assert_eq!(DatumSize::nearest(513).size().unwrap(), 640); 195 | assert_eq!(DatumSize::nearest(640).size().unwrap(), 640); 196 | assert_eq!(DatumSize::nearest(641).size().unwrap(), 768); 197 | 198 | assert_eq!(DatumSize::nearest(98_303).size().unwrap(), 98_304); 199 | assert_eq!(DatumSize::nearest(98_304).size().unwrap(), 98_304); 200 | assert_eq!(DatumSize::nearest(98_305).size(), None); 201 | } 202 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | /// Error type. 2 | #[derive(Debug, derive_more::Display, derive_more::From)] 3 | pub enum Error { 4 | /// An I/O error. 5 | #[display(fmt="I/O error: {}", _0)] 6 | Io(std::io::Error), 7 | 8 | /// Metadata is bad. 9 | #[display(fmt="Bad metadata")] 10 | BadMetadata, 11 | 12 | /// Unsupported version. 13 | #[display(fmt="Unsupported version")] 14 | UnsupportedVersion, 15 | 16 | /// The index has become full. 17 | #[display(fmt="Index full")] 18 | IndexFull, 19 | } 20 | impl std::error::Error for Error {} 21 | -------------------------------------------------------------------------------- /src/freemap.rs: -------------------------------------------------------------------------------- 1 | pub struct FreeMap<'a>(&'a mut [u64]); 2 | impl<'a> FreeMap<'a> { 3 | pub fn new(data: &'a mut [u64]) -> Self { 4 | Self(data) 5 | } 6 | 7 | pub fn set(&mut self, i: usize) { 8 | if !self.get(i) { 9 | self.0[i / 64] |= (1u64 << (i % 64) as u64); 10 | self.1 += 1; 11 | } 12 | } 13 | 14 | pub fn clear(&mut self, i: usize) { 15 | if self.get(i) { 16 | self.0[i / 64] &= !(1u64 << (i % 64) as u64); 17 | self.1 -= 1; 18 | } 19 | } 20 | 21 | pub fn get(&self, i: usize) -> bool { 22 | (self.0[i / 64] & (1u64 << (i % 64) as u64)) != 0 23 | } 24 | 25 | pub fn next_free(&self, count: usize) -> Option { 26 | self.0.iter() 27 | .enumerate() 28 | .find(|(_, v)| v != u64::max_value()) 29 | .map(|(i, v)| (!v).leading_zeros() as usize + i * 64) 30 | .filter(|&x| x < count) 31 | } 32 | 33 | pub fn total_set(&self) -> usize { 34 | self.0.iter().map(|&x| x.count_ones() as usize).sum() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/index.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use std::fs::{OpenOptions}; 3 | use std::fmt::Debug; 4 | use std::convert::TryInto; 5 | use memmap::MmapMut; 6 | use parity_scale_codec::Codec; 7 | use smallvec::SmallVec; 8 | use log::trace; 9 | 10 | use crate::types::{KeyType, SimpleWriter, EncodedSize}; 11 | use crate::index_item::{IndexItem, IndexEntry}; 12 | use crate::Error; 13 | 14 | pub struct Index { 15 | index: MmapMut, 16 | 17 | suffix_len: usize, 18 | key_bytes: usize, 19 | index_mask: usize, 20 | index_bits: usize, 21 | index_full_bytes: usize, 22 | 23 | item_count: usize, 24 | item_size: usize, 25 | 26 | skipped_count_watermark: u8, 27 | key_correction_watermark: usize, 28 | _dummy: std::marker::PhantomData<(K, V)>, 29 | } 30 | 31 | impl Drop for Index { 32 | fn drop(&mut self) { 33 | self.commit(); 34 | } 35 | } 36 | 37 | impl Index { 38 | pub fn commit(&mut self) { 39 | self.index.flush().expect("Flush errored?"); 40 | } 41 | } 42 | 43 | impl Index { 44 | /// Open a database if it already exists and create a new one if not. 45 | pub fn open(filename: PathBuf, key_bytes: usize, index_bits: usize) -> Result { 46 | let file = OpenOptions::new() 47 | .read(true) 48 | .write(true) 49 | .create(true) 50 | .open(&filename) 51 | .expect("Path must be writable."); 52 | 53 | let index_full_bytes = index_bits / 8; 54 | let suffix_len = key_bytes - index_full_bytes; 55 | let index_mask = ((1u128 << index_bits as u128) - 1) as usize; 56 | let item_size = 2 + 1 + V::encoded_size() + suffix_len; 57 | let item_count = 1 << index_bits; 58 | 59 | file.set_len((item_count * item_size) as u64).expect("Path must be writable."); 60 | let index = unsafe { 61 | MmapMut::map_mut(&file).expect("Path must be writable.") 62 | }; 63 | 64 | Ok(Self { 65 | index, key_bytes, suffix_len, index_mask, skipped_count_watermark: 0, 66 | key_correction_watermark: 0, 67 | index_bits, index_full_bytes, item_size, item_count, _dummy: Default::default() 68 | }) 69 | } 70 | 71 | /// Open a database if it already exists and create a new one if not. 72 | pub fn anonymous(key_bytes: usize, index_bits: usize) -> Result { 73 | let index_full_bytes = index_bits / 8; 74 | let suffix_len = key_bytes - index_full_bytes; 75 | let index_mask = ((1u128 << index_bits as u128) - 1) as usize; 76 | let item_size = 2 + 1 + V::encoded_size() + suffix_len; 77 | let item_count = 1 << index_bits; 78 | 79 | let index = MmapMut::map_anon(item_count * item_size).expect("Out of memory?"); 80 | 81 | Ok(Self { 82 | index, key_bytes, suffix_len, index_mask, skipped_count_watermark: 0, 83 | key_correction_watermark: 0, 84 | index_bits, index_full_bytes, item_size, item_count, _dummy: Default::default() 85 | }) 86 | } 87 | 88 | /// Alters an index item in the index table store according to the given `f` function. 89 | fn mutate_item(&mut self, index: usize, f: impl FnOnce(&mut IndexItem) -> R) -> R { 90 | let data = &mut self.index[index * self.item_size..(index + 1) * self.item_size]; 91 | let mut entry = IndexItem::decode(&mut &data[..], self.suffix_len) 92 | .expect("Database corrupted?!"); 93 | let r = f(&mut entry); 94 | entry.encode_to(&mut SimpleWriter(data, 0), self.suffix_len); 95 | r 96 | } 97 | 98 | /// Reads and returns an index item from the index table store. 99 | fn read_item(&self, index: usize) -> IndexItem { 100 | let data = &self.index[index * self.item_size..(index + 1) * self.item_size]; 101 | let r = IndexItem::decode(&mut &data[..], self.suffix_len).expect("Database corrupted?!"); 102 | trace!(target: "index", "read_item({}): {} -> {:?}", index, hex::encode(data), r); 103 | r 104 | } 105 | 106 | /// Writes a given index item to the index table store. 107 | fn write_item(&mut self, index: usize, entry: IndexItem) { 108 | let data = &mut self.index[index * self.item_size..(index + 1) * self.item_size]; 109 | entry.encode_to(&mut SimpleWriter(data, 0), self.suffix_len); 110 | trace!(target: "index", "write_item({}): {:?} -> {}", index, entry, hex::encode(data)); 111 | } 112 | 113 | /// Determines the `index` (first location where it should be found in the index table) and 114 | /// the `key_suffix` for a given key `hash`. 115 | /// 116 | /// It's up to the caller to ensure that `hash` is big enough. It needs to be both at least 117 | /// `self.key_bytes` and at least the next power of two from the `index_bits` divided by 8. 118 | /// If the `hash.len()` is at least 8 then you'll probably be fine. 119 | fn index_suffix_of(&self, hash: &[u8]) -> (usize, SmallVec<[u8; 4]>) { 120 | let index = match self.index_bits { 121 | 0 => 0, 122 | 1..=8 => hash[0] as usize, 123 | 9..=16 => u16::from_le_bytes(hash[..2].try_into().expect("hash len must be >=2")) as usize, 124 | 17..=32 => u32::from_le_bytes(hash[..4].try_into().expect("hash len must be >=4")) as usize, 125 | 32..=64 => u64::from_le_bytes(hash[..8].try_into().expect("hash len must be >=8")) as usize, 126 | _ => unimplemented!("Too big an index!"), 127 | }; 128 | (index & self.index_mask, hash[self.index_full_bytes..self.key_bytes].into()) 129 | } 130 | 131 | /// Determines the first part of the hash/key from the index and the key-suffix. A partial 132 | /// reversion of `index_suffix_of`. 133 | fn key_prefix(&self, index: usize, suffix: &[u8]) -> SmallVec<[u8; 8]> { 134 | let mut prefix: SmallVec<[u8; 8]> = match self.index_full_bytes { 135 | 0 => SmallVec::new(), 136 | 1 => (index as u8).to_le_bytes().as_ref()[..self.index_full_bytes].into(), 137 | 2 => (index as u16).to_le_bytes().as_ref()[..self.index_full_bytes].into(), 138 | 3 | 4 => (index as u32).to_le_bytes().as_ref()[..self.index_full_bytes].into(), 139 | 5 | 6 | 7 | 8 => (index as u64).to_le_bytes().as_ref()[..self.index_full_bytes].into(), 140 | _ => unimplemented!("Too big an index!"), 141 | }; 142 | prefix.extend_from_slice(suffix); 143 | prefix 144 | } 145 | 146 | /// Attempt to run a function `f` on the probable `IndexEntry` found which represents the 147 | /// entry for `hash` in the index. 148 | /// 149 | /// NOTE: It does *not* check that the `hash` really is in this index. Everything is done to 150 | /// ensure the highest probability that it is, but it is theoretically possible (if rather 151 | /// unrealistic) that it might be some other value (under expected loads this should be a 152 | /// roughly 1 in 4 billion chance, but hey - you never know). If it turns out not to be, then 153 | /// the function `f` may end up getting called multiple times. This will probably never happen 154 | /// outside of testing/toy environments. 155 | pub fn with_item_try( 156 | &self, 157 | hash: &K, 158 | mut f: impl FnMut(IndexEntry) -> Result 159 | ) -> Option { 160 | let (mut index, suffix) = self.index_suffix_of(hash.as_ref()); 161 | trace!(target: "index", "Finding item; primary index {}; suffix: {:?}", index, suffix); 162 | for correction in 0.. { 163 | let item = self.read_item(index); 164 | trace!(target: "index", "Checking {:?}", item); 165 | if let Some(entry) = item.maybe_entry { 166 | if entry.key_correction == correction && entry.key_suffix == suffix { 167 | // Almost certainly the correct item. 168 | trace!(target: "index", "Found probable item: {:?}", entry); 169 | // Actually ensure it's the correct item. 170 | if let Ok(result) = f(entry) { 171 | return Some(result); 172 | } 173 | } 174 | } 175 | // Check for a past collision... 176 | if item.skipped_count == 0 { 177 | // No collision - item not there. 178 | return None 179 | } 180 | index = (index + 1) % self.item_count; 181 | } 182 | unreachable!() 183 | } 184 | 185 | pub fn edit_in( 186 | &mut self, 187 | hash: &K, 188 | f: impl FnMut(Option<&V>) -> Result<(Option, R), ()>, 189 | ) -> Result { 190 | let (primary_index, key_suffix) = self.index_suffix_of(hash.as_ref()); 191 | self.edit_in_position(primary_index, key_suffix, f) 192 | } 193 | 194 | fn edit_in_position( 195 | &mut self, 196 | primary_index: usize, 197 | key_suffix: SmallVec<[u8; 4]>, 198 | mut f: impl FnMut(Option<&V>) -> Result<(Option, R), ()>, 199 | ) -> Result { 200 | let mut key_correction = 0; 201 | let mut try_index = primary_index; 202 | trace!(target: "index", " Primary index {:?}", try_index); 203 | const MAX_CORRECTION: usize = 32768; 204 | for _ in 0..MAX_CORRECTION.min(self.item_count) { 205 | let mut item = self.read_item(try_index); 206 | if let Some(ref mut e) = item.maybe_entry { 207 | if &e.key_suffix == &key_suffix && e.key_correction == key_correction { 208 | if let Ok(result) = f(Some(&e.address)) { 209 | return Ok(result.1) 210 | } 211 | } 212 | } else { 213 | let (maybe_address, result) = f(None) 214 | .expect("May not return an Err when provided with None"); 215 | if let Some(address) = maybe_address { 216 | item.maybe_entry = Some(IndexEntry { 217 | key_suffix, 218 | address, 219 | key_correction, 220 | }); 221 | trace!(target: "index", "Written {:?} at index {:?}", item, try_index); 222 | self.write_item(try_index, item); 223 | } else { 224 | // Undo changing those skipped counts. 225 | self.decrement_skip_counts(primary_index, key_correction); 226 | } 227 | return Ok(result); 228 | } 229 | // Collision - flag the item as skipped and continue around loop. 230 | trace!(target: "index", "Collision at index {:?} with {:?}", try_index, item); 231 | 232 | item.skipped_count = if let Some(n) = item.skipped_count.checked_add(1) { n } else { break }; 233 | self.skipped_count_watermark = self.skipped_count_watermark.max(item.skipped_count); 234 | self.write_item(try_index, item); 235 | key_correction += 1; 236 | self.key_correction_watermark = self.key_correction_watermark.max(key_correction); 237 | try_index = (try_index + 1) % self.item_count; 238 | } 239 | 240 | // If we're here, then the index must be getting full: either we've had to increment an 241 | // item's skipped count too much (because it was a preferential space to more than 255 other 242 | // items), or we've had to stray too many items far from the primary index (more than 32767 243 | // or the number of items in the index). 244 | // 245 | // We will bump the size of the index and retry. 246 | Err(Error::IndexFull) 247 | } 248 | 249 | fn decrement_skip_counts(&mut self, begin: usize, count: usize) { 250 | for i in begin..begin + count { 251 | trace!(target: "index", "Unincrementing skipped trail for {}", i % self.item_count); 252 | self.mutate_item( 253 | i % self.item_count, 254 | |item| item.skipped_count = item.skipped_count.checked_sub(1) 255 | .expect("Skip count underflow. Database corruption?")); 256 | } 257 | } 258 | 259 | pub fn edit_out( 260 | &mut self, 261 | hash: &K, 262 | mut if_maybe_found: impl FnMut(V) -> Result<(Option>, R), ()>, 263 | ) -> Result { 264 | let (primary_index, suffix) = self.index_suffix_of(hash.as_ref()); 265 | let mut try_index = primary_index; 266 | trace!(target: "index", "Removing item; primary index {}; suffix: {:?}", try_index, suffix); 267 | for correction in 0.. { 268 | let item = self.read_item(try_index); 269 | trace!(target: "index", "Checking {:?}", item); 270 | if let Some(entry) = item.maybe_entry { 271 | if entry.key_correction == correction && entry.key_suffix == suffix { 272 | // Almost certainly the correct item. 273 | match if_maybe_found(entry.address) { 274 | Err(()) => {} 275 | Ok((None, result)) => return Ok(result), 276 | Ok((Some(Some(address)), result)) => { 277 | let item = IndexItem { 278 | skipped_count: item.skipped_count, 279 | maybe_entry: Some(IndexEntry { address, .. entry }), 280 | }; 281 | self.write_item(try_index, item); 282 | return Ok(result); 283 | } 284 | Ok((Some(None), result)) => { 285 | let item = IndexItem { 286 | skipped_count: item.skipped_count, 287 | maybe_entry: None, 288 | }; 289 | trace!(target: "index", "Expunging index: {:?} {:?}", try_index, item); 290 | self.write_item(try_index, item); 291 | self.decrement_skip_counts(primary_index, correction); 292 | return Ok(result); 293 | } 294 | } 295 | } 296 | } 297 | // Check for a past collision... 298 | if item.skipped_count == 0 { 299 | // No collision - item not there. 300 | return Err(()) 301 | } 302 | try_index = (try_index + 1) % self.item_count; 303 | } 304 | unreachable!() 305 | } 306 | 307 | pub fn from_existing(filename: PathBuf, source: &Self, key_bytes: usize, index_bits: usize) -> Result { 308 | // Open new index. 309 | let mut result = Index::open(filename, key_bytes, index_bits)?; 310 | 311 | if key_bytes <= source.key_bytes { 312 | for i in 0..source.item_count { 313 | let item = source.read_item(i); 314 | if let Some(entry) = item.maybe_entry { 315 | let index = (i + source.item_count - entry.key_correction) % source.item_count; 316 | let mut partial_key = source.key_prefix(index, &entry.key_suffix); 317 | // we put zeros on the end since they won't affect LE representations and we extend 318 | // in order to guarantee that it's big enough for `index_suffix_of`. 319 | assert!(partial_key.len() >= result.key_bytes); 320 | partial_key.resize(8, 0); 321 | let (index, key_suffix) = result.index_suffix_of(partial_key.as_ref()); 322 | let mut the_address = Some(entry.address); 323 | result.edit_in_position(index & result.index_mask, key_suffix, |maybe_same| { 324 | if maybe_same.is_some() { 325 | Err(()) 326 | } else { 327 | Ok((Some(the_address.take().expect("This branch can only be called once")), ())) 328 | } 329 | })?; 330 | } 331 | } 332 | } else { 333 | unimplemented!(); 334 | } 335 | Ok(result) 336 | } 337 | 338 | pub fn next_size(&self) -> (usize, usize) { 339 | let index_bits = self.index_bits + 1; 340 | let key_bytes = self.key_bytes.max((self.index_bits + 7) / 8); 341 | (key_bytes, index_bits) 342 | } 343 | 344 | pub fn take_watermarks(&mut self) -> (u8, usize) { 345 | let r = (self.skipped_count_watermark, self.key_correction_watermark); 346 | self.skipped_count_watermark = 0; 347 | self.key_correction_watermark = 0; 348 | r 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /src/index_item.rs: -------------------------------------------------------------------------------- 1 | use smallvec::{SmallVec, smallvec}; 2 | use parity_scale_codec::{self as codec, Encode, Decode, Codec}; 3 | 4 | /// An item possibly describing an entry in this database. 5 | #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] 6 | pub struct IndexItem { 7 | /// The number of items currently in the database that would have been placed in this slot at 8 | /// preference, but had to go into a later slot do to this being occupied. 9 | pub skipped_count: u8, 10 | 11 | /// An entry, if there is one. 12 | pub maybe_entry: Option>, 13 | } 14 | 15 | /// An item describing an entry in this database. It doesn't contain its data; only where to find 16 | /// it. It fits in 8 bytes when encoded. 17 | #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] 18 | pub struct IndexEntry { 19 | /// The number of items that had to be skipped from the slot derived from the key. 20 | /// Encodes to use 15 bits. 21 | pub key_correction: usize, 22 | 23 | /// Any incomplete or undefined bytes placed on the end of the key derivable from the index 24 | /// position to build it into the short-form key (currently 4 bytes but eventually this will be 25 | /// configurable) 26 | pub key_suffix: SmallVec<[u8; 4]>, 27 | 28 | /// Always 32-bit. 29 | pub address: Payload, 30 | } 31 | 32 | impl IndexItem { 33 | /// None if the slot is empty. 34 | pub fn decode(input: &mut I, suffix_len: usize) -> Result { 35 | let maybe_key_correction = ::decode(input)?; 36 | let skipped_count = input.read_byte()?; 37 | 38 | if maybe_key_correction & 0b1000_0000_0000_0000u16 == 0 { 39 | // Unoccupied. Skip the rest of it and return none. 40 | for _ in 0..suffix_len + 4 { input.read_byte()?; } 41 | return Ok(Self { skipped_count, maybe_entry: None }) 42 | } 43 | 44 | let key_correction = (maybe_key_correction & !0b1000_0000_0000_0000u16) as usize; 45 | 46 | let mut key_suffix = smallvec![0; suffix_len]; 47 | input.read(&mut key_suffix[..])?; 48 | 49 | let address = Decode::decode(input)?; 50 | let entry = IndexEntry { key_correction, key_suffix, address }; 51 | 52 | Ok(Self { skipped_count, maybe_entry: Some(entry) }) 53 | } 54 | 55 | pub fn encode_to(&self, output: &mut O, suffix_len: usize) { 56 | if let Some(ref entry) = self.maybe_entry { 57 | // We set the MSB to indicate that the slot is taken. 58 | ((entry.key_correction as u16) | 0b1000_0000_0000_0000u16).encode_to(output); 59 | output.push_byte(self.skipped_count); 60 | output.write(entry.key_suffix.as_ref()); 61 | entry.address.encode_to(output); 62 | } else { 63 | output.push_byte(0); 64 | output.push_byte(0); 65 | output.push_byte(self.skipped_count); 66 | for _ in 0..suffix_len + 4 { output.push_byte(0); } 67 | } 68 | }} 69 | 70 | #[test] 71 | fn index_item_encodes_decodes_correctly() { 72 | let item = IndexItem { 73 | skipped_count: 0, 74 | maybe_entry: Some(IndexEntry { 75 | key_correction: 0, 76 | key_suffix: SmallVec::from(&[45][..]), 77 | address: 42u32, 78 | }), 79 | }; 80 | let mut encoded = Vec::::new(); 81 | item.encode_to(&mut encoded, 1); 82 | let item2 = IndexItem::decode(&mut &encoded[..], 1).unwrap(); 83 | assert_eq!(item, item2); 84 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod content; 2 | mod content_address; 3 | mod datum_size; 4 | mod database; 5 | mod error; 6 | mod index; 7 | mod index_item; 8 | mod metadata; 9 | mod safe_database; 10 | mod table; 11 | mod types; 12 | 13 | pub use database::{Options, Database}; 14 | pub use safe_database::SafeDatabase; 15 | pub use content_address::ContentAddress; 16 | pub use error::Error; 17 | pub use types::KeyType; 18 | 19 | // DONE: Better format for index n-bytes up to 4 bytes rest-of-key, 16-bit location-correction, 8- 20 | // bit skipped counter. 21 | // - for 0-7 bit table (1 - 128 entries), then 4 bytes rest-of-key. 22 | // - for 8-15 bit table (256 - 32768 entries), then 3 bytes rest-of-key. 23 | // - for 16-23 bit table (65536 - ~8M entries), then 2 bytes rest-of-key. 24 | // - for 24-31 bit table (~16M - ~2B entries), then 1 byte rest-of-key. 25 | // Then 16-bit for location correction (65536 positions, which is subtracted from the actual 26 | // location index to give the correct key. 27 | // Then 8-bit for skipped-counter (256 positions, which is the number of items following 28 | // this position which would have been indexed here but had to skip over this position because 29 | // it was already taken. 30 | // DONE: Versioning. 31 | // DONE: Remove items. 32 | // DONE: Adaptive index size (bitwise increase). 33 | // DONE: Oversize content tables. 34 | // DONE: Content tables should be able to grow. 35 | // TODO: Stored friend links. 36 | // TODO: Remove panickers. 37 | // TODO: Comprehensive tests. 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | use log::info; 43 | use std::path::PathBuf; 44 | use crate::types::Blake2Output; 45 | 46 | fn init() { 47 | let _ = simplelog::CombinedLogger::init( 48 | vec![ 49 | simplelog::TermLogger::new(simplelog::LevelFilter::Info, simplelog::Config::default(), simplelog::TerminalMode::Mixed).unwrap(), 50 | ] 51 | ); 52 | } 53 | 54 | #[test] 55 | fn contains_key_works() { 56 | init(); 57 | let path = PathBuf::from("/tmp/test-contains_key_works"); 58 | let _ = std::fs::remove_dir_all(&path); 59 | 60 | type Key = Blake2Output<[u8; 8]>; 61 | let key = { 62 | let mut db = Options::new() 63 | .key_bytes(2) 64 | .index_bits(4) 65 | .path(path.clone()) 66 | .open::() 67 | .unwrap(); 68 | db.store(b"Hello world!").1 69 | }; 70 | 71 | { 72 | let mut db = Options::from_path(path.clone()).open::().unwrap(); 73 | // Check it's there. 74 | assert!(db.contains_key(&key)); 75 | db.remove(&key).unwrap(); 76 | assert!(!db.contains_key(&key)); 77 | } 78 | } 79 | 80 | #[test] 81 | fn oversize_allocation_works() { 82 | init(); 83 | let path = PathBuf::from("/tmp/test-oversize_allocation_works"); 84 | let _ = std::fs::remove_dir_all(&path); 85 | 86 | type Key = Blake2Output<[u8; 8]>; 87 | let key = { 88 | let mut db = Options::new() 89 | .key_bytes(2) 90 | .index_bits(4) 91 | .path(path.clone()) 92 | .open::() 93 | .unwrap(); 94 | // Insert 1MB of zeros 95 | db.store(&[0u8; 1024*1024][..]).1 96 | }; 97 | 98 | { 99 | let mut db = Options::from_path(path.clone()).open::().unwrap(); 100 | // Check it's there. 101 | assert_eq!(db.get_ref(&key).unwrap().as_ref(), &[0u8; 1024 * 1024][..]); 102 | // Delete it. 103 | db.remove(&key).unwrap(); 104 | } 105 | 106 | { 107 | let db = Options::from_path(path.clone()).open::().unwrap(); 108 | // Check it's not there. 109 | assert!(!db.contains_key(&key)); 110 | } 111 | } 112 | 113 | #[test] 114 | fn oversize_allocation_shrink_works() { 115 | init(); 116 | let path = PathBuf::from("/tmp/test-oversize_allocation_shrink_works"); 117 | let _ = std::fs::remove_dir_all(&path); 118 | 119 | type Key = Blake2Output<[u8; 8]>; 120 | let mut db = Options::new() 121 | .key_bytes(2) 122 | .index_bits(4) 123 | .oversize_shrink(8 * 1024 * 1024, 2 * 1024 * 1024) 124 | .all_items_backed() 125 | .path(path.clone()) 126 | .open::() 127 | .unwrap(); 128 | let keys = (0..8).map(|i| 129 | // Insert 1MB of zeros 130 | db.store(&[i; 1024 * 1024][..]).1 131 | ).collect::>(); 132 | assert_eq!(db.bytes_mapped(), 8 * 1024 * 1024 + 655360); 133 | 134 | // Trigger shrinking. 135 | let key8 = db.store(&[8u8; 1024 * 1024][..]).1; 136 | assert_eq!(db.bytes_mapped(), 2 * 1024 * 1024 + 655360); 137 | 138 | // Should only be 6 & 7 left now. 139 | assert_eq!(db.get(&keys[7]).unwrap(), &[7u8; 1024 * 1024][..]); 140 | assert_eq!(db.get(&key8).unwrap(), &[8u8; 1024 * 1024][..]); 141 | assert_eq!(db.bytes_mapped(), 2 * 1024 * 1024 + 655360); 142 | 143 | // Mapping key 0 will have to go to disk. 144 | assert_eq!(db.get(&keys[0]).unwrap(), &[0u8; 1024 * 1024][..]); 145 | assert_eq!(db.bytes_mapped(), 3 * 1024 * 1024 + 655360); 146 | } 147 | 148 | #[test] 149 | fn general_use_should_work() { 150 | init(); 151 | let path = PathBuf::from("/tmp/test-general_use_should_work"); 152 | let _ = std::fs::remove_dir_all(&path); 153 | 154 | type Key = Blake2Output<[u8; 8]>; 155 | let key = { 156 | let mut db = Options::new() 157 | .key_bytes(2) 158 | .index_bits(4) 159 | .path(path.clone()) 160 | .open::() 161 | .unwrap(); 162 | db.store(b"Hello world!").1 163 | }; 164 | 165 | let mut number3 = Key::default(); 166 | { 167 | let mut db = Options::from_path(path.clone()).open::().unwrap(); 168 | for i in 0..100 { 169 | let value = format!("The number {}", i); 170 | println!("👉 Inserting: {}", value); 171 | let key = db.store(value.as_bytes()).1; 172 | if i == 3 { 173 | number3 = key; 174 | } 175 | } 176 | } 177 | 178 | { 179 | let mut db = Options::from_path(path.clone()).open::().unwrap(); 180 | 181 | let value = db.get(&key); 182 | println!("Value: {:?}", value.and_then(|b| String::from_utf8(b).ok())); 183 | println!("Refs: {}", db.get_ref_count(&key)); 184 | 185 | let value = db.get(&Default::default()); 186 | println!("Empty value: {:?}", value); 187 | 188 | println!("Reindexing..."); 189 | db.reindex(2, 8).unwrap(); 190 | 191 | let value = db.get(&key); 192 | println!("Value: {:?}", value.and_then(|b| String::from_utf8(b).ok())); 193 | println!("Refs: {}", db.get_ref_count(&key)); 194 | 195 | info!("Info: {:?}", db.info()); 196 | 197 | let _value = db.get(&key); 198 | db.remove(&key).unwrap(); 199 | } 200 | 201 | { 202 | let db = Options::from_path(path.clone()).open::().unwrap(); 203 | 204 | info!("Info: {:?}", db.info()); 205 | 206 | let value = db.get(&number3).and_then(|s| String::from_utf8(s).ok()); 207 | println!("Number3 (key: {}) is {:?}", hex::encode(number3), value); 208 | 209 | let value = db.get(&key); 210 | println!("Value: {:?}", value.and_then(|b| String::from_utf8(b).ok())); 211 | } 212 | } 213 | } -------------------------------------------------------------------------------- /src/metadata.rs: -------------------------------------------------------------------------------- 1 | use parity_scale_codec::{self as codec, Encode, Decode}; 2 | use std::path::PathBuf; 3 | use crate::{Error, database::Options}; 4 | 5 | type Version = u32; 6 | 7 | const CURRENT_VERSION: Version = 1; 8 | 9 | pub struct MetadataV1 { 10 | pub(crate) key_bytes: usize, 11 | pub(crate) index_bits: usize, 12 | } 13 | 14 | impl Metadata for MetadataV1 {} 15 | 16 | impl Decode for MetadataV1 { 17 | fn decode(input: &mut I) -> Result { 18 | Ok(Self { 19 | key_bytes: u32::decode(input)? as usize, 20 | index_bits: u32::decode(input)? as usize, 21 | }) 22 | } 23 | } 24 | 25 | impl Encode for MetadataV1 { 26 | fn encode_to(&self, dest: &mut O) { 27 | (self.key_bytes as u32).encode_to(dest); 28 | (self.index_bits as u32).encode_to(dest); 29 | } 30 | } 31 | 32 | pub trait Metadata: Encode + Decode { 33 | fn filename(path: &PathBuf) -> PathBuf { 34 | let mut filename = path.clone(); 35 | filename.push("metadata.subdb"); 36 | filename 37 | } 38 | 39 | fn write(&self, path: &PathBuf) -> Result<(), Error> { 40 | (b"SBDB", CURRENT_VERSION, &self) 41 | .using_encoded(|e| std::fs::write(Self::filename(path), e))?; 42 | Ok(()) 43 | } 44 | 45 | fn try_read(path: &PathBuf) -> Result, Error> { 46 | let filename = Self::filename(path); 47 | if !filename.is_file() { 48 | return Ok(None); 49 | } 50 | let metadata = std::fs::read(Self::filename(path))?; 51 | let mut input = &metadata[..]; 52 | 53 | let magic = <[u8; 4]>::decode(&mut input).map_err(|_| Error::BadMetadata)?; 54 | if &magic != b"SBDB" { 55 | return Err(Error::BadMetadata); 56 | } 57 | let version = Version::decode(&mut input).map_err(|_| Error::BadMetadata)?; 58 | if version != CURRENT_VERSION { 59 | return Err(Error::UnsupportedVersion); 60 | } 61 | Ok(Some(Self::decode(&mut input).map_err(|_| Error::BadMetadata)?)) 62 | } 63 | } 64 | 65 | impl<'a> From<&'a Options> for MetadataV1 { 66 | fn from(o: &'a Options) -> Self { 67 | Self { 68 | key_bytes: o.key_bytes, 69 | index_bits: o.index_bits, 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/safe_database.rs: -------------------------------------------------------------------------------- 1 | use parking_lot::RwLock; 2 | use blake2_rfc::blake2b::blake2b; 3 | use sp_database::{self, ColumnId}; 4 | use parity_scale_codec::Encode; 5 | use crate::database::Database; 6 | use crate::types::KeyType; 7 | 8 | /// A database hidden behind an RwLock, so that it implements Send + Sync. 9 | /// 10 | /// Construct by creating a `Database` and then using `.into()`. 11 | pub struct SafeDatabase(RwLock>); 12 | impl From> for SafeDatabase { 13 | fn from(db: Database) -> Self { 14 | Self(RwLock::new(db)) 15 | } 16 | } 17 | 18 | impl sp_database::Database for SafeDatabase { 19 | fn get(&self, col: ColumnId, key: &[u8]) -> Option> { 20 | let mut hash = H::default(); 21 | (col, key).using_encoded(|d| 22 | hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) 23 | ); 24 | self.0.read().get(&hash) 25 | } 26 | 27 | fn with_get(&self, col: ColumnId, key: &[u8], f: &mut dyn FnMut(&[u8])) { 28 | let mut hash = H::default(); 29 | (col, key).using_encoded(|d| 30 | hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) 31 | ); 32 | let _ = self.0.read().get_ref(&hash).map(|d| f(d.as_ref())); 33 | } 34 | 35 | fn set(&self, col: ColumnId, key: &[u8], value: &[u8]) { 36 | let mut hash = H::default(); 37 | (col, key).using_encoded(|d| 38 | hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) 39 | ); 40 | self.0.write().insert(&value, &hash); 41 | } 42 | 43 | fn remove(&self, col: ColumnId, key: &[u8]) { 44 | let mut hash = H::default(); 45 | (col, key).using_encoded(|d| 46 | hash.as_mut().copy_from_slice(blake2b(32, &[], d).as_bytes()) 47 | ); 48 | let _ = self.0.write().remove(&hash); 49 | } 50 | 51 | fn lookup(&self, hash: &H) -> Option> { 52 | self.0.read().get(hash) 53 | } 54 | 55 | fn with_lookup(&self, hash: &H, f: &mut dyn FnMut(&[u8])) { 56 | let _ = self.0.read().get_ref(hash).map(|d| f(d.as_ref())); 57 | } 58 | 59 | fn store(&self, hash: &H, preimage: &[u8]) { 60 | self.0.write().insert(preimage, hash); 61 | } 62 | 63 | fn release(&self, hash: &H) { 64 | let _ = self.0.write().remove(hash); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/table.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use std::fs::{File, OpenOptions}; 3 | use std::mem::size_of; 4 | use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering::{Relaxed, Acquire, Release}}; 5 | use std::ops::{Deref, DerefMut}; 6 | use parking_lot::{ 7 | RwLock, RwLockWriteGuard, RwLockReadGuard, MappedRwLockReadGuard, RwLockUpgradableReadGuard 8 | }; 9 | use log::{trace, debug}; 10 | use memmap::{MmapMut, MmapOptions}; 11 | use parity_scale_codec::{self as codec, Encode, Decode}; 12 | use crate::types::{KeyType, SimpleWriter}; 13 | use crate::datum_size::DatumSize; 14 | 15 | /// How many references a storage table item has. 16 | pub type RefCount = u16; 17 | 18 | /// Where in a storage table an item is. 19 | pub type TableItemIndex = u16; 20 | 21 | /// How many table items; must be able to store a range from 0 to TableItemIndex::max_value() + 1 22 | /// inclusive, therefore needs the next biggest type up. 23 | pub type TableItemCount = u32; 24 | 25 | /// A time index for our LRU system. 26 | pub type LruIndex = AtomicU64; 27 | 28 | pub struct Table { 29 | file: File, 30 | path: PathBuf, 31 | data: RwLock, 32 | header_data: RwLock, 33 | header: TableHeader, 34 | item_header_size: usize, 35 | item_size: usize, 36 | item_count: TableItemCount, 37 | value_size: usize, 38 | table_header_size: usize, 39 | correction_factor: CorrectionFactor, 40 | 41 | maps: RwLock>>, 42 | lru_index: LruIndex, 43 | mapped: AtomicUsize, 44 | 45 | _dummy: std::marker::PhantomData, 46 | } 47 | 48 | /// Rather unsafe. 49 | #[derive(Clone, Copy, Encode, Decode, Debug)] 50 | struct TableHeader { 51 | /// The number of items used. Never more than `touched_count`. 52 | used: TableItemCount, 53 | /// Ignore if used == touched_count; otherwise it is the next free item. 54 | next_free: TableItemIndex, 55 | /// The number of unique slots that have been allocated at some point. Never more than 56 | /// `item_count`. 57 | /// 58 | /// Item indices equal to this and less than `item_count` may be allocated in addition to the 59 | /// linked list starting at `next_free`. 60 | touched_count: TableItemCount, 61 | /// Total amount of bytes in all external files. Only matters when size is > 0 62 | external_data: u64, 63 | } 64 | 65 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] 66 | enum CorrectionFactor { 67 | None, 68 | U8, 69 | U16, 70 | U32, 71 | } 72 | 73 | #[derive(Clone, Debug)] 74 | enum ItemHeader + AsMut<[u8]> + Default> { 75 | Allocated { 76 | /// Number of times this item has been inserted, without a corresponding remove, into the 77 | /// database. 78 | ref_count: RefCount, 79 | size_correction: u32, 80 | key: K, 81 | }, 82 | Free( 83 | /// If `used < touched_count`, then the next free item's index. If the two are equal, then 84 | /// this is undefined. 85 | TableItemIndex, 86 | ), 87 | } 88 | 89 | impl + AsMut<[u8]> + Default + Eq> ItemHeader { 90 | fn as_next_free(&self) -> TableItemIndex { 91 | match self { 92 | ItemHeader::Free(next_free) => *next_free, 93 | ItemHeader::Allocated {..} => panic!("Free expected. Database corruption?"), 94 | } 95 | } 96 | 97 | fn as_allocation(&self, check_hash: Option<&K>) -> Result<(RefCount, usize), ()> { 98 | match self { 99 | ItemHeader::Allocated { ref_count, size_correction, key } => { 100 | if check_hash.map_or(true, |hash| hash == key) { 101 | Ok((*ref_count, *size_correction as usize)) 102 | } else { 103 | Err(()) 104 | } 105 | }, 106 | ItemHeader::Free(_) => panic!("Allocated expected. Database corruption?"), 107 | } 108 | } 109 | 110 | #[allow(dead_code)] 111 | fn to_maybe_key(self) -> Option { 112 | match self { 113 | ItemHeader::Allocated { key, .. } => Some(key), 114 | ItemHeader::Free(_) => None, 115 | } 116 | } 117 | 118 | fn decode(input: &mut I, correction_factor: CorrectionFactor) -> Result { 119 | let first_byte = input.read_byte()?; 120 | Ok(if first_byte > 0 { 121 | let second_byte = input.read_byte()? as u16; 122 | let ref_count = (((first_byte & 0b01111111) as u16) << 8) + second_byte; 123 | let size_correction = match correction_factor { 124 | CorrectionFactor::None => 0u32, 125 | CorrectionFactor::U8 => u8::decode(input)? as u32, 126 | CorrectionFactor::U16 => u16::decode(input)? as u32, 127 | CorrectionFactor::U32 => u32::decode(input)?, 128 | }; 129 | let mut key = K::default(); 130 | input.read(key.as_mut())?; 131 | Self::Allocated { ref_count, size_correction, key } 132 | } else { 133 | Self::Free(TableItemIndex::decode(input)?) 134 | }) 135 | } 136 | 137 | fn encode_to(&self, output: &mut O, correction_factor: CorrectionFactor) { 138 | match self { 139 | ItemHeader::Allocated { ref_count, size_correction, key} => { 140 | assert!(*ref_count < 32768); 141 | let first_byte = ((*ref_count >> 8) | 0b10000000) as u8; 142 | first_byte.encode_to(output); 143 | (*ref_count as u8).encode_to(output); 144 | match correction_factor { 145 | CorrectionFactor::None => {}, 146 | CorrectionFactor::U8 => (*size_correction as u8).encode_to(output), 147 | CorrectionFactor::U16 => (*size_correction as u16).encode_to(output), 148 | CorrectionFactor::U32 => (*size_correction as u32).encode_to(output), 149 | } 150 | output.write(key.as_ref()); 151 | } 152 | ItemHeader::Free(index) => { 153 | (0u8, index).encode_to(output); 154 | } 155 | } 156 | } 157 | } 158 | 159 | impl Table { 160 | pub fn commit(&mut self) { 161 | self.data.write().flush().expect("I/O Error"); 162 | } 163 | 164 | pub fn open(path: PathBuf, datum_size: DatumSize, min_items_backed: TableItemCount) -> Self { 165 | assert!(!path.exists() || path.is_file(), "Path must either not exist or be a file."); 166 | 167 | let file = OpenOptions::new() 168 | .read(true) 169 | .write(true) 170 | .create(true) 171 | .open(&path) 172 | .expect("Path must be writable."); 173 | let len = file.metadata().expect("File must be readable").len(); 174 | let value_size = datum_size.size().unwrap_or(0); 175 | let (correction_factor, correction_factor_size) = match datum_size.size_range().unwrap_or(0) { 176 | 0 => (CorrectionFactor::None, 0), 177 | 1..=255 => (CorrectionFactor::U8, 1), 178 | 256..=65535 => (CorrectionFactor::U16, 2), 179 | _ => (CorrectionFactor::U32, 4), 180 | }; 181 | trace!(target: "table", "Table size correction: {:?}/{} bytes", correction_factor, correction_factor_size); 182 | let item_count = datum_size.contents_entries() as TableItemCount; 183 | let key_size = std::mem::size_of::(); 184 | let item_header_size = (size_of::() + correction_factor_size + key_size) 185 | .max(1 + size_of::()); 186 | let item_size = value_size + item_header_size; 187 | trace!(target: "table", "Item size: {} bytes = rc {} + cfs {} + key {} + value {}", item_size, size_of::(), correction_factor_size, key_size, value_size); 188 | let table_header_size = size_of::(); 189 | let total_size = table_header_size + item_size * item_count as usize; 190 | let minimum_size = table_header_size + item_size * item_count.min(min_items_backed) as usize; 191 | 192 | assert!( 193 | len == 0 || len >= minimum_size as u64 || len <= total_size as u64, 194 | "File exists but length is unexpected" 195 | ); 196 | if len == 0 { 197 | file.set_len(minimum_size as u64).expect("Path must be writable."); 198 | } 199 | 200 | let header_data = unsafe { 201 | MmapOptions::new() 202 | .len(table_header_size) 203 | .map_mut(&file) 204 | .expect("Path must be writable.") 205 | }; 206 | let data = unsafe { 207 | MmapOptions::new() 208 | .offset(table_header_size as u64) 209 | .map_mut(&file) 210 | .expect("Path must be writable.") 211 | }; 212 | let header = TableHeader::decode(&mut header_data.as_ref()) 213 | .expect("Invalid table header. Database corruption?"); 214 | trace!(target: "table", "Read header: {:?}", header); 215 | let maps_count = if value_size == 0 { header.touched_count as usize } else { 0 }; 216 | let mut maps = Vec::new(); 217 | maps.resize_with(maps_count,|| None); 218 | trace!(target: "table", "Maps is now: {} items: {:?}", maps.len(), maps); 219 | 220 | Self { 221 | path, file, data: RwLock::new(data), header_data: RwLock::new(header_data), header, item_count, item_size, item_header_size, value_size, correction_factor, 222 | table_header_size, maps: RwLock::new(maps), lru_index: Default::default(), mapped: Default::default(), _dummy: Default::default() 223 | } 224 | } 225 | 226 | /// Extend the file, and also the amount mapped to hold twice as many items as it does currently 227 | /// but no more than its maximum allowed `item_count`. 228 | fn extend(&mut self, min_items: TableItemCount) { 229 | self.item_count = ((self.data.read().len() / self.item_size * 2) 230 | .min(self.item_count as usize) as TableItemCount) 231 | .max(min_items); 232 | self.file.set_len(self.item_count as u64 * self.item_size as u64 + self.table_header_size as u64) 233 | .expect("File must be writable."); 234 | *self.header_data.write() = unsafe { 235 | MmapOptions::new() 236 | .len(self.table_header_size) 237 | .map_mut(&self.file) 238 | .expect("Path must be writable.") 239 | }; 240 | *self.data.write() = unsafe { 241 | MmapOptions::new() 242 | .offset(self.table_header_size as u64) 243 | .map_mut(&self.file) 244 | .expect("Path must be writable.") 245 | }; 246 | } 247 | 248 | /// Ensures that the backing file is grown sufficiently large that `index` is referencable. 249 | /// 250 | /// This will panic if `index >= self.item_count`. 251 | fn ensure_referencable(&mut self, index: TableItemIndex) { 252 | let items_backed = (self.data.read().len() / self.item_size) as TableItemCount; 253 | let index = index as TableItemCount; 254 | assert!(index < self.item_count, "Oversize index. WTF?"); 255 | if index >= items_backed { 256 | self.extend(index + 1); 257 | } 258 | } 259 | 260 | /// Ensures that an item's contents are (immutably) mapped. This will never mutate anything in 261 | /// such a way that an existing reference becomes invalid. Specifically it is *NOT ALLOWED* to 262 | /// change a `Some(MmapMut)` into a `None`, only a `None` into a `Some`. This ensures that the 263 | /// unsafe function used later in `item_ref` is always safe, since it relies on those references 264 | /// staying valid as long as there's no mutable reference taken to this struct. (A mutable 265 | /// reference is needed in order to invalidate any of those references.) 266 | /// 267 | /// Will return `None` if `i` is not an item we currently have stored, `Some(mapped_bytes)` with 268 | /// the number of bytes that has been additionally mapped (0 if it was already mapped) if it is 269 | /// stored. 270 | fn ensure_mapped(&self, i: TableItemIndex, create: Option) -> Result>>, ()> { 271 | trace!(target: "table", "Mapping table index {}", i); 272 | let maps = self.maps.upgradable_read(); 273 | let lru_index = self.lru_index.fetch_add(1, Relaxed); 274 | let i = i as usize; 275 | let maps = if maps.get(i).ok_or(())?.deref().is_some() { 276 | trace!(target: "table", "Already mapped"); 277 | maps[i] 278 | .as_ref() 279 | .expect("is_some above ^") 280 | .1.store(lru_index, Relaxed); 281 | maps 282 | } else { 283 | trace!(target: "table", "Opening table index contents..."); 284 | let name = self.contents_name(i as TableItemIndex); 285 | let file = OpenOptions::new() 286 | .read(true) 287 | .write(true) 288 | .create(create.is_some()) 289 | .open(&name) 290 | .map_err(|_| ())?; 291 | if let Some(size) = create { 292 | file.set_len(size).map_err(|_| ())?; 293 | } 294 | let data = unsafe { MmapOptions::new().map_mut(&file).map_err(|_| ())? }; 295 | self.mapped.fetch_add(data.len(), Release); 296 | trace!(target: "table", "Contents: {}", hex::encode(data.as_ref())); 297 | let mut maps = RwLockUpgradableReadGuard::upgrade(maps); 298 | *maps.get_mut(i) 299 | .ok_or(())? 300 | .deref_mut() = Some((data, lru_index.into())); 301 | RwLockWriteGuard::downgrade_to_upgradable(maps) 302 | }; 303 | Ok(maps) 304 | } 305 | 306 | fn contents_name(&self, i: TableItemIndex) -> PathBuf { 307 | let mut path = self.path.clone(); 308 | path.set_extension(format!("{}", i)); 309 | path 310 | } 311 | 312 | /// Returns `Some(bytes)` with the bytes unmapped, if it was previously mapped. `Some(0)` if it 313 | /// was not previously mapped, and `None` if we are not storing an item at this index. 314 | fn ensure_not_mapped(&mut self, i: TableItemIndex) -> Option { 315 | let bytes = self.maps.write().get_mut(i as usize)?.take().map_or(0, |i| i.0.len()); 316 | self.mapped.fetch_sub(bytes, Release); 317 | Some(bytes) 318 | } 319 | 320 | /// Reduce the number of items mapped until the total size is less than `maximum_size`. 321 | pub fn shrink_to(&mut self, maximum_size: usize, shrink_size: usize) { 322 | let current_size = self.mapped.load(Acquire); 323 | trace!(target: "table", "Considering shrinking. max: {}, shrink: {}, current: {}", maximum_size, shrink_size, current_size); 324 | if current_size > maximum_size { 325 | let mut sorted = { 326 | self.maps.read().iter() 327 | .enumerate() 328 | .filter_map(|(i, c)| c.as_ref().clone().map(|x| (x.1.load(Relaxed), i as TableItemIndex))) 329 | .collect::>() 330 | }; 331 | sorted.sort(); 332 | for (_, i) in sorted.into_iter() { 333 | let bytes_unmapped = self.ensure_not_mapped(i).unwrap_or(0); 334 | let current_size = self.mapped.load(Acquire); 335 | debug!(target: "table", "Unmapped {}. current: {}, target: {}", bytes_unmapped, current_size, shrink_size); 336 | if current_size <= shrink_size { 337 | break; 338 | } 339 | } 340 | } 341 | } 342 | 343 | fn set_header(&mut self, h: TableHeader) { 344 | self.header = h; 345 | self.header.encode_to(&mut SimpleWriter(self.header_data.write().as_mut(), 0)); 346 | } 347 | 348 | /// The total amount of bytes stored on disk for this table. 349 | pub fn bytes_used(&self) -> usize { 350 | self.data.read().len() + self.header.external_data as usize 351 | } 352 | 353 | /// The amount of bytes currently mapped into memory for this table. 354 | #[allow(dead_code)] 355 | pub fn bytes_mapped(&self) -> usize { 356 | if self.value_size == 0 { 357 | self.data.read().len() + self.mapped.load(Relaxed) 358 | } else { 359 | self.data.read().len() 360 | } 361 | } 362 | 363 | fn mutate_item_header(&mut self, 364 | i: TableItemIndex, 365 | f: impl FnOnce(&mut ItemHeader) -> R, 366 | ) -> Result { 367 | if i as TableItemCount >= self.item_count { return Err(()) } 368 | let offset = self.item_size * i as usize; 369 | let data = self.data.upgradable_read(); 370 | let mut h = { 371 | let mut item_data = &data[offset..offset + self.item_header_size]; 372 | ItemHeader::decode(&mut item_data, self.correction_factor) 373 | .expect("Database corrupt?") 374 | }; 375 | let r = f(&mut h); 376 | 377 | let mut data = RwLockUpgradableReadGuard::upgrade(data); 378 | let item_data = &mut data[offset..offset + self.item_header_size]; 379 | h.encode_to(&mut SimpleWriter(item_data, 0), self.correction_factor); 380 | Ok(r) 381 | } 382 | 383 | fn item_header(&self, i: TableItemIndex) -> Result, ()> { 384 | if i as TableItemCount >= self.item_count { return Err(()) } 385 | let offset = self.item_size * i as usize; 386 | let data = self.data.read(); 387 | let mut item_data = &data[offset..offset + self.item_header_size]; 388 | Ok(ItemHeader::decode(&mut item_data, self.correction_factor) 389 | .expect("Database corrupt?")) 390 | } 391 | 392 | #[allow(dead_code)] 393 | fn set_item_header(&mut self, i: TableItemIndex, h: ItemHeader) -> Result<(), ()> { 394 | if i as TableItemCount >= self.item_count { return Err(()) } 395 | let offset = self.item_size * i as usize; 396 | let mut data = self.data.write(); 397 | let item_data = &mut data[offset..offset + self.item_header_size]; 398 | h.encode_to(&mut SimpleWriter(item_data, 0), self.correction_factor); 399 | Ok(()) 400 | } 401 | 402 | /// Retrieve a table item's data as an immutable pointer. 403 | pub fn item_ref_count(&self, i: TableItemIndex, check_hash: Option<&K>) -> Result { 404 | Ok(self.item_header(i).and_then(|h| h.as_allocation(check_hash))?.0) 405 | } 406 | 407 | /// Retrieve a table item's key hash. 408 | #[allow(dead_code)] 409 | pub fn item_hash(&self, i: TableItemIndex) -> Result { 410 | self.item_header(i).and_then(|h| h.to_maybe_key().ok_or(())) 411 | } 412 | 413 | /// Retrieve a table item's data as an immutable pointer. 414 | pub fn item_ref<'a>(&'a self, i: TableItemIndex, check_hash: Option<&K>) -> Result, ()> { 415 | let header = self.item_header(i).and_then(|h| h.as_allocation(check_hash))?; 416 | Ok(if self.value_size == 0 { 417 | let map: MappedRwLockReadGuard<'a, MmapMut> = RwLockReadGuard::map( 418 | RwLockUpgradableReadGuard::downgrade(self.ensure_mapped(i, None)?), 419 | |maps| &maps[i as usize].as_ref().expect("guaranteed above").0, 420 | ); 421 | fn extract(mmap: &MmapMut) -> &[u8] { &mmap.as_ref() } 422 | MappedRwLockReadGuard::<'a, MmapMut>::map(map, extract) 423 | } else { 424 | let size = self.value_size - header.1; 425 | let p = self.item_size * i as usize + self.item_header_size; 426 | RwLockReadGuard::map(self.data.read(), |d| &d[p..p + size]) 427 | }) 428 | } 429 | 430 | pub fn set_item(&mut self, i: TableItemIndex, data: &[u8]) -> Result<(), ()> { 431 | let header = self.item_header(i)?; 432 | if self.value_size == 0 { 433 | let mut maps = RwLockUpgradableReadGuard::upgrade(self.ensure_mapped(i, Some(data.len() as u64))?); 434 | maps[i as usize] 435 | .as_mut() 436 | .expect("guaranteed above").0 437 | .copy_from_slice(data); 438 | } else { 439 | let size = self.value_size - header.as_allocation(None)?.1; 440 | let p = self.item_size * i as usize + self.item_header_size; 441 | self.data.write()[p..p + size].copy_from_slice(data) 442 | } 443 | Ok(()) 444 | } 445 | 446 | fn check_key(hash: Option<&K>, key: &K) -> Result<(), ()> { 447 | if hash.map_or(true, |k| k == key) { 448 | Ok(()) 449 | } else { 450 | Err(()) 451 | } 452 | } 453 | 454 | /// Add another reference to a slot that is already allocated and return the resulting number of 455 | /// references. Err if the slot is not allocated or if the given `hash` if different to the 456 | /// hash of the entry. 457 | pub fn bump(&mut self, i: TableItemIndex, hash: Option<&K>) -> Result { 458 | let mut item = self.item_header(i)?; 459 | let rc = match item { 460 | ItemHeader::Allocated { ref mut ref_count, ref key, .. } => { 461 | Self::check_key(hash, key)?; 462 | *ref_count += 1; 463 | *ref_count 464 | } 465 | ItemHeader::Free(..) => return Err(()), 466 | }; 467 | self.set_item_header(i, item)?; 468 | Ok(rc) 469 | } 470 | 471 | /// Attempt to allocate a slot. 472 | pub fn allocate(&mut self, key: &K, size: usize) -> Option { 473 | let mut h = self.header.clone(); 474 | let size_correction = if self.value_size > 0 { (self.value_size - size) as u32 } else { 0 }; 475 | // OPTIMISE: Avoid extra copy of `key` by writing directly to map. 476 | let new_item = ItemHeader::Allocated { ref_count: 1, size_correction, key: key.clone() }; 477 | let result = if h.used < h.touched_count { 478 | let result = h.next_free; 479 | let new_next_free = self.mutate_item_header(result, |item| { 480 | let new_next_free = item.as_next_free(); 481 | *item = new_item; 482 | new_next_free 483 | }).ok()?; 484 | h.next_free = new_next_free; 485 | result 486 | } else { 487 | if h.touched_count < self.item_count { 488 | let result = h.touched_count as TableItemIndex; 489 | self.ensure_referencable(result); 490 | self.mutate_item_header(result, |item| { 491 | assert!(matches!(item, ItemHeader::Free(_)), "Free slot expected. Database corrupt?"); 492 | *item = new_item; 493 | }).ok()?; 494 | h.touched_count += 1; 495 | result 496 | } else { 497 | return None 498 | } 499 | }; 500 | h.used += 1; 501 | if self.value_size == 0 { 502 | h.external_data += size as u64; 503 | } 504 | self.set_header(h); 505 | let maps = self.maps.upgradable_read(); 506 | if maps.len() <= result as usize { 507 | let new_len = (result as usize * 3 / 2).max(self.item_count as usize); 508 | RwLockUpgradableReadGuard::upgrade(maps).resize_with(new_len, || None); 509 | } 510 | Some(result) 511 | } 512 | 513 | /// Free up a slot or decrease the reference count if it's greater than 1. Returns Ok along with 514 | /// the number of refs remaining, or Err if the slot was already free. 515 | pub fn free(&mut self, i: TableItemIndex, check_hash: Option<&K>) -> Result { 516 | let mut h = self.header.clone(); 517 | let result = self.mutate_item_header(i, |item| { 518 | match item { 519 | ItemHeader::Allocated { ref mut ref_count, ref key, .. } => { 520 | Self::check_key(check_hash, key)?; 521 | assert!(*ref_count > 0, "Database corrupt? Zero refs."); 522 | if *ref_count > 1 { 523 | *ref_count -= 1; 524 | return Ok(*ref_count) 525 | } 526 | } 527 | ItemHeader::Free(..) => return Err(()), 528 | } 529 | // Stich the old free list head onto this item. 530 | *item = ItemHeader::Free(h.next_free); 531 | Ok(0) 532 | })??; 533 | if result == 0 { 534 | if self.value_size == 0 { 535 | // Actually remove the mapping and the file. 536 | self.ensure_not_mapped(i); 537 | let filename = self.contents_name(i); 538 | let size = std::fs::metadata(&filename).expect("Table file missing. Database corruption?").len(); 539 | std::fs::remove_file(filename) 540 | .expect("cannot remove data file. Permissions wrong?"); 541 | h.external_data = h.external_data.checked_sub(size) 542 | .expect("external_data underflow. Database corruption?"); 543 | } 544 | // Add the item to the free list. 545 | h.used = h.used.checked_sub(1) 546 | .expect("Database corrupt? used count underflow"); 547 | h.next_free = i; 548 | self.set_header(h); 549 | } 550 | Ok(result) 551 | } 552 | 553 | /// The amount of slots that are occupied with data in this table. 554 | #[allow(dead_code)] 555 | pub fn used(&self) -> TableItemCount { 556 | self.header.used 557 | } 558 | 559 | /// The total number of items that this table could ever hold at once. 560 | #[allow(dead_code)] 561 | pub fn total(&self) -> TableItemCount { 562 | self.item_count 563 | } 564 | 565 | /// The amount of slots that are unoccupied with data in this table. 566 | #[allow(dead_code)] 567 | pub fn available(&self) -> TableItemCount { 568 | self.item_count - self.header.used 569 | } 570 | } 571 | 572 | #[cfg(test)] 573 | mod tests { 574 | use super::*; 575 | use std::path::PathBuf; 576 | 577 | #[test] 578 | fn database_should_work() { 579 | let path = PathBuf::from("/tmp/test-table-database_should_work"); 580 | let x = { 581 | let mut t = Table::<[u8; 1]>::open(path.clone(), 0.into(), 65536); 582 | let x = t.allocate(&[42u8], 12).unwrap(); 583 | t.set_item(x, b"Hello world!").unwrap(); 584 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 585 | t.commit(); 586 | x 587 | }; 588 | let t = Table::<[u8; 1]>::open(path.clone(), 0.into(), 65536); 589 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 590 | } 591 | 592 | #[test] 593 | fn thin_table_should_work() { 594 | let path = PathBuf::from("/tmp/test-table-thin_table_should_work"); 595 | for i in 0..10 { let _ = std::fs::remove_file(format!("/tmp/test-table.{}", i)); } 596 | let x = { 597 | let mut t = Table::<[u8; 1]>::open(path.clone(), DatumSize::Oversize, 65536); 598 | let x = t.allocate(&[42u8], 12).unwrap(); 599 | t.set_item(x, b"Hello world!").unwrap(); 600 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 601 | t.commit(); 602 | x 603 | }; 604 | let t = Table::<[u8; 1]>::open(path.clone(), DatumSize::Oversize, 65536); 605 | assert_eq!(t.item_ref(x, Some(&[42u8])).unwrap().as_ref(), b"Hello world!"); 606 | } 607 | 608 | #[test] 609 | fn table_extension_should_work() { 610 | let path = PathBuf::from("/tmp/test-table-table_extension_should_work"); 611 | let _ = std::fs::remove_file(&path); 612 | let x = { 613 | let mut t = Table::<[u8; 1]>::open(path.clone(), 0.into(), 0); 614 | assert_eq!(t.bytes_used(), 0); 615 | let x = t.allocate(&[42u8], 12).unwrap(); 616 | t.set_item(x, b"Hello world!").unwrap(); 617 | assert_eq!(t.bytes_used(), 36); 618 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 619 | t.commit(); 620 | x 621 | }; 622 | let t = Table::<[u8; 1]>::open(path.clone(), 0.into(), 0); 623 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 624 | } 625 | 626 | #[test] 627 | fn oversize_table_extension_should_work() { 628 | let path = PathBuf::from("/tmp/test-table-oversize_table_extension_should_work"); 629 | let _ = std::fs::remove_file(&path); 630 | for i in 0..10 { let _ = std::fs::remove_file(format!("/tmp/test-table.{}", i)); } 631 | let x = { 632 | let mut t = Table::<[u8; 1]>::open(path.clone(), DatumSize::Oversize, 0); 633 | assert_eq!(t.bytes_used(), 0); 634 | let x = t.allocate(&[42u8], 12).unwrap(); 635 | t.set_item(x, b"Hello world!").unwrap(); 636 | assert_eq!(t.bytes_used(), 15); 637 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 638 | t.commit(); 639 | x 640 | }; 641 | let t = Table::<[u8; 1]>::open(path.clone(), DatumSize::Oversize, 0); 642 | assert_eq!(t.item_ref(x, None).unwrap().as_ref(), b"Hello world!"); 643 | } 644 | } -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use blake2_rfc::blake2b::blake2b; 2 | use parity_scale_codec::{self as codec, Encode}; 3 | use std::fmt::Debug; 4 | 5 | pub type TableIndex = usize; 6 | pub type EntryIndex = usize; 7 | 8 | pub trait KeyType: AsRef<[u8]> + AsMut<[u8]> + Default + Eq + PartialEq + Clone + Debug + Send + Sync {} 9 | 10 | impl< 11 | T: AsRef<[u8]> + AsMut<[u8]> + Default + Eq + PartialEq + Clone + Debug + Send + Sync 12 | > KeyType for T {} 13 | 14 | pub trait EncodedSize: Encode { 15 | fn encoded_size() -> usize; 16 | } 17 | 18 | pub trait HashOutput: KeyType { 19 | fn from_data(data: &[u8]) -> Self; 20 | } 21 | 22 | #[derive(Default, Eq, PartialEq, Clone, Debug)] 23 | pub struct Blake2Output(pub T); 24 | 25 | macro_rules! do_array { 26 | ($n:tt $( $rest:tt )*) => { 27 | impl HashOutput for Blake2Output<[u8; $n]> { 28 | fn from_data(data: &[u8]) -> Self { 29 | let mut r = Self::default(); 30 | r.as_mut().copy_from_slice(&blake2b($n, &[], data).as_bytes()[..]); 31 | r 32 | } 33 | } 34 | impl AsRef<[u8]> for Blake2Output<[u8; $n]> { 35 | fn as_ref(&self) -> &[u8] { 36 | &self.0[..] 37 | } 38 | } 39 | impl AsMut<[u8]> for Blake2Output<[u8; $n]> { 40 | fn as_mut(&mut self) -> &mut [u8] { 41 | &mut self.0[..] 42 | } 43 | } 44 | do_array!{ $($rest)* } 45 | }; 46 | () => {} 47 | } 48 | 49 | do_array!( 50 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 51 | ); 52 | 53 | pub struct SimpleWriter<'a>(pub &'a mut[u8], pub usize); 54 | impl<'a> codec::Output for SimpleWriter<'a> { 55 | fn write(&mut self, d: &[u8]) { 56 | self.0[self.1..self.1 + d.len()].copy_from_slice(d); 57 | self.1 += d.len(); 58 | } 59 | } 60 | --------------------------------------------------------------------------------