From 44fc28cc85f570b93c657edd281877be41d3b515 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Thu, 30 Mar 2023 08:32:05 +0200 Subject: [PATCH 01/11] Dirty: vendor irmin 3.7.2 (db291414633ed62302572d12921308b07fb45f24) --- .../.github/workflows/changelog-check.yml | 20 + vendors/irmin/.github/workflows/coverage.yml | 67 + vendors/irmin/.github/workflows/git.yml | 13 + vendors/irmin/.gitignore | 12 + vendors/irmin/.ocamlformat | 6 + vendors/irmin/CHANGES.md | 2168 +++++++++++++ vendors/irmin/CONTRIBUTING.md | 48 + vendors/irmin/LICENSE.md | 15 + vendors/irmin/Makefile | 26 + vendors/irmin/README.md | 379 +++ vendors/irmin/README_LIBIRMIN.md | 173 + vendors/irmin/README_PPX.md | 128 + vendors/irmin/RELEASE.md | 183 ++ vendors/irmin/bench/irmin-pack/_layers.mli | 1 + .../irmin/bench/irmin-pack/bench_common.ml | 193 ++ .../irmin/bench/irmin-pack/bench_common.mli | 50 + vendors/irmin/bench/irmin-pack/dune | 94 + vendors/irmin/bench/irmin-pack/import.ml | 17 + vendors/irmin/bench/irmin-pack/main.ml | 55 + vendors/irmin/bench/irmin-pack/main.mli | 1 + .../bench/irmin-pack/tezos_history_metrics.ml | 178 + .../bench/irmin-pack/trace_collection.ml | 258 ++ .../irmin/bench/irmin-pack/trace_common.ml | 285 ++ .../bench/irmin-pack/trace_definitions.ml | 505 +++ .../irmin/bench/irmin-pack/trace_replay.ml | 524 +++ .../irmin/bench/irmin-pack/trace_replay.mli | 17 + .../bench/irmin-pack/trace_replay_intf.ml | 134 + .../bench/irmin-pack/trace_stat_summary.ml | 1106 +++++++ .../bench/irmin-pack/trace_stat_summary_cb.ml | 247 ++ .../irmin-pack/trace_stat_summary_conf.ml | 42 + .../bench/irmin-pack/trace_stat_summary_pp.ml | 1114 +++++++ .../irmin-pack/trace_stat_summary_utils.ml | 636 ++++ .../irmin-pack/trace_stat_summary_utils.mli | 398 +++ vendors/irmin/bench/irmin-pack/trace_stats.ml | 213 ++ vendors/irmin/bench/irmin-pack/tree.ml | 672 ++++ vendors/irmin/bench/irmin-pack/tree.mli | 1 + .../irmin/data/bench_fixed_size_string_set.ml | 124 + vendors/irmin/bench/irmin/data/dune | 3 + vendors/irmin/codecov.yml | 4 + vendors/irmin/doc/irmin-pack/design/README.md | 5 + .../doc/irmin-pack/design/chunked_suffix.md | 210 ++ .../design/imgs/chunked_suffix/0dXEkNs.png | Bin 0 -> 35949 bytes .../design/imgs/chunked_suffix/2OQmmez.png | Bin 0 -> 38178 bytes .../design/imgs/chunked_suffix/2bSEzad.png | Bin 0 -> 23614 bytes .../design/imgs/chunked_suffix/Av5J4Zb.png | Bin 0 -> 43602 bytes .../design/imgs/chunked_suffix/NQVgpqN.png | Bin 0 -> 104394 bytes .../design/imgs/chunked_suffix/PUTfEkm.png | Bin 0 -> 96486 bytes .../design/imgs/chunked_suffix/Yg65T4T.png | Bin 0 -> 23017 bytes .../design/imgs/chunked_suffix/aVtdXI3.png | Bin 0 -> 28988 bytes .../design/imgs/chunked_suffix/c9RmxfR.png | Bin 0 -> 29550 bytes .../design/imgs/chunked_suffix/hgbTwYv.png | Bin 0 -> 23646 bytes .../design/imgs/chunked_suffix/j4O6FSd.png | Bin 0 -> 23605 bytes .../design/imgs/chunked_suffix/n9FqctU.png | Bin 0 -> 26481 bytes .../design/imgs/chunked_suffix/nyr4DMY.png | Bin 0 -> 49960 bytes .../design/imgs/chunked_suffix/s0HCu2y.png | Bin 0 -> 58974 bytes .../design/imgs/chunked_suffix/sQX4H8b.png | Bin 0 -> 26803 bytes .../design/imgs/chunked_suffix/uAGz0tE.png | Bin 0 -> 66045 bytes .../design/imgs/chunked_suffix/uFBENIj.png | Bin 0 -> 98529 bytes .../design/imgs/chunked_suffix/uwzqD0x.png | Bin 0 -> 49670 bytes .../design/imgs/lower_layer/DBAFgWu.png | Bin 0 -> 261783 bytes .../design/imgs/lower_layer/bXuEjOi.png | Bin 0 -> 25024 bytes .../design/imgs/lower_layer/gYQPmLU.png | Bin 0 -> 80943 bytes .../design/imgs/lower_layer/gYsLcmj.png | Bin 0 -> 50153 bytes .../design/imgs/lower_layer/jqAbf7o.png | Bin 0 -> 25855 bytes .../design/imgs/lower_layer/ywNyqGa.png | Bin 0 -> 51818 bytes .../doc/irmin-pack/design/imgs/suffix.png | Bin 0 -> 7139 bytes .../doc/irmin-pack/design/layered_store.md | 545 ++++ .../doc/irmin-pack/design/lower_layer.md | 458 +++ vendors/irmin/doc/irmin-pack/dune | 3 + vendors/irmin/doc/irmin-pack/index.mld | 19 + vendors/irmin/doc/irmin/dune | 3 + vendors/irmin/doc/irmin/index.mld | 32 + vendors/irmin/dune | 6 + vendors/irmin/dune-project | 4 + vendors/irmin/examples/config.ml | 22 + vendors/irmin/examples/custom_graphql.ml | 122 + vendors/irmin/examples/custom_merge.ml | 165 + vendors/irmin/examples/custom_storage.ml | 101 + vendors/irmin/examples/deploy.ml | 142 + vendors/irmin/examples/dune | 62 + vendors/irmin/examples/fold.ml | 100 + vendors/irmin/examples/irmin-pack/dune | 3 + vendors/irmin/examples/irmin-pack/gc.ml | 204 ++ vendors/irmin/examples/irmin-pack/kv.ml | 108 + vendors/irmin/examples/irmin_git_store.ml | 65 + vendors/irmin/examples/merkle_proof_1.jpg | Bin 0 -> 46268 bytes vendors/irmin/examples/merkle_proof_2.jpg | Bin 0 -> 116873 bytes vendors/irmin/examples/merkle_proofs.md | 155 + vendors/irmin/examples/plugin/README.md | 33 + vendors/irmin/examples/plugin/dune | 14 + vendors/irmin/examples/plugin/plugin.ml | 28 + vendors/irmin/examples/plugin/plugin.t | 9 + vendors/irmin/examples/process.ml | 179 ++ vendors/irmin/examples/push.ml | 54 + vendors/irmin/examples/readme.ml | 33 + vendors/irmin/examples/sync.ml | 42 + vendors/irmin/examples/trees.ml | 71 + vendors/irmin/irmin-bench.opam | 50 + vendors/irmin/irmin-chunk.opam | 26 + vendors/irmin/irmin-cli.opam | 56 + vendors/irmin/irmin-containers.opam | 33 + vendors/irmin/irmin-fs.opam | 28 + vendors/irmin/irmin-git.opam | 44 + vendors/irmin/irmin-graphql.opam | 36 + vendors/irmin/irmin-http.opam | 39 + vendors/irmin/irmin-mirage-git.opam | 27 + vendors/irmin/irmin-mirage-graphql.opam | 26 + vendors/irmin/irmin-mirage.opam | 23 + vendors/irmin/irmin-pack-tools.opam | 38 + vendors/irmin/irmin-pack.opam | 35 + vendors/irmin/irmin-test.opam | 39 + vendors/irmin/irmin-tezos.opam | 29 + vendors/irmin/irmin.opam | 55 + vendors/irmin/libirmin.opam | 25 + vendors/irmin/logo.svg | 10 + vendors/irmin/ppx_irmin.opam | 25 + vendors/irmin/src/irmin-chunk/dune | 8 + vendors/irmin/src/irmin-chunk/import.ml | 18 + vendors/irmin/src/irmin-chunk/irmin_chunk.ml | 259 ++ vendors/irmin/src/irmin-chunk/irmin_chunk.mli | 91 + vendors/irmin/src/irmin-cli/bin/dune | 5 + vendors/irmin/src/irmin-cli/bin/main.ml | 17 + vendors/irmin/src/irmin-cli/cli.ml | 1058 ++++++ vendors/irmin/src/irmin-cli/cli.mli | 42 + vendors/irmin/src/irmin-cli/dune | 23 + vendors/irmin/src/irmin-cli/import.ml | 17 + vendors/irmin/src/irmin-cli/info.ml | 34 + vendors/irmin/src/irmin-cli/info.mli | 21 + vendors/irmin/src/irmin-cli/irmin_cli.ml | 18 + vendors/irmin/src/irmin-cli/irmin_cli.mli | 7 + vendors/irmin/src/irmin-cli/resolver.ml | 732 +++++ vendors/irmin/src/irmin-cli/resolver.mli | 135 + .../irmin/src/irmin-containers/blob_log.ml | 81 + .../irmin/src/irmin-containers/blob_log.mli | 54 + vendors/irmin/src/irmin-containers/counter.ml | 59 + .../irmin/src/irmin-containers/counter.mli | 54 + vendors/irmin/src/irmin-containers/dune | 8 + vendors/irmin/src/irmin-containers/import.ml | 19 + .../src/irmin-containers/irmin_containers.ml | 47 + .../irmin/src/irmin-containers/linked_log.ml | 168 + .../irmin/src/irmin-containers/linked_log.mli | 61 + .../src/irmin-containers/lww_register.ml | 65 + .../src/irmin-containers/lww_register.mli | 53 + vendors/irmin/src/irmin-containers/stores.ml | 22 + vendors/irmin/src/irmin-containers/time.ml | 33 + vendors/irmin/src/irmin-containers/time.mli | 32 + vendors/irmin/src/irmin-fs/dune | 8 + vendors/irmin/src/irmin-fs/import.ml | 18 + vendors/irmin/src/irmin-fs/irmin_fs.ml | 424 +++ vendors/irmin/src/irmin-fs/irmin_fs.mli | 109 + vendors/irmin/src/irmin-fs/unix/dune | 8 + .../irmin/src/irmin-fs/unix/irmin_fs_unix.ml | 311 ++ .../irmin/src/irmin-fs/unix/irmin_fs_unix.mli | 30 + vendors/irmin/src/irmin-git/atomic_write.ml | 308 ++ vendors/irmin/src/irmin-git/atomic_write.mli | 20 + .../irmin/src/irmin-git/atomic_write_intf.ml | 43 + vendors/irmin/src/irmin-git/backend.ml | 133 + vendors/irmin/src/irmin-git/backend.mli | 51 + vendors/irmin/src/irmin-git/branch.ml | 32 + vendors/irmin/src/irmin-git/branch.mli | 24 + vendors/irmin/src/irmin-git/commit.ml | 126 + vendors/irmin/src/irmin-git/commit.mli | 40 + vendors/irmin/src/irmin-git/conf.ml | 70 + vendors/irmin/src/irmin-git/conf.mli | 36 + .../src/irmin-git/content_addressable.ml | 96 + .../src/irmin-git/content_addressable.mli | 20 + .../src/irmin-git/content_addressable_intf.ml | 31 + vendors/irmin/src/irmin-git/contents.ml | 64 + vendors/irmin/src/irmin-git/contents.mli | 28 + vendors/irmin/src/irmin-git/dune | 8 + vendors/irmin/src/irmin-git/import.ml | 22 + vendors/irmin/src/irmin-git/irmin_git.ml | 348 ++ vendors/irmin/src/irmin-git/irmin_git.mli | 20 + vendors/irmin/src/irmin-git/irmin_git_intf.ml | 156 + vendors/irmin/src/irmin-git/metadata.ml | 33 + vendors/irmin/src/irmin-git/metadata.mli | 19 + vendors/irmin/src/irmin-git/node.ml | 204 ++ vendors/irmin/src/irmin-git/node.mli | 41 + vendors/irmin/src/irmin-git/reference.ml | 45 + vendors/irmin/src/irmin-git/reference.mli | 30 + vendors/irmin/src/irmin-git/remote.ml | 99 + vendors/irmin/src/irmin-git/remote.mli | 25 + vendors/irmin/src/irmin-git/schema.ml | 52 + vendors/irmin/src/irmin-git/unix/dune | 8 + .../src/irmin-git/unix/irmin_git_unix.ml | 18 + vendors/irmin/src/irmin-git/unix/xgit.ml | 91 + vendors/irmin/src/irmin-git/unix/xgit.mli | 22 + vendors/irmin/src/irmin-git/unix/xgit_intf.ml | 78 + vendors/irmin/src/irmin-git/value.ml | 17 + vendors/irmin/src/irmin-git/value.mli | 18 + vendors/irmin/src/irmin-git/value_intf.ml | 28 + vendors/irmin/src/irmin-graphql/dune | 15 + vendors/irmin/src/irmin-graphql/import.ml | 18 + vendors/irmin/src/irmin-graphql/server.ml | 969 ++++++ vendors/irmin/src/irmin-graphql/server.mli | 119 + vendors/irmin/src/irmin-graphql/unix/dune | 8 + .../irmin-graphql/unix/irmin_graphql_unix.ml | 76 + .../irmin-graphql/unix/irmin_graphql_unix.mli | 53 + vendors/irmin/src/irmin-http/closeable.ml | 118 + vendors/irmin/src/irmin-http/closeable.mli | 32 + vendors/irmin/src/irmin-http/common.ml | 29 + vendors/irmin/src/irmin-http/dune | 19 + vendors/irmin/src/irmin-http/import.ml | 18 + vendors/irmin/src/irmin-http/irmin_http.ml | 566 ++++ vendors/irmin/src/irmin-http/irmin_http.mli | 60 + .../irmin/src/irmin-http/irmin_http_server.ml | 406 +++ .../src/irmin-http/irmin_http_server.mli | 34 + vendors/irmin/src/irmin-http/s.ml | 124 + vendors/irmin/src/irmin-http/unix/dune | 8 + .../src/irmin-http/unix/irmin_http_unix.ml | 44 + .../src/irmin-http/unix/irmin_http_unix.mli | 38 + vendors/irmin/src/irmin-mirage/dune | 6 + vendors/irmin/src/irmin-mirage/git/dune | 15 + .../src/irmin-mirage/git/irmin_mirage_git.ml | 355 ++ .../src/irmin-mirage/git/irmin_mirage_git.mli | 18 + .../irmin-mirage/git/irmin_mirage_git_intf.ml | 150 + vendors/irmin/src/irmin-mirage/graphql/dune | 14 + .../graphql/irmin_mirage_graphql.ml | 73 + .../graphql/irmin_mirage_graphql.mli | 36 + .../irmin/src/irmin-mirage/irmin_mirage.ml | 24 + .../irmin/src/irmin-mirage/irmin_mirage.mli | 27 + vendors/irmin/src/irmin-pack-tools/README.md | 99 + vendors/irmin/src/irmin-pack-tools/ppcf/dune | 8 + .../irmin/src/irmin-pack-tools/ppcf/ppcf.ml | 44 + vendors/irmin/src/irmin-pack-tools/ppidx/dune | 8 + .../irmin/src/irmin-pack-tools/ppidx/ppidx.ml | 33 + .../src/irmin-pack-tools/tezos_explorer/dune | 17 + .../irmin-pack-tools/tezos_explorer/files.ml | 151 + .../irmin-pack-tools/tezos_explorer/import.ml | 5 + .../irmin-pack-tools/tezos_explorer/main.ml | 69 + .../irmin-pack-tools/tezos_explorer/parse.ml | 141 + .../irmin-pack-tools/tezos_explorer/ring.ml | 11 + .../irmin-pack-tools/tezos_explorer/show.ml | 900 ++++++ vendors/irmin/src/irmin-pack/atomic_write.ml | 37 + vendors/irmin/src/irmin-pack/atomic_write.mli | 17 + .../irmin/src/irmin-pack/atomic_write_intf.ml | 56 + vendors/irmin/src/irmin-pack/conf.ml | 159 + vendors/irmin/src/irmin-pack/conf.mli | 150 + vendors/irmin/src/irmin-pack/dune | 8 + vendors/irmin/src/irmin-pack/import.ml | 29 + vendors/irmin/src/irmin-pack/indexable.ml | 38 + vendors/irmin/src/irmin-pack/indexable.mli | 18 + .../irmin/src/irmin-pack/indexable_intf.ml | 56 + .../irmin/src/irmin-pack/indexing_strategy.ml | 53 + .../src/irmin-pack/indexing_strategy.mli | 47 + vendors/irmin/src/irmin-pack/inode.ml | 2406 ++++++++++++++ vendors/irmin/src/irmin-pack/inode.mli | 18 + vendors/irmin/src/irmin-pack/inode_intf.ml | 297 ++ vendors/irmin/src/irmin-pack/irmin_pack.ml | 33 + vendors/irmin/src/irmin-pack/irmin_pack.mli | 18 + .../irmin/src/irmin-pack/irmin_pack_intf.ml | 121 + vendors/irmin/src/irmin-pack/layout.ml | 153 + vendors/irmin/src/irmin-pack/mem/dune | 8 + vendors/irmin/src/irmin-pack/mem/import.ml | 24 + vendors/irmin/src/irmin-pack/mem/indexable.ml | 135 + .../irmin/src/irmin-pack/mem/indexable.mli | 31 + .../src/irmin-pack/mem/irmin_pack_mem.ml | 170 + .../src/irmin-pack/mem/irmin_pack_mem.mli | 25 + vendors/irmin/src/irmin-pack/pack_key.ml | 29 + vendors/irmin/src/irmin-pack/pack_value.ml | 240 ++ vendors/irmin/src/irmin-pack/pack_value.mli | 46 + .../irmin/src/irmin-pack/pack_value_intf.ml | 116 + vendors/irmin/src/irmin-pack/stats.ml | 116 + vendors/irmin/src/irmin-pack/stats.mli | 68 + .../src/irmin-pack/unix/append_only_file.ml | 175 + .../src/irmin-pack/unix/append_only_file.mli | 18 + .../irmin-pack/unix/append_only_file_intf.ml | 192 ++ vendors/irmin/src/irmin-pack/unix/async.ml | 121 + vendors/irmin/src/irmin-pack/unix/async.mli | 18 + .../irmin/src/irmin-pack/unix/async_intf.ml | 51 + .../irmin/src/irmin-pack/unix/atomic_write.ml | 195 ++ .../src/irmin-pack/unix/atomic_write.mli | 21 + vendors/irmin/src/irmin-pack/unix/checks.ml | 802 +++++ vendors/irmin/src/irmin-pack/unix/checks.mli | 20 + .../irmin/src/irmin-pack/unix/checks_intf.ml | 224 ++ .../src/irmin-pack/unix/chunked_suffix.ml | 359 +++ .../src/irmin-pack/unix/chunked_suffix.mli | 18 + .../irmin-pack/unix/chunked_suffix_intf.ml | 141 + .../irmin/src/irmin-pack/unix/control_file.ml | 400 +++ .../src/irmin-pack/unix/control_file.mli | 18 + .../src/irmin-pack/unix/control_file_intf.ml | 423 +++ vendors/irmin/src/irmin-pack/unix/dict.ml | 97 + vendors/irmin/src/irmin-pack/unix/dict.mli | 18 + .../irmin/src/irmin-pack/unix/dict_intf.ml | 32 + .../irmin/src/irmin-pack/unix/dispatcher.ml | 153 + .../irmin/src/irmin-pack/unix/dispatcher.mli | 18 + .../src/irmin-pack/unix/dispatcher_intf.ml | 105 + vendors/irmin/src/irmin-pack/unix/dune | 22 + vendors/irmin/src/irmin-pack/unix/errors.ml | 169 + .../irmin/src/irmin-pack/unix/file_manager.ml | 1063 ++++++ .../src/irmin-pack/unix/file_manager.mli | 18 + .../src/irmin-pack/unix/file_manager_intf.ml | 313 ++ vendors/irmin/src/irmin-pack/unix/gc.ml | 342 ++ vendors/irmin/src/irmin-pack/unix/gc.mli | 63 + vendors/irmin/src/irmin-pack/unix/gc_args.ml | 83 + vendors/irmin/src/irmin-pack/unix/gc_stats.ml | 292 ++ .../irmin/src/irmin-pack/unix/gc_stats.mli | 51 + .../irmin/src/irmin-pack/unix/gc_worker.ml | 436 +++ .../irmin/src/irmin-pack/unix/gc_worker.mli | 52 + vendors/irmin/src/irmin-pack/unix/import.ml | 85 + vendors/irmin/src/irmin-pack/unix/inode.ml | 74 + vendors/irmin/src/irmin-pack/unix/inode.mli | 18 + .../irmin/src/irmin-pack/unix/inode_intf.ml | 94 + vendors/irmin/src/irmin-pack/unix/io.ml | 298 ++ vendors/irmin/src/irmin-pack/unix/io.mli | 18 + .../irmin/src/irmin-pack/unix/io_errors.ml | 109 + vendors/irmin/src/irmin-pack/unix/io_intf.ml | 162 + .../irmin/src/irmin-pack/unix/io_legacy.ml | 206 ++ .../irmin/src/irmin-pack/unix/io_legacy.mli | 17 + .../src/irmin-pack/unix/io_legacy_intf.ml | 48 + .../src/irmin-pack/unix/irmin_pack_unix.ml | 62 + .../src/irmin-pack/unix/irmin_pack_unix.mli | 67 + vendors/irmin/src/irmin-pack/unix/lower.ml | 418 +++ vendors/irmin/src/irmin-pack/unix/lower.mli | 18 + .../irmin/src/irmin-pack/unix/lower_intf.ml | 191 ++ .../irmin/src/irmin-pack/unix/pack_index.ml | 122 + .../irmin/src/irmin-pack/unix/pack_index.mli | 18 + .../src/irmin-pack/unix/pack_index_intf.ml | 75 + vendors/irmin/src/irmin-pack/unix/pack_key.ml | 168 + .../irmin/src/irmin-pack/unix/pack_key.mli | 18 + .../src/irmin-pack/unix/pack_key_intf.ml | 128 + .../irmin/src/irmin-pack/unix/pack_store.ml | 560 ++++ .../irmin/src/irmin-pack/unix/pack_store.mli | 18 + .../src/irmin-pack/unix/pack_store_intf.ml | 107 + .../irmin/src/irmin-pack/unix/pack_value.ml | 23 + vendors/irmin/src/irmin-pack/unix/ranges.ml | 133 + vendors/irmin/src/irmin-pack/unix/ranges.mli | 38 + vendors/irmin/src/irmin-pack/unix/snapshot.ml | 344 ++ .../irmin/src/irmin-pack/unix/snapshot.mli | 18 + .../src/irmin-pack/unix/snapshot_intf.ml | 81 + .../irmin/src/irmin-pack/unix/sparse_file.ml | 304 ++ .../irmin/src/irmin-pack/unix/sparse_file.mli | 18 + .../src/irmin-pack/unix/sparse_file_intf.ml | 157 + vendors/irmin/src/irmin-pack/unix/stats.ml | 304 ++ vendors/irmin/src/irmin-pack/unix/stats.mli | 18 + .../irmin/src/irmin-pack/unix/stats_intf.ml | 304 ++ vendors/irmin/src/irmin-pack/unix/store.ml | 777 +++++ vendors/irmin/src/irmin-pack/unix/store.mli | 20 + .../irmin/src/irmin-pack/unix/store_intf.ml | 380 +++ .../src/irmin-pack/unix/traverse_pack_file.ml | 437 +++ vendors/irmin/src/irmin-pack/unix/utils.ml | 91 + vendors/irmin/src/irmin-pack/version.ml | 80 + vendors/irmin/src/irmin-pack/version.mli | 54 + vendors/irmin/src/irmin-test/common.ml | 324 ++ vendors/irmin/src/irmin-test/dune | 40 + vendors/irmin/src/irmin-test/helpers.ml | 19 + vendors/irmin/src/irmin-test/import.ml | 18 + vendors/irmin/src/irmin-test/irmin_bench.ml | 190 ++ vendors/irmin/src/irmin-test/irmin_bench.mli | 21 + vendors/irmin/src/irmin-test/irmin_test.ml | 20 + vendors/irmin/src/irmin-test/irmin_test.mli | 74 + vendors/irmin/src/irmin-test/node.ml | 150 + vendors/irmin/src/irmin-test/rusage.ml | 38 + vendors/irmin/src/irmin-test/rusage_stubs.c | 57 + vendors/irmin/src/irmin-test/store.ml | 2549 +++++++++++++++ vendors/irmin/src/irmin-test/store.mli | 24 + vendors/irmin/src/irmin-test/store_graph.ml | 209 ++ vendors/irmin/src/irmin-test/store_graph.mli | 17 + vendors/irmin/src/irmin-test/store_watch.ml | 379 +++ vendors/irmin/src/irmin-test/store_watch.mli | 17 + vendors/irmin/src/irmin-tezos/dune | 6 + vendors/irmin/src/irmin-tezos/irmin_tezos.ml | 28 + vendors/irmin/src/irmin-tezos/irmin_tezos.mli | 31 + vendors/irmin/src/irmin-tezos/schema.ml | 151 + vendors/irmin/src/irmin-tezos/schema.mli | 24 + vendors/irmin/src/irmin/append_only.ml | 17 + vendors/irmin/src/irmin/append_only.mli | 18 + vendors/irmin/src/irmin/append_only_intf.ml | 51 + vendors/irmin/src/irmin/atomic_write.ml | 61 + vendors/irmin/src/irmin/atomic_write.mli | 18 + vendors/irmin/src/irmin/atomic_write_intf.ml | 110 + vendors/irmin/src/irmin/backend.ml | 119 + vendors/irmin/src/irmin/branch.ml | 36 + vendors/irmin/src/irmin/branch.mli | 20 + vendors/irmin/src/irmin/branch_intf.ml | 62 + vendors/irmin/src/irmin/commit.ml | 699 ++++ vendors/irmin/src/irmin/commit.mli | 27 + vendors/irmin/src/irmin/commit_intf.ml | 330 ++ vendors/irmin/src/irmin/conf.ml | 175 + vendors/irmin/src/irmin/conf.mli | 167 + .../irmin/src/irmin/content_addressable.ml | 84 + .../irmin/src/irmin/content_addressable.mli | 18 + .../src/irmin/content_addressable_intf.ml | 69 + vendors/irmin/src/irmin/contents.ml | 251 ++ vendors/irmin/src/irmin/contents.mli | 20 + vendors/irmin/src/irmin/contents_intf.ml | 107 + vendors/irmin/src/irmin/data/dune | 6 + .../src/irmin/data/fixed_size_string_set.ml | 237 ++ .../src/irmin/data/fixed_size_string_set.mli | 60 + vendors/irmin/src/irmin/data/hashset.ml | 33 + vendors/irmin/src/irmin/data/irmin_data.ml | 22 + vendors/irmin/src/irmin/diff.ml | 18 + vendors/irmin/src/irmin/diff.mli | 19 + vendors/irmin/src/irmin/dot.ml | 226 ++ vendors/irmin/src/irmin/dot.mli | 45 + vendors/irmin/src/irmin/dune | 22 + .../irmin/src/irmin/export_for_backends.ml | 21 + vendors/irmin/src/irmin/hash.ml | 118 + vendors/irmin/src/irmin/hash.mli | 18 + vendors/irmin/src/irmin/hash_intf.ml | 133 + vendors/irmin/src/irmin/import.ml | 157 + vendors/irmin/src/irmin/indexable.ml | 83 + vendors/irmin/src/irmin/indexable.mli | 19 + vendors/irmin/src/irmin/indexable_intf.ml | 149 + vendors/irmin/src/irmin/info.ml | 41 + vendors/irmin/src/irmin/info.mli | 18 + vendors/irmin/src/irmin/info_intf.ml | 67 + vendors/irmin/src/irmin/irmin.ml | 245 ++ vendors/irmin/src/irmin/irmin.mli | 504 +++ vendors/irmin/src/irmin/key.ml | 25 + vendors/irmin/src/irmin/key.mli | 92 + vendors/irmin/src/irmin/key_intf.ml | 62 + vendors/irmin/src/irmin/lock.ml | 66 + vendors/irmin/src/irmin/lock.mli | 37 + vendors/irmin/src/irmin/logging.ml | 61 + vendors/irmin/src/irmin/logging.mli | 18 + vendors/irmin/src/irmin/logging_intf.ml | 48 + vendors/irmin/src/irmin/lru.ml | 147 + vendors/irmin/src/irmin/lru.mli | 27 + vendors/irmin/src/irmin/mem/dune | 6 + vendors/irmin/src/irmin/mem/import.ml | 18 + vendors/irmin/src/irmin/mem/irmin_mem.ml | 167 + vendors/irmin/src/irmin/mem/irmin_mem.mli | 47 + vendors/irmin/src/irmin/merge.ml | 421 +++ vendors/irmin/src/irmin/merge.mli | 227 ++ vendors/irmin/src/irmin/metadata.ml | 24 + vendors/irmin/src/irmin/metadata.mli | 18 + vendors/irmin/src/irmin/metadata_intf.ml | 31 + vendors/irmin/src/irmin/metrics.ml | 46 + vendors/irmin/src/irmin/metrics.mli | 54 + vendors/irmin/src/irmin/node.ml | 785 +++++ vendors/irmin/src/irmin/node.mli | 27 + vendors/irmin/src/irmin/node_intf.ml | 476 +++ vendors/irmin/src/irmin/object_graph.ml | 291 ++ vendors/irmin/src/irmin/object_graph.mli | 20 + vendors/irmin/src/irmin/object_graph_intf.ml | 139 + vendors/irmin/src/irmin/path.ml | 48 + vendors/irmin/src/irmin/path.mli | 20 + vendors/irmin/src/irmin/path_intf.ml | 67 + vendors/irmin/src/irmin/perms.ml | 66 + vendors/irmin/src/irmin/proof.ml | 664 ++++ vendors/irmin/src/irmin/proof.mli | 17 + vendors/irmin/src/irmin/proof_intf.ml | 357 +++ vendors/irmin/src/irmin/read_only.ml | 17 + vendors/irmin/src/irmin/read_only.mli | 18 + vendors/irmin/src/irmin/read_only_intf.ml | 57 + vendors/irmin/src/irmin/remote.ml | 33 + vendors/irmin/src/irmin/remote.mli | 20 + vendors/irmin/src/irmin/remote_intf.ml | 69 + vendors/irmin/src/irmin/reversed_list.ml | 20 + vendors/irmin/src/irmin/reversed_list.mli | 25 + vendors/irmin/src/irmin/schema.ml | 73 + vendors/irmin/src/irmin/slice.ml | 58 + vendors/irmin/src/irmin/slice.mli | 18 + vendors/irmin/src/irmin/slice_intf.ml | 56 + vendors/irmin/src/irmin/storage.ml | 146 + vendors/irmin/src/irmin/storage.mli | 23 + vendors/irmin/src/irmin/storage_intf.ml | 62 + vendors/irmin/src/irmin/store.ml | 1292 ++++++++ vendors/irmin/src/irmin/store.mli | 21 + vendors/irmin/src/irmin/store_intf.ml | 1263 ++++++++ vendors/irmin/src/irmin/store_properties.ml | 19 + vendors/irmin/src/irmin/store_properties.mli | 18 + .../irmin/src/irmin/store_properties_intf.ml | 72 + vendors/irmin/src/irmin/sync.ml | 221 ++ vendors/irmin/src/irmin/sync.mli | 20 + vendors/irmin/src/irmin/sync_intf.ml | 102 + vendors/irmin/src/irmin/tree.ml | 2854 +++++++++++++++++ vendors/irmin/src/irmin/tree.mli | 19 + vendors/irmin/src/irmin/tree_intf.ml | 504 +++ vendors/irmin/src/irmin/type.ml | 23 + vendors/irmin/src/irmin/type.mli | 24 + vendors/irmin/src/irmin/unix/dune | 8 + vendors/irmin/src/irmin/unix/info.ml | 33 + vendors/irmin/src/irmin/unix/info.mli | 21 + vendors/irmin/src/irmin/unix/irmin_unix.ml | 20 + vendors/irmin/src/irmin/unix/irmin_unix.mli | 30 + vendors/irmin/src/irmin/version.ml | 17 + vendors/irmin/src/irmin/watch.ml | 326 ++ vendors/irmin/src/irmin/watch.mli | 21 + vendors/irmin/src/irmin/watch_intf.ml | 96 + vendors/irmin/src/libirmin/commit.ml | 160 + vendors/irmin/src/libirmin/config.ml | 150 + vendors/irmin/src/libirmin/dune | 5 + vendors/irmin/src/libirmin/gen/dune | 4 + vendors/irmin/src/libirmin/gen/generate.ml | 98 + vendors/irmin/src/libirmin/info.ml | 69 + vendors/irmin/src/libirmin/lib/dune | 31 + vendors/irmin/src/libirmin/lib/libirmin.ml | 17 + .../irmin/src/libirmin/libirmin_bindings.ml | 27 + vendors/irmin/src/libirmin/path.ml | 123 + vendors/irmin/src/libirmin/repo.ml | 193 ++ vendors/irmin/src/libirmin/store.ml | 450 +++ vendors/irmin/src/libirmin/tree.ml | 242 ++ vendors/irmin/src/libirmin/type.ml | 194 ++ vendors/irmin/src/libirmin/types.ml | 68 + vendors/irmin/src/libirmin/types.mli | 17 + vendors/irmin/src/libirmin/types_intf.ml | 82 + vendors/irmin/src/libirmin/util.ml | 286 ++ vendors/irmin/src/libirmin/value.ml | 250 ++ vendors/irmin/src/ppx_irmin/dune | 9 + vendors/irmin/src/ppx_irmin/internal/dune | 21 + .../ppx_irmin/internal/ppx_irmin_internal.ml | 103 + .../ppx_irmin/internal/ppx_irmin_internal.mli | 1 + .../internal/ppx_irmin_internal_lib.ml | 30 + vendors/irmin/src/ppx_irmin/ppx_irmin.ml | 25 + vendors/irmin/src/ppx_irmin/ppx_irmin.mli | 1 + .../data/tezos_actions_1commit.repr | Bin 0 -> 300 bytes vendors/irmin/test/irmin-bench/dune | 17 + vendors/irmin/test/irmin-bench/ema.ml | 179 ++ vendors/irmin/test/irmin-bench/import.ml | 17 + vendors/irmin/test/irmin-bench/misc.ml | 86 + vendors/irmin/test/irmin-bench/replay.ml | 187 ++ vendors/irmin/test/irmin-bench/test.ml | 19 + vendors/irmin/test/irmin-bench/test.mli | 1 + vendors/irmin/test/irmin-chunk/dune | 15 + vendors/irmin/test/irmin-chunk/test.ml | 83 + vendors/irmin/test/irmin-chunk/test.mli | 1 + vendors/irmin/test/irmin-chunk/test_chunk.ml | 77 + vendors/irmin/test/irmin-cli/dune | 17 + vendors/irmin/test/irmin-cli/test.ml | 42 + vendors/irmin/test/irmin-cli/test.yml | 4 + .../irmin/test/irmin-cli/test_command_line.t | 96 + .../irmin/test/irmin-containers/blob_log.ml | 90 + vendors/irmin/test/irmin-containers/common.ml | 24 + .../irmin/test/irmin-containers/common.mli | 19 + .../irmin/test/irmin-containers/counter.ml | 91 + vendors/irmin/test/irmin-containers/dune | 9 + vendors/irmin/test/irmin-containers/import.ml | 17 + .../irmin/test/irmin-containers/linked_log.ml | 115 + .../test/irmin-containers/lww_register.ml | 96 + vendors/irmin/test/irmin-containers/test.ml | 24 + vendors/irmin/test/irmin-containers/test.mli | 1 + vendors/irmin/test/irmin-fs/dune | 31 + vendors/irmin/test/irmin-fs/test.ml | 20 + vendors/irmin/test/irmin-fs/test.mli | 1 + vendors/irmin/test/irmin-fs/test_fs.ml | 28 + vendors/irmin/test/irmin-fs/test_fs_unix.ml | 45 + vendors/irmin/test/irmin-fs/test_unix.ml | 21 + vendors/irmin/test/irmin-git/dune | 46 + vendors/irmin/test/irmin-git/test.ml | 22 + vendors/irmin/test/irmin-git/test.mli | 1 + vendors/irmin/test/irmin-git/test_git.ml | 240 ++ vendors/irmin/test/irmin-git/test_git.mli | 33 + vendors/irmin/test/irmin-git/test_git_unix.ml | 55 + vendors/irmin/test/irmin-git/test_unix.ml | 23 + vendors/irmin/test/irmin-graphql/common.ml | 197 ++ vendors/irmin/test/irmin-graphql/common.mli | 141 + vendors/irmin/test/irmin-graphql/dune | 19 + vendors/irmin/test/irmin-graphql/import.ml | 17 + vendors/irmin/test/irmin-graphql/test.ml | 353 ++ vendors/irmin/test/irmin-graphql/test.mli | 1 + vendors/irmin/test/irmin-http/dune | 37 + vendors/irmin/test/irmin-http/test.ml | 20 + vendors/irmin/test/irmin-http/test.mli | 1 + vendors/irmin/test/irmin-http/test_http.ml | 238 ++ vendors/irmin/test/irmin-http/test_http.mli | 21 + vendors/irmin/test/irmin-mem/bench.ml | 23 + vendors/irmin/test/irmin-mem/dune | 20 + vendors/irmin/test/irmin-mem/test.ml | 20 + vendors/irmin/test/irmin-mem/test.mli | 1 + vendors/irmin/test/irmin-mem/test_mem.ml | 20 + vendors/irmin/test/irmin-pack/_layered.mli | 17 + vendors/irmin/test/irmin-pack/common.ml | 385 +++ vendors/irmin/test/irmin-pack/common.mli | 134 + .../test/irmin-pack/data/corrupted/index/log | Bin 0 -> 428 bytes .../irmin-pack/data/corrupted/store.branches | Bin 0 -> 43 bytes .../test/irmin-pack/data/corrupted/store.dict | Bin 0 -> 24 bytes .../test/irmin-pack/data/corrupted/store.pack | Bin 0 -> 347 bytes .../irmin-pack/data/corrupted_inode/index/log | Bin 0 -> 824 bytes .../data/corrupted_inode/store.branches | Bin 0 -> 46 bytes .../data/corrupted_inode/store.dict | Bin 0 -> 24 bytes .../data/corrupted_inode/store.pack | Bin 0 -> 887 bytes .../irmin-pack/data/empty_store/index/log | Bin 0 -> 32 bytes .../data/empty_store/store.branches | Bin 0 -> 16 bytes .../irmin-pack/data/empty_store/store.dict | Bin 0 -> 16 bytes .../irmin-pack/data/empty_store/store.pack | Bin 0 -> 16 bytes .../test/irmin-pack/data/version_1/index/log | Bin 0 -> 428 bytes .../irmin-pack/data/version_1/store.branches | Bin 0 -> 70 bytes .../test/irmin-pack/data/version_1/store.dict | Bin 0 -> 24 bytes .../test/irmin-pack/data/version_1/store.pack | Bin 0 -> 456 bytes .../irmin-pack/data/version_1_large/README.md | 65 + .../data/version_1_large/index/lock | 1 + .../irmin-pack/data/version_1_large/index/log | Bin 0 -> 1525292 bytes .../data/version_1_large/store.branches | Bin 0 -> 44 bytes .../data/version_1_large/store.dict | Bin 0 -> 24 bytes .../data/version_1_large/store.pack | Bin 0 -> 5563487 bytes .../data/version_2_always/index/log | Bin 0 -> 197 bytes .../data/version_2_always/store.branches | Bin 0 -> 16 bytes .../data/version_2_always/store.dict | Bin 0 -> 40 bytes .../data/version_2_always/store.pack | Bin 0 -> 180 bytes .../data/version_2_minimal/index/log | Bin 0 -> 65 bytes .../data/version_2_minimal/store.branches | Bin 0 -> 16 bytes .../data/version_2_minimal/store.dict | Bin 0 -> 40 bytes .../data/version_2_minimal/store.pack | Bin 0 -> 180 bytes .../data/version_2_to_3_always/index/log | Bin 0 -> 197 bytes .../data/version_2_to_3_always/store.0.suffix | Bin 0 -> 180 bytes .../data/version_2_to_3_always/store.branches | Bin 0 -> 16 bytes .../data/version_2_to_3_always/store.control | Bin 0 -> 44 bytes .../data/version_2_to_3_always/store.dict | Bin 0 -> 40 bytes .../data/version_3_always/index/log | Bin 0 -> 197 bytes .../data/version_3_always/store.0.suffix | Bin 0 -> 164 bytes .../data/version_3_always/store.branches | Bin 0 -> 16 bytes .../data/version_3_always/store.control | Bin 0 -> 25 bytes .../data/version_3_always/store.dict | Bin 0 -> 24 bytes .../data/version_3_minimal/index/log | Bin 0 -> 65 bytes .../data/version_3_minimal/store.0.suffix | Bin 0 -> 164 bytes .../data/version_3_minimal/store.branches | Bin 0 -> 16 bytes .../data/version_3_minimal/store.control | Bin 0 -> 25 bytes .../data/version_3_minimal/store.dict | Bin 0 -> 24 bytes .../data/version_3_minimal_gced/index/log | Bin 0 -> 65 bytes .../version_3_minimal_gced/store.1.mapping | Bin 0 -> 24 bytes .../version_3_minimal_gced/store.1.prefix | Bin 0 -> 93 bytes .../version_3_minimal_gced/store.1.suffix | Bin 0 -> 42 bytes .../version_3_minimal_gced/store.branches | Bin 0 -> 16 bytes .../data/version_3_minimal_gced/store.control | Bin 0 -> 34 bytes .../data/version_3_minimal_gced/store.dict | Bin 0 -> 24 bytes vendors/irmin/test/irmin-pack/dune | 70 + vendors/irmin/test/irmin-pack/import.ml | 17 + vendors/irmin/test/irmin-pack/test.ml | 21 + vendors/irmin/test/irmin-pack/test.mli | 1 + vendors/irmin/test/irmin-pack/test_async.ml | 43 + vendors/irmin/test/irmin-pack/test_async.mli | 17 + .../irmin/test/irmin-pack/test_corrupted.ml | 89 + .../irmin/test/irmin-pack/test_corrupted.mli | 17 + .../irmin/test/irmin-pack/test_dispatcher.ml | 103 + .../irmin/test/irmin-pack/test_dispatcher.mli | 17 + .../test/irmin-pack/test_existing_stores.ml | 351 ++ .../test/irmin-pack/test_existing_stores.mli | 17 + .../test/irmin-pack/test_flush_reload.ml | 240 ++ vendors/irmin/test/irmin-pack/test_gc.ml | 1501 +++++++++ vendors/irmin/test/irmin-pack/test_gc.mli | 51 + vendors/irmin/test/irmin-pack/test_hashes.ml | 321 ++ vendors/irmin/test/irmin-pack/test_hashes.mli | 24 + .../test/irmin-pack/test_indexing_strategy.ml | 116 + .../irmin-pack/test_indexing_strategy.mli | 17 + vendors/irmin/test/irmin-pack/test_inode.ml | 911 ++++++ vendors/irmin/test/irmin-pack/test_inode.mli | 17 + vendors/irmin/test/irmin-pack/test_lower.ml | 554 ++++ vendors/irmin/test/irmin-pack/test_lower.mli | 23 + vendors/irmin/test/irmin-pack/test_mapping.ml | 112 + .../irmin/test/irmin-pack/test_mapping.mli | 17 + .../irmin/test/irmin-pack/test_nearest_geq.ml | 27 + .../test/irmin-pack/test_nearest_leq.mli | 1 + vendors/irmin/test/irmin-pack/test_pack.ml | 580 ++++ vendors/irmin/test/irmin-pack/test_pack.mli | 18 + .../test/irmin-pack/test_pack_version_bump.ml | 160 + .../irmin-pack/test_pack_version_bump.mli | 1 + vendors/irmin/test/irmin-pack/test_ranges.ml | 38 + .../irmin/test/irmin-pack/test_readonly.ml | 124 + .../irmin/test/irmin-pack/test_readonly.mli | 17 + .../irmin/test/irmin-pack/test_snapshot.ml | 311 ++ vendors/irmin/test/irmin-pack/test_tree.ml | 721 +++++ vendors/irmin/test/irmin-pack/test_upgrade.ml | 713 ++++ vendors/irmin/test/irmin-tezos/dune | 33 + vendors/irmin/test/irmin-tezos/generate.ml | 68 + vendors/irmin/test/irmin-tezos/generate.mli | 1 + .../test/irmin-tezos/irmin-fsck-help.txt | 33 + vendors/irmin/test/irmin-tezos/irmin_fsck.ml | 38 + vendors/irmin/test/irmin-tezos/stat.t/run.t | 25 + vendors/irmin/test/irmin/data/dune | 4 + vendors/irmin/test/irmin/data/import.ml | 22 + vendors/irmin/test/irmin/data/test.ml | 6 + vendors/irmin/test/irmin/data/test.mli | 1 + .../irmin/data/test_fixed_size_string_set.ml | 104 + .../irmin/data/test_fixed_size_string_set.mli | 1 + vendors/irmin/test/irmin/dune | 18 + vendors/irmin/test/irmin/generic-key/dune | 15 + vendors/irmin/test/irmin/generic-key/test.ml | 22 + .../generic-key/test_inlined_contents.ml | 94 + .../irmin/generic-key/test_store_offset.ml | 142 + vendors/irmin/test/irmin/test.ml | 36 + vendors/irmin/test/irmin/test.mli | 1 + vendors/irmin/test/irmin/test_conf.ml | 46 + vendors/irmin/test/irmin/test_conf.mli | 17 + vendors/irmin/test/irmin/test_hash.ml | 37 + vendors/irmin/test/irmin/test_hash.mli | 17 + vendors/irmin/test/irmin/test_lru.ml | 88 + vendors/irmin/test/irmin/test_tree.ml | 881 +++++ vendors/irmin/test/irmin/test_tree.mli | 17 + vendors/irmin/test/libirmin/dune | 27 + vendors/irmin/test/libirmin/greatest.h | 1290 ++++++++ vendors/irmin/test/libirmin/test.c | 164 + vendors/irmin/test/ppx_irmin/dune | 55 + .../test/ppx_irmin/test_logs-output.expected | 5 + .../ppx_irmin/test_logs-processed.expected | 62 + vendors/irmin/test/ppx_irmin/test_logs.ml | 46 + 687 files changed, 81805 insertions(+) create mode 100644 vendors/irmin/.github/workflows/changelog-check.yml create mode 100644 vendors/irmin/.github/workflows/coverage.yml create mode 100644 vendors/irmin/.github/workflows/git.yml create mode 100644 vendors/irmin/.gitignore create mode 100644 vendors/irmin/.ocamlformat create mode 100644 vendors/irmin/CHANGES.md create mode 100644 vendors/irmin/CONTRIBUTING.md create mode 100644 vendors/irmin/LICENSE.md create mode 100644 vendors/irmin/Makefile create mode 100644 vendors/irmin/README.md create mode 100644 vendors/irmin/README_LIBIRMIN.md create mode 100644 vendors/irmin/README_PPX.md create mode 100644 vendors/irmin/RELEASE.md create mode 100644 vendors/irmin/bench/irmin-pack/_layers.mli create mode 100644 vendors/irmin/bench/irmin-pack/bench_common.ml create mode 100644 vendors/irmin/bench/irmin-pack/bench_common.mli create mode 100644 vendors/irmin/bench/irmin-pack/dune create mode 100644 vendors/irmin/bench/irmin-pack/import.ml create mode 100644 vendors/irmin/bench/irmin-pack/main.ml create mode 100644 vendors/irmin/bench/irmin-pack/main.mli create mode 100644 vendors/irmin/bench/irmin-pack/tezos_history_metrics.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_collection.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_common.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_definitions.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_replay.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_replay.mli create mode 100644 vendors/irmin/bench/irmin-pack/trace_replay_intf.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_stat_summary.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_stat_summary_cb.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_stat_summary_conf.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_stat_summary_pp.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.ml create mode 100644 vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.mli create mode 100644 vendors/irmin/bench/irmin-pack/trace_stats.ml create mode 100644 vendors/irmin/bench/irmin-pack/tree.ml create mode 100644 vendors/irmin/bench/irmin-pack/tree.mli create mode 100644 vendors/irmin/bench/irmin/data/bench_fixed_size_string_set.ml create mode 100644 vendors/irmin/bench/irmin/data/dune create mode 100644 vendors/irmin/codecov.yml create mode 100644 vendors/irmin/doc/irmin-pack/design/README.md create mode 100644 vendors/irmin/doc/irmin-pack/design/chunked_suffix.md create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/0dXEkNs.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/2OQmmez.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/2bSEzad.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/Av5J4Zb.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/NQVgpqN.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/PUTfEkm.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/Yg65T4T.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/aVtdXI3.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/c9RmxfR.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/hgbTwYv.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/j4O6FSd.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/n9FqctU.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/nyr4DMY.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/s0HCu2y.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/sQX4H8b.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uAGz0tE.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uFBENIj.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uwzqD0x.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/DBAFgWu.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/bXuEjOi.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/gYQPmLU.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/gYsLcmj.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/jqAbf7o.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/ywNyqGa.png create mode 100644 vendors/irmin/doc/irmin-pack/design/imgs/suffix.png create mode 100644 vendors/irmin/doc/irmin-pack/design/layered_store.md create mode 100644 vendors/irmin/doc/irmin-pack/design/lower_layer.md create mode 100644 vendors/irmin/doc/irmin-pack/dune create mode 100644 vendors/irmin/doc/irmin-pack/index.mld create mode 100644 vendors/irmin/doc/irmin/dune create mode 100644 vendors/irmin/doc/irmin/index.mld create mode 100644 vendors/irmin/dune create mode 100644 vendors/irmin/dune-project create mode 100644 vendors/irmin/examples/config.ml create mode 100644 vendors/irmin/examples/custom_graphql.ml create mode 100644 vendors/irmin/examples/custom_merge.ml create mode 100644 vendors/irmin/examples/custom_storage.ml create mode 100644 vendors/irmin/examples/deploy.ml create mode 100644 vendors/irmin/examples/dune create mode 100644 vendors/irmin/examples/fold.ml create mode 100644 vendors/irmin/examples/irmin-pack/dune create mode 100644 vendors/irmin/examples/irmin-pack/gc.ml create mode 100644 vendors/irmin/examples/irmin-pack/kv.ml create mode 100644 vendors/irmin/examples/irmin_git_store.ml create mode 100644 vendors/irmin/examples/merkle_proof_1.jpg create mode 100644 vendors/irmin/examples/merkle_proof_2.jpg create mode 100644 vendors/irmin/examples/merkle_proofs.md create mode 100644 vendors/irmin/examples/plugin/README.md create mode 100644 vendors/irmin/examples/plugin/dune create mode 100644 vendors/irmin/examples/plugin/plugin.ml create mode 100644 vendors/irmin/examples/plugin/plugin.t create mode 100644 vendors/irmin/examples/process.ml create mode 100644 vendors/irmin/examples/push.ml create mode 100644 vendors/irmin/examples/readme.ml create mode 100644 vendors/irmin/examples/sync.ml create mode 100644 vendors/irmin/examples/trees.ml create mode 100644 vendors/irmin/irmin-bench.opam create mode 100644 vendors/irmin/irmin-chunk.opam create mode 100644 vendors/irmin/irmin-cli.opam create mode 100644 vendors/irmin/irmin-containers.opam create mode 100644 vendors/irmin/irmin-fs.opam create mode 100644 vendors/irmin/irmin-git.opam create mode 100644 vendors/irmin/irmin-graphql.opam create mode 100644 vendors/irmin/irmin-http.opam create mode 100644 vendors/irmin/irmin-mirage-git.opam create mode 100644 vendors/irmin/irmin-mirage-graphql.opam create mode 100644 vendors/irmin/irmin-mirage.opam create mode 100644 vendors/irmin/irmin-pack-tools.opam create mode 100644 vendors/irmin/irmin-pack.opam create mode 100644 vendors/irmin/irmin-test.opam create mode 100644 vendors/irmin/irmin-tezos.opam create mode 100644 vendors/irmin/irmin.opam create mode 100644 vendors/irmin/libirmin.opam create mode 100644 vendors/irmin/logo.svg create mode 100644 vendors/irmin/ppx_irmin.opam create mode 100644 vendors/irmin/src/irmin-chunk/dune create mode 100644 vendors/irmin/src/irmin-chunk/import.ml create mode 100644 vendors/irmin/src/irmin-chunk/irmin_chunk.ml create mode 100644 vendors/irmin/src/irmin-chunk/irmin_chunk.mli create mode 100644 vendors/irmin/src/irmin-cli/bin/dune create mode 100644 vendors/irmin/src/irmin-cli/bin/main.ml create mode 100644 vendors/irmin/src/irmin-cli/cli.ml create mode 100644 vendors/irmin/src/irmin-cli/cli.mli create mode 100644 vendors/irmin/src/irmin-cli/dune create mode 100644 vendors/irmin/src/irmin-cli/import.ml create mode 100644 vendors/irmin/src/irmin-cli/info.ml create mode 100644 vendors/irmin/src/irmin-cli/info.mli create mode 100644 vendors/irmin/src/irmin-cli/irmin_cli.ml create mode 100644 vendors/irmin/src/irmin-cli/irmin_cli.mli create mode 100644 vendors/irmin/src/irmin-cli/resolver.ml create mode 100644 vendors/irmin/src/irmin-cli/resolver.mli create mode 100644 vendors/irmin/src/irmin-containers/blob_log.ml create mode 100644 vendors/irmin/src/irmin-containers/blob_log.mli create mode 100644 vendors/irmin/src/irmin-containers/counter.ml create mode 100644 vendors/irmin/src/irmin-containers/counter.mli create mode 100644 vendors/irmin/src/irmin-containers/dune create mode 100644 vendors/irmin/src/irmin-containers/import.ml create mode 100644 vendors/irmin/src/irmin-containers/irmin_containers.ml create mode 100644 vendors/irmin/src/irmin-containers/linked_log.ml create mode 100644 vendors/irmin/src/irmin-containers/linked_log.mli create mode 100644 vendors/irmin/src/irmin-containers/lww_register.ml create mode 100644 vendors/irmin/src/irmin-containers/lww_register.mli create mode 100644 vendors/irmin/src/irmin-containers/stores.ml create mode 100644 vendors/irmin/src/irmin-containers/time.ml create mode 100644 vendors/irmin/src/irmin-containers/time.mli create mode 100644 vendors/irmin/src/irmin-fs/dune create mode 100644 vendors/irmin/src/irmin-fs/import.ml create mode 100644 vendors/irmin/src/irmin-fs/irmin_fs.ml create mode 100644 vendors/irmin/src/irmin-fs/irmin_fs.mli create mode 100644 vendors/irmin/src/irmin-fs/unix/dune create mode 100644 vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.ml create mode 100644 vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.mli create mode 100644 vendors/irmin/src/irmin-git/atomic_write.ml create mode 100644 vendors/irmin/src/irmin-git/atomic_write.mli create mode 100644 vendors/irmin/src/irmin-git/atomic_write_intf.ml create mode 100644 vendors/irmin/src/irmin-git/backend.ml create mode 100644 vendors/irmin/src/irmin-git/backend.mli create mode 100644 vendors/irmin/src/irmin-git/branch.ml create mode 100644 vendors/irmin/src/irmin-git/branch.mli create mode 100644 vendors/irmin/src/irmin-git/commit.ml create mode 100644 vendors/irmin/src/irmin-git/commit.mli create mode 100644 vendors/irmin/src/irmin-git/conf.ml create mode 100644 vendors/irmin/src/irmin-git/conf.mli create mode 100644 vendors/irmin/src/irmin-git/content_addressable.ml create mode 100644 vendors/irmin/src/irmin-git/content_addressable.mli create mode 100644 vendors/irmin/src/irmin-git/content_addressable_intf.ml create mode 100644 vendors/irmin/src/irmin-git/contents.ml create mode 100644 vendors/irmin/src/irmin-git/contents.mli create mode 100644 vendors/irmin/src/irmin-git/dune create mode 100644 vendors/irmin/src/irmin-git/import.ml create mode 100644 vendors/irmin/src/irmin-git/irmin_git.ml create mode 100644 vendors/irmin/src/irmin-git/irmin_git.mli create mode 100644 vendors/irmin/src/irmin-git/irmin_git_intf.ml create mode 100644 vendors/irmin/src/irmin-git/metadata.ml create mode 100644 vendors/irmin/src/irmin-git/metadata.mli create mode 100644 vendors/irmin/src/irmin-git/node.ml create mode 100644 vendors/irmin/src/irmin-git/node.mli create mode 100644 vendors/irmin/src/irmin-git/reference.ml create mode 100644 vendors/irmin/src/irmin-git/reference.mli create mode 100644 vendors/irmin/src/irmin-git/remote.ml create mode 100644 vendors/irmin/src/irmin-git/remote.mli create mode 100644 vendors/irmin/src/irmin-git/schema.ml create mode 100644 vendors/irmin/src/irmin-git/unix/dune create mode 100644 vendors/irmin/src/irmin-git/unix/irmin_git_unix.ml create mode 100644 vendors/irmin/src/irmin-git/unix/xgit.ml create mode 100644 vendors/irmin/src/irmin-git/unix/xgit.mli create mode 100644 vendors/irmin/src/irmin-git/unix/xgit_intf.ml create mode 100644 vendors/irmin/src/irmin-git/value.ml create mode 100644 vendors/irmin/src/irmin-git/value.mli create mode 100644 vendors/irmin/src/irmin-git/value_intf.ml create mode 100644 vendors/irmin/src/irmin-graphql/dune create mode 100644 vendors/irmin/src/irmin-graphql/import.ml create mode 100644 vendors/irmin/src/irmin-graphql/server.ml create mode 100644 vendors/irmin/src/irmin-graphql/server.mli create mode 100644 vendors/irmin/src/irmin-graphql/unix/dune create mode 100644 vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.ml create mode 100644 vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.mli create mode 100644 vendors/irmin/src/irmin-http/closeable.ml create mode 100644 vendors/irmin/src/irmin-http/closeable.mli create mode 100644 vendors/irmin/src/irmin-http/common.ml create mode 100644 vendors/irmin/src/irmin-http/dune create mode 100644 vendors/irmin/src/irmin-http/import.ml create mode 100644 vendors/irmin/src/irmin-http/irmin_http.ml create mode 100644 vendors/irmin/src/irmin-http/irmin_http.mli create mode 100644 vendors/irmin/src/irmin-http/irmin_http_server.ml create mode 100644 vendors/irmin/src/irmin-http/irmin_http_server.mli create mode 100644 vendors/irmin/src/irmin-http/s.ml create mode 100644 vendors/irmin/src/irmin-http/unix/dune create mode 100644 vendors/irmin/src/irmin-http/unix/irmin_http_unix.ml create mode 100644 vendors/irmin/src/irmin-http/unix/irmin_http_unix.mli create mode 100644 vendors/irmin/src/irmin-mirage/dune create mode 100644 vendors/irmin/src/irmin-mirage/git/dune create mode 100644 vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.ml create mode 100644 vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.mli create mode 100644 vendors/irmin/src/irmin-mirage/git/irmin_mirage_git_intf.ml create mode 100644 vendors/irmin/src/irmin-mirage/graphql/dune create mode 100644 vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.ml create mode 100644 vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.mli create mode 100644 vendors/irmin/src/irmin-mirage/irmin_mirage.ml create mode 100644 vendors/irmin/src/irmin-mirage/irmin_mirage.mli create mode 100644 vendors/irmin/src/irmin-pack-tools/README.md create mode 100644 vendors/irmin/src/irmin-pack-tools/ppcf/dune create mode 100644 vendors/irmin/src/irmin-pack-tools/ppcf/ppcf.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/ppidx/dune create mode 100644 vendors/irmin/src/irmin-pack-tools/ppidx/ppidx.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/dune create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/files.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/import.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/main.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/parse.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/ring.ml create mode 100644 vendors/irmin/src/irmin-pack-tools/tezos_explorer/show.ml create mode 100644 vendors/irmin/src/irmin-pack/atomic_write.ml create mode 100644 vendors/irmin/src/irmin-pack/atomic_write.mli create mode 100644 vendors/irmin/src/irmin-pack/atomic_write_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/conf.ml create mode 100644 vendors/irmin/src/irmin-pack/conf.mli create mode 100644 vendors/irmin/src/irmin-pack/dune create mode 100644 vendors/irmin/src/irmin-pack/import.ml create mode 100644 vendors/irmin/src/irmin-pack/indexable.ml create mode 100644 vendors/irmin/src/irmin-pack/indexable.mli create mode 100644 vendors/irmin/src/irmin-pack/indexable_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/indexing_strategy.ml create mode 100644 vendors/irmin/src/irmin-pack/indexing_strategy.mli create mode 100644 vendors/irmin/src/irmin-pack/inode.ml create mode 100644 vendors/irmin/src/irmin-pack/inode.mli create mode 100644 vendors/irmin/src/irmin-pack/inode_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/irmin_pack.ml create mode 100644 vendors/irmin/src/irmin-pack/irmin_pack.mli create mode 100644 vendors/irmin/src/irmin-pack/irmin_pack_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/layout.ml create mode 100644 vendors/irmin/src/irmin-pack/mem/dune create mode 100644 vendors/irmin/src/irmin-pack/mem/import.ml create mode 100644 vendors/irmin/src/irmin-pack/mem/indexable.ml create mode 100644 vendors/irmin/src/irmin-pack/mem/indexable.mli create mode 100644 vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.ml create mode 100644 vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.mli create mode 100644 vendors/irmin/src/irmin-pack/pack_key.ml create mode 100644 vendors/irmin/src/irmin-pack/pack_value.ml create mode 100644 vendors/irmin/src/irmin-pack/pack_value.mli create mode 100644 vendors/irmin/src/irmin-pack/pack_value_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/stats.ml create mode 100644 vendors/irmin/src/irmin-pack/stats.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/append_only_file.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/append_only_file.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/append_only_file_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/async.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/async.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/async_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/atomic_write.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/atomic_write.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/checks.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/checks.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/checks_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/chunked_suffix.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/chunked_suffix.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/chunked_suffix_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/control_file.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/control_file.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/control_file_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/dict.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/dict.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/dict_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/dispatcher.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/dispatcher.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/dispatcher_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/dune create mode 100644 vendors/irmin/src/irmin-pack/unix/errors.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/file_manager.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/file_manager.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/file_manager_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/gc.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/gc.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/gc_args.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/gc_stats.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/gc_stats.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/gc_worker.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/gc_worker.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/import.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/inode.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/inode.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/inode_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/io.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/io.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/io_errors.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/io_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/io_legacy.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/io_legacy.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/io_legacy_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/lower.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/lower.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/lower_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_index.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_index.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_index_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_key.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_key.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_key_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_store.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_store.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_store_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/pack_value.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/ranges.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/ranges.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/snapshot.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/snapshot.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/snapshot_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/sparse_file.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/sparse_file.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/sparse_file_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/stats.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/stats.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/stats_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/store.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/store.mli create mode 100644 vendors/irmin/src/irmin-pack/unix/store_intf.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/traverse_pack_file.ml create mode 100644 vendors/irmin/src/irmin-pack/unix/utils.ml create mode 100644 vendors/irmin/src/irmin-pack/version.ml create mode 100644 vendors/irmin/src/irmin-pack/version.mli create mode 100644 vendors/irmin/src/irmin-test/common.ml create mode 100644 vendors/irmin/src/irmin-test/dune create mode 100644 vendors/irmin/src/irmin-test/helpers.ml create mode 100644 vendors/irmin/src/irmin-test/import.ml create mode 100644 vendors/irmin/src/irmin-test/irmin_bench.ml create mode 100644 vendors/irmin/src/irmin-test/irmin_bench.mli create mode 100644 vendors/irmin/src/irmin-test/irmin_test.ml create mode 100644 vendors/irmin/src/irmin-test/irmin_test.mli create mode 100644 vendors/irmin/src/irmin-test/node.ml create mode 100644 vendors/irmin/src/irmin-test/rusage.ml create mode 100644 vendors/irmin/src/irmin-test/rusage_stubs.c create mode 100644 vendors/irmin/src/irmin-test/store.ml create mode 100644 vendors/irmin/src/irmin-test/store.mli create mode 100644 vendors/irmin/src/irmin-test/store_graph.ml create mode 100644 vendors/irmin/src/irmin-test/store_graph.mli create mode 100644 vendors/irmin/src/irmin-test/store_watch.ml create mode 100644 vendors/irmin/src/irmin-test/store_watch.mli create mode 100644 vendors/irmin/src/irmin-tezos/dune create mode 100644 vendors/irmin/src/irmin-tezos/irmin_tezos.ml create mode 100644 vendors/irmin/src/irmin-tezos/irmin_tezos.mli create mode 100644 vendors/irmin/src/irmin-tezos/schema.ml create mode 100644 vendors/irmin/src/irmin-tezos/schema.mli create mode 100644 vendors/irmin/src/irmin/append_only.ml create mode 100644 vendors/irmin/src/irmin/append_only.mli create mode 100644 vendors/irmin/src/irmin/append_only_intf.ml create mode 100644 vendors/irmin/src/irmin/atomic_write.ml create mode 100644 vendors/irmin/src/irmin/atomic_write.mli create mode 100644 vendors/irmin/src/irmin/atomic_write_intf.ml create mode 100644 vendors/irmin/src/irmin/backend.ml create mode 100644 vendors/irmin/src/irmin/branch.ml create mode 100644 vendors/irmin/src/irmin/branch.mli create mode 100644 vendors/irmin/src/irmin/branch_intf.ml create mode 100644 vendors/irmin/src/irmin/commit.ml create mode 100644 vendors/irmin/src/irmin/commit.mli create mode 100644 vendors/irmin/src/irmin/commit_intf.ml create mode 100644 vendors/irmin/src/irmin/conf.ml create mode 100644 vendors/irmin/src/irmin/conf.mli create mode 100644 vendors/irmin/src/irmin/content_addressable.ml create mode 100644 vendors/irmin/src/irmin/content_addressable.mli create mode 100644 vendors/irmin/src/irmin/content_addressable_intf.ml create mode 100644 vendors/irmin/src/irmin/contents.ml create mode 100644 vendors/irmin/src/irmin/contents.mli create mode 100644 vendors/irmin/src/irmin/contents_intf.ml create mode 100644 vendors/irmin/src/irmin/data/dune create mode 100644 vendors/irmin/src/irmin/data/fixed_size_string_set.ml create mode 100644 vendors/irmin/src/irmin/data/fixed_size_string_set.mli create mode 100644 vendors/irmin/src/irmin/data/hashset.ml create mode 100644 vendors/irmin/src/irmin/data/irmin_data.ml create mode 100644 vendors/irmin/src/irmin/diff.ml create mode 100644 vendors/irmin/src/irmin/diff.mli create mode 100644 vendors/irmin/src/irmin/dot.ml create mode 100644 vendors/irmin/src/irmin/dot.mli create mode 100644 vendors/irmin/src/irmin/dune create mode 100644 vendors/irmin/src/irmin/export_for_backends.ml create mode 100644 vendors/irmin/src/irmin/hash.ml create mode 100644 vendors/irmin/src/irmin/hash.mli create mode 100644 vendors/irmin/src/irmin/hash_intf.ml create mode 100644 vendors/irmin/src/irmin/import.ml create mode 100644 vendors/irmin/src/irmin/indexable.ml create mode 100644 vendors/irmin/src/irmin/indexable.mli create mode 100644 vendors/irmin/src/irmin/indexable_intf.ml create mode 100644 vendors/irmin/src/irmin/info.ml create mode 100644 vendors/irmin/src/irmin/info.mli create mode 100644 vendors/irmin/src/irmin/info_intf.ml create mode 100644 vendors/irmin/src/irmin/irmin.ml create mode 100644 vendors/irmin/src/irmin/irmin.mli create mode 100644 vendors/irmin/src/irmin/key.ml create mode 100644 vendors/irmin/src/irmin/key.mli create mode 100644 vendors/irmin/src/irmin/key_intf.ml create mode 100644 vendors/irmin/src/irmin/lock.ml create mode 100644 vendors/irmin/src/irmin/lock.mli create mode 100644 vendors/irmin/src/irmin/logging.ml create mode 100644 vendors/irmin/src/irmin/logging.mli create mode 100644 vendors/irmin/src/irmin/logging_intf.ml create mode 100644 vendors/irmin/src/irmin/lru.ml create mode 100644 vendors/irmin/src/irmin/lru.mli create mode 100644 vendors/irmin/src/irmin/mem/dune create mode 100644 vendors/irmin/src/irmin/mem/import.ml create mode 100644 vendors/irmin/src/irmin/mem/irmin_mem.ml create mode 100644 vendors/irmin/src/irmin/mem/irmin_mem.mli create mode 100644 vendors/irmin/src/irmin/merge.ml create mode 100644 vendors/irmin/src/irmin/merge.mli create mode 100644 vendors/irmin/src/irmin/metadata.ml create mode 100644 vendors/irmin/src/irmin/metadata.mli create mode 100644 vendors/irmin/src/irmin/metadata_intf.ml create mode 100644 vendors/irmin/src/irmin/metrics.ml create mode 100644 vendors/irmin/src/irmin/metrics.mli create mode 100644 vendors/irmin/src/irmin/node.ml create mode 100644 vendors/irmin/src/irmin/node.mli create mode 100644 vendors/irmin/src/irmin/node_intf.ml create mode 100644 vendors/irmin/src/irmin/object_graph.ml create mode 100644 vendors/irmin/src/irmin/object_graph.mli create mode 100644 vendors/irmin/src/irmin/object_graph_intf.ml create mode 100644 vendors/irmin/src/irmin/path.ml create mode 100644 vendors/irmin/src/irmin/path.mli create mode 100644 vendors/irmin/src/irmin/path_intf.ml create mode 100644 vendors/irmin/src/irmin/perms.ml create mode 100644 vendors/irmin/src/irmin/proof.ml create mode 100644 vendors/irmin/src/irmin/proof.mli create mode 100644 vendors/irmin/src/irmin/proof_intf.ml create mode 100644 vendors/irmin/src/irmin/read_only.ml create mode 100644 vendors/irmin/src/irmin/read_only.mli create mode 100644 vendors/irmin/src/irmin/read_only_intf.ml create mode 100644 vendors/irmin/src/irmin/remote.ml create mode 100644 vendors/irmin/src/irmin/remote.mli create mode 100644 vendors/irmin/src/irmin/remote_intf.ml create mode 100644 vendors/irmin/src/irmin/reversed_list.ml create mode 100644 vendors/irmin/src/irmin/reversed_list.mli create mode 100644 vendors/irmin/src/irmin/schema.ml create mode 100644 vendors/irmin/src/irmin/slice.ml create mode 100644 vendors/irmin/src/irmin/slice.mli create mode 100644 vendors/irmin/src/irmin/slice_intf.ml create mode 100644 vendors/irmin/src/irmin/storage.ml create mode 100644 vendors/irmin/src/irmin/storage.mli create mode 100644 vendors/irmin/src/irmin/storage_intf.ml create mode 100644 vendors/irmin/src/irmin/store.ml create mode 100644 vendors/irmin/src/irmin/store.mli create mode 100644 vendors/irmin/src/irmin/store_intf.ml create mode 100644 vendors/irmin/src/irmin/store_properties.ml create mode 100644 vendors/irmin/src/irmin/store_properties.mli create mode 100644 vendors/irmin/src/irmin/store_properties_intf.ml create mode 100644 vendors/irmin/src/irmin/sync.ml create mode 100644 vendors/irmin/src/irmin/sync.mli create mode 100644 vendors/irmin/src/irmin/sync_intf.ml create mode 100644 vendors/irmin/src/irmin/tree.ml create mode 100644 vendors/irmin/src/irmin/tree.mli create mode 100644 vendors/irmin/src/irmin/tree_intf.ml create mode 100644 vendors/irmin/src/irmin/type.ml create mode 100644 vendors/irmin/src/irmin/type.mli create mode 100644 vendors/irmin/src/irmin/unix/dune create mode 100644 vendors/irmin/src/irmin/unix/info.ml create mode 100644 vendors/irmin/src/irmin/unix/info.mli create mode 100644 vendors/irmin/src/irmin/unix/irmin_unix.ml create mode 100644 vendors/irmin/src/irmin/unix/irmin_unix.mli create mode 100644 vendors/irmin/src/irmin/version.ml create mode 100644 vendors/irmin/src/irmin/watch.ml create mode 100644 vendors/irmin/src/irmin/watch.mli create mode 100644 vendors/irmin/src/irmin/watch_intf.ml create mode 100644 vendors/irmin/src/libirmin/commit.ml create mode 100644 vendors/irmin/src/libirmin/config.ml create mode 100644 vendors/irmin/src/libirmin/dune create mode 100644 vendors/irmin/src/libirmin/gen/dune create mode 100644 vendors/irmin/src/libirmin/gen/generate.ml create mode 100644 vendors/irmin/src/libirmin/info.ml create mode 100644 vendors/irmin/src/libirmin/lib/dune create mode 100644 vendors/irmin/src/libirmin/lib/libirmin.ml create mode 100644 vendors/irmin/src/libirmin/libirmin_bindings.ml create mode 100644 vendors/irmin/src/libirmin/path.ml create mode 100644 vendors/irmin/src/libirmin/repo.ml create mode 100644 vendors/irmin/src/libirmin/store.ml create mode 100644 vendors/irmin/src/libirmin/tree.ml create mode 100644 vendors/irmin/src/libirmin/type.ml create mode 100644 vendors/irmin/src/libirmin/types.ml create mode 100644 vendors/irmin/src/libirmin/types.mli create mode 100644 vendors/irmin/src/libirmin/types_intf.ml create mode 100644 vendors/irmin/src/libirmin/util.ml create mode 100644 vendors/irmin/src/libirmin/value.ml create mode 100644 vendors/irmin/src/ppx_irmin/dune create mode 100644 vendors/irmin/src/ppx_irmin/internal/dune create mode 100644 vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.ml create mode 100644 vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.mli create mode 100644 vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal_lib.ml create mode 100644 vendors/irmin/src/ppx_irmin/ppx_irmin.ml create mode 100644 vendors/irmin/src/ppx_irmin/ppx_irmin.mli create mode 100644 vendors/irmin/test/irmin-bench/data/tezos_actions_1commit.repr create mode 100644 vendors/irmin/test/irmin-bench/dune create mode 100644 vendors/irmin/test/irmin-bench/ema.ml create mode 100644 vendors/irmin/test/irmin-bench/import.ml create mode 100644 vendors/irmin/test/irmin-bench/misc.ml create mode 100644 vendors/irmin/test/irmin-bench/replay.ml create mode 100644 vendors/irmin/test/irmin-bench/test.ml create mode 100644 vendors/irmin/test/irmin-bench/test.mli create mode 100644 vendors/irmin/test/irmin-chunk/dune create mode 100644 vendors/irmin/test/irmin-chunk/test.ml create mode 100644 vendors/irmin/test/irmin-chunk/test.mli create mode 100644 vendors/irmin/test/irmin-chunk/test_chunk.ml create mode 100644 vendors/irmin/test/irmin-cli/dune create mode 100644 vendors/irmin/test/irmin-cli/test.ml create mode 100644 vendors/irmin/test/irmin-cli/test.yml create mode 100644 vendors/irmin/test/irmin-cli/test_command_line.t create mode 100644 vendors/irmin/test/irmin-containers/blob_log.ml create mode 100644 vendors/irmin/test/irmin-containers/common.ml create mode 100644 vendors/irmin/test/irmin-containers/common.mli create mode 100644 vendors/irmin/test/irmin-containers/counter.ml create mode 100644 vendors/irmin/test/irmin-containers/dune create mode 100644 vendors/irmin/test/irmin-containers/import.ml create mode 100644 vendors/irmin/test/irmin-containers/linked_log.ml create mode 100644 vendors/irmin/test/irmin-containers/lww_register.ml create mode 100644 vendors/irmin/test/irmin-containers/test.ml create mode 100644 vendors/irmin/test/irmin-containers/test.mli create mode 100644 vendors/irmin/test/irmin-fs/dune create mode 100644 vendors/irmin/test/irmin-fs/test.ml create mode 100644 vendors/irmin/test/irmin-fs/test.mli create mode 100644 vendors/irmin/test/irmin-fs/test_fs.ml create mode 100644 vendors/irmin/test/irmin-fs/test_fs_unix.ml create mode 100644 vendors/irmin/test/irmin-fs/test_unix.ml create mode 100644 vendors/irmin/test/irmin-git/dune create mode 100644 vendors/irmin/test/irmin-git/test.ml create mode 100644 vendors/irmin/test/irmin-git/test.mli create mode 100644 vendors/irmin/test/irmin-git/test_git.ml create mode 100644 vendors/irmin/test/irmin-git/test_git.mli create mode 100644 vendors/irmin/test/irmin-git/test_git_unix.ml create mode 100644 vendors/irmin/test/irmin-git/test_unix.ml create mode 100644 vendors/irmin/test/irmin-graphql/common.ml create mode 100644 vendors/irmin/test/irmin-graphql/common.mli create mode 100644 vendors/irmin/test/irmin-graphql/dune create mode 100644 vendors/irmin/test/irmin-graphql/import.ml create mode 100644 vendors/irmin/test/irmin-graphql/test.ml create mode 100644 vendors/irmin/test/irmin-graphql/test.mli create mode 100644 vendors/irmin/test/irmin-http/dune create mode 100644 vendors/irmin/test/irmin-http/test.ml create mode 100644 vendors/irmin/test/irmin-http/test.mli create mode 100644 vendors/irmin/test/irmin-http/test_http.ml create mode 100644 vendors/irmin/test/irmin-http/test_http.mli create mode 100644 vendors/irmin/test/irmin-mem/bench.ml create mode 100644 vendors/irmin/test/irmin-mem/dune create mode 100644 vendors/irmin/test/irmin-mem/test.ml create mode 100644 vendors/irmin/test/irmin-mem/test.mli create mode 100644 vendors/irmin/test/irmin-mem/test_mem.ml create mode 100644 vendors/irmin/test/irmin-pack/_layered.mli create mode 100644 vendors/irmin/test/irmin-pack/common.ml create mode 100644 vendors/irmin/test/irmin-pack/common.mli create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted_inode/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted_inode/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted_inode/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/corrupted_inode/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/empty_store/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/empty_store/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/empty_store/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/empty_store/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/version_1/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_1/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_1/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_1/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/version_1_large/README.md create mode 100644 vendors/irmin/test/irmin-pack/data/version_1_large/index/lock create mode 100644 vendors/irmin/test/irmin-pack/data/version_1_large/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_1_large/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_1_large/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_1_large/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_always/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_always/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_always/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_always/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_minimal/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_minimal/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_minimal/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_minimal/store.pack create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_to_3_always/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_to_3_always/store.0.suffix create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_to_3_always/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_to_3_always/store.control create mode 100644 vendors/irmin/test/irmin-pack/data/version_2_to_3_always/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_always/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_always/store.0.suffix create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_always/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_always/store.control create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_always/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal/store.0.suffix create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal/store.control create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal/store.dict create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/index/log create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.1.mapping create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.1.prefix create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.1.suffix create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.branches create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.control create mode 100644 vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.dict create mode 100644 vendors/irmin/test/irmin-pack/dune create mode 100644 vendors/irmin/test/irmin-pack/import.ml create mode 100644 vendors/irmin/test/irmin-pack/test.ml create mode 100644 vendors/irmin/test/irmin-pack/test.mli create mode 100644 vendors/irmin/test/irmin-pack/test_async.ml create mode 100644 vendors/irmin/test/irmin-pack/test_async.mli create mode 100644 vendors/irmin/test/irmin-pack/test_corrupted.ml create mode 100644 vendors/irmin/test/irmin-pack/test_corrupted.mli create mode 100644 vendors/irmin/test/irmin-pack/test_dispatcher.ml create mode 100644 vendors/irmin/test/irmin-pack/test_dispatcher.mli create mode 100644 vendors/irmin/test/irmin-pack/test_existing_stores.ml create mode 100644 vendors/irmin/test/irmin-pack/test_existing_stores.mli create mode 100644 vendors/irmin/test/irmin-pack/test_flush_reload.ml create mode 100644 vendors/irmin/test/irmin-pack/test_gc.ml create mode 100644 vendors/irmin/test/irmin-pack/test_gc.mli create mode 100644 vendors/irmin/test/irmin-pack/test_hashes.ml create mode 100644 vendors/irmin/test/irmin-pack/test_hashes.mli create mode 100644 vendors/irmin/test/irmin-pack/test_indexing_strategy.ml create mode 100644 vendors/irmin/test/irmin-pack/test_indexing_strategy.mli create mode 100644 vendors/irmin/test/irmin-pack/test_inode.ml create mode 100644 vendors/irmin/test/irmin-pack/test_inode.mli create mode 100644 vendors/irmin/test/irmin-pack/test_lower.ml create mode 100644 vendors/irmin/test/irmin-pack/test_lower.mli create mode 100644 vendors/irmin/test/irmin-pack/test_mapping.ml create mode 100644 vendors/irmin/test/irmin-pack/test_mapping.mli create mode 100644 vendors/irmin/test/irmin-pack/test_nearest_geq.ml create mode 100644 vendors/irmin/test/irmin-pack/test_nearest_leq.mli create mode 100644 vendors/irmin/test/irmin-pack/test_pack.ml create mode 100644 vendors/irmin/test/irmin-pack/test_pack.mli create mode 100644 vendors/irmin/test/irmin-pack/test_pack_version_bump.ml create mode 100644 vendors/irmin/test/irmin-pack/test_pack_version_bump.mli create mode 100644 vendors/irmin/test/irmin-pack/test_ranges.ml create mode 100644 vendors/irmin/test/irmin-pack/test_readonly.ml create mode 100644 vendors/irmin/test/irmin-pack/test_readonly.mli create mode 100644 vendors/irmin/test/irmin-pack/test_snapshot.ml create mode 100644 vendors/irmin/test/irmin-pack/test_tree.ml create mode 100644 vendors/irmin/test/irmin-pack/test_upgrade.ml create mode 100644 vendors/irmin/test/irmin-tezos/dune create mode 100644 vendors/irmin/test/irmin-tezos/generate.ml create mode 100644 vendors/irmin/test/irmin-tezos/generate.mli create mode 100644 vendors/irmin/test/irmin-tezos/irmin-fsck-help.txt create mode 100644 vendors/irmin/test/irmin-tezos/irmin_fsck.ml create mode 100644 vendors/irmin/test/irmin-tezos/stat.t/run.t create mode 100644 vendors/irmin/test/irmin/data/dune create mode 100644 vendors/irmin/test/irmin/data/import.ml create mode 100644 vendors/irmin/test/irmin/data/test.ml create mode 100644 vendors/irmin/test/irmin/data/test.mli create mode 100644 vendors/irmin/test/irmin/data/test_fixed_size_string_set.ml create mode 100644 vendors/irmin/test/irmin/data/test_fixed_size_string_set.mli create mode 100644 vendors/irmin/test/irmin/dune create mode 100644 vendors/irmin/test/irmin/generic-key/dune create mode 100644 vendors/irmin/test/irmin/generic-key/test.ml create mode 100644 vendors/irmin/test/irmin/generic-key/test_inlined_contents.ml create mode 100644 vendors/irmin/test/irmin/generic-key/test_store_offset.ml create mode 100644 vendors/irmin/test/irmin/test.ml create mode 100644 vendors/irmin/test/irmin/test.mli create mode 100644 vendors/irmin/test/irmin/test_conf.ml create mode 100644 vendors/irmin/test/irmin/test_conf.mli create mode 100644 vendors/irmin/test/irmin/test_hash.ml create mode 100644 vendors/irmin/test/irmin/test_hash.mli create mode 100644 vendors/irmin/test/irmin/test_lru.ml create mode 100644 vendors/irmin/test/irmin/test_tree.ml create mode 100644 vendors/irmin/test/irmin/test_tree.mli create mode 100644 vendors/irmin/test/libirmin/dune create mode 100644 vendors/irmin/test/libirmin/greatest.h create mode 100644 vendors/irmin/test/libirmin/test.c create mode 100644 vendors/irmin/test/ppx_irmin/dune create mode 100644 vendors/irmin/test/ppx_irmin/test_logs-output.expected create mode 100644 vendors/irmin/test/ppx_irmin/test_logs-processed.expected create mode 100644 vendors/irmin/test/ppx_irmin/test_logs.ml diff --git a/vendors/irmin/.github/workflows/changelog-check.yml b/vendors/irmin/.github/workflows/changelog-check.yml new file mode 100644 index 000000000000..c731485f782a --- /dev/null +++ b/vendors/irmin/.github/workflows/changelog-check.yml @@ -0,0 +1,20 @@ +name: Changelog check + +on: + pull_request: + branches: [ main ] + types: [ opened, synchronize, reopened, labeled, unlabeled ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + + - name: git diff + if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-changelog-needed') }} + env: + BASE_REF: ${{ github.event.pull_request.base.ref }} + run: | + ! git diff --exit-code origin/$BASE_REF -- CHANGES.md diff --git a/vendors/irmin/.github/workflows/coverage.yml b/vendors/irmin/.github/workflows/coverage.yml new file mode 100644 index 000000000000..3f888004e97f --- /dev/null +++ b/vendors/irmin/.github/workflows/coverage.yml @@ -0,0 +1,67 @@ +name: coverage + +on: + push: + branches: + - main + pull_request: + schedule: + # Prime the caches every Monday + - cron: 0 1 * * MON + +jobs: + build: + if: github.repository_owner == 'mirage' + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + packages: [ '.' ] + ocaml-compiler: + - 4.13.x + + runs-on: ${{ matrix.os }} + + steps: + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Use OCaml ${{ matrix.ocaml-compiler }} + uses: ocaml/setup-ocaml@v2 + with: + ocaml-compiler: ${{ matrix.ocaml-compiler }} + opam-local-packages: $${ matrix.opam-local-packages }} + opam-depext-flags: --with-test + + - name: Pin local packages + run: | + # Pin all local opam files to avoid internal conflicts + # + # TODO: replace with `opam pin --with-version` when Opam 2.1 is + # available via `setup-ocaml`. + find . -maxdepth 1 -name '*.opam' -printf '%P\n' |\ + cut -d. -f1 |\ + xargs -I{} -n 1 opam pin add {}.dev ./ -n + + - name: Install depexts + run: | + find . -maxdepth 1 -name '*.opam' -printf '%P\n' |\ + cut -d. -f1 |\ + xargs opam depext --update -y + + - name: Install Opam dependencies + run: opam install ${{ matrix.packages }} --with-test --deps-only + + - name: Run tests with coverage instrumentation + run: opam exec -- dune runtest --instrument-with bisect_ppx + + - name: Send coverage report to Codecov + run: opam exec -- bisect-ppx-report send-to Codecov + env: + PULL_REQUEST_NUMBER: ${{ github.event.number }} diff --git a/vendors/irmin/.github/workflows/git.yml b/vendors/irmin/.github/workflows/git.yml new file mode 100644 index 000000000000..171834167786 --- /dev/null +++ b/vendors/irmin/.github/workflows/git.yml @@ -0,0 +1,13 @@ +name: Git Checks + +on: + pull_request: + +jobs: + block-fixup: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2.0.0 + - name: Block Fixup Commit Merge + uses: 13rac1/block-fixup-merge-action@v2.0.0 diff --git a/vendors/irmin/.gitignore b/vendors/irmin/.gitignore new file mode 100644 index 000000000000..33745a639c68 --- /dev/null +++ b/vendors/irmin/.gitignore @@ -0,0 +1,12 @@ +_build +_coverage +_metrics +*~ +*.install +*.merlin +_opam +.envrc +\#* +.#* +.*.swp +**/.DS_Store diff --git a/vendors/irmin/.ocamlformat b/vendors/irmin/.ocamlformat new file mode 100644 index 000000000000..a47ebdcf58f4 --- /dev/null +++ b/vendors/irmin/.ocamlformat @@ -0,0 +1,6 @@ +version = 0.24.1 +profile = conventional + +ocaml-version = 4.08.0 +break-infix = fit-or-vertical +parse-docstrings = true diff --git a/vendors/irmin/CHANGES.md b/vendors/irmin/CHANGES.md new file mode 100644 index 000000000000..9c25a6ad56b1 --- /dev/null +++ b/vendors/irmin/CHANGES.md @@ -0,0 +1,2168 @@ +## Unreleased + +### Fixed + +- **irmin-pack** + - Fix snapshot export when using lower layer (#2257, @metanivek) + +## 3.7.1 + +### Fixed + +- **irmin-pack** + - Fix issue when migrating v2 stores to use lower layer (@metanivek, #2241) + - Fix issue when calling GC for a commit in the lower after migration + (@metanivek, #2242) + +## 3.7.0 (2023-04-26) + +### Added + +- **irmin** + - Add `Conf.pp` and `Conf.equal` to print and compare configuration values + (#2227, @samoht) + - Add a `clear` optional arguments to all function that adds a new commit: + `Commit.v`, `set`, `set_tree`, `remove`, `test_and_set`, + `test_and_set_tree`, `test_set_and_get`, `test_set_and_get_tree`, `merge`, + `merge_tree` and `with_tree`. This new argument allows to control whether + the tree caches are cleared up after objects are exported to disk during + the commit. (#2225, @samoht) + +- **irmin-pack** + - Add configuration option, `lower_root`, to specify a path for archiving data + during a GC. (#2177, @metanivek) + - Add `is_split_allowed` to check if a store allows split. (#2175, @metanivek) + - Add `add_volume` to allow creating new empty volume in lower layer. (#2188, + @metanivek) + - Add a `behaviour` function to the GC to check wether the GC will archive or + delete data. (#2190, @Firobe) + - Add a migration on `open_rw` to move the data to the `lower_root` if + the configuration was enabled (#2205, @art-w) + +### Changed + +- **irmin** + - Expose type equality for `Schema.Info` to avoid defining the `info` function + multiple times when using similar stores (#2189, #2193, @samoht) +- **irmin-pack** + - GC now changes its behaviour depending on the presence of a lower layer. + (#2190, @Firobe) + - Split now raises an exception if it is not allowed. It is not allowed on + stores that do not allow GC. (#2175, @metanivek) + - GC now supports stores imported V1/V2 stores, in presence of a lower layer + only. (#2190, @art-w, @Firobe) + - Upgrade on-disk format to version 5. (#2184, @metanivek) + - Archive to lower volume does not copy orphaned commits. (#2215, @art-w) + +### Fixed +- **irmin-pack** + - Unhandled exceptions in GC worker process are now reported as a failure + (#2163, @metanivek) + - Fix the silent mode for the integrity checks. (#2179, @icristescu) + - Fix file descriptor leak caused by `mmap`. (#2232, @art-w) + +## 3.6.1 (2023-03-15) + +### Fixed + +- **irmin-pack** + - Clear LRU when calling `reload` after a GC (#2200, @metanivek) + +## 3.5.2 (2023-03-02) + +### Fixed + +- **irmin-pack** + - Clear LRU when calling `reload` after a GC (#2200, @metanivek) + +## 3.6.0 (2023-02-16) + +### Changed + +- **irmin-pack** + - Improve GC reachability traversal to optimize memory, speed and remove + the need for temporary files. (#2085, @art-w) + +## 3.5.1 (2023-01-10) + +### Fixed + +- **irmin-pack** + - Integrity check of a commit works on stores using the minimal indexing + strategy. (#2160, @icristescu) + +## 3.5.0 (2022-12-15) + +### Added + +- **irmin-pack** + - Add `Irmin_pack_unix.Stats.Latest_gc` which is now the parameter of GC's + `finished` callback (#2089, @Ngoguey42) + - Add `Gc.oldest_live_commit` which returns the key of the commit on which the + latest gc was called on. (#2110, @icristescu) + - Add `split` to create a new suffix chunk. Subsequent writes will append to + this chunk until `split` is called again. (#2118, @icristescu) + - Add `create_one_commit_store` to create a new store from the existing one, + containing only one commit. (#2125, @icristescu) + +### Changed + +- **irmin-pack** + - Upgraded on-disk format to version 4. (#2110, @icristescu) + - Detecting control file corruption with a checksum (#2119, @art-w) + - Change on-disk layout of the suffix from a single file to a multiple, + chunked file design (#2115, @metanivek) + - Modify GC to work with new chunked suffix. See `examples/gc.ml` for a + demonstration of how it works with the new `split` function. (#2126, + @metanivek) + +## 3.4.3 (2022-10-19) + +### Fixed + +- **irmin-pack** + - Fix read-only opening flags of mapping for read-only opening of stores that + do not have read-write rights on the files. (#2121, @Ngoguey42) + +## 3.4.2 (2022-10-06) + +### Added + +- **irmin** + - Add `test_set_and_get*` functions to retrieve commit associated with an update to the store (#2074, @patricoferris) + +- **irmin-graphql** + - Expose `test_set_and_get` function as a new mutation (#2074, @patricoferris) + - Add `contents_hash` function to get a value's hash (#2099, @patricoferris) + +- **irmin-pack** + - Expose `Gc.cancel` to abort a running GC (#2101, @art-w) + - Add `Irmin_pack_unix.Stats.Latest_gc` which is now the parameter of GC's + `finished` callback (#2089, @Ngoguey42) + +- **irmin-tezos-utils** + - Add package `irmin-tezos-utils` containing a graphical tool for manual pack + files analysis. (#1939, @clecat) + +### Changed + +- **irmin-pack** + - `irmin_pack_mem` no longer exposes disk specifics functions (#2081, + @icristescu) + - Move unix specific details for `Pack_key` and `Pack_value` from `irmin-pack` + to `irmin-pack.unix` (#2084, @metanivek) + - Remove unnecessary files at `open_rw` and after a failed GC (#2095, @art-w) + - Move the gc commit from the suffix file to the prefix. (#2102, @icristescu) + +### Fixed + +- **irmin-pack** + - Fix data race in RO instances when reading control file (#2100, @Ngoguey42) + - Fix bugs in gc related to commits that share the same tree. (#2106, + @icristescu) + - Fix the traverse pack files commands in the `irmin-tezos` CLI to work with + gced stores. (#1919, @icristescu) + +## 3.4.1 (2022-09-07) + +### Added + +- **irmin** + - Add `Storage` module for creating custom storage layers (#2047, @metanivek) + +- **irmin-pack** + - Add `Gc.is_allowed` (#2076, @icristescu) + - Add a `weight` parameter in the LRU implementation to bound + memory usage (#2050, @samoht) + +### Changed + +- **irmin** + - Removed `Irmin_unix.set_listen_dir_hook` (#2071, @zshipko) + +### Fixed + +- **irmin-pack** + - Fix the behaviour of irmin-pack regarding hashes and keys to GCed objects. + It used to not correctly ignore these entries, which could have resulted in + various bugs. E.g. the impossibility to append an object that used to be + dead and that has its hash in index. (#2070, @Ngoguey42) + +## 3.4.0 (2022-08-25) + +### Added + +- **irmin** + - Add `Tree.seq` to `Tree`'s public API (#1923, @metanivek) + +- **irmin-fs** + - Add unix subpackage, `irmin-fs.unix` (#1948, @metanivek) + +- **irmin-git** + - Add unix subpackage, `irmin-git.unix` (#1948, @metanivek) + +- **irmin-graphql** + - Add unix subpackage, `irmin-graphql.unix` (#1948, @metanivek) + +- **irmin-http** + - Add unix subpackage, `irmin-http.unix` (#1948, @metanivek) + +- **irmin-cli** + - Add new package for `irmin` command-line tool (#1951, @metanivek) + +- **irmin-pack** + - Add a garbage collection feature, allowing a user to discard commits older + than a specified commit. This feature is only enabled for stores that use + `Indexing_strategy.minimal`. The primary API is `Store.Gc.run`, + `Store.Gc.wait`, and `Store.Gc.is_finished`. See `examples/gc.ml` for a + demonstration of usage. + - Add a consistency check for the files on disk when opening store (#2004, + @icristescu) + +### Changed + +- **irmin** + - Replaced `Tree.node_fn` type with more general `Tree.folder` type to + represent the different ways to use `Tree.fold` (#1918, @metanivek) + +- **irmin-unix** + - Removed the `irmin-unix` package. Unix backends are now subpackages of their + relevant backend (see `irmin-fs.unix` and `irmin-git.unix`). The CLI tool is + in `irmin-cli`. For common unix utilities, see `irmin.unix`. (#1953, @metanivek) + +- **irmin-graphql** + - Updated to `graphql.0.14.0` (#1843, @patricoferris, @zshipko) + +### Fixed + +- **irmin** + - Fix a bug in Irmin.LRU.clear that disables the cache completly + after a clear. This is not used in any production code as only + the GC is clearing LRU so far (#1998, @samoht) + +## 3.3.2 (2022-07-25) + +### Fixed + +- Add a consistency check for the files on disk when opening store + (#2004, #2007, #@icristescu) +- Fix `irmin-tezos` CLI and `./tezos-node storage` to work with + v2 inodes (#1903, @icristescu, @Ngoguey42) + +## 3.3.1 (2022-06-22) + +### Fixed + +- **irmin-pack** + - Fix topology irregularities on disk which may lead to post-gc crashes. + (#1925, @Ngoguey42, @icristescu) + +## 3.3.0 (2022-06-20) + +### Added + +- **irmin** + - Add `Metrics` module to describe metric gathering in irmin. + (#1817, @maiste) + - Add `Repo.config` to access config used to create repo + (#1886, @zshipko) + +- **irmin-unix** + - Add `--plugin` flag to load Dynlink plugins that can register new + contents, hash and store types (#1808, @zshipko) + +- **irmin-pack** + - Add `use_fsync`, `dict_auto_flush_threshold` and + - `suffix_auto_flush_threshold` in store configuration. (#1865, @Ngoguey42) + - Add `no_migrate` in store configuration. (#1893, @zshipko) + +### Changed + +- **irmin-pack** + - Move `Irmin_pack.Pack_store.Indexing_strategy` to + `Irmin_pack.Indexing_strategy` and the rest of `Pack_store` + to `Irmin_pack_unix` (#1833, @Ngoguey42) + - Different repos opened using the same store module no longer share caches + and file descriptors (#1852, @Ngoguey42) + - `Snapshot.Import.close` requires a repo as additional argument (#1872, + @icristescu) + - Upgraded on-disk format to version 3 to support better synchronisation + mechanism between readwrite and readonly instances. This change is *not* + backwards-compatible with existing stores using `irmin-pack.x.x < 3.3.0` + versions. A migration done by the readwrite instance is necessary to open + older stores with `irmin-pack.3.3.0`. It is not forwards compatible. (#1865) + - Rename `Store.sync` to `Store.reload` (#1900, @Ngoguey42). + - Add `Pack_error` exception that centralizes many error cases alongside + `RO_not_allowed` and `Unix.Unix_error` (#1899, @Ngoguey42) + +### Fixed + +- **irmin-pack** + - Allow snapshot export to work on indexed root nodes (#1845, @icristescu) + +- **irmin** + - Fix Tree.export for nodes exported twice using different repos. (#1795, + @Ngoguey42) + +## 3.2.1 (2022-04-07) + +- Support all version of cmdliner (#1803, @samoht) + +## 3.2.0 (2022-03-28) + +### Added + +- **irmin-pack** + - Add `forbid_empty_dir_persistence` in store configuration. (#1789, + @ngoguey42) + - Add `Store.Snapshot` to expose the inodes for tezos snapshots (#1757, + @icristescu). + +### Changed + +- **irmin** + - Add error types in the API or proof verifiers. (#1791, @icristescu) + - Reduced the memory footprint of ``Tree.fold ~uniq:`True`` by a factor of 2. + (#1770, @CraigFe) + - Remove `clear` from all content addresssable stores. (#1794, @icristescu) + +## 3.1.0 (2022-02-25) + +### Fixed + +- **irmin-pack** + - Drop unnecessary runtime dependency on `ppx_irmin`. (#1782, @hhugo) + - Split the unix part of irmin-pack into irmin-pack.unix (#1783, @hhugo) + +- **irmin-unix** + - Fix conflicting command line arguments for `push`, `pull`, `fetch` and + `clone` (#1776, @zshipko) + - Fix issues with Sync functions by provided a better default `Mimic.ctx`. A + side-effect of this update is that the `remote` function now returns an Lwt + promise. (#1778, @zshipko) + +### Added + +- **libirmin** + - Create `libirmin` package providing a C interface to the irmin API + (#1713, @zshipko) + +### Changed + +- **irmin-bench** + - Make trace replay API public and simpler (#1781, @Ngoguey42) + +## 3.0.0 (2022-02-11) + +### Fixed + +- **irmin** + - Fix the implementation of comparison on `Irmin.Tree` objects to use the + comparison defined on hashes. The previous implementation was unstable. + (#1519, @CraigFe) + - Default implementation for contents, nodes and commits can no longer trigger + pre_hash collisions. This changes their hash. (#1715, @Ngoguey42, + @icristescu) + +- **irmin-pack** + - Improve the performance of Index encode and decode operations by + eliminating intermediate allocations. (#1577, @CraigFe) + +- **irmin-unix** + - Fix terms that can be manipulated at runtime by delaying computation + (#1645, @zshipko) + +### Added + +- **irmin** + - Add `Read_only.S` and `Read_only.Maker` module types (#1343, @samoht) + - Append-only and content-addressable backend implementations have to + provide `close` and `batch` functions (#1345, @samoht) + - Atomic-write backend implementations have to provide a `close` function + (#1345, @samoht) + - Add a function `Store.Tree.singleton` for building trees with a single + contents binding. (#1567, @CraigFe) + - Add `with_handler` and `head` to `Store.Backend.Node` and + `Store.Backend.Node_portable`to work with recursive node structures from + irmin core. (#1712, #1746 @Ngoguey42). Forward + port of #1692 and #1670. + - Add `proof`, `to_proof` and `of_proof` to `Store.Backend.Node_portable` + (#1716, @Ngoguey42). Forward port from #1583. + - Add `hash_exn` to `Store.Backend.Node.Val` and `Store.Backend.Node_portable` + (#TODO, @Ngoguey42) Forward ported from #1741. + - Add a `Store.Tree.kinded_hash` function. (#1767, @Ngoguey) Forward ported + from #1625. + - Add `Contents.String_v2`, `Node.Generic_key.Make_v2` and + `Commit.Generic_key.Make_v2` for backward compatibility with older stores. + (#1715, @icristescu) + +- **irmin-bench** + - Many improvements to the actions trace replay: + - Support for the layered store (#1293, @Ngoguey42) + - Fix replay for the first ~650k commits (was ~13k) (#1314, @Ngoguey42) + - Can change inode configuration prior to replay (#1326, @Ngoguey42) + - Check hash of commits (#1328, @icristescu) + - Fix the path flattening technique (#1357, @Ngoguey42) + - Introduce a new actions trace that can support replaying up to ~1300k + commits. (#1358, @Ngoguey42) + - Improve the stats collection and stats report (#1367, #1384, #1403, + #1404, #1416, #1429, #1438, #1501, #1616, @Ngoguey42, @maiste) + - Enable replay in CI (#1430, @Ngoguey42) + - Enable replay in CB (#1441, @Ngoguey42) + +- **irmin-mem** + - Add `Irmin_mem.Content_addressable` (#1369, @samoht) + +- **irmin-pack** + - Add a `stat-store` command to `irmin-fsck` to output stats on the tree + under a specified commit (#1391, @icristescu, @Ngoguey42, @CraigFe). + - Add new counters in `Stats` (#1570, @Ngoguey42). + - Add an option to configure the index function and pick the relevant bits + in a cryptographic hash by default (#1677 #1699, @samoht) + - Verify inode depth invariants (#1711, @Ngoguey42). Forward port of #1665. + +- **irmin-unix** + - Update `irmin` CLI to raise an exception when an invalid/non-existent + config file is specified (#1413, @zshipko) + - Add `--commit` flag to CLI to load a store from a specific commit hash + (#1721, @zshipko) + +- **irmin-tezos** + - Add a new package to mirror Tezos `tezos-context.encoding` library. + That'll simplify building benchmarks and custom tools (#1579, @samoht) + +### Changed + +- **irmin** + - `Irmin.Sync` is now a namespace: use `Irmin.Sync.Make(S)` instead of + `Irmin.Sync(S)` (#1338, @samoht) + - `Irmin.Private` is now `Irmin.Backend` (#1530, @CraigFe) + - `Store.master` is now `Store.main`. The existing `Store.master` function is + deprecated and will be removed in a future release. (#1564, @CraigFe) + - `Store.Private` is now `Store.Backend` (#1530, @CraigFe) + - `Store.Private.Sync` is now `Store.Backend.Remote` (#1338, @samoht) + - `Irmin.Branch.S.master` is now `Irmin.Branch.S.main` (#1564, @CraigFe) + - `Irmin.Private.{Commit,Node}` are now `Irmin.{Node,Commit}`. (#1471, + @CraigFe) + - All module types are now using snake-case and are not capitalized anymore. + (#1341, @samoht) + - Move signatures for backend stores into their own modules. All the + `X_STORE` sigs have moved to `X.S`: + - `APPEND_ONLY_STORE` is now `Append_only.S` + - `CONTENT_ADDRESSABLE_STORE` is now `Content_addressable.S` + - `ATOMIC_WRITE_STORE` is now `Irmin.Atomic_write.S` + And all the `X_STORE_MAKER` have moved to `X.Maker`: + - `APPEND_ONLY_STORE_MAKER` is now `Append_only.Maker` + - `CONTENT_ADDRESSABLE_STORE_MAKER` is now `Content_addressable.Maker` + - `ATOMIC_WRITE_STORE_MAKER` is now `Atomic_write.Maker` + This gives some space to move convenient functors closer to where they + belong: + - `Content_addressable` is now `Content_addressable.Make` + - New `Content_adddressable.Check_closed` and `Atomic_write.Check_closed` + (#1342, @samoht) + - Rename `Irmin.Make` into `Irmin.Maker` ; stage its result to return + `Make` functor once provided with a content-addressable and an + atomic-writes stores (#1369, @samoht) + - Rename `Irmin.Make_ext` into `Irmin.Maker_ext` ; stage its result to + return `Make` functor once provided with a content-addressable and an + atomic-writes stores, as well as node and commit makers (#1369, @samoht) + - Require at least `lwt.5.3.0` to use `Lwt.Syntax` in the codebase + (#1401, @samoht) + - `Info` implementations are not part of store: use `S.Info.v` + instead of `Irmin.Info.v` (#1400, @samoht) + - Rename `Commit.V1` to `Commit.V1.Make`. This functor now takes separate + hash and key implementations as arguments. (#1431 #1634, @CraigFe + @icristescu) + - Introduce a `Schema` module to hold all the types that users can + define in an Irmin store. Use this as a parameter to every `Maker` + functor. This is a large change which touches all the backends. + (#1470, @samoht, @CraigFe) + - Add `Irmin.Backend.Conf.Schema` for grouping configuration keys. Now + `Irmin.Backend.Conf.key` takes an additional `~spec` parameter. + (#1492, @zshipko) + - `Tree.empty` and `Node.empty` now both take a unit argument. (#1566 #1629, + @CraigFe) + - Rename `key` type to `path` and `Key` module to `Path` when it is in a path + context in `Tree` and `Store`. (#1569, @maiste) + - Move `Node.default` metadata default values into a `Node.Metadata.default` + to give room for other metadata values (#1611, @samoht) + + - Add support for non-content-addressed ("generic key") backend stores. This + allows Irmin to work with backends in which not all values are addressed by + their hash. In particular, this includes: + - New functions: `Store.{Commit,Contents,Tree}.of_key`. + - Adds `Irmin.{Node,Commit}.Generic_key` modules. + - Adds new types that must be provided by backends: `Node.Portable` and + `Commit.Portable`. + - Adds a new type of backend store: `Irmin.Indexable.S`. + (#1510 #1647, @CraigFe) + - Cache hits in several `Tree` functions are more frequent than before. + (#1724, @Ngoguey42, @CraigFe) + - Add a new `Pruned_hash` tag to the error case of several `Store.Tree` + functions (#1744 @Ngoguey42). Forward ported from #1583. + +- **irmin-containers** + - Removed `Irmin_containers.Store_maker`; this is now equivalent to + `Irmin.Content_addressable.S` (#1369, @samoht) + - Renamed `Irmin_containers.CAS_maker` to + `Irmin_containers.Content_addressable` (#1369, @samoht) + +- **irmin-fs** + - Renamed `Irmin_fs.Make` into `Irmin_fs.Maker` (#1369, @samoht) + - Renamed `Irmin_fs.Make_ext` into `Irmin_fs.Maker_ext` (#1369, @samoht) + +- **irmin-git** + - All of the configuration keys have moved into their own namespace: + - `Irmin_git.root` is now `Irmin_git.Conf.root` + - `Irmin_git.head` is now `Irmin_git.Conf.head` + - `Irmin_git.bare` is now `Irmin_git.Conf.bare` + - `Irmin_git.level` is now `Irmin_git.Conf.level` + - `Irmin_git.buffers` is now `Irmin_git.Conf.buffers` + - `Irmin_git.dot_git` is now `Irmin_git.Conf.dot_git` + (#1347, @samoht) + - Renamed `Irmin_git.Make` into `Irmin_git.Maker` (#1369, @samoht) + - Require at least `git.3.7.0` in the codebase (#1632, @dinosaure) + +- **irmin-graphql**: + - Changed the name of the default branch node from `master` to `main` in the + GraphQL API. (#1564, @CraigFe) + - Updated to be compatible with generic keys. + - The `Key` type is now called `Path` to match the new name in `irmin` + - All `key` fields and parameters have been renamed to `path` + (#1618, @zshipko) + +- **irmin-mirage** + - Renamed `Irmin_mirage_git.Make` into `Irmin_mirage_git.Maker` + (#1369, @samoht) + +- **irmin-pack** + - Changed the implementation of backend store keys to use direct pointers to + store contents (by offset in the pack file) when possible, rather than + querying the index on each lookup. (#1659, @CraigFe @ngoguey42 @icristescu) + - The `Irmin_pack.Maker` module type now no longer takes a `Conf` argument. + (#1641, @CraigFe) + - The backend configuration type `Conf.S` requires a new parameter + `contents_length_header` that (optionally) further specifies the encoding + format used for commits in order to improve performance. (#1644, @CraigFe) + - Upgraded on-disk format of pack files to support more efficient lookups and + reduce indexing overhead. This change is fully backwards-compatible with + existing stores using `irmin-pack.2.x` versions, but not + forwards compatible. (#1649 #1655, @CraigFe @Ngoguey42) + - Added support for user-specified indexing strategies. The default strategy + is to index all objects appended to the pack file (as before), but users may + now choose to index fewer objects in order to improve the write performance + of the store, at the cost of introducing potential duplicate values to the + pack file. (#1664, #1761, @CraigFe, @maiste) + +- **irmin-unix** + - Clean up command line interface. Allow config file to be specified when + using `Irmin_unix.Resolver.load_config` and make command line options + take precedence over config options. + (#1464, #1543, #1607 @zshipko) + - `Irmin_unix.Resolver.destruct` has been removed (and partially replaced by + `Resolver.spec`). (#1603, @CraigFe) + - Update `irmin` CLI to support empty path in `list` subcommand. + (#1575, @maiste) + - Add new commands to CLI: `branches` for listing available branches and + `log` which is similar to `git log` (#1609, #1727, @zshipko) + - Update `irmin watch` to take parameters to specify a command that should + be executed when there are new changes (#1608, @zshipko) + +### Removed + +- **irmin-pack** + - Removed the `irmin-pack.layered` library. Support for the layered store + will be restored on a future release of `irmin-pack`. (#1651, @CraigFe) + - Removed support for the `clear` operation in `irmin-pack`. This operation + is incompatible with performance optimisations made in this release. + (#1655, @CraigFe) + +- **irmin-layers** + - This experimental package has been removed. + +## 2.10.2 (2022-02-02) + +### Fixed + +- **irmin** + - Fixed a bug causing stream proof extender nodes to have their segments be + returned in reverse order (i.e. bottom to top, rather then top-down). + (#1742, @CraigFe) + + - Fixed a bug that allowed the creation of overly-large stable inodes via + stream proofs. (#1741, @Ngoguey42) + +### Added + +- **irmin** + - Add `Store.Private.Node.Val.hash_exn` (#1741, @Ngoguey42) + +## 2.10.1 (2022-01-20) + +### Fixed + +- **irmin** + - Fix bug introduced in #1683 which causes `Tree.seq` and `Tree.list` to + produce pruned children (#1720, @Ngoguey42) + +## 2.10.0 (2022-01-07) + +### Fixed + +- **irmin** + - Conversion between proofs and trees are now done in CPS (#1624, @samoht) + - Better support for s390x to workaround https://github.com/ocaml/ocaml/issues/10857 + (#1694, @icristescu) + +- **irmin-pack** + - Fix proofs for large inodes by tracking side-effects reads inside the + inode implementation (#1670, @samoht, @Ngoguey42) + - Flush branch store without calling `Repo.close` (#1707, @zshipko) + +### Added + +- **irmin** + - Add `Tree.produce_proof` and `Tree.verify_proof` to produce and verify + proofs from complex computations. `produce_proof` and `verify_proof` + takes a callback over tree and instead of a static list of operations + -- this now means that the full `Tree` API can now be used in proofs, + including sub-tree operations, folds and paginated lists + (#1625, #1663, #1683, @samoht, @Ngoguey42) + - Add `Tree.produce_stream` and `Tree.verify_stream` to produce and + verify stream proofs (#1684, #1692, #1691, @samoht, @Ngoguey42, @icristescu) + +- **irmin-pack** + - Verify inode depth invariants (#1665, @samoht) + +- **irmin-unix** + - Add `tezos` store type for `irmin` command-line (#1678, @zshipko) + +### Changed + +- **irmin** + - Remove `Tree.Proof.of_keys`. Use `Tree.produce_proof` instead + (#1625, @samoht) + - `Tree.empty` now takes a unit argument. (#1566, @CraigFe) + - `Tree.length` now takes a tree as argument (#1676, @samoht) + - `Tree.Proof.t` now uses a more precise datatype to encode value + invariants (#1688, @samoht) + +- **irmin-pack** + - irmin-pack: add an option to configure the index function and pick + the relevant bits in cryptographic a hash by default (#1677, @samoht) + +- **irmin-git** + - Require at least `git.3.7.0` in the codebase (#1637, @dinosaure) + +## 2.9.1 (2022-01-10) + +### Fixed + +- **irmin** + - Better support for s390x to workaround + https://github.com/ocaml/ocaml/issues/10857 (#1694, @icristescu) + +## 2.9.0 (2021-11-15) + +### Fixed + +- **irmin-pack** + - Improved the performance of Index encode and decode operations by + eliminating intermediate allocations (up to 5% fewer minor words + allocated) (#1577, @CraigFe) + - Reduce the number of backend nodes built during export + (up to 20% fewer minor words allocated) (#1553, @Ngoguey42) + +### Added + +- **irmin** + - Add Merkle Proofs and expose function to convert a proof to and from a tree. + Once converted, normal tree operations can be performed on the proof, as + long at it access values contained in the proof. + (#1583, @samoht, @Ngoguey42, @icristescu) + +### Changed + +- **irmin-pack** + - Limit inode depth (#1596, #samoht) + - Adapt to index 1.5.0 (#1593, @icristescu) + +## 2.8.0 (2021-10-15) + +### Fixed + +- **irmin** + - `Tree` operations now raise a `Dangling_hash` exception when called with a + path that contains dangling hashes in the underlying store, rather than + interpreting such paths as ending with empty nodes (#1477, @CraigFe) + - Fix the pre-hashing function for big-endian architectures. (#1505, + @Ngoguey42, @dinosaure) + - Fix a bug in `Tree.export` where nodes could be exported before + some of their contents, resulting in indirect hashes in irmin-pack + (#1508, @Ngoguey42) + +### Added + +- **irmin** + - `Node.seq` and `Node.of_seq` are added to avoid allocating intermediate + lists when it is not necessary (#1508, @samoht) + - New optional `cache` parameter to `Tree.hash`, `Tree.Contents.hash`, + `Tree.list`, `Node.list`, `Node.seq` and `Node.find` to control the storing + of lazily loaded data (#1526, @Ngoguey42) + - Add `Node.clear` to clear internal caches (#1526, @Ngoguey42) + - Added a `tree` argument to `Tree.fold` to manipulate the subtrees (#1527, + @icristescu, @Ngoguey42) + - Add a function `Store.Tree.pruned` for building purely in-memory tree + objects with known hashes. (#1537, @CraigFe) + - Added a `order` argument to specify the order of traversal in `Tree.fold` + (#1548, @icristescu, @CraigFe) + +### Changed + +- **irmin** + - `Node.v` is renamed to `Node.of_list` (#1508, @samoht) + - Rewrite `Tree.export` in order to minimise the memory footprint. + (#1508, @Ngoguey42) + - Remove the ``~force:`And_clear`` case parameter from `Tree.fold`, + ``~force:`True ~cache:false`` is the new equivalent. (#1526, @Ngoguey42) + - `` `Tree.fold ~force:`True`` and `` `Tree.fold ~force:`False`` don't + cache the lazily loaded data any more. Pass `~cache:true` to enable it + again. (#1526, @Ngoguey42) + - Do not allocate large lists in `Irmin.Tree.clear` (#1515, @samoht) + +- **irmin-git** + - Upgrade `irmin-git` to `git.3.5.0`. (#1495, @dinosaure) + +## 2.7.2 (2021-07-20) + +### Added + +- **irmin-pack** + - Added `integrity-check-index` command in `irmin-fsck`. (#1480, #1487 + @icristescu, @samoht) + +### Changed + +- **irmin-pack** + - `reconstruct_index` is now `traverse_pack_file`, it allows for both index + reconstruction and index checking (#1478, @Ngoguey42) + +## 2.7.1 (2021-07-02) + +### Fixed + +- **irmin-pack** + - Fix termination condition of reconstruct index (#1468, @Ngoguey42) + +## 2.7.0 (2021-06-22) + +### Fixed + +- **irmin** + - Added `Store.Tree.length`. (#1316, @Ngoguey42) + - Fixed fold for non-persisted, cleared trees (#1442, @samoht, @Ngoguey42) + +- **irmin-layers** + - Do not fail on double-close errors for private nodes (#1421, @samoht) + +- **irmin-pack** + - Do not clear and bump the generation for empty files (#1420, @samoht) + +### Added + +- **irmin-pack** + - Added `Irmin_pack.Version.{V1,V2}` modules for convenience. (#1457, + @CraigFe) + - Added a `irmin-pack.mem` package (#1436, @icristescu, @craigfe) + +- **irmin-graphql** + - Added `last_modified` field to GraphQL interface (#1393, @kluvin) + +### Changed + +- **irmin-layers** + - Remove `copy_in_upper` from the repo configuration. The default is now to + copy. (#1322, @Ngoguey42) + - Simplify the API of `freeze`. It is now possible to specify two distinct + commit closures for the copy to lower and the copy to next upper. + (#1322, @Ngoguey42) + - Renamed `Irmin_layered_pack.Make` and Irmin_layers.Make` into + `Irmin_layered_pack.Maker` and `Irmin_layers.Maker` (#1369, @samoht) + - Renamed `Irmin_layered_pack.Make_ext` and and Irmin_layers.Make_ext` into + into `Irmin_layered_pack.Maker_ext` and `Irmin_layers.Maker_ext` + (#1369, @samoht) + - Renamed `Irmin_layered_pack.Config` into `Irmin_layered_pack.Conf` + (#1370, @samoht) + - Readonly instances can check for an ongoing freeze (#1382, @icristescu, + @Ngoguey42) + +- **irmin-pack** + - It is no longer possible to modify an `inode` that doesn't point to the root + of a directory. (#1292, @Ngoguey42) + - When configuring a store, is it no longer possible to set `entries` to a + value larger than `stable_hash`. (#1292, @Ngoguey42) + - Added number of objects to the output of `stat-pack` command in + `irmin-fsck`. (#1311, @icristescu) + - Renamed the `Version` module type into `Version.S` and `io_version` into + `version`. The `Pack.File` and `Atomic_write` functors now take + `Version` as their first parameter (#1352, @samoht) + - Renamed `Irmin_pack.Make` into `Irmin_pack.V1` (#1369, @samoht) + - Renamed `Irmin_pack.Config` into `Irmin_pack.Conf` (#1370, @samoht) + - Renamed `Irmin_pack.Pack` into `Irmin_pack.Content_addressable` and + `Irmin_pack.Pack.File` into `Irmin_pack.Content_addressable.Maker` + (#1377, @samoht) + - Moved `Irmin_pack.Store.Atomic_write` into its own module (#1378, @samoht) + - `Checks.Reconstruct_index.run` now takes an optional `index_log_size` + parameter for customising the interval between merges during + reconstruction. (#1459, @CraigFe) + +## 2.6.1 (2021-04-29) + +This release contains 2.6.0 plus the changes described in 2.5.4. + +## 2.6.0 (2021-04-13) + +** Note: this release is based on 2.5.3, and does not contain 2.5.4. Use 2.6.1 +for access to those changes. ** + +### Fixed + +- **irmin** + - Fix stack overflow exception when working with wide trees (#1313, @zshipko) + + - `Tree.of_concrete` now prunes empty subdirectories, and raises + `Invalid_argument` if the input contains duplicate bindings. (#1385, + @CraigFe) + +- **irmin-chunk** + - Use the pre_hash function to compute entry keys instead of + their raw binary representation (#1308, @samoht) + +### Changed + +- **irmin-git** + - Upgrade `irmin-git` with `git.3.4.0`. (#1392, @dinosaure) + +## 2.5.4 (2021-04-28) + +### Fixed + +- **irmin-pack** + - Revert a patch introduced in 2.3.0 which was calling `Index.try_merge`. + This function was supposed to hint index to schedule merges after + every commit. However, `Index.try_merge` is buggy and stacks merges + which causes the node to block and wait for any existing merge to + complete. We will revisit that feature in future once we fix + `Index.try_merge` (#1409, @CraigFe) + +- **irmin** + - Fix peformance issue in `Tree.update_tree` and `Tree.add_tree` for + large directories (#1315, @Ngoguey42) + +### Added + +- **irmin-pack** + - Expose internal inode trees (#1273, @mattiasdrp, @samoht) + +## 2.5.3 (2021-04-13) + +### Fixed + +- **irmin** + - Fixed a bug causing equality functions derived from `Store.tree_t` to return + false-negatives. (#1371, @CraigFe) + +### Added + +- **irmin** + - Added `Store.Tree.is_empty`. (#1373, @CraigFe) + +## 2.5.2 (2021-04-08) + +### Fixed + +- **irmin** + - The `Tree.update_tree` and `Tree.add_tree` functions now interpret adding + an empty subtree as a remove operation, rather than adding an empty + directory. (#1335, @craigfe) + +- **irmin-pack** + - Fixed a performance regression where all caches were always cleaned by + `Store.sync` when using the V1 format (#1360, @samoht) + +## 2.5.1 (2021-02-19) + +- **irmin-git** + - Use the last version of git 3.3.0. It fixes a bug about trailing LF on + message. For Irmin users, it should not change anything (#1301, @dinosaure, + @CraigFe) + +## 2.5.0 (2021-02-16) + +### Changed + +- **irmin** + - `Store.Tree.remove` is now much faster when operating on large directories. + The commits following removals are also much faster. (#1289, @Ngoguey42) + + - Changed `Store.Tree.{of_hash, shallow}` to take kinded hashes, allowing the + creation of unforced contents values. (#1285, @CraigFe) + + - Changed `Tree.destruct` to return _lazy_ contents values, which may be forced + with `Tree.Contents.force`. (#1285, @CraigFe) + +- **irmin-bench** + - New features in benchmarks for tree operations (#1269, @Ngoguey42) + +## 2.4.0 (2021-02-02) + +### Fixed +- **irmin-pack** + - Fix a bug in `inode` where the `remove` function could cause hashing + instabilities. No user-facing change since this function is not being used + yet. (#1247, @Ngoguey42, @icristescu) + +- **irmin** + - Ensure that `Tree.add_tree t k v` complexity does not depend on `v` size. + (#1267, @samoht @Ngoguey42 and @CraigFe) + +### Added + +- **irmin** + - Added a `Perms` module containing helper types for using phantom-typed + capabilities as used by the store backends. (#1262, @CraigFe) + + - Added an `Exported_for_stores` module containing miscellaneous helper types + for building backends. (#1262, @CraigFe) + + - Added new operations `Tree.update` and `Tree.update_tree` for efficient + read-and-set on trees. (#1274, @CraigFe) + +- **irmin-pack**: + - Added `integrity-check-inodes` command to `irmin-fsck` for checking the + integrity of inodes. (#1253, @icristescu, @Ngoguey42) + +- **irmin-bench** + - Added benchmarks for tree operations. (#1237, @icristescu, @Ngoguey42, + @Craigfe) + +#### Changed + +- The `irmin-mem` package is now included with the `irmin` package under the + library name `irmin.mem`. It keeps the same top-level module name of + `Irmin_mem`. (#1276, @CraigFe) + +#### Removed + +- `Irmin_mem` no longer provides the layered in-memory store `Make_layered`. + This can be constructed manually via `Irmin_layers.Make`. (#1276, @CraigFe) + +## 2.3.0 (2021-01-12) + +### Fixed + +- **irmin-git** + - Update `irmin` to the last version of `ocaml-git` (#1065) + It fixes an issue on serialization/deserialization of big tree object + (see #1001) + +- **irmin-pack*** + - Fix a major bug in the LRU which was never used (#1035, @samoht) + +- **irmin*** + - Improve performance of `last_modified` (#948, @pascutto) + + - Changed the pattern matching of the function `last_modified`. The case of a + created key is now considered a modification by the function. (#1167, + @clecat) + + - Make Tree.clear tail-recursive (#1171, @samoht) + + - Fix `Tree.fold ~force:(False f)` where results where partially skipped + (#1174, @Ngoguey42, @samoht and @CraigFe ) + + - Fix `Tree.kind`. Empty path on a tree used to return a None instead of a + `` `Node``. (#1218, @Ngoguey42) + +- **ppx_irmin** + - Fix a bug causing certain type derivations to be incorrect due to unsound + namespacing. (#1083, @CraigFe) + +- **irmin-unix** + - Update irmin config path to respect `XDG_CONFIG_HOME`. (#1168, @zshipko) + +### Added + +- **irmin-layers** (_new_): + - Created a new package, `irmin-layers` that includes common signatures for + layered stores. It contains a stub `Make_layers` functor (#882, @icristescu) + +- **irmin-bench** (_new_): + - Created a new package to contain benchmarks for Irmin and its various + backends. (#1142, @CraigFe) + - Added ability to get json output and a make target to run layers benchmark. + (#1146, @gs0510) + +- **irmin** + - Added `Tree.Contents` module exposing operations over lazy tree contents. + (#1022 #1241, @CraigFe @samoht) + + - Added `Type.Unboxed.{encode_bin,decode_bin,size_of}` to work with unboxed + values (#1030, @samoht) + + - Remove the `headers` option in `Type.{encode_bin,decode_bin,size_of}`. Use + `Type.Unboxed.` instead (#1030, @samoht) + + - `Type.v` now takes an extra mandatory `unit` argument (#1030, @samoht) + + - Added `Type.pp_dump`, which provides a way to pretty-print values with a + syntax almost identical to native OCaml syntax, so that they can easily be + copy-pasted into an OCaml REPL for inspection. (#1046, @liautaud) + + - Generic functions in `Irmin.Type` are now more efficient when a partial + closure is constructed to the type representation (#1030 #1093, @samoht + @CraigFe). To make this even more explicit, these functions are now staged + and `Type.{unstage,stage}` can manipulate these. The goal is to encourage + users to write this kind of (efficent) pattern: + ```ocaml + let encode_bin = Type.(unstage (encode_bin ty)) + let _ = ... encode_bin foo ... + ``` + - Added a `clear` function for stores (#1071, @icristescu, @CraigFe) + + - Requires digestif>=0.9 to use digestif's default variants + (#873, @pascutto, @samoht) + + - Added `iter_commits` and `iter_nodes` functions to traverse the commits and + nodes graphs (#1077, @icristescu) + + - Added `Repo.iter` to traverse object graphs (#1128, @samoht) + +- **irmin-pack**: + - Added `index_throttle` option to `Irmin_pack.config`, which exposes the + memory throttle feature of `Index` in `Irmin-Pack`. (#1049, @icristescu) + + - Added `Pack.clear` and `Dict.clear` (#1047, @icristescu, @CraigFe, @samoht) + + - Added a `migrate` function for upgrading stores with old formats (#1070, + @icristescu, @CraigFe) + + - Added a `flush` function for a repo (#1092, @icristescu) + + - Added `Layered.Make functor, to construct layered stores from irmin-pack. + (#882, @icristescu) + + - Added `Checks.Make which provides some offline checks for irmin-pack + stores. (#1117, @icristescu, @CraigFe) + + - Added `reconstruct_index` to reconstruct an index from a pack file. (#1097, + @icristescu) + + - Added `reconstruct-index` command to `irmin-fsck` for reconstructing an index from + the command line (#1189, @zshipko) + + - Added `integrity-check` command to `irmin-fsck` for checking the integrity of + an `irmin-pack` store (#1196, @zshipko) + +- **ppx_irmin**: + + - Added support for deriving type representations for types with type + parameters. Type `'a t` generates a representation of type + `'a Type.t -> 'a t Type.t` (#1085, @CraigFe) + + - Added a `--lib` command-line option which has the same behaviour as the + `lib` run-time argument (i.e. `--lib Foo` will cause `ppx_irmin` to derive + type representations using combinators in the `Foo` module). (#1086, + @CraigFe) + + - Added an extension point `[typ: ]` for deriving type + representations inline. (#1087, @CraigFe) + +### Changed + +- **irmin** + - Renamed the `Tree.tree` type to `Tree.t`. (#1022, @CraigFe) + + - Replaced `Tree.pp_stats` with the type representation `Tree.stats_t`. (#TODO, @CraigFe) + + - Changed the JSON encoding of special floats. `Float.nan`, `Float.infinity` + and `Float.neg_infinity` are now encoded as `"nan"`, `"inf"` and `"-inf"` + respectively. (#979, @liautaud) + + - The functions `Type.{v,like,map}` no longer take a `~cli` argument, and now + take separate `~pp` and `~of_string` arguments instead. (#1103, @CraigFe) + + - The `Irmin.Type` combinators are now supplied by the `repr` package. The + API of `Irmin.Type` is not changed. (#1106, @CraigFe) + + - `Irmin.Type` uses staging for `equal`, `short_hash` and `compare` to + speed-up generic operations (#1130, #1131, #1132, @samoht) + + - Make `Tree.fold` more expressive and ensure it uses a bounded memory + (#1169, @samoht) + + - Changed `list` and `Tree.list` to take optional `offset` and `length` + arguments to help with pagination. Also return direct pointers to the + subtrees to speed up subsequent accesses (#1241, @samoht, @zshipko, + @CraigFe, @Ngoguey42 and @icristescu) + +- **irmin-pack**: + - `sync` has to be called by the read-only instance to synchronise with the + files on disk. (#1008, @icristescu) + + - Renamed `sync` to `flush` for the operation that flushes to disk all buffers + of a read-write instance. (#1008, @icristescu) + + - Changed the format of headers for the files on disk to include a generation + number. Version 1 of irmin-pack was used for the previous format, version 2 + is used with the new format. (#1047, @icristescu, @CraigFe, @samoht) + + - Use `Repo.iter` to speed-up copies between layers (#1149, #1150 @samoht) + + - Add an option to bypass data integrity checks on reads (#1154, @samoht) + + - Add `heads` parameter to `check-self-contained` command in `Checks` (#1224, @zshipko) + +- **ppx_irmin**: + + - The `[@generic ...]` attribute has been renamed to `[@repr ...]`. (#1082, + @CraigFe) + +## 2.2.0 (2020-06-26) + +### Added + +- **irmin**: + - Added `Irmin.Type.empty` to represent an uninhabited type. (#961, @CraigFe) + - Added `Store.Tree.concrete_t`. (#1003, @CraigFe) + +- **irmin-containers** (_new_): + - Created a new package, `irmin-containers`, which provides a set of simple + mergeable datastructures implemented using Irmin. (#1014, @ani003) + +- **ppx_irmin** + - Added support for the `@nobuiltin` attribute, which can be used when + shadowing primitive types such as `unit`. See `README_PPX` for details. + (#993, @CraigFe) + + - Added support for a `lib` argument, which can be used to supply primitive + type representations from modules other than `Irmin.Type`. (#994, @CraigFe) + +### Changed + +- **irmin**: + - Require OCaml 4.07 (#961, @CraigFe) + - Add sanity checks when creating `Irmin.Type` records, variants and enums + (#956 and #966, @liautaud): + - `Irmin.Type.{sealr,sealv,enum}` will now raise `Invalid_argument` if two + components have the same name; + - `Irmin.Type.{field,case0,case1}` will now raise `Invalid_argument` if + the component name is not a valid UTF-8 string. + - Changed the JSON encoding of options and unit to avoid ambiguous cases + (#967, @liautaud): + - `()` is now encoded as `{}`; + - `None` is now encoded as `null`; + - `Some x` is now encoded as `{"some": x}`; + - Fields of records which have value `None` are still omitted; + - Fields of records which have value `Some x` are still unboxed into `x`. + + - Changed pretty-printing of Irmin types to more closely resemble OCaml types. + e.g. `pair int string` prints as `int * string`. (#997, @CraigFe) + + - The type `Irmin.S.tree` is now abstract. The previous form can be coerced + to/from the abstract representation with the new functions + `Irmin.S.Tree.{v,destruct}` respectively. (#990, @CraigFe) + +- **irmin-mem** + - Stores created with `KV` now expose their unit metadata type. (#995, + @CraigFe) + +### Fixed + +- **irmin-graphql** + - Fixed an issue with keys inside `get_{contents,tree}` fields having + incorrect ordering (#989, @CraigFe) + +## 2.1.0 (2020-02-01) + +### Added + +- **ppx_irmin** (_new_): + - Created a new package, `ppx_irmin`, which provides a PPX deriving plugin + for generating Irmin generics. + +- **irmin-unix**: + - Added a `--hash` parameter to the command-line interface, allowing the hash + function to be specified. For BLAKE2b and BLAKE2s, the bit-length may be + specified with a trailing slash, as in `--hash=blake2b/16`. The `hash` + function may also be specified in the configuration file. (#898, @craigfe) + +- **irmin**: + - Added `Irmin.Hash.Make_BLAKE2B` and `Irmin.Hash.Make_BLAKE2S` functors for + customizing the bit-length of these hash functions. (#898, @craigfe) + - Added `iter` function over a closure graph (#912, @ioana) + - Added `Type.pp_ty` for pretty-printing Irmin generics. (#926, @craigfe) + - Added `Merge.with_conflict` for modifying the conflict error message of a + merge function. (#926, @craigfe) + +### Changed + +- **irmin-pack**: + - Changed the bit-length of serialized hashes from 60 to 30. (#897, + @icristescu) + - `integrity_check` can now try to repair corrupted values. (#947, @pascutto) + +- **irmin-graphql**: + - Changed default GraphQL type names to ensure uniqueness. (#944, @andreas) + +## 2.0.0 + +### Added + +- **irmin-pack** (_new_): + - Created a new Irmin backend, `irmin-pack`, which uses a space-optimised + on-disk format. + +- **irmin-graphql** (_new_): + - Created a new package, `irmin-graphql`, which provides a GraphQL server + implementation that can be used with both the MirageOS and Unix backends. + Additionally, a `graphql` command has been added to the command-line + interface for starting `irmin-graphql` servers. (#558, @andreas, @zshipko) + + - Contents can now be queried directly using `irmin-graphql` with + `Irmin_graphql.Server.Make_ext` and the `Irmin_graphql.Server.PRESENTER` + interface. (#643, @andreas) + +- **irmin-test** (_new_): + - Added a new package, `irmin-test`, which allows for packages to access the + Irmin test-suite. This package can now be used for new packages that + implement custom backends to test their implementations against the same + tests that the core backends are tested against. (#508, @zshipko) + +- **irmin-unix**: + - Add `Cli` module to expose some methods to simplify building command-line + interfaces using Irmin. (#517, @zshipko) + + - Add global config file `$HOME/.irmin/config.yml` which may be overridden by + either `$PWD/.irmin.yml` or by passing `--config `. See `irmin help + irmin.yml` for details. (#513, @zshipko) + +- **irmin-git**: + - Allow import/export of Git repositories using Irmin slices. (#561, @samoht) + +- **irmin-http**: + - Expose a `/trees/merge` route for server-side merge operations. (#714, + @samoht) + +- **irmin**: + - Add `Json_value` and `Json` content types. (#516 #694, @zshipko) + + - Add optional seed parameter to the `Irmin.Type` generic hash functions. + (#712, @samoht) + + - Add `V1` submodules in `Commit`, `Contents` and `Hash` to provide + compatibility with 1.x serialisation formats. (#644 #666, @samoht) + + - Add `Store.last_modified` function, which provides a list of commits where + the given key was modified last. (#617, @pascutto) + + - Add a `Content_addressable.unsafe_add` function allowing the key of the new + value to be specified explicitly (for performance reasons). (#783, @samoht) + + - Add `save_contents` function for saving contents to the database. (#689, + @samoht) + + - Add pretty-printers for the results of Sync operations. (#789, @craigfe) + + - `Private.Lock` now exposes a `stats` function returning the number of held + locks. (#704, @samoht) + +### Changed + +- **irmin-unix**: + - Rename `irmin read` to `irmin get` and `irmin write` to `irmin set`. (#501, + @zshipko) + + - Switch from custom configuration format to YAML. (#504, @zshipko) + +- **irmin-git**: + - Require `ocaml-git >= 2.0`. (#545, @samoht) + + - Cleanup handling of remote stores. (#552, @samoht) + +- **irmin-http**: + - Rename `CLIENT` to `HTTP_CLIENT` and simplify the signatures necessary to + construct HTTP clients and servers. (#701, @samoht) + +- **irmin-mirage** + - Split `irmin-mirage` into `irmin-{mirage,mirage-git,mirage-graphql}` to + allow for more granular dependency selection. Any instances of + `Irmin_mirage.Git` should be replaced with `Irmin_mirage_git`. (#686, + @zshipko) + +- **irmin**: + - Update to use dune (#534, @samoht) and opam 2.0. (#583, @samoht) + + - Replace `Irmin.Contents.S0` with `Irmin.Type.S`. + + - Rename `Type.pre_digest` -> `Type.pre_hash` and `Type.hash` -> + `Type.short_hash`. (#720, @samoht) + + - Change `Irmin.Type` to use _incremental_ hash functions (functions of type + `'a -> (string -> unit) -> unit`) for performance reasons. (#751, @samoht) + + - Simplify the `Irmin.Type.like` constructor and add a new `Irmin.Type.map` + with the previous behaviour. + + - Improvements to `Irmin.Type` combinators. (#550 #538 #652 #653 #655 #656 + #688, @samoht) + + - Modify `Store.set` to return a result type and create a new `Store.set_exn` + with the previous exception-raising behaviour. (#572, @samoht) + + - Rename store module types to be more descriptive: + - replace `Irmin.AO` with `Irmin.CONTENT_ADDRESSABLE_STORE`; + - replace `Irmin.AO_MAKER` with `Irmin.CONTENT_ADDRESSABLE_STORE_MAKER`; + - replace `Irmin.RW` with `Irmin.ATOMIC_WRITE_STORE`; + - replace `Irmin.RW_MAKER` with `Irmin.ATOMIC_WRITE_STORE_MAKER`. (#601, + @samoht) + + - Rename `export_tree` to `save_tree` (#689, @samoht) and add an option to + conditionally clear the tree cache (#702 #725, @samoht). + + - Change hash function for `Irmin_{fs,mem,unix}.KV` to BLAKE2b rather than + SHA1 for security reasons. (#811, @craigfe) + + - Move `Irmin.remote_uri` to `Store.remote`, for stores that support remote + operations. (#552, @samoht) + + - Simplify the error cases of fetch/pull/push operations. (#684, @zshipko) + + - A `batch` function has been added to the backend definition to allow for + better control over how groups of operations are processed. (#609, @samoht) + + - A `close` function has been added to allow backends to close any held + resources (e.g. file descriptors for the `FS` backend). (#845, @samoht) + + - Simplify `Private.Node.Make` parameters to use a simpler notion of 'path' in + terms of a list of steps. (#645, @samoht) + + - Rename `Node.update` to `Node.add`. (#713, @samoht) + +### Fixed + +- **irmin-unix**: + - Fix parsing of commit hashes in `revert` command. (#496, @zshipko) + +- **irmin-git**: + - Fix `Node.add` to preserve sharing. (#802, @samoht) + +- **irmin-http**: + - Respond with a 404 if a non-existent resource is requested. (#706, @samoht) + +- **irmin**: + - Fix a bug whereby `S.History.is_empty` would return `true` for a store with + exactly one commit. (#865, @pascutto) + +### Removed + +- **irmin**: + - Remove `pp` and `of_string` functions from `Irmin.Contents.S` in favour of + `Irmin.Type.to_string` and `Irmin.Type.of_string`. + + - Remove `Bytes` content type. (#708, @samoht) + + - Remove `Cstruct` dependency and content type. If possible, switch to + `Irmin.Contents.String` or else use `Irmin.Type.map` to wrap the Cstruct + type. (#544, @samoht) + +## 1.4.0 (2018-06-06) + +- Add types for `Contents.hash`, `Tree.hash` and `Commit.hash` (#512, @samoht) +- `Tree.hash` and `Tree.of_hash` now work on leaf nodes. To do this, `Tree.hash` + has to return a more complex type (#512, @samoht) +- support for webmachine 0.6.0 (#505, @ansiwen) + +## 1.3.3 (2018-01-03) + +- complete support for OCaml 4.06 (#484, @samoht) +- support cohttp 1.0 (#484, @samoht) + +## 1.3.2 (2017-11-22) + +- support OCaml 4.06 where `-safe-string` is enabled by default (#477, @djs55) + +## 1.3.1 (2017-08-25) + +- irmin-http: update to cohttp.0.99 (#467, @samoht) + +## 1.3.0 (2017-07-27) + +**irmin-chunk** + +Add a new package: `irmin-chunk`, which was initially in a separate repository +created by @mounirnasrallah and @samoht and ported to the new Irmin API by +@g2p (#464) + +**irmin-unix** + +Re-add the `irmin` binary, the example application which used to be +installed by irmin-unix` before we switched to use `jbuilder` +(#466, @samoht -- reported by @ouenzzo and @dudelson) + +**irmin** + +That releases saw a nice series of patches to improve the performance of +`Irmin.Tree` contributed by the Tezos team: + +- Improve complexity of `Irmin.Tree` operations: on trivial benchmarks with + a lot of values, this patch introduces a 10-times speed-up + (#457, @OCamlPro-Henry) + +- Add missing equality for `Irmin.Type` primitives (#458, @OCamlPro-Henry) + +- Change the type of `Hash.digest` to also take a type representation + (#458, @OCamlPro-Henry) + +- add `Irmin.Type.{encode,decode}_cstruct` (#458, @OCamlPro-Henry) + +- remove `Irmin.Contents.RAW` (#458, @OCamlPro-Henry) + +- avoid unecessary serialization and deserialization when computing hashes + of cstructs (#459, @OCamlPro-Henry) + +- remove `{Type,Merge}.int` which might cause some issue on 32 bits platforms. + Intead use the more explicit (and portable) `{Type,Merge}.int32` or + `{Type,Merge}.int64` (#469, @samoht) + +## 1.2.0 (2017-06-06) + +This release changes the build system to use +[jbuilder](https://github.com/janestreet/jbuilder). By doing so, it introduces +two new packages: `irmin-mem` and `irmin-fs` -- containing `Irmin_mem` and +`Irmin_fs` respectively. That release also fixes a bunch of regressions +introduced in the big 1.0 rewrite. + +**all** + +- Use `jbuilder` (#444, @samoht) +- Use mtime 1.0 (#445, @samoht) + +**irmin** + +- Fix `Irmin.Contents.Cstruct`: pretty-print the raw contents, not the hexdump + (#442, @samoht) +- `Irmin.Hash.X.of_string` should not raise an exception on invalid hash + (#443, @samoht) + +**irmin-mem** + +- New package! Use it if you want to use the `Irmin_mem` module. + +**irmin-fs** + +- New package! Use it if you want to use the `Irmin_fs` module. + +**irmin-git** + +- Fix watches (#446, @samoht) + +## 1.1.0 (2017-04-24) + +**irmin** + +- Change the type of `S.Tree.find_tree` to return a `tree option` instead of + `tree`. This is a breaking API change but it let distinguish between + the empty and non-existent cases (#431, @samoht) +- Allow to specify branches in urls for fetch using the `url#branch` syntax + (#432, @samoht) +- Expose `Irmin.Merge.idempotent` for values with idempotent operations + (#433, @samoht) +- Add a `S.repo` type as an alias to the `S.Repo.t` (#436, @samoht) +- Fix regression in `S.Tree.diff` intoduced in the 1.0 release: nested + differences where reported with the wrong path (#438, @samoht) + +**irmin-unix** + +- Update to irmin.1.1.0 API changes (@samoht) + +**irmin-git** + +- Update to irmin.1.1.0 API changes (@samoht) + +## 1.0.2 (2017-03-27) + +**irmin** + +- Add a cstruct type combinator (#429, @samoht) +- Fix regression introduced in 1.0.1 on merge of base buffers (strings, + cstruct). For these types, updates are idempotent, e.g. it is fine + if two concurrent branches make the same update. (#429, @samoht) + +**irmin-unix** + +- Add irminconfig man page (#427, @dudelson) + +## 1.0.1 (2017-03-14) + +**irmin** + +- Default merge function should not assume idempotence of edits + (#420, @kayceesrk) +- Wrap the merge functions for pair and triple with the default case. + (#420, @kayceesrk) + +**irmin-unix** + +- Support all versions of cmdliner, 1.0.0 included (@samoht) + +## 1.0.0 (2017-02-21) + +Major API changes: + +- It is now simpler to define mergeable contents, using new + combinators to describe data-types (see `Type`). + +- The mutable views have been replaced by immutable trees, and made + first-class citizen in the API (see available `S.Tree`). + Transactions now only ensure snapshot isolation instead of full + serialisability. + +- Creating a store with default path and branch implementations + is now easier using the `KV` functors which just take one parameter: + the contents. + +- the backend and user-facing API are now totally independant (instead + of being half-included in each other in `irmin.0.*`), so that + backends have to implement the minimum set of functions to be + Irmin-compatible, and users can have many convenient high-level + functions when using the Irmin API. The backends implement + `AO` and `RW`, the frontend provides `S`. + +The package is also now split into 5 opam packages: `irmin`, irmin-git`, +`irmin-http`, `irmin-unix` and `irmin-mirage` with similarly named +`ocamlfind` libraries. + +More detailled changes: + +* use result type everywhere (#397, @samoht) +* use `Fmt` everywhere (#397, @samoht) +* rename `create` functions into `v` (#397, @samoht) + +**irmin** + +* [info] rename `Task` into `Info` to denote commit info (#397, @samoht) +* [info] remove `Task.uid` (#397, @samoht) +* [info] Commit messages are now plain strings (instead of a lists of + strings): change `Task.messages` into `Info.message`, take a string + instead of a list of strings as parameter and remove `Task.add` + (#397, @samoht) +* [info] change `Info.f` to only takes `unit` as argument. Previously + it was taken an `'a` which was used by the update functions. The + update functions now take a full `Info.f` function as parameter, + which should be less confusing (#397, @samoht) + +* [merge] replace the dependency to `mirage-tc` by a new internal module + `Type` using type-based combinators. This makes defining new mergeable + data-types much easier, especially records and variants (#397, @samoht) +* [merge] change [Merge.t] to be an abstract type (#397, @samoht) +* [merge] add [Merge.f] to transform a [Merge.t] value into a merge function + (#397, @samoht) +* [merge] add base merge combinators: `Merge.unit`, `Merge.bool`, + `Merge.char`, `Merge.int`, `Merge.int32`, `Merge.int64`, + `Merge.float` (#397, @samoht) +* [merge] simplify the type of `Merge.option`, `Merge.pair`, Merge.triple` and + `Merge.alist` (#397, @samoht) +* [merge] simplify and rename `Merge.MSet` into `Merge.MultiSet` (#397, @samoht) +* [merge] simplify and rename `Merge.set` into `Merge.Set` (#397, @samoht) +* [merge] rename `Merge.OP` into `Merge.Infix` and rename operators to + avoid name-clashing with other monads (#397, @samoht) +* [merge] remove the `path` argument from the merge functions (#397, @samoht) +* [merge] remove the need to defined a `Path` submodule in `Contents.S` + (#397, @samoht) +* [merge] add a (very simple at the moment) `Diff` module (#397, @samoht) + +* [api] read operations do not take a task parameter anymore (#397, @samoht) +* [api] write operations not take a full commit info instead of a confusing + `'a` parameter (#397, @samoht) +* [api] rename [Ref] into [Branch] (#397, @samoht) +* [api] replace `S.read` by `S.find` (#397, @samoht) +* [api] replace `S.read_exn` by `S.get` (#397, @samoht) +* [api] add `S.kind` to check the kind of store entries (files, directories) + (#397, @samoht) +* [api] remove the `View` functor, replaced by first-class support for + immutable trees `S.Tree` (#397, @samoht) +* [api] add `S.find_tree` to find immutable subtrees (#397, @samoht) +* [api] add `S.find_all` to find contents and metadat (#397, @samoht) +* [api] change `S.mem` to only check for contents, not subtree (#397, @samoht) +* [api] add `S.mem_tree` to check for subtrees (similar behavior to + `S.mem` in `irmin.0.*`) (#397, @samoht) +* [api] add `S.with_tree` for atomic update of subtrees. This + operation replaces `with_hrw_view`, but a weaker consistency + guarantee: instead of providing full seriasilabilty, `S.with_tree` + provides snapshot isolation, which is consistent enough for most of + the users. (#397, @samoht) +* [api] rename `S.update` into `S.set` and ensure that the operation is + atomic by using a combination of test-and-set and optimistic concurrency + control. (#397, @samoht) +* [api] change `S.remove` to ensure the operation is atomtic. +* [api] add `S.status` to mimick `git status`. (#397, @samoht) +* [api] remove all the `_id` suffixes. (#397, @samoht) +* [api] add `S.merge_with_commit` and `S.merge_with_branch` (#397, @samoht) +* [api] more precise return type for `S.Head.fast_forward` (#401, @samoht) +* [api] add `S.Commit`, `S.Branch` (#401, @samoht) +* [api] add `KV_MAKER` to ease the creation of store with string lists + as paths and strings as branches (#405, @samoht) + +* [backend] replace `RO.read` by `RO.find` (#397, @samoht) +* [backend] no more `RO.read_exn` (#397, @samoht) +* [backend] no more `RO.iter`, replaced by `RW.list` (#397, @samoht) +* [backend] replace `RW.update` by `RW.set` (#397, @samoht) +* [backend] rename `RW.compare_and_set` into `RW.test_and_set` (#397, @samoht) +* [backend] new `RW.watch`, `RW.watch_key` and `RW.unwatch` functions + to set-up low-level notifications (#397, @samoht) + +**irmin-git** + +- Adapt to `git.0.10.0` (#397, @samoht) +- Remove the `LOCK` modules (#397, @samoht) +- Rename `S.Internals` into `S.Git` (#397, @samoht) +- Rename `S.Internals.commit_of_id` into `S.Git.git_commit` (#397, @samoht) +- Add `S.Git.of_repo` to convert an Irmin repo into a Git repo (#397, @samoht) +- Add `S.Git.to_repo` to convert a Git repo into an Irmin repo (#397, @samoht) +- Expose `S.Git_mem.clear` and `S.Git_mem.clear_all` for in-memory Git + backends (#397, @samoht) +- Rename `Memory` into `Mem.Make` (#405, @samoht) +- Rename `FS` into `FS.Make` (#405, @samoht) +- Remove `CONTEXT` and fold it into `IO` (#405, @samoht) +- Add `Mem.KV` and `FS.KV` to ease creatin of store with default + implementations for branches and paths (#405, @samoht) +- Add `Mem.Ref` and `FS.Ref` access tags, remotes and other Git references + (#407, @samoht) +- Allow to set-up a custom `.git` path (#409, @samoht) + +**irmin-mirage** + +- Adapt to Mirage3 (@hannesm, @yomimono, @samoht) +- Rename the `Task` module into `Info` to reflect the core API changes +- Change `Info.f` to accept an optional `author` argument and a format + string as a message parameter (#261, #406 @samoht) +- Rename `Irmin_git` into `Git` (#405, @samoht) + +**irmin-http** + +- Remove the high-level HTTP API (#397, @samoht) +- Rewrite the low-level (backend) API using `ocaml-webmachine` (#397, @samoht) +- Add `KV` to ease creatin of store with default implementations for + branches and paths (#405, @samoht) + +**irmin-unix** + +- Rename `Irmin_unix.task` into `Irmin_unix.info` (#397, @samoht) +- Remove `LOCK` (#397, @samoht) +- Change `Irmin_unix.info` to take an optional `author` argument and accept + a format string as message parameter (#261, #406 @samoht) +- Rename `Irmin_fs` into `FS` (#405, @samoht) +- Rename `Irmin_git` into `Git` (#405, @samoht) +- Rename `Irmin_http` into `Http` (#405, @samoht) + +## 0.12.0 (2016-11-17) + +* Depends on irmin-watcher 0.2.0 to use portable file-system watches + (fsevents on OSX or inotify on Linux) to replace the slow and CPU + intensive file-system polling that was the default (#380, @samoht) +* Do not use `Lwt_unix.fork` in the tests anymore (#383, @samoht) +* Switch from Stringext to Astring (#382, @samoht) +* Fix regression in the tests for using Git over HTTP (#376, @samoht) +* Catch top-level exceptions in watch callbacks (#375, @samoht) +* Fix merge of assoc list with no common ancestor (#374, @samoht) +* Improve documentation for Git bare repositories (#363, @kayceesrk) +* New functor `Make_with_metadata` to customize the type of the + nodes metadata (#364, @samoht) +* Remove mentions of private modules from the public interface + (#364, @samoht) + +## 0.11.1 (2016-06-14) + +* Fix compilation of examples (#359, @samoht) + +## 0.11.0 (2016-05-04) + +* Use Logs (#342, @talex5) +* Improve non-unix portablity of `Irmin_fs` (#345, @samoht) +* Change the signature of `Store.iter` to defer opening the + file only when needed. This was causing a file-descriptor + early exhaustion on Windows (#345, @samoht) +* Fix paths for references on Windows (#345, @samoht) +* Port to `ocaml-git` 1.8.0 +* Rather large API change in `Irmin.Private.Contents.Store` + and `Irmin.Private.Commit.Store` to make it easier to + build new and efficient Irmin backends. (#346, @samoht) +* Fix performance problem in the computation of LCAs (#351, @talex5) +* Fix sort order for Git trees (#352, @talex5) + +## 0.10.1 (2015-11-26) + +* Support for launchd: the `--address` argument of the CLI now + supports a URI `launchd://` where `` corresponds + to the section in the property list file (#321, by @djs55) +* Expose `/watch-rec` in the REST API (#326, by @samoht) +* Expose Store.Key = Contents.Path in Irmin.Maker. Otherwise, + the type of steps is abstract. (#327, by @talex5) + +## 0.10.0 (2015-10-14) + +* Fix the `Irmin_mem` backend to work when equal keys might be not + structurally equal (`Pervasives.(=)` is evil) +* Fix `Hash.SHA1.equal` to always return true when the underlying + bigarrays are equals. Before that, this was only the case when + the whole `Cstruct.t` where identical: ie. same bigarray but also + same offset in the `Cstruct.t` value, which is obviously not + always the case. Apply the same fix to `Hash.SHA1.compare` and + `Hash.SHA1.hash`. +* Renamed "tag" to "branch" in the API, as "tag" is confusing for Git + users. `BC.tag` is now `BC.name` and `BC.branch` is now `BC.head_ref`. + The various "Tag" modules are now called "Ref" ("Branch" would be + confusing here since they only store references to commits, not the + branch contents). + Note: The remote HTTP protocol still uses "tag". +* Remove `Irmin_http_server.listen`. Instead, return the Cohttp + configuration for the server and let the user perform the listen. The + resulting API is simpler (removes `timeout` and `uri` parameters), + more flexible, and easier to use from Mirage. +* Remove `Irmin.task` from API of internal stores (commit, node, etc). + Tasks are now passed explicitly to operations that need them, so it + is now explicit which operations create commits. For example, the + API now makes it clear that `lcas` doesn't change anything, while + `lca` requires a task because it may create commits. + Apart from simplifying the code, this change also makes it possible to + create the internal stores once, not once per commit message. + Note: this does not affect the main BC API, so most users will see no + difference. +* Remove `Irmin.Basic`. This was a functor that took a functor for making + stores and returned a functor for making stores with strings for + branch names and SHA1 for the hash. It's easier to write the + application out in full than to explain to people what it does. + This change also makes it possible for back-ends to provide extra + operations in a type-safe way. In particular, `Irmin_git.Internals` + has moved inside the store type and the runtime check that it is only + used with the correct store type is now enforced at compile time + instead. +* Removed `AO.config`. It was only used by the removed `Git.Internals` hack. +* Moved `AO.create` to `AO_MAKER`. +* Remove dummy functions that are no longer needed with the new API: + - `View.task` is gone (it never did anything). + - `View.create` is gone (it ignored both its arguments and called `View.empty`). + - `Ir_node.Graph.Store.create` (unused, but previously required by `AO`). + - `Ir_commit.History.Store.create` (same). +* Removed the unused-and-not-exported `Ir_bc.Make` and `Ir_bc.MAKER` + features. +* Combine `Ir_bc.STORE_EXT` and `Ir_s.STORE`. `Ir_s` was the only + consumer of the `Ir_bc.STORE_EXT` interface, and all it did was repack + the values to match its own interface. Now, `Ir_bc` exports the final + public API directly, which simplifies the code. +* Moved module types into `ir_s.mli` and removed `ir_s.ml`. + Before, all module types were duplicated in the .ml and .mli files. +* `BC` stores now contain a `Repo` module. A `Repo.t` represents a + repository as a whole, rather than any particular branch. Operations + which do not look at the current branch have been moved to this + module. They are: `branches`, `remove_branch`, `heads`, + `watch_branches`, `import`, `export`, and `task_of_head`. + When updating old code, you can use `BC.repo t` to get a `Repo.t` + from a branch. + Note that `heads` previously ensured that the current branch's head was + included in the returned set (which made a difference for anonymous + branches). This feature has been removed. In the future, the plan is + to use OCaml's GC to track which anonymous branches are still being + used and return all of them. +* The internal stores (commit, node, etc) used to implement a full `BC` + store are now created by the back-ends, not by `Ir_bc`. This allows + back-ends to use their own APIs for this. In particular, back-ends + can now share resources (such as a database connection) between + stores. Internal stores no longer need to deal with `config` values + at all. +* `Sync.create` now takes a `Repo.t`, not a `config`, allowing + `Repo.config` to be removed and allowing sharing of the back-end's + internal state with the sync code. For example, the Git back-end + no longer needs to create a new Git store object for sync. +* Change `type head` to `type commit_id`. `head` was confusing because + it applied to all commits, not just branch heads. Putting `id` in the + name makes it clear that this is just data and (for example) holding + an ID will not prevent the corresponding commit from being GC'd (once + we have GC). `of_head` is now `of_commit_id`, `task_of_head` is now + `task_of_commit_id`, `Internals.commit_of_head` is now + `Internals.commit_of_id` and `BC.Head` is now `BC.Hash`. + +## 0.9.10 (2015-10-01) + +* Expose the Git compression level (#104, #298 by @samoht) +* Add an optional `config` argument to all the backend's config + functions. This allow the backends to composed more easily. (initial + patch by @nasrallahmounir, integration by @samoht) +* Add signatures for immutable link store, to store links between + keys: `Irmin.LINK` and `Irmin.LINK_MAKER`. Add `Irmin_mem.Link` and + `Irmin_fs.Link` which implement `Irmin.LINK_MAKER` in these backends + (initial patch by @nasrallahmounir, integration by @samoht) +* Add signatures for raw values (ie. whose values are of type + `Cstruct.t`): `Irmin.RAW` and raw store maker: `Irmin.AO_MAKER_RAW` + (initial patch by @nasrallahmounir, integration by @samoht) +* Expose `Irmin.Hash.digest_size` (initial patch by @nasrallahmounir, + integration by @samoht) +* Expose `/view` to the REST API (#292, by @samoht) +* Expose `Irmin.Private.merge_node` (#292 by @samoht) +* Change the JSON stream API, which requres ezjsonm.0.4.2. (#266, #269, + #273 by @samoht) +* Fix a race when a lot of processes are trying to add a watch at the + same time. (#270, #271, by @samoht) +* Expose `Irmin_git.Irmin_value_store` functor. This provides the + Irmin Contents/Node/Commit APIs on top of a Git-type store. This is + useful for backends that want to store data using the Git object + format, to be able to sync with Git, but without using Git's + filesystem layout and locking. (#268 by @talex5) +* Remove the first-class module API. It's confusing to duplicate the API + (#293, by @talex5) + +## 0.9.9 (2015-08-14) + +* Allow raw bodies in queries and responses for the REST API. This is + controlled by the `Content-type` field set by the client: + by default, we still use JSON (or use `application/json`) but using + `application/octet-stream` will avoid having to hex-encode large + binary blobs to make them JSON-compatible. This feature is still + experimental (especially when using Git on the server) (#255) +* Adapt to `ocaml-git.1.7.1` (which works with `lwt.2.5.0`) +* Expose `Store.config` for all the stores (`AO`, `RW`, etc.) +* Expose `Irmin_git.Internals` to be able to get back the + Git commit objects from an `head` value (#245, #241) +* Expose `Irmin.Private.remove_node` +* Remove the special `__root__` filename in Irmin stores and in views + (#233) + - This fixes `View.update_path` when the view contains a value at its + root. Now the updated path contains a the value stored at the root + of the view. + - Writing a value to the root of a store is now an error + - Reading a value at the root of a store always return `None` +* Make the HTTP backend re-raise the `Invalid_argument` and `Failure` + exceptions that were raised by the server. + +## 0.9.8 (2015-07-17) + +* Fix wrong interaction of in-memory views and temporary branches in the store + (#237) +* Fix `Irmin.update_tag` for HTTP clients +* Initial MirageOS support. Expose `Mirage_irmin.KV_RO` to surface an + Irmin store as a read-only key/value store implementing `V1_LWT.KV_RO + (#107) +* Expose `Irmin_git.Memory_ext. This allows the Git memory backend to be + configured with a non-empty conduit context. +* Expose `Irmin.SYNC` +* Transmit client tasks to the HTTP server on DELETE too (#227, @dsheets) +* Do note expose private types in the public interface (#234, @koleini) +* Fix missing zero padding for date pretty-printing (#228, @dsheets) +* Update the tests to use `ocaml-git.1.6.0` +* Improve the style of the HTTP commit graph. +* Constraint the string tags to contain only alpha-numeric characters + and few mores (`-`, `_`, '.' and `/`) (#186) +* Fix a race condition in `Irmin.clone`. (#221) +* Escpate double quotes in the output of commit messages to workaround + HTML display issues. (#222) + +## 0.9.7 (2015-07-06) + +* Add a version check for HTTP client and server. The client might add the + version in the HTTP headers using the `X-IrminVersion` header - the server + might decide to enfore the version check or not. The server always reply + with its version in the JSON reply, using a `version` field. The client + might use that information to bail out nicely instead of failing because + of some random unmarshalling errors due to API changes (#167) +* Fix a regression in 0.9.5 and 0.9.6 when inserting new child in Git trees. + This could cause a tree to have duplicate childs having the same names, + which would confuse the merge functions, make `git fsck` and `git gc` + complain a lot (with good reasons) and do some fency things with git + index. The regression has been introduced while trying to fix #190 (the fix + is in #229) + +## 0.9.6 (2015-07-03) + +* Fix the datamodel: it is not possible to store data in intermediate nodes + anymore (#209) +* Fix serialization of slices (#204) +* Do not fail silently when the synchronisation fails (#202) +* Fix a race in the HTTP backend between adding a watch and updating the store. + In some cases, the watch callback wasn't able to see the first few updates + (#198) +* Fix a race for all the on-disk backends between adding a watch and updating + the store. This is fixed by making `Irmin.Private.Watch.listen_dir` and + `Irmin.Private.Watch.set_listen_dir_hook` synchronous. +* Update the tests to use `alcotest >= 0.4`. This removes the dependency towards + `OUnit` and `nocrypto` for the tests. +* Make the file-locking code a bit more robust + +## 0.9.5 (2015-06-11) + +* Fix `Irmin.export` for the HTTP backend (#196, patch from Alex Zatelepin) +* Fix a race in `Irmin.export` (#196, patch from Alex Zatelepin) +* Add `Task.empty` (the empty task) and `Task.none` (the empty task constructor) +* Completely rewrite the notification mechanism. All the watch functions now + take a callback as argument and return a de-allocation function. The callbacks + receive a heads values (the last and current ones) and diff values. (#187) + - Add `Irmin.watch_head` to watch for the changes of the current branch's head + - Add `Irmin.watch_tags` to watch for the changes of all the tags in the store + - Add `Irmin.watch_key` to watch for the changes of the values associated to a + given key (this is not recursive anymore). + - Add `View.watch_path` to watch for the changes in a subtree. The function + return views and the user can use `View.diff` to compute differences between + views if needed. +* Transfer the HTTP client task to the server to make the commit messages + relative to the client state (and not the server's) (#136) +* Fix `View.remove` to clean-up empty directories (#190) +* Fix the ordering of tree entries in the Git backend (#190) +* Allow to create a new head from a view and a list of parents with + `View.make_head` (#188) +* Allow to create an empty temporary branch with `Irmin.empty` (#161) +* Use a pure OCaml implementation of SHA1, do not depend on nocrypto anymore + (#183, by @talex5) +* Remove `Irmin.Snapshot`. Nobody was using it and it can be easily replaced by + `Irmin.head`, `Irmin.watch_head` and `Irmin.update_head`. +* Change signature of `Irmin.iter` to include the values and move it into + the `Irmin.RO` signature. +* Add `Irmin.fast_forward_head` (#172) +* Add `Irmin.compare_and_set_head` (#171) +* Simplify the RW_MAKER signature (#158) +* Fix Irmin_git.RW_MAKER (#159) +* Improve the efficiency of the LCA computation (#174, with @talex5 help) +* By default, explore the full graph when computing the LCAs. The previous + behavior was to limit the depth of the exploration to be 256 by default. + +## 0.9.4 (2015-03-16) + +* Ensure that `Irmin.update` and `Irmin.merge` are atomic. +* Fix `Irmin.clone` of an empty branch +* Add `Irmin.RW.compare_and_test` that the backends now have to implement + to guarantee atomicity of Irmin's high-level operations. +* Add `Irmin.Private.Lock` to provide per-handler, per-key locking. This + can be used by backend to implement simple locking policies. +* Add `Lwt.t` to the return type of `Irmin.tag` and `Irmin.tag_exn` +* Do not throw [Not_found]. Now all the `_exn` function raise `Invalid_argument` + (#144) +* Remove `Irmin.switch` and `Irmin.detach` +* Add `Irmin.history` to get the branch history as a DAG of heads (#140). +* Fix performance of lcas computation (#160) +* Add `Irmin.Merge.promise` combinators + +## 0.9.3 (2015-01-04) + +* Fix the invalidation of the view caches (report by @gregtatcam). + This was causing some confusing issues where views' sub-keys where + not properly updated to to their new values when the view is merged + back to the store. The issues is a regression introduced in 0.9.0. +* Add post-commit hooks for the HTTP server. +* Add `Irmin.watch_tags` to monitor tag creation and desctructions. +* Fix `Irmin.push` +* Add `Irmin.with_hrw_view` to easily use transactions. +* Add a phantom type to `Irmin.t` to denote the store capabilities + read-only, read-write or branch-consistent. +* The `~old` argument of a merge function can now be optional to + signify that there is no common ancestor. +* Expose `Irmin.with_rw_view` to create a temporary, in-memory and + mutable view of the store. This can be used to perform atomic + operations in the store (ie. non-persistent transactions). +* Simplify the view API again +* Expose the task of previous commits. This let the user access + the Git timestamp and other info such as the committer name (#90) +* The user-defined merge functions now takes an `unit -> 'a result + Lwt.t` argument for `~old` (instead of `'a`). Evalutating the + function will compute the least-common ancestors. Merge functions + which ignore the `old` argument don't have to pay the cost of + computing the lcas anymore. +* Expose `S.lca` to get the least common ancestors +* Update to ocaml-git 1.4.6 + +## 0.9.2 (2015-01-19) + +* Fix `S.of_head` for the HTTP client (regression introduced in 0.9.0) +* Fix regression in displaying the store's graph over HTTP introduced by + 0.9.0. +* Fix regression in watch handling introduced in 0.9.0. +* Fix regressions in `Views` introduced in 0.9.0. (thx @buzzheavyyear for + the report) +* Always add a commit when calling a update function (`Irmin.update` + `Irmin.remove`, `Irmin.remove_rec`) even if the contents' store have + not changed. +* The [head] argument of [Git_unix.config] now has a proper type. +* Expose synchronisation functions for basic Irmin stores. +* The user-provided merge function now takes optional values. The + function is now called much more often during recursive merges + (even if one of the 3 buckets of the 3-way merge function is not + filled -- in that case, it uses `None`). +* Also expose the type of the keys in the type basic Irmin stores. Use + `('key, 'value) Irmint.t` instead of `'value Irmin.t`. +* The user-defined `merge` functions now take the current filename being + merged as an additional argument. +* The user-defined `Contents` should expose a `Path` sub-module. Keys of + the resulting Irmin store will be of type `Path.t`. +* Fix `irmin init --help`. (#103) + +## 0.9.1 (2014-12-26) + +* Port to Cohttp 0.14.0+ HTTP interface (#102) + +## 0.9.0 (2014-12-20) + +* Improve the efficiency of the Git backend +* Expose a cleaner API for the Unix backends +* Expose a cleaner public API +* Rename `Origin` into `Task` and use it pervasively through the API +* Expose a high-level REST API over HTTP (#80) +* Fix the Git backend to stop constantly overwrite `.git/HEAD` (#76) +* Add a limit on concurrently open files (#93, #75) +* Add `remove_rec` to remove directories (#74, #85) +* Remove dependency to `core_kernel` (#22, #81) +* Remove dependency to `cryptokit and `sha1` and use `nocrypto` instead +* Remove dependency to caml4 +* Fix writing contents at the root of the store (#73) +* More efficient synchronization protocol between Irmin stores (#11) + +## 0.8.3 (2014-06-25) + +* Views now keep track of their parent commits - this makes + View.merge_path looks like a merge between branches. All the + view operations are squashed in a unique commit. +* Better graphs, where we only show the commit history (the + full graph is still available using `--full` on the + command-lineor or `?full=1` on the web interface) +* By default, do not call `dot` when dumping a graph on the + command-line. `dot` does not like big graphs, but that's + still useful to have the `.dot` file to analyze it. + +## 0.8.2 (2014-06-11) + +* Support backend specific protocols for push/pull +* The Irmin Git backend can now sync with remote Git repositories +* Simplify the organisation of the libraries: irmin, irmin.backend, + irmin.server and irmin.unix (check how the example are compiled) +* Small refactoring to ease the use of the API. Now use `open Irmin_unix` + at the top of your file and use less functor in your code (again, + check the examples) + +## 0.8.1 (2014-06-02) + +* Fix the behavior of `IrminMemory.Make` to return an hanlder to a + shared datastore instead of creating a fresh one. Add + `IrminMemory.Fresh` to return a fresh in-memory datastore maker. +* The HTTP server now outputs some nice graph (using dagre-d3). Don't + expect to display very large graphs +* More friendly tag names in the Git backend (no need to prefix + everything by `refs/heads/` anymore) +* Partial support for recursive stores (WIP) + +## 0.8.0 (2014-05-27) + +* Spring clean-ups in the API. Separation in IrminBranch for + fork/join operations, IrminSnapshot for snapshot/revert + operations and IrminDump for import/export operations. + The later two implementation can be derived automaticaly + from a base IrminBranch implementation. The update and merge + operations are supported on each backend +* IrminGit does not depend on unix anymore and can thus be + compile to javascript or xen with mirage +* No need to have bin_io converter for contents anymore +* No need to have JSON converter for contents anymore +* No more IrminDispatch +* Add an optional branch argument to Irmin.create to use + an already existing branch +* Fix order of arguments in Irmin.merge + +## 0.7.0 (2014-05-02) + +* Feature: support for in-memory transactions. They are built + on top of views. +* Feature: add support for views: these are temporary stores with + lazy reads + in-memory writes; they can be used to convert back + and forth an OCaml value into a store, or to have a fast stagging + area without the need to commit every operation to the store. +* Support custom messages in commit messages +* Improve the IrminMerge API +* Backend: add a 'dispatch' backend for combining multiple backends + into one. This can be used to have a P2P store where there is + well-defined mapping between keys and host (as a DHT). +* Fix: limit the number of simulteanous open files in the Git and + the file-system backend +* Speed-up the in-memory store +* Speed-up the import/export codepath +* Speed-up the reads +* Speed-up IrminValue.Mux +* Deps: use ocaml-sha instead of cryptokit + +## 0.6.0 (2014-04-12) + +* Support for user-defined contents (with custom merge operators) +* Support for merge operations +* Rename `IrminTree` to `IrminNode` to reflect the fact that we + can support arbitrary immutable graphs (it's better if they are + DAGs but that's not mandatory) +* Rename `IrminBlob` to `IrminContents` to reflect the fact that + we also support structured contents (as JSON objects) +* Support for linking the library without linking to camlp4 as well (#23) + +## 0.5.1 (2014-03-02) + +* Port to use Cohttp 0.10.0 interface. + +## 0.5.0 (2014-02-21) + +* More consistent support for notifications. `irmin watch` works + now for all backends. +* Support for different blob formats on the command-line +* Support for JSON blobs +* More flexible `irmin fetch` command: we can now choose the backend to + import the data in +* Fix import of Git objects when the blobs were not imported first +* Support non-UTF8 strings as path name and blob contents (for all + backends, including the JSON one) +* Speed-up the `slow` tests execution time +* Improve the output graph when objects of different kinds might have + the same SHA1 + +## 0.4 (2014-01-21) + +* The command-line tool now looks in the environment for the variable + `IRMIN` to configure its default backend +* Add a Git backend +* Add Travis CI scripts to the repo +* Use `Lwt_bytes` and `Lwt_unix` instead of the custom-made `IrminChannel` +* Use `bin_prot` instead of a custom binary protocol +* Major refactoring: `Value` is now `Blob`, `Revision` is now `Commit` + and `Tag` becomes `Reference` (rational: consistency with Git names) +* Use `core_kernel` instead of building a custom `Identiable.S` +* Use `dolog` instead of a custom log library +* Use `mstruct` (mutable buffers on top of `cstruct`) which is now + released independently + +## 0.3 (2013-12-13) + +* Fix a fd leak in the filesystem bakend +* Functorize the CRUD interface over the HTTP client implementation +* Use oasis to build the project +* Use the now released separately `ezjsonm` and `alcotest` libraries + +## 0.2 (2013-11-23) + +* Fix the HTTP server responses +* More high-level tests +* Add unit-tests for the client CRUD interfaces (over memory and/or filesystem) +* Fix issues with the Tree API +* Implement a relatively efficent Import/Export scheme (#3) +* For more safety, the marshalled values are now typed in the binary protocol +* Add functions to dump the contents of the store as a Graphviz graph +* Polish the CLI which now looks usable enough +* Optimize the CRUD backend by executing high-level API functions on the server +* Improve and make the CLI easier to use +* Implement clone/pull/push/snapshot/revert in the CLI + +## 0.1 (2013-10-30) + +* Use an HTTP server as a front-end +* Initial support for in-memory and filesystem backends +* Simple signature for backends +* Binary protocol for storing values and metadata and for future network exchange diff --git a/vendors/irmin/CONTRIBUTING.md b/vendors/irmin/CONTRIBUTING.md new file mode 100644 index 000000000000..1b0460986744 --- /dev/null +++ b/vendors/irmin/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contribute to Irmin + +## License + +Irmin is distributed under the ISC license. Every OCaml source file +should start with a header comment instantiating the following +template (use appropriate comment syntax for other languages): + +``` +(* + * Copyright (c) [year(s)] [Holder ] + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) +``` + +Note that: + +- The holder, on the copyright line, is the name of individual + contributors and/or their company; +- When adding a significant new contribution to a file (i.e. more like + whole new features, rather than simple fixes), check whether there + already is a copyright for your copyright holder (see above): + - If there is one, mentioning any year, it is not required to add + the current year (but this is allowed). In no case should you + replace the existing year with the current one. + - If there is no line for your copyright holder, you should add one, + with the current year. + +For example, for a source file with multiple contributors spanning +several years, the copyright lines may look as follows: + +``` +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2018-2022 Tarides + * +``` diff --git a/vendors/irmin/LICENSE.md b/vendors/irmin/LICENSE.md new file mode 100644 index 000000000000..68422c3dbd6a --- /dev/null +++ b/vendors/irmin/LICENSE.md @@ -0,0 +1,15 @@ +## ISC License + +Copyright (c) 2013-2017 Thomas Gazagnaire + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendors/irmin/Makefile b/vendors/irmin/Makefile new file mode 100644 index 000000000000..10b1525273cf --- /dev/null +++ b/vendors/irmin/Makefile @@ -0,0 +1,26 @@ +.PHONY: all clean test fuzz bench-pack bench doc examples + +all: + dune build + +test: + dune runtest + +bench-pack-with-trace-replay: + @dune exec -- ./bench/irmin-pack/tree.exe --mode trace /home/opam/bench-dir/current-bench-data/mirage/irmin/tezos_actions_1commit.repr --ncommits-trace 12000 --artefacts ./cb_artefacts 1>&2 + @dune exec -- ./bench/irmin-pack/trace_stats.exe cb ./cb_artefacts/stat_summary.json + @rm -rf ./cb_artefacts + +bench: bench-pack-with-trace-replay + +fuzz: + dune build @fuzz --no-buffer + +examples: + dune build @examples + +clean: + dune clean + +doc: + dune build @doc diff --git a/vendors/irmin/README.md b/vendors/irmin/README.md new file mode 100644 index 000000000000..6762605895e6 --- /dev/null +++ b/vendors/irmin/README.md @@ -0,0 +1,379 @@ +
+ + Irmin logo + +
+ A Distributed Database Built on the Same Principles as Git +
+ +
+
+ +[![OCaml-CI Build Status](https://img.shields.io/endpoint?url=https%3A%2F%2Fci.ocamllabs.io%2Fbadge%2Fmirage%2Firmin%2Fmain&logo=ocaml&style=flat-square)](https://ci.ocamllabs.io/github/mirage/irmin) +[![codecov](https://codecov.io/gh/mirage/irmin/branch/main/graph/badge.svg?token=n4mWfgURqT)](https://codecov.io/gh/mirage/irmin) +[![GitHub release (latest by date)](https://img.shields.io/github/v/release/mirage/irmin?style=flat-square&color=09aa89)](https://github.com/mirage/irmin/releases/latest) +[![docs](https://img.shields.io/badge/doc-online-blue.svg?style=flat-square)](https://mirage.github.io/irmin/) + +
+ +
+ +
+ + Irmin is an OCaml library for building mergeable, branchable distributed + data stores. + +
+ +
+ +Irmin is based on distributed version-control systems (DVCs), +extensively used in software development to enable developers to keep +track of change provenance and expose modifications in the source +code. Irmin applies DVC's principles to large-scale distributed data +and exposes similar functions to Git (clone, push, pull, branch, +rebase). It is highly customizable: users can define their types to +store application-specific values and define custom storage layers (in +memory, on disk, in a remote Redis database, in the browser, +etc.). The Git workflow was initially designed for humans to manage +changes within source code. Irmin scales this to hanlde automatic +programs performing a very high number of operations per second, with +a fully automated handling of update conflicts. Finally, Irmin exposes +an event-driven API to define programmable dynamic behaviours and to +program distributed dataflow pipelines. + +Irmin was created at the University of Cambridge in 2013 to be the +default storage layer for [MirageOS][] applications (both to store and +orchestrate unikernel binaries and the data that these unikernels are +using). As such, Irmin is not, strictly speaking, a complete database +engine. Instead, similarly to other MirageOS components, it is a +collection of libraries designed to solve different flavours of the +challenges raised by the [CAP Theorem][]. Each application +can select the right combination of libraries to solve its particular +distributed problem. + +Irmin consists of a core of well-defined low-level data structures +that specify how data should be persisted and be shared across +nodes. It defines algorithms for efficient synchronization of those +distributed low-level constructs. It also builds a collection of +higher-level data structures that developers can use without knowing +precisely how Irmin works underneath. Some of these components even +have a [formal semantics][], including [Conflict-free Replicated +Data-Types (CRDT)][]. Since it's a part of MirageOS, Irmin does not +make strong assumptions about the OS environment that it runs in. This +makes the system very portable: it works well for in-memory databases +and slower persistent serialization such as SSDs, hard drives, web +browser local storage, or even the Git file format. + +Irmin is primarily developed and maintained by [Tarides][], with +contributions from many [contributors][] from various +organizations. External maintainers and contributors are welcome. + +[MirageOS]: https://mirage.io +[CAP Theorem]: http://en.wikipedia.org/wiki/CAP_theorem +[formal semantics]: https://kcsrk.info/papers/banyan_aplas20.pdf +[Conflict-free Replicated Data-Types (CRDT)]: https://arxiv.org/abs/2203.14518 +[Tarides]: https://tarides.com +[contributors]: https://github.com/mirage/irmin/graphs/contributors + +
+ +* [Features](#Features) +* [Documentation](#Documentation) +* [Installation](#Installation) + * [Prerequisites](#Prerequisites) + * [Development Version](#Development-Version) +* [Usage](#Usage) + * [Example](#Example) + * [Command-line](#Commandline) +* [Context](#Context) + * * [Irmin as a portable and efficient structured key-value store](#Irmin-as-a-portable-and-efficient-structured-keyvalue-store) + * [Irmin as a distributed store](#Irmin-as-a-distributed-store) + * [Irmin as a dataflow scheduler](#Irmin-as-a-dataflow-scheduler) +* [Issues](#Issues) +* [License](#License) +* [Acknowledgements](#Acknowledgements) + +
+ +## Features + +- **Built-in Snapshotting** - backup and restore +- **Storage Agnostic** - you can use Irmin on top of your own storage layer +- **Custom Datatypes** - (de)serialization for custom data types, derivable via + [`ppx_irmin`][ppx_irmin-readme] +- **Highly Portable** - runs anywhere from Linux to web browsers and Xen unikernels +- **Git Compatibility** - `irmin-git` uses an on-disk format that can be + inspected and modified using Git +- **Dynamic Behavior** - allows the users to define custom merge functions, + use in-memory transactions (to keep track of reads as well as writes) and + to define event-driven workflows using a notification mechanism + +## Documentation + +API documentation can be found online at [https://mirage.github.io/irmin](https://mirage.github.io/irmin) + +## Installation + +### Prerequisites + +Please ensure to install the minimum `opam` and `ocaml` versions. Find the latest +version and install instructions on [ocaml.org](https://ocaml.org/docs/install.html). + +To install Irmin with the command-line tool and all unix backends using `opam`: + + +```bash + opam install irmin-cli +``` + +A minimal installation containing the reference in-memory backend can be +installed by running: + + +```bash + opam install irmin +``` + +The following packages have are available on `opam`: + +- `irmin` - the base package, plus an in-memory storage implementation +- `irmin-chunk` - chunked storage +- `irmin-cli` - a simple command-line tool +- `irmin-fs` - filesystem-based storage using `bin_prot` +- `irmin-git` - Git compatible storage +- `irmin-graphql` - GraphQL server +- `irmin-http` - a simple REST interface +- `irmin-mirage` - mirage compatibility +- `irmin-mirage-git` - Git compatible storage for mirage +- `irmin-mirage-graphql` - mirage compatible GraphQL server +- `irmin-pack` - compressed, on-disk, posix backend +- `ppx_irmin` - PPX deriver for Irmin content types (see [README_PPX.md][ppx_irmin-readme]) +- `irmin-containers` - collection of simple, ready-to-use mergeable data structures + +To install a specific package, simply run: + + +```bash + opam install +``` + +### Development Version + +To install the development version of Irmin in your current `opam switch`, clone +this repository and `opam install` the packages inside: + + +```bash + git clone https://github.com/mirage/irmin + cd irmin/ + opam install . +``` + +## Usage + +### Example + +Below is a simple example of setting a key and getting the value out of a +Git-based, filesystem-backed store. + + +```ocaml +open Lwt.Syntax + +(* Irmin store with string contents *) +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) + +(* Database configuration *) +let config = Irmin_git.config ~bare:true "/tmp/irmin/test" + +(* Commit author *) +let author = "Example " + +(* Commit information *) +let info fmt = Irmin_git_unix.info ~author fmt + +let main = + (* Open the repo *) + let* repo = Store.Repo.v config in + + (* Load the main branch *) + let* t = Store.main repo in + + (* Set key "foo/bar" to "testing 123" *) + let* () = + Store.set_exn t ~info:(info "Updating foo/bar") [ "foo"; "bar" ] + "testing 123" + in + + (* Get key "foo/bar" and print it to stdout *) + let+ x = Store.get t [ "foo"; "bar" ] in + Printf.printf "foo/bar => '%s'\n" x + +(* Run the program *) +let () = Lwt_main.run main +``` + +The example is contained in [examples/readme.ml](./examples/readme.ml) It can +be compiled and executed with dune: + + +```bash +$ dune build examples/readme.exe +$ dune exec examples/readme.exe +foo/bar => 'testing 123' +``` + +The [examples](./examples/) directory also contains more advanced examples, +which can be executed in the same way. + +### Command-line + +The same thing can also be accomplished using `irmin`, the command-line +application installed with `irmin-cli`, by running: + +```bash +$ echo "root: ." > irmin.yml +$ irmin init +$ irmin set foo/bar "testing 123" +$ irmin get foo/bar +testing 123 +``` + +`irmin.yml` allows for `irmin` flags to be set on a per-directory basis. You +can also set flags globally using `$HOME/.irmin/config.yml`. Run +`irmin help irmin.yml` for further details. + +Also see `irmin --help` for list of all commands and either +`irmin --help` or `irmin help ` for more help with a +specific command. + +## Context + +Irmin's initial desing is directly inspired from +[XenStore](https://dl.acm.org/doi/10.1145/1631687.1596581), with: + +- the need for efficient optimistic concurrency control features to be + able to let thousands of virtual machine concurrently access and + modify a central configuration database (the Xen stack uses XenStore + as an RPC mechanism to setup VM configuration on boot). Very early + on, the initial focus was to specify and handle [potential + conflicts](https://hal.inria.fr/hal-01099136v1/document) when the + optimistic assumptions do not usually work so well. +- the need for a convenient way to debug and audit possible issues + that might happen in that system. Our [initial + experiments](https://mirage.io/blog/introducing-irmin-in-xenstore) + showed that it was possible to design a reliable system using Git as + backend to persist configuation data reliably (to safely restart + after a crash), while making system debugging easy and go really + fast, thanks to efficient merging strategy. + +In 2014, the first release of Irmin was announced part of the MirageOS +2.0 release [here](https://mirage.io/blog/introducing-irmin). Since +then, several projects started using and improving Irmin. These can +roughly be split into 3 categories: (i) use Irmin as a portable, +structured key-value store (with expressive, mergeable types); (ii) +use Irmin as distributed database (with a customizable consistency +semantics) and (iii) an event-driven dataflow engine. + + +#### Irmin as a portable and efficient structured key-value store + +- [XenStored](https://github.com/xen-project/xen/tree/master/tools/ocaml/xenstored) + is an information storage space shared between all the Xen virtual + machines running in the same host. Each virtual machines gets its + own path in the store. When values are changed in the store, the + appropriate drivers are notified. The initial OCaml implementation + was later extended to use Irmin + [here](https://github.com/mirage/ocaml-xenstore-server). More + details + [here](https://mirage.io/blog/introducing-irmin-in-xenstore). +- [Jitsu](https://github.com/mirage/jitsu) is an experimental + orchestrator for unikernels. It uses Irmin to store the unikernel + configuration (and manage dynamic DNS entries). See more details + [here](https://www.usenix.org/system/files/conference/nsdi15/nsdi15-paper-madhavapeddy.pdf). +- [Cuekeeper](https://github.com/talex5/cuekeeper) is a web-based GTD + (a fancy TODO list) that runs entirely in the browser. It uses Irmin + in the browser to store data locally, with support for structured + concurrent editing and snapshot export and import. More details + [here](https://roscidus.com/blog/blog/2015/04/28/cuekeeper-gitting-things-done-in-the-browser/). +- [Canopy](https://github.com/Engil/Canopy) and + [Unipi](https://github.com/roburio/unipi) both use Irmin to serve + static websites pull from Git repositories and deployed as + unikernels. +- [Caldav](https://github.com/roburio/caldav) is using Irmin to store + calendar entries and back them into a Git repository. More + information [here](https://robur.io/Our%20Work/Projects). +- [Datakit](https://github.com/moby/datakit) was developed at Docker + and provided a 9p interface to the Irmin API. It was used to manage + the configuration of Docker for Desktop, with merge policies on + upgrade, full auditing, and snapshot/rollback capabilites. +- [Tezos](https://gitlab.com/tezos/tezos/) started using Irmin in 2017 + to store the + ledger state. The first prototype used irmin-git before switching to + irmin-lmdb and irmin-leveldb (and now irmin-pack). More details + [here](https://tarides.com/blog/2019-11-21-irmin-v2#tezos-and-irmin-pack). + +#### Irmin as a distributed store + +- An [IMAP](ttps://github.com/gregtatcam/imaplet-lwt) server using + Irmin to store emails. More details + [here](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-918.pdf). The + goal of that project was both to use Irmin to store emails (so using + Irmin as a local key-value store) but also to experiment with + replacing the IMAP on-wire protocol by an explicit Git push/pull + mechanism. +- [irmin-ARP](https://github.com/yomimono/irmin-arp) uses Irmin to + store and audit ARP configuration. It's using Irmin as a local + key-value store for very low-level information (which are normally + stored very deep in the kernel layers), but the main goal was really + to replace the broadcasting on-wire protocol by point-to-point + pull/push synchronisation primitives, with a full audit log of ARP + operations over a network. More details + [here](http://somerandomidiot.com/blog/2015/04/24/what-a-distributed-version-controlled-ARP-cache-gets-you/). +- [Banyan](https://github.com/prismlab/irmin-scylla) uses Irmin to + implement a distributed cache over a geo-replicated cluster. It's + using [Cassandra](https://cassandra.apache.org/_/index.html) as a + storage backend. More information + [here](https://kcsrk.info/papers/banyan_aplas20.pdf). +- [irmin-fdb](https://github.com/andreas/irmin-fdb) implements an + Irmin store backed by + [FoundationDB](https://www.foundationdb.org/). More details + [here](https://www.youtube.com/watch?v=NArvw-9axeg&ab_channel=TheLinuxFoundation). + +#### Irmin as a dataflow scheduler + +- [Datakit CI](https://github.com/moby/datakit/tree/master/ci) is a + continuous integration service that monitors GitHub project and + tests each branch, tag and pull request. It displays the test + results as status indicators in the GitHub UI. It keeps all of its + state and logs in DataKit, rather than a traditional relational + database, allowing review with the usual Git tools. The core of the + project is a scheduler that manage dataflow pipelines across Git + repositories. It was used for a few years as the CI system test + Docker for Desktop on bare-metal and virtual machines, as well as + all the new opam package submissions to ocaml/opam-repository. More + details + [here](https://www.docker.com/blog/docker-unikernels-open-source/). +- [Causal RPC](https://github.com/CraigFe/causal-rpc) implements an + RPC framework using Irmin as a network substrate. More details + [here](https://www.craigfe.io/causalrpc.pdf). +- [CISO](https://github.com/samoht/ciso) is an experimental + (distributed) Continuous Integration engine for OPAM. It was + designed as a replacement of Datakit-CI and finally turned into + [ocurrent](https://github.com/ocurrent/ocurrent). + +## Issues + +Feel free to report any issues using the [GitHub bugtracker](https://github.com/mirage/irmin/issues). + +## License + +See the [LICENSE file](./LICENSE.md). + +## Acknowledgements + +Development of Irmin was supported in part by the EU FP7 User-Centric Networking +project, Grant No. 611001. + +[ppx_irmin-readme]: ./README_PPX.md diff --git a/vendors/irmin/README_LIBIRMIN.md b/vendors/irmin/README_LIBIRMIN.md new file mode 100644 index 000000000000..1fcd7148fd3f --- /dev/null +++ b/vendors/irmin/README_LIBIRMIN.md @@ -0,0 +1,173 @@ +# libirmin + +`libirmin` provides C bindings to the irmin API. + +## Installation + +To install from the root of this repo: + +``` +$ opam pin add libirmin . +``` + +After installing `libirmin.so` can be found in `$OPAM_SWITCH_PREFIX/libirmin/lib` +and `irmin.h` will be in `$OPAM_SWITCH_PREFIX/libirmin/include` + +This means when compiling programs that use `libirmin` you will need to include those +directories: + +``` +$ export IRMIN_CFLAGS=-I$OPAM_SWITCH_PREFIX/libirmin/include +$ export IRMIN_LDFLAGS=-L$OPAM_SWITCH_PREFIX/libirmin/lib -lirmin +$ cc $IRMIN_CFLAGS my-program.c -o my-program $IRMIN_LDFLAGS +``` + +## Usage examples + +### Opening a store + +The first thing you will need to do is configure a backend: + +Using `irmin-git`: + +```c +IrminConfig *config = irmin_config_git("string"); +if (config == NULL){ + // Print error message + IrminString *err = irmin_error_msg(); + fputs(irmin_string_data(err), stderr); + irmin_string_free(err); +} +``` + +When using `irmin-mem`, `irmin-fs` or `irmin-pack` you can specify the hash type +in addition to the content type: + +```c +IrminConfig *config = irmin_config_mem("sha256", "string"); +``` + +Available backends: `irmin_config_mem`, `irmin_config_git`, `irmin_config_git_mem`, `irmin_config_fs`, +`irmin_config_pack`, `irmin_config_tezos` + +If `NULL` is passed for the content parameter then `string` will be used by default and +when `NULL` is passed for the hash argument `blake2b` is used. + +Available content types: `string`, `json` (JSON objects), `json-value` (any JSON value) +Available hash types: `blake2b`, `blake2s`, `rmd160`, `sha1`, `sha224`, `sha256`, `sha384`, +`sha512`, `tezos` + +The `IrminConfig*` value should eventually be freed using `irmin_config_free`. + +When using a backend that stores information on disk, you will probably want to set the `root` parameter: + +```c +assert(irmin_config_set_root(config, "path/to/store")); +``` + +Next you can initialize the repo: + +```c +IrminRepo *repo = irmin_repo_new(config); +if (repo == NULL){ + // handle error +} +``` + +From there you can create a store using the main branch: + +```c +Irmin *store = irmin_main(repo); +``` + +Or from your branch of choice: + +```c +Irmin *store = irmin_of_branch(repo, "my-branch"); +``` + +### Cleanup + +Every `IrminX` type should be released using the matching `irmin_X_free` function: + +```c +irmin_free(store); +irmin_repo_free(repo); +irmin_config_free(config); +``` + +### Setting values + +Setting a value when using string contents: + +```c +IrminString *value = irmin_string_new("Hello, world!", -1); +IrminPath *path = irmin_path_of_string(repo, "a/b/c"); +IrminInfo *info = irmin_info_new(repo, "author", "commit message"); +assert(irmin_set(store, path, (IrminContents*)value, info)); +irmin_info_free(info); +irmin_path_free(path); +irmin_string_free(value); +``` + +The `-1` argument to `irmin_string_new` is used to pass the length of +the string. If it ends with a NULL byte then passing `-1` will auto- +matically detect the string length. This also shows that `IrminString` +can be cast to `IrminContents` safely when using `string` contents. + +When using `json` contents: + +```c +IrminType *t = irmin_type_json(); +IrminContents *value = irmin_contents_of_string(t, "{\"foo\": \"bar\"}", -1); +IrminPath *path = irmin_path_of_string(repo, "a/b/c"); +IrminInfo *info = irmin_info_new(repo, "author", "commit message"); +assert(irmin_set(store, path, value, info)); +irmin_info_free(info); +irmin_path_free(path); +irmin_contents_free(value); +irmin_type_free(t); +``` + +### Getting values + +The following will get the value associated with a path and print its string +representation to stdout: + +```c +IrminPath *path = irmin_path_of_string(repo, "a/b/c"); +IrminContents *value = irmin_find(store, path); +if (value != NULL){ + // value exists, print it to stdout + IrminString *s = irmin_contents_to_string(repo, value); + puts(irmin_string_data(s)); + irmin_string_free(s); + irmin_contents_free(value); +} +irmin_path_free(path); +``` + +### Trees + +Working with trees is similar to working with stores, only you will be using the +`irmin_tree_X` functions: + +```c +IrminTree *tree = irmin_tree_new(repo); +IrminString *value = irmin_string_new("Hello, world!", -1); +IrminPath *path = irmin_path_of_string(repo, "a/b/c"); +assert(irmin_tree_add(tree, path, value, NULL); // The NULL parameter here is for + // metadata and will typically be + // NULL + +IrminPath *empty_path = irmin_path_empty(); +IrminInfo *info = irmin_info_new(repo, "author", "commit message"); +irmin_set_tree(store, empty_path, tree, info); + +irmin_string_free(value); +irmin_path_free(path); +irmin_path_free(empty_path); +irmin_info_free(info); +irmin_tree_free(tree); +``` + diff --git a/vendors/irmin/README_PPX.md b/vendors/irmin/README_PPX.md new file mode 100644 index 000000000000..cb023c9e2432 --- /dev/null +++ b/vendors/irmin/README_PPX.md @@ -0,0 +1,128 @@ +## ppx_irmin + +PPX extension for automatically generating Irmin type representations. + +### Overview + +`ppx_irmin` automatically generates Irmin type representations (values of type +`_ Irmin.Type.t`) corresponding to type declarations in your code. For example: + +```ocaml +type 'a tree = + | Branch of tree * bool option * tree + | Leaf of 'a [@@deriving irmin] +``` + +will be expanded to: + +```ocaml +type 'a tree = (* as above *) + +let tree_t leaf_t = + let open Irmin.Type in + mu (fun tree_t -> + variant "tree" (fun branch leaf -> function + | Branch (x1, x2, x3) -> branch (x1, x2, x3) + | Leaf x1 -> leaf x1 + |~ case1 "Branch" (triple tree_t (option bool) tree_t) (fun (x1, x2, x3) -> Branch (x1, x2, x3)) + |~ case1 "Leaf" leaf_t (fun x1 -> Leaf x1) + |> sealv) +``` + +Type representations can also be derived inline using the `[%typ: ]` +extension point. + +### Installation and usage + +`ppx_irmin` may be installed via [opam](https://opam.ocaml.org/): + +``` +opam install ppx_irmin +``` + +If you're using the [dune](https://github.com/ocaml/dune) build system, add the +following field to your `library`, `executable` or `test` stanza: + +``` +(preprocess (pps ppx_irmin)) +``` + +You can now use `[@@deriving irmin]` after a type declaration in your code to +automatically derive an Irmin type representation with the same name. + +### Specifics + +`ppx_irmin` supports all of the type combinators exposed in the +[Irmin.Type](https://docs.mirage.io/irmin/Irmin/Type/index.html) module (basic +types, records, variants (plain and closed polymorphic), recursive types etc.). +Types with parameters will result in parameterised representations (i.e. type +`'a t` is generated a representation of type `'a Type.t -> 'a t Type.t`). + +To supply base representations from a module other than `Irmin.Type` (such as +when `Irmin.Type` is aliased to a different module path), the `lib` argument +can be passed to `@@deriving irmin`: + +```ocaml +type foo = unit [@@deriving irmin { lib = Some "Mylib.Types" }] + +(* generates the value *) +val foo_t = Mylib.Types.unit +``` + +This argument can also be passed as a command-line option (i.e. `--lib +Mylib.Types`, with `--lib ''` interpreted as the current module). + +#### Naming scheme + +The generated type representation will be called `_t`, unless the +type-name is `t`, in which case the representation is simply `t`. This +behaviour can be overridden using the `name` argument, as in: + +```ocaml +type foo = string list * int32 [@@deriving irmin { name = "foo_repr" }] + +(* generates the value *) +val foo_repr = Irmin.Type.(pair (list string) int32) +``` + +If the type contains an abstract type, `ppx_irmin` will expect to find a +corresponding type representation using its own naming rules. This can be +overridden using the `[@repr ...]` attribute, as in: + +```ocaml +type bar = (foo [@repr foo_repr], string) result [@@deriving irmin] + +(* generates the value *) +val bar_t = Irmin.Type.(result foo_repr string) +``` + +Built-in abstract types such as `unit` are assumed to be represented in +`Irmin.Type`. This behaviour can be overridden with the `[@nobuiltin]` +attribute: + +```ocaml +type t = unit [@nobuiltin] [@@deriving irmin] + +(* generates the value *) +let t = unit_t (* not [Irmin.Type.unit] *) +``` + +#### Signature type definitions + +The `ppx_irmin` deriver can also be used in signatures to expose the +auto-generated value: + +```ocaml +module Contents : sig + type t = int32 [@@deriving irmin] + + (* exposes repr in signature *) + val t : t Irmin.Type.t + +end = struct + type t = int32 [@@deriving irmin] + + (* generates repr value *) + let t = Irmin.Type.int32 +end +``` diff --git a/vendors/irmin/RELEASE.md b/vendors/irmin/RELEASE.md new file mode 100644 index 000000000000..185e893c15c9 --- /dev/null +++ b/vendors/irmin/RELEASE.md @@ -0,0 +1,183 @@ +# Release process + +This file documents the necessary steps for releasing Irmin to its various users +(via GitHub, `opam-repository` and Tezos). + +At a high level, releasing Irmin consists of publishing the following artefacts: + +- a Git [commit tag][git-tags]; +- a set of documentation on GitHub pages (e.g. [`mirage.github.io/irmin`][pages-docs]); +- a release archive (`.tbz` file containing the project source) on GitHub; +- a set of `.opam` files in [`opam-repository`][opam-repo] that point to this + release archive; +- (optionally) a copy of these `.opam` files in the Tezos + [`opam-repository`][tezos-opam-repo]. + +Most of this can be handled automatically by [`dune-release`][dune-release], as +described in the instructions below. + +[git-tags]: https://git-scm.com/book/en/v2/Git-Basics-Tagging +[pages-docs]: https://mirage.github.io/irmin +[dune-release]: https://github.com/ocamllabs/dune-release +[opam-repo]: https://github.com/ocaml/opam-repository + + +## Manual benchmarking + +Before releasing, it is important to make sure that the new version doesn't +induce performance regressions. The trace replay benchmarks should be used +for that purpose. + +The performances of individual releases of irmin are saved inside the +benchmarking server at `/bench/releases/`: +``` +. +└── ncommits_200k + ├── irmin2.7.0_index1.4.0_repr0.4.0 + │   ├── packet_b + │   │   ├── stat_summary.json + │   │   └── stat_trace.repr + │   └── packet_a + │   ├── stat_summary.json + │   └── stat_trace.repr + ├── irmin2.5.4_index1.3.1_repr0.3.0 + │   ├── packet_b + │   │   ├── stat_summary.json + │   │   └── stat_trace.repr + │   └── packet_a + │   ├── stat_summary.json + │   └── stat_trace.repr + └── irmin2.2.0_index1.2.1 +    ├── packet_b +    │   ├── stat_summary.json +    │   └── stat_trace.repr +    └── packet_a +    ├── stat_summary.json +    └── stat_trace.repr +``` + +To test a new release, setup an `c3-small-x86-01` Equinix instance, fetch a large +enough replay trace and setup the right versions of the right libraries +before running the benchmarks. + +The benchmark should be run at least twice (to give insights about the noise), +the two resulting `stat_trace.repr` files should be copied to +`/bench/releases/` using the same naming convention as above. Also set the file +permissions to read-only using `chmod 444 stat_trace.repr`. + +A run of the benchmark is expected to last \~35min. + +See [this script](https://github.com/tarides/irmin-tezos/blob/master/bench.sh) for an example of a setup and a bench run. + +### Visualising the results + +A `stat_summary.json` can be computed from a `stat_trace.repr`. + +If missing or out of date (resulting in a parsing error), the JSON can be +(re)generated using the following commands: +``` +dune exec -- bench/irmin-pack/trace_stats.exe summarise stat_trace.repr >stat_summary.json +``` + +A conversion is expected to last \~4 min. + +One or more summaries can be pretty printed together. The following command +will pretty print both runs of 2 releases side by side: +```sh +; export ROOT='/bench/releases/ncommits_200k/irmin2.7.0_index1.4.0_repr0.4.0/' +; export ROOT_OLD='/bench/releases/ncommits_200k/irmin2.2.0_index1.2.1/' +; dune exec -- bench/irmin-pack/trace_stats.exe pp \ + -f old,$ROOT_OLD/packet_a/stat_summary.json \ + -f old,$ROOT_OLD/packet_b/stat_summary.json \ + -f old,$ROOT/packet_a/stat_summary.json \ + -f old,$ROOT/packet_b/stat_summary.json +``` + +See [this script](https://github.com/tarides/irmin-tezos/blob/master/summarise.sh) for an example of a batch conversion to JSON. + +## Releasing to opam-repository and GitHub + +- Check that no `.opam` files contain `pin-depends` fields. If so, release those + packages first. + +```sh +; git grep -A 10 "pin-depends" *.opam +``` + +- Make a pull-request to this repository containing pre-release changes (drop + `pin-depends`, add release number to `CHANGES.md`, any new constraints) and an + empty commit to host the release tag. + +```sh +; git fetch upstream +; git checkout -B release-X.Y.Z upstream/main +; git commit -m "Prepare X.Y.Z release" -- CHANGES.md +; git commit --allow-empty -m "Release X.Y.Z" +; hub pull-request +``` + +- Wait for the CI to pass on the release PR, then perform the following steps to + release to `opam-repository`: + +```sh +; opam upgrade odoc # Use the latest Odoc + +; dune-release tag # Create appropriate Git tag by reading CHANGES.md +; dune-release distrib --skip-tests # Build release archive +; dune-release publish distrib --verbose # Push release archive to GitHub +; dune-release publish doc --verbose # Push documentation to GitHub pages +; dune-release opam pkg # Generate `opam` files for `opam-repository` +; dune-release opam submit # Make PR to `opam-repository` +``` + +- Once the release PR is merged on `opam-repository`, merge the release PR on + the development repository. If any changes to `.opam` files were necessary in + the `opam-repository` PR, add those to the release PR before merging. + +### Re-cutting a failed Opam release + +It may be necessary to re-cut an attempted release, for instance if the +`opam-repository` CI raised issues that couldn't be fixed via if the +`opam-repository`. + +First delete the release distribution via the GitHub UI, then cleanup the Git +tags and re-perform the required release steps: + +```sh +; git tag -d X.Y.Z # Erase git tag locally +; git push -d upstream X.Y.Z # Erase git tag on GitHib + +; dune-release tag # Re-create tag +; dune-release distrib --skip-tests +; dune-release publish distrib --verbose +; dune-release publish doc --verbose # ... if necessary +; dune-release opam pkg +; dune-release opam submit ^C # Exit at prompt to avoid creating pull request +; cd +; git push -u origin --force # Add new `.opam` files to PR +``` + +## Releasing to Tezos' opam-repository + +The Tezos project uses [its own `opam-repository`][tezos-opam-repo] to source +its dependencies, so upgrading its dependencies requires making a separate +release to this _after_ having released to the main `opam-repository`. The +process is as follows: + +```sh +for p in ; do + # Remove old version of this package from Tezos' opam-repository + rm ~/t/tezos-opam-repository/packages/$p/*/ -rf + + # Copy opam file for the new release of this package + cp ~/t/{opam-repository,tezos-opam-repository}/packages/$p/$p. -r +done +``` + +(The above process is somewhat automated by [this +script][tezos-downstream-script].) Once this is done, make an MR to the Tezos +opam-repository and – if necessary – a corresponding MR to Tezos to adjust to +any API changes. + +[tezos-opam-repo]: https://gitlab.com/tezos/opam-repository +[tezos-downstream-script]: https://github.com/CraigFe/dotfiles/blob/main/scripts/.scripts/tezos-downstream diff --git a/vendors/irmin/bench/irmin-pack/_layers.mli b/vendors/irmin/bench/irmin-pack/_layers.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/_layers.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/bench/irmin-pack/bench_common.ml b/vendors/irmin/bench/irmin-pack/bench_common.ml new file mode 100644 index 000000000000..7ba4b5dcbe6e --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/bench_common.ml @@ -0,0 +1,193 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends + +let c0 = Mtime_clock.counter () +let now_us () = Mtime_clock.count c0 |> Mtime.Span.to_us +let last = ref (now_us ()) + +let dt_us () = + let l = now_us () in + let d = l -. !last in + last := l; + d + +let reporter ?(prefix = "") () = + let report src level ~over k msgf = + let k _ = + over (); + k () + in + let ppf = match level with Logs.App -> Fmt.stdout | _ -> Fmt.stderr in + let with_stamp h _tags k fmt = + let dt = dt_us () in + Fmt.kpf k ppf + ("%s%+04.0fus %a %a @[" ^^ fmt ^^ "@]@.") + prefix dt Logs_fmt.pp_header (level, h) + Fmt.(styled `Magenta string) + (Logs.Src.name src) + in + msgf @@ fun ?header ?tags fmt -> with_stamp header tags k fmt + in + { Logs.report } + +let setup_log style_renderer level = + Fmt_tty.setup_std_outputs ?style_renderer (); + Logs.set_level level; + Logs.set_reporter (reporter ()); + () + +let reset_stats () = + Index.Stats.reset_stats (); + Irmin_pack.Stats.reset_stats () + +let random_char () = char_of_int (Random.int 256) +let random_string n = String.init n (fun _i -> random_char ()) +let random_blob () = random_string 10 |> Bytes.of_string +let random_key () = random_string 5 + +let default_artefacts_dir = + let ( / ) = Filename.concat in + Unix.getcwd () / "_artefacts" / Uuidm.to_string (Uuidm.v `V4) + +let prepare_artefacts_dir path = + let rec mkdir_p path = + if Sys.file_exists path then () + else + let path' = Filename.dirname path in + if path' = path then failwith "Failed to prepare result dir"; + mkdir_p path'; + Unix.mkdir path 0o755 + in + mkdir_p path + +let with_timer f = + let t0 = Sys.time () in + let+ a = f () in + let t1 = Sys.time () -. t0 in + (t1, a) + +let with_progress_bar ~message ~n ~unit = + let open Progress in + let config = + Config.v ~max_width:(Some 79) ~min_interval:(Some Duration.(of_sec 0.5)) () + in + let bar = + Line.( + list + [ + const message; + count_to n; + const unit; + elapsed (); + parens (const "ETA: " ++ eta n); + bar n; + percentage_of n; + ]) + in + with_reporter ~config bar + +module Conf = Irmin_tezos.Conf + +module Schema = struct + open Irmin + module Metadata = Metadata.None + module Contents = Contents.String + module Path = Path.String_list + module Branch = Branch.String + module Hash = Hash.SHA1 + module Node = Node.Make (Hash) (Path) (Metadata) + module Commit = Commit.Make (Hash) + module Info = Info.Default +end + +module Info (I : Irmin.Info.S) = struct + let f () = I.v ~author:"tests" ~message:"commit" 0L +end + +module FSHelper = struct + let file f = + try (Unix.stat f).st_size with Unix.Unix_error (Unix.ENOENT, _, _) -> 0 + + let dict root = file (Irmin_pack.Layout.V1_and_v2.dict ~root) / 1024 / 1024 + let pack root = file (Irmin_pack.Layout.V1_and_v2.pack ~root) / 1024 / 1024 + + let index root = + let index_dir = Filename.concat root "index" in + let a = file (Filename.concat index_dir "data") in + let b = file (Filename.concat index_dir "log") in + let c = file (Filename.concat index_dir "log_async") in + (a + b + c) / 1024 / 1024 + + let size root = dict root + pack root + index root + let get_size root = size root + + let rm_dir root = + if Sys.file_exists root then ( + let cmd = Printf.sprintf "rm -rf %s" root in + [%logs.info "exec: %s" cmd]; + let _ = Sys.command cmd in + ()) +end + +module Generate_trees + (Store : Irmin.Generic_key.KV with type Schema.Contents.t = bytes) = +struct + let key depth = + let rec aux i acc = + if i >= depth then acc + else + let k = random_key () in + aux (i + 1) (k :: acc) + in + aux 0 [] + + let chain_tree tree depth path = + let k = path @ key depth in + Store.Tree.add tree k (random_blob ()) + + let add_chain_trees depth nb tree = + let path = key 2 in + let rec aux i tree = + if i >= nb then Lwt.return tree + else + let* tree = chain_tree tree depth path in + aux (i + 1) tree + in + aux 0 tree + + let large_tree path tree width = + let rec aux i tree = + if i >= width then Lwt.return tree + else + let k = path @ [ random_key () ] in + let* tree = Store.Tree.add tree k (random_blob ()) in + aux (i + 1) tree + in + aux 0 tree + + let add_large_trees width nb tree = + let path = key 1 in + let rec aux i tree = + if i >= nb then Lwt.return tree + else + let path = path @ [ random_key () ] in + let* tree = large_tree path tree width in + aux (i + 1) tree + in + aux 0 tree +end diff --git a/vendors/irmin/bench/irmin-pack/bench_common.mli b/vendors/irmin/bench/irmin-pack/bench_common.mli new file mode 100644 index 000000000000..9f2cf0335b3f --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/bench_common.mli @@ -0,0 +1,50 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val default_artefacts_dir : string +val prepare_artefacts_dir : string -> unit +val reporter : ?prefix:string -> unit -> Logs.reporter +val setup_log : Fmt.style_renderer option -> Logs.level option -> unit +val reset_stats : unit -> unit +val with_timer : (unit -> 'a Lwt.t) -> (float * 'a) Lwt.t + +val with_progress_bar : + message:string -> n:int -> unit:string -> ((int -> unit) -> 'a) -> 'a + +val random_blob : unit -> bytes + +module Info (I : Irmin.Info.S) : sig + val f : I.f +end + +module Conf : Irmin_pack.Conf.S +module Schema : Irmin.Schema.S + +module FSHelper : sig + val rm_dir : string -> unit + val get_size : string -> int +end + +module Generate_trees + (Store : Irmin.Generic_key.KV with type Schema.Contents.t = bytes) : sig + val add_chain_trees : int -> int -> Store.tree -> Store.tree Lwt.t + (** [add_chain_trees depth nb tree] adds [nb] random contents to [tree], + depthwise. *) + + val add_large_trees : int -> int -> Store.tree -> Store.tree Lwt.t + (** [add_large_trees width nb tree] adds [nb] random contents to [tree], + breadthwise. *) +end diff --git a/vendors/irmin/bench/irmin-pack/dune b/vendors/irmin/bench/irmin-pack/dune new file mode 100644 index 000000000000..b95a7cc62460 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/dune @@ -0,0 +1,94 @@ +(executables + (names main) + (public_names bench-pack) + (modules main import) + (package irmin-bench) + (preprocess + (pps ppx_irmin.internal ppx_repr)) + (libraries + irmin-pack + irmin-test.bench + lwt + unix + cmdliner + logs + repr + ppx_repr + bench_common + mtime + rusage)) + +(library + (name bench_common) + (public_name irmin-bench.common) + (modules bench_common) + (libraries irmin-pack irmin-pack.unix irmin-tezos unix progress uuidm) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) + +(library + (name irmin_traces) + (public_name irmin-bench.traces) + (modules + trace_common + trace_definitions + trace_collection + trace_stat_summary + trace_stat_summary_conf + trace_stat_summary_utils + trace_stat_summary_pp + trace_replay + trace_replay_intf + tezos_history_metrics + trace_stat_summary_cb) + (preprocess + (pps ppx_irmin.internal ppx_repr ppx_deriving.enum)) + (libraries + irmin + irmin-pack + unix + lwt + repr + ppx_repr + bentov + mtime + printbox + printbox-text + mtime.clock.os + bench_common) + (instrumentation + (backend bisect_ppx))) + +(executable + (name tree) + (modules tree) + (preprocess + (pps ppx_irmin.internal ppx_repr)) + (libraries + irmin-pack + irmin-pack.mem + irmin-test.bench + lwt + unix + cmdliner + logs + repr + ppx_repr + bench_common + irmin-tezos + irmin_traces)) + +(executable + (name trace_stats) + (modules trace_stats) + (libraries cmdliner irmin_traces)) + +;; Require the executables to compile during tests + +(rule + (alias runtest) + (package irmin-bench) + (deps main.exe tree.exe trace_stats.exe) + (action (progn))) diff --git a/vendors/irmin/bench/irmin-pack/import.ml b/vendors/irmin/bench/irmin-pack/import.ml new file mode 100644 index 000000000000..2fed488f984d --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/import.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/bench/irmin-pack/main.ml b/vendors/irmin/bench/irmin-pack/main.ml new file mode 100644 index 000000000000..828480924ff2 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/main.ml @@ -0,0 +1,55 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let config ~root = Irmin_pack.config ~fresh:false root + +module Config = struct + let entries = 2 + let stable_hash = 3 + let contents_length_header = Some `Varint + let inode_child_order = `Hash_bits + let forbid_empty_dir_persistence = false +end + +module KV = struct + module Maker = Irmin_pack_unix.KV (Config) + include Maker.Make (Irmin.Contents.String) +end + +module Bench = Irmin_bench.Make (KV) + +let file f = + (* in MiB *) + try (Unix.stat f).st_size / 1024 / 1024 + with Unix.Unix_error (Unix.ENOENT, _, _) -> 0 + +let index root = + let rec aux acc i = + if i = 256 then acc + else + let filename = Format.sprintf "store.index.%d" i in + let s = file (Filename.concat root filename) in + aux (acc + s) (i + 1) + in + aux 0 0 + +let size ~root = + let index_size = index root in + Irmin_pack.Layout.V1_and_v2.all ~root + |> List.map file + |> List.fold_left ( + ) index_size + +let () = Bench.run ~config ~size diff --git a/vendors/irmin/bench/irmin-pack/main.mli b/vendors/irmin/bench/irmin-pack/main.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/main.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/bench/irmin-pack/tezos_history_metrics.ml b/vendors/irmin/bench/irmin-pack/tezos_history_metrics.ml new file mode 100644 index 000000000000..2078a1e743d3 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/tezos_history_metrics.ml @@ -0,0 +1,178 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** List of tuples of week timestamp, week transaction count, week ops count and + week block count. + + There is ~1 block per minute in tezos and 10080 minutes in a week. Hence the + content of the last columns. + + Computed using: + + https://api.tzstats.com/series/block.json?collapse=1w&columns=n_tx,n_ops,count *) +let weekly_stats = + [ + (1529884800000, 497, 16396, 1814); + (1530489600000, 10337, 103366, 10031); + (1531094400000, 6444, 24425, 8478); + (1531699200000, 6268, 41311, 9674); + (1532304000000, 4423, 126915, 9916); + (1532908800000, 3951, 153091, 9561); + (1533513600000, 3709, 151066, 9088); + (1534118400000, 5103, 164351, 9442); + (1534723200000, 7744, 174163, 9504); + (1535328000000, 16856, 196819, 9627); + (1535932800000, 9080, 195198, 9756); + (1536537600000, 11296, 200613, 9759); + (1537142400000, 34291, 234489, 9935); + (1537747200000, 11029, 203505, 9657); + (1538352000000, 15221, 211566, 9718); + (1538956800000, 12279, 212965, 9857); + (1539561600000, 16400, 216941, 9706); + (1540166400000, 17277, 224464, 9875); + (1540771200000, 13674, 219879, 9855); + (1541376000000, 17780, 222633, 9781); + (1541980800000, 43862, 243942, 9582); + (1542585600000, 265754, 552326, 8583); + (1543190400000, 29911, 199036, 8446); + (1543795200000, 46262, 255443, 9395); + (1544400000000, 46809, 265757, 9433); + (1545004800000, 17226, 223122, 9601); + (1545609600000, 14758, 224245, 9671); + (1546214400000, 20025, 234288, 9775); + (1546819200000, 15696, 227917, 9667); + (1547424000000, 20349, 235370, 9743); + (1548028800000, 17173, 232767, 9725); + (1548633600000, 17551, 234505, 9714); + (1549238400000, 22169, 241307, 9741); + (1549843200000, 17892, 239578, 9787); + (1550448000000, 17899, 239569, 9784); + (1551052800000, 23444, 244467, 9749); + (1551657600000, 17721, 236558, 9666); + (1552262400000, 24563, 247532, 9743); + (1552867200000, 22835, 250750, 9835); + (1553472000000, 23011, 251950, 9845); + (1554076800000, 29518, 257341, 9739); + (1554681600000, 21775, 246456, 9683); + (1555286400000, 30670, 257784, 9771); + (1555891200000, 27023, 251536, 9687); + (1556496000000, 22465, 248722, 9767); + (1557100800000, 32423, 259129, 9773); + (1557705600000, 27606, 258295, 9859); + (1558310400000, 24614, 252204, 9771); + (1558915200000, 32625, 248919, 9520); + (1559520000000, 26519, 251351, 9736); + (1560124800000, 32499, 258754, 9683); + (1560729600000, 33250, 257565, 9578); + (1561334400000, 29034, 252155, 9611); + (1561939200000, 37005, 260170, 9597); + (1562544000000, 31342, 255413, 9618); + (1563148800000, 27970, 250786, 9563); + (1563753600000, 43176, 273231, 9702); + (1564358400000, 31888, 268034, 9877); + (1564963200000, 38565, 272631, 9781); + (1565568000000, 40317, 269809, 9669); + (1566172800000, 32076, 266277, 9802); + (1566777600000, 36307, 269958, 9789); + (1567382400000, 35313, 263821, 9683); + (1567987200000, 30223, 264633, 9799); + (1568592000000, 38428, 276965, 9913); + (1569196800000, 38314, 279131, 9914); + (1569801600000, 42121, 282076, 9921); + (1570406400000, 32572, 272638, 9900); + (1571011200000, 33358, 261102, 9723); + (1571616000000, 52981, 280392, 9812); + (1572220800000, 40154, 270988, 9876); + (1572825600000, 61329, 296468, 9889); + (1573430400000, 40552, 262779, 9608); + (1574035200000, 39421, 264409, 9742); + (1574640000000, 55234, 289723, 9931); + (1575244800000, 46487, 284110, 9976); + (1575849600000, 64465, 307251, 9978); + (1576454400000, 53005, 289408, 9920); + (1577059200000, 42832, 281309, 9975); + (1577664000000, 56314, 294350, 9961); + (1578268800000, 51173, 289804, 9966); + (1578873600000, 68059, 309998, 10023); + (1579478400000, 64670, 308314, 10001); + (1580083200000, 71682, 314239, 10034); + (1580688000000, 77387, 320814, 9996); + (1581292800000, 100282, 346279, 9975); + (1581897600000, 86670, 329707, 9957); + (1582502400000, 76753, 311822, 9901); + (1583107200000, 83277, 304617, 9745); + (1583712000000, 80841, 304818, 9802); + (1584316800000, 94173, 322773, 9905); + (1584921600000, 71931, 300080, 9921); + (1585526400000, 69493, 299321, 9977); + (1586131200000, 89672, 321104, 9984); + (1586736000000, 74397, 308355, 10054); + (1587340800000, 100712, 336139, 10055); + (1587945600000, 93507, 327961, 10037); + (1588550400000, 112609, 346175, 10039); + (1589155200000, 91704, 324183, 10033); + (1589760000000, 102430, 335567, 10058); + (1590364800000, 94686, 324824, 10029); + (1590969600000, 91343, 322663, 10029); + (1591574400000, 125174, 357268, 10032); + (1592179200000, 95985, 329653, 10023); + (1592784000000, 122939, 357827, 10035); + (1593388800000, 95589, 327834, 10029); + (1593993600000, 128419, 362984, 10032); + (1594598400000, 122955, 359831, 10044); + (1595203200000, 121149, 354555, 10033); + (1595808000000, 123127, 356107, 10026); + (1596412800000, 139315, 372670, 10004); + (1597017600000, 157274, 393230, 10022); + (1597622400000, 135269, 366162, 9974); + (1598227200000, 148236, 374878, 9964); + (1598832000000, 127456, 352065, 9963); + (1599436800000, 151080, 373997, 9952); + (1600041600000, 126361, 350427, 9968); + (1600646400000, 140182, 365980, 10025); + (1601251200000, 138945, 362958, 9987); + (1601856000000, 125262, 348689, 10029); + (1602460800000, 163734, 386645, 10011); + (1603065600000, 130914, 354378, 9999); + (1603670400000, 165121, 389401, 10033); + (1604275200000, 138447, 361921, 10028); + (1604880000000, 189794, 404942, 9870); + (1605484800000, 146999, 362987, 9841); + (1606089600000, 164426, 389926, 9989); + (1606694400000, 168238, 392715, 10022); + (1607299200000, 140107, 361585, 10031); + (1607904000000, 189296, 412488, 10009); + (1608508800000, 152377, 376164, 10008); + (1609113600000, 198728, 420519, 9846); + (1609718400000, 185671, 406782, 9654); + (1610323200000, 179296, 398205, 9664); + (1610928000000, 218730, 439105, 9667); + (1611532800000, 172690, 392509, 9691); + (1612137600000, 187690, 410862, 9643); + (1612742400000, 264982, 494725, 9773); + (1613347200000, 232473, 465874, 9975); + (1613952000000, 273033, 504512, 9991); + (1614556800000, 240863, 470355, 9998); + (1615161600000, 302082, 533510, 10011); + (1615766400000, 258743, 487761, 10004); + (1616371200000, 344647, 569310, 9989); + (1616976000000, 445942, 674148, 10012); + (1617580800000, 547832, 775660, 9947); + (1618185600000, 656723, 887993, 10012); + (1618790400000, 811462, 1036103, 9922); + (1619395200000, 810847, 1040980, 9952); + (1620000000000, 273545, 359345, 3779); + ] diff --git a/vendors/irmin/bench/irmin-pack/trace_collection.ml b/vendors/irmin/bench/irmin-pack/trace_collection.ml new file mode 100644 index 000000000000..20b7b0320906 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_collection.ml @@ -0,0 +1,258 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Trace file construction. + + This file is meant to be used from Tezos. OCaml version 4.09 and the 32bit + architecture should be supported. + + A module [Make_replayable] has yet to be implemented. *) + +open Lwt.Syntax + +(** Make state trace collector. *) +module Make_stat (Store : Irmin.Generic_key.KV) = struct + module Def = Trace_definitions.Stat_trace + + type t = { + writer : Def.writer; + store_path : string; + mutable t0 : Mtime_clock.counter; + mutable prev_merge_durations : float list; + mutable commit_before : Def.bag_of_stats * Def.store_before; + } + (** Imperative stat trace collector. It is optimised to minimise the CPU + footprint. *) + + module Bag_of_stats = struct + let pack () = + let module Pack_stats = Irmin_pack.Stats in + let module Unix_pack_stats = Irmin_pack_unix.Stats in + let pack_s = Pack_stats.get () in + let unix_s = Unix_pack_stats.get () in + let inode = Pack_stats.(Inode.export pack_s.inode) in + let pack_store = Unix_pack_stats.(Pack_store.export unix_s.pack_store) in + let finds = + Def. + { + total = pack_store.total; + from_staging = pack_store.from_staging; + from_lru = pack_store.from_lru; + from_pack_direct = pack_store.from_pack_direct; + from_pack_indexed = pack_store.from_pack_indexed; + } + in + Def. + { + finds; + appended_hashes = pack_store.appended_hashes; + appended_offsets = pack_store.appended_offsets; + inode_add = inode.inode_add; + inode_remove = inode.inode_remove; + inode_of_seq = inode.inode_of_seq; + inode_of_raw = inode.inode_of_raw; + inode_rec_add = inode.inode_rec_add; + inode_rec_remove = inode.inode_rec_remove; + inode_to_binv = inode.inode_to_binv; + inode_decode_bin = inode.inode_decode_bin; + inode_encode_bin = inode.inode_encode_bin; + } + + let tree () = + let open Store.Tree in + let v = counters () in + Def. + { + contents_hash = v.contents_hash; + contents_find = v.contents_find; + contents_add = v.contents_add; + node_hash = v.node_hash; + node_mem = v.node_mem; + node_add = v.node_add; + node_find = v.node_find; + node_val_v = v.node_val_v; + node_val_find = v.node_val_find; + node_val_list = v.node_val_list; + } + + let index prev_merge_durations = + let open Index.Stats in + let v = get () in + let new_merge_durations = + if v.merge_durations == prev_merge_durations then [] + else + (* This is anoying to compute. We can't rely on nb_merge. + Assume that all merge durations are unique. + Assume that we never have >10 merges at once. + *) + let rec aux acc = function + | [] -> acc + | hd :: tl -> + if List.mem hd prev_merge_durations then ( + assert (acc = []) (* No oldie after a newies *); + aux acc tl) + else aux ((hd /. 1e6) :: acc) tl + in + let l = aux [] v.merge_durations in + assert (l <> []) (* At least one newie *); + l + in + Def. + { + bytes_read = v.bytes_read; + nb_reads = v.nb_reads; + bytes_written = v.bytes_written; + nb_writes = v.nb_writes; + nb_merge = v.nb_merge; + new_merge_durations; + } + + let gc () = + let open Gc in + let v = quick_stat () in + Def. + { + minor_words = v.minor_words; + promoted_words = v.promoted_words; + major_words = v.major_words; + minor_collections = v.minor_collections; + major_collections = v.major_collections; + heap_words = v.heap_words; + compactions = v.compactions; + top_heap_words = v.top_heap_words; + stack_size = v.stack_size; + } + + let size_of_file path = + let open Unix.LargeFile in + try (stat path).st_size with Unix.Unix_error _ -> 0L + + let disk store_path = + let ( / ) left right = Filename.concat left right in + Def. + { + index_data = store_path / "index" / "data" |> size_of_file; + index_log = store_path / "index" / "log" |> size_of_file; + index_log_async = store_path / "index" / "log_async" |> size_of_file; + store_dict = store_path / "store.dict" |> size_of_file; + store_pack = store_path / "store.pack" |> size_of_file; + } + + let now () = + Mtime_clock.now () |> Mtime.to_uint64_ns |> Int64.to_float |> ( *. ) 1e-9 + + let create store_path prev_merge_durations = + Def. + { + pack = pack (); + tree = tree (); + index = index prev_merge_durations; + gc = gc (); + disk = disk store_path; + timestamp_wall = now (); + timestamp_cpu = Sys.time (); + } + end + + let create_file : string -> Def.config -> string -> t = + fun path config store_path -> + let header = + Def. + { + config; + hostname = Unix.gethostname (); + word_size = Sys.word_size; + timeofday = Unix.gettimeofday (); + initial_stats = + Bag_of_stats.create store_path + Index.Stats.((get ()).merge_durations); + } + in + let dummy_commit_before = + ( header.initial_stats, + Def.{ nodes = 0; leafs = 0; skips = 0; depth = 0; width = 0 } ) + in + { + writer = Def.create_file path header; + store_path; + t0 = Mtime_clock.counter (); + prev_merge_durations = Index.Stats.((get ()).merge_durations); + commit_before = dummy_commit_before; + } + + let flush { writer; _ } = Def.flush writer + let close { writer; _ } = Def.close writer + let remove { writer; _ } = Def.remove writer + let short_op_begin t = t.t0 <- Mtime_clock.counter () + + let short_op_end { t0; writer; _ } short_op = + let duration = + Mtime_clock.count t0 |> Mtime.Span.to_s |> Int32.bits_of_float + in + let op = + match short_op with + | `Add -> `Add duration + | `Remove -> `Remove duration + | `Find -> `Find duration + | `Mem -> `Mem duration + | `Mem_tree -> `Mem_tree duration + | `Checkout -> `Checkout duration + | `Copy -> `Copy duration + in + Def.append_row writer op + + let create_store_before tree = + let+ Store.Tree.{ nodes; leafs; skips; depth; width } = + Store.Tree.stats ~force:false tree + in + Def.{ nodes; leafs; skips; depth; width } + + let create_store_after tree = + let* watched_nodes_length = + Lwt_list.map_s + (fun (_, steps) -> Store.Tree.length tree steps) + Def.step_list_per_watched_node + in + Lwt.return Def.{ watched_nodes_length } + + let commit_begin t tree = + short_op_begin t; + let stats_before = + Bag_of_stats.create t.store_path t.prev_merge_durations + in + t.prev_merge_durations <- Index.Stats.((get ()).merge_durations); + let+ store_before = create_store_before tree in + t.commit_before <- (stats_before, store_before) + + let commit_end t tree = + let duration = Mtime_clock.count t.t0 |> Mtime.Span.to_s in + let duration = duration |> Int32.bits_of_float in + let stats_after = Bag_of_stats.create t.store_path t.prev_merge_durations in + t.prev_merge_durations <- Index.Stats.((get ()).merge_durations); + let+ store_after = create_store_after tree in + let op = + `Commit + Def. + { + duration; + before = fst t.commit_before; + after = stats_after; + store_before = snd t.commit_before; + store_after; + } + in + Def.append_row t.writer op +end diff --git a/vendors/irmin/bench/irmin-pack/trace_common.ml b/vendors/irmin/bench/irmin-pack/trace_common.ml new file mode 100644 index 000000000000..ce2773d0cd50 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_common.ml @@ -0,0 +1,285 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Trace_common] contains utility to simplify the management of files using + the following layout: + + {v + - Magic (Magic.t, 8 bytes) + - Version (int32, 4 bytes) + - Length of header (varint, >=1 byte) + - Header (header_t, _ bytes) + - Arbitrary long series of rows, of unspecified length, each prefixed by their length: + - Length of row (varint, >=1 byte) + - Row (row_t, _ bytes) + v} + + This file is meant to be used from Tezos. OCaml version 4.09 and the 32bit + architecture should be supported. + + {3 Example} + + {[ + module Example = struct + module V2 = struct + let version = 2 + + type header = unit [@@deriving repr] + type row = [ `A | `B | `C ] [@@deriving repr] + end + + module V1 = struct + let version = 1 + + type header = unit [@@deriving repr] + type row = [ `A | `B ] [@@deriving repr] + + let to_v2 x = (x :> V2.row) + end + + module V0 = struct + let version = 0 + + type header = unit [@@deriving repr] + type row = [ `A of int | `B of int ] [@@deriving repr] + + let to_v1 = function `A _ -> `A | `B _ -> `B + end + + module Latest = V2 + include Latest + + include Trace_common.Io (struct + module Latest = Latest + + let magic = Trace_common.Magic.of_string "Magique_" + + let get_version_converter = function + | 2 -> + Trace_common.Version_converter + { + header_t = V2.header_t; + row_t = V2.row_t; + upgrade_header = Fun.id; + upgrade_row = Fun.id; + } + | 1 -> + Version_converter + { + header_t = V1.header_t; + row_t = V1.row_t; + upgrade_header = Fun.id; + upgrade_row = V1.to_v2; + } + | 0 -> + Version_converter + { + header_t = V0.header_t; + row_t = V0.row_t; + upgrade_header = Fun.id; + upgrade_row = (fun x -> V0.to_v1 x |> V1.to_v2); + } + | i -> Fmt.invalid_arg "Unknown Example version %d" i + end) + end + ]} *) + +module Seq = struct + include Seq + + (* Backported from ocaml 4.11 *) + let rec unfold f u () = + match f u with None -> Nil | Some (x, u') -> Cons (x, unfold f u') +end + +module Magic : sig + type t + + val of_string : string -> t + val to_string : t -> string + val pp : Format.formatter -> t -> unit +end = struct + type t = string + + let of_string s = + if String.length s <> 8 then + invalid_arg "Magic.of_string, string should have 8 chars"; + s + + let to_string s = s + let pp ppf s = Format.fprintf ppf "%s" (String.escaped s) +end + +type ('latest_header, 'latest_row, 'header, 'row) version_converter' = { + header_t : 'header Repr.ty; + row_t : 'row Repr.ty; + upgrade_header : 'header -> 'latest_header; + upgrade_row : 'row -> 'latest_row; +} +(** Contains everything needed to read a file as if it is written with the + lastest version. *) + +(** A box containing the above record *) +type ('latest_header, 'latest_row) version_converter = + | Version_converter : + ('latest_header, 'latest_row, 'header, 'row) version_converter' + -> ('latest_header, 'latest_row) version_converter + +module type File_format = sig + (** The latest up-to-date definition of the file format *) + module Latest : sig + val version : int + + type header [@@deriving repr] + type row [@@deriving repr] + end + + val magic : Magic.t + + val get_version_converter : + int -> (Latest.header, Latest.row) version_converter +end + +(** Very similar to what can be found in "repr/type_binary.ml", but working + straight off channels. + + [Var_int.read_exn] reads the chars one by one from the provided [chan]. The + recursion stops as soon as a read char has its 8th bit equal to [0]. + + [Var_int.write] could be implemented using [Repr.encode_bin int], but since + [read_exn] isn't implemented using repr, [write] isn't either. *) +module Var_int = struct + let chars = + Array.init 256 (fun i -> Bytes.unsafe_to_string (Bytes.make 1 (Char.chr i))) + + let write : int -> out_channel -> unit = + let int i k = + let rec aux n k = + if n >= 0 && n < 128 then k chars.(n) + else + let out = 128 lor (n land 127) in + k chars.(out); + aux (n lsr 7) k + in + aux i k + in + fun i chan -> int i (output_string chan) + + let read_exn : in_channel -> int = + fun chan -> + let max_bits = Sys.word_size - 1 in + let rec aux n p = + if p >= max_bits then failwith "Failed to decode varint"; + let i = input_char chan |> Char.code in + let n = n + ((i land 127) lsl p) in + if i >= 0 && i < 128 then n else aux n (p + 7) + in + aux 0 0 +end + +(** Derive the IO operations from a file format. Only the write operations are + performance sensitive, the read operations are not. *) +module Io (Ff : File_format) = struct + let decode_i32 = Repr.(decode_bin int32 |> unstage) + let encode_i32 = Repr.(encode_bin int32 |> unstage) + let encode_lheader = Repr.(encode_bin Ff.Latest.header_t |> unstage) + let encode_lrow = Repr.(encode_bin Ff.Latest.row_t |> unstage) + let magic = Ff.magic + + let read_with_prefix_exn : (string -> int ref -> 'a) -> in_channel -> 'a = + fun decode chan -> + (* First read the prefix *) + let len = Var_int.read_exn chan in + (* Then read the repr. *) + let pos_ref = ref 0 in + let v = + (* This could fail if [len] is not long enough for repr (corruption) *) + decode (really_input_string chan len) pos_ref + in + if len <> !pos_ref then + Fmt.failwith + "An value read in the Trace was expected to take %d bytes, but it took \ + only %d." + len !pos_ref; + v + + let decoded_seq_of_encoded_chan_with_prefixes : + 'a Repr.ty -> in_channel -> 'a Seq.t = + fun repr chan -> + let decode = Repr.decode_bin repr |> Repr.unstage in + let produce_row () = + try + let row = read_with_prefix_exn decode chan in + Some (row, ()) + with End_of_file -> None + in + Seq.unfold produce_row () + + let open_reader : string -> Ff.Latest.header * Ff.Latest.row Seq.t = + fun path -> + let chan = open_in_bin path in + let len = LargeFile.in_channel_length chan in + if len < 12L then + Fmt.invalid_arg "File '%s' should be at least 12 byte long." path; + + let magic = Magic.of_string (really_input_string chan 8) in + if magic <> Ff.magic then + Fmt.invalid_arg "File '%s' has magic '%a'. Expected '%a'." path Magic.pp + magic Magic.pp Ff.magic; + + let (Version_converter vc) = + let pos_ref = ref 0 in + let version = decode_i32 (really_input_string chan 4) pos_ref in + assert (!pos_ref = 4); + Ff.get_version_converter (Int32.to_int version) + in + + let header = + let decode_header = Repr.(decode_bin vc.header_t |> unstage) in + read_with_prefix_exn decode_header chan |> vc.upgrade_header + in + let seq = + decoded_seq_of_encoded_chan_with_prefixes vc.row_t chan + |> Seq.map vc.upgrade_row + in + (header, seq) + + type writer = { path : string; channel : out_channel; buffer : Buffer.t } + + let create_file path header = + let channel = open_out path in + let buffer = Buffer.create 0 in + output_string channel (Magic.to_string Ff.magic); + encode_i32 (Int32.of_int Ff.Latest.version) (output_string channel); + encode_lheader header (Buffer.add_string buffer); + Var_int.write (Buffer.length buffer) channel; + output_string channel (Buffer.contents buffer); + Buffer.clear buffer; + { path; channel; buffer } + + let append_row { channel; buffer; _ } row = + encode_lrow row (Buffer.add_string buffer); + Var_int.write (Buffer.length buffer) channel; + output_string channel (Buffer.contents buffer); + Buffer.clear buffer + + let flush { channel; _ } = flush channel + let close { channel; _ } = close_out channel + + let remove { channel; path; _ } = + close_out channel; + Sys.remove path +end diff --git a/vendors/irmin/bench/irmin-pack/trace_definitions.ml b/vendors/irmin/bench/irmin-pack/trace_definitions.ml new file mode 100644 index 000000000000..bfaecf2d66be --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_definitions.ml @@ -0,0 +1,505 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Traces file format definitions. + + This file is meant to be used from Tezos. OCaml version 4.09 and the 32bit + architecture should be supported. + + {3 Traces Workflow} + + A Tezos node (may) output a [Raw_replayable_trace] file. Such a trace should + be postprocessed to create a [Replayable_trace]. + + A Tezos node (may) output a [Stat_trace] file. + + {e trace_stats.exe summarise} takes a [Stat_trace] file and summarises it to + a {e stat_summary.json} file. + + A series of python script take a {e stat_summary.json} file and produce + plots (e.g. png files). + + {e tree.exe} takes a [Replayable_trace] file, internally produces a + [Stat_trace] file and yields it to [Trace_stat_summary] to produce a + {e stat_summary.json} file. *) + +(** [Replayable_trace], a trace of Tezos's interactions with Irmin. + + {3 Interleaved Contexts and Commits} + + All the recorded operations in Tezos operate on (and create new) immutable + records of type [context]. Most of the time, everything is linear (i.e. the + input context to an operation is the latest output context), but there + sometimes are several parallel chains of contexts, where all but one will + end up being discarded. + + Similarly to contexts, commits are not always linear, i.e. a checkout may + choose a parent that is not the latest commit. + + To solve this conundrum when replaying the trace, we need to remember all + the [context_id -> tree] and [trace commit hash -> real commit hash] pairs + to make sure an operation is operating on the right parent. + + In the trace, the context indices and the commit hashes are 'scoped', + meaning that they are tagged with a boolean information indicating if this + is the very last occurence of that value in the trace. This way we can + discard a recorded pair as soon as possible. + + In practice, there is only 1 context and 1 commit in history, and sometimes + 0 or 2, but the code is ready for more. *) +module Replayable_trace = struct + module V0 = struct + let version = 0 + + type header = unit [@@deriving repr] + type 'a scope = Forget of 'a | Keep of 'a [@@deriving repr] + type key = string list [@@deriving repr] + type hash = string [@@deriving repr] + type message = string [@@deriving repr] + type context_id = int64 [@@deriving repr] + + type add = { + key : key; + value : string; + in_ctx_id : context_id scope; + out_ctx_id : context_id scope; + } + [@@deriving repr] + + type copy = { + key_src : key; + key_dst : key; + in_ctx_id : context_id scope; + out_ctx_id : context_id scope; + } + [@@deriving repr] + + type commit = { + hash : hash scope; + date : int64; + message : message; + parents : hash scope list; + in_ctx_id : context_id scope; + } + [@@deriving repr] + + type row = + (* Operation(s) that create a context from none *) + | Checkout of hash scope * context_id scope + (* Operations that create a context from one *) + | Add of add + | Remove of key * context_id scope * context_id scope + | Copy of copy + (* Operations that just read a context *) + | Find of key * bool * context_id scope + | Mem of key * bool * context_id scope + | Mem_tree of key * bool * context_id scope + | Commit of commit + [@@deriving repr] + end + + module Latest = V0 + include Latest + + include Trace_common.Io (struct + module Latest = Latest + + (** Irmin's Replayable Bootstrap Trace *) + let magic = Trace_common.Magic.of_string "IrmRepBT" + + let get_version_converter = function + | 0 -> + Trace_common.Version_converter + { + header_t = V0.header_t; + row_t = V0.row_t; + upgrade_header = Fun.id; + upgrade_row = Fun.id; + } + | i -> Fmt.invalid_arg "Unknown Replayable_trace version %d" i + end) +end + +(** Trace of a tezos node run, or a replay run. + + May be summarised to a JSON file. + + {3 Implicitly Auto-Upgradable File Format} + + The stat trace has these two properties: + + - It supports extensions, in order to change or add new stats in the future. + - Old trace files from old versions are still readable. + + There are multiple reasons for wanting compatibility with old versions: + + - Because one of the goal of the benchmarks is to assess the evolution of + performances across distant versions of irmin, we need stability in order + to avoid recomputing everything every time. + - When those traces will be produced by Tezos nodes, we have no control over + the version of those traces. + + For this system to work, the "decoding shape" of a version of the stat trace + shouldn't ever change (once fixed). The way the trace is built for a version + should be stable too. + + To modify something in the definition or the collection: append a new + version. *) +module Stat_trace = struct + module V0 = struct + let version = 0 + + type float32 = int32 [@@deriving repr] + + type pack = { + finds : int; + cache_misses : int; + appended_hashes : int; + appended_offsets : int; + } + [@@deriving repr] + (** Stats extracted from [Irmin_pack.Stats.get ()]. *) + + type tree = { + contents_hash : int; + contents_find : int; + contents_add : int; + node_hash : int; + node_mem : int; + node_add : int; + node_find : int; + node_val_v : int; + node_val_find : int; + node_val_list : int; + } + [@@deriving repr] + (** Stats extracted from [Irmin.Tree.counters ()]. *) + + type index = { + bytes_read : int; + nb_reads : int; + bytes_written : int; + nb_writes : int; + nb_merge : int; + new_merge_durations : float list; + } + [@@deriving repr] + (** Stats extracted from [Index.Stats.get ()]. + + [new_merge_durations] is not just a mirror of + [Index.Stats.merge_durations], it only contains the new entries since + the last time it was recorded. This list is always empty when in the + header. *) + + type gc = { + minor_words : float; + promoted_words : float; + major_words : float; + minor_collections : int; + major_collections : int; + heap_words : int; + compactions : int; + top_heap_words : int; + stack_size : int; + } + [@@deriving repr] + (** Stats extracted from [Gc.quick_stat ()]. *) + + type disk = { + index_data : int64; + index_log : int64; + index_log_async : int64; + store_dict : int64; + store_pack : int64; + } + [@@deriving repr] + (** Stats extracted from filesystem. Requires the path to the irmin store. *) + + type 'pack_stats bag_of_stats_base = { + pack : 'pack_stats; + tree : tree; + index : index; + gc : gc; + disk : disk; + timestamp_wall : float; + timestamp_cpu : float; + } + [@@deriving repr] + (** Melting pot of stats, recorded before and after every commits. + + They are necessary in order to compute any throughput analytics. *) + + type store_before = { + nodes : int; + leafs : int; + skips : int; + depth : int; + width : int; + } + [@@deriving repr] + (** Stats computed from the [tree] value passed to the commit operation, + before the commit, when the tree still carries the modifications brought + by the previous operations. *) + + type watched_node = + [ `Contracts_index + | `Big_maps_index + | `Rolls_index + | `Rolls_owner_current + | `Commitments + | `Contracts_index_ed25519 + | `Contracts_index_originated ] + [@@deriving repr, enum] + + type store_after = { watched_nodes_length : int list } [@@deriving repr] + (** Stats computed on the [tree] value passed to the commit operation, after + the commit, when the inode has been reconstructed and that [Tree.length] + is now innexpensive to perform. *) + + type 'pack_stats commit_base = { + duration : float32; + before : 'pack_stats bag_of_stats_base; + after : 'pack_stats bag_of_stats_base; + store_before : store_before; + store_after : store_after; + } + [@@deriving repr] + + type 'pack_stats row_base = + [ `Add of float32 + | `Remove of float32 + | `Find of float32 + | `Mem of float32 + | `Mem_tree of float32 + | `Checkout of float32 + | `Copy of float32 + | `Commit of 'pack_stats commit_base ] + [@@deriving repr] + + type row = pack row_base [@@deriving repr] + (** Stats gathered while running an operation. + + {3 Operation durations} + + For each operation we record its wall time length using a [float32], a + [float16] would be suitable too (it has >3 digits of precision). + + {3 Time and disk performance considerations} + + On commit we record a lot of things, thankfuly the frequency is low: + ~1/600. 599 small operations weigh ~3600 bytes, 1 commit weighs ~300 + bytes. The trace reaches 1GB after ~250k commits. *) + + type setup_play = unit [@@deriving repr] + (** Informations gathered from the tezos node. + + Noting so far. Any ideas? *) + + type setup_replay = { + path_conversion : [ `None | `V1 | `V0_and_v1 | `V0 ]; + artefacts_dir : string; + } + [@@deriving repr] + (** Informations gathered from the tree.exe parameters. *) + + type config = { + inode_config : int * int * int; + store_type : [ `Pack | `Pack_layered | `Pack_mem ]; + setup : [ `Play of setup_play | `Replay of setup_replay ]; + } + [@@deriving repr] + + type 'pack_stats header_base = { + config : config; + hostname : string; + timeofday : float; + word_size : int; + initial_stats : 'pack_stats bag_of_stats_base; + } + [@@deriving repr] + + type header = pack header_base [@@deriving repr] + (** File header. + + {3 Timestamps} + + [stats.timestamp_wall] and [stats.timestamp_cpu] are the starting points + of the trace, they are to be substracted from their counterpart in + [commit] to compute time spans. + + [timeofday] is the date and time at which the stats started to be + accumulated. + + [stats.timestamp_wall] may originate from [Mtime_clock.now]. + + [stats.timestamp_cpu] may originate from [Sys.time]. + + It would be great to be able to record the library/sources versions. *) + + type commit = pack commit_base [@@deriving repr] + type bag_of_stats = pack bag_of_stats_base [@@deriving repr] + end + + module V1 = struct + include V0 + + let version = 1 + + type finds = { + total : int; + from_staging : int; + from_lru : int; + from_pack_direct : int; + from_pack_indexed : int; + } + [@@deriving repr] + (** Stats extracted from [Irmin_pack.Stats.get ()]. *) + + type pack = { + finds : finds; + appended_hashes : int; + appended_offsets : int; + inode_add : int; + inode_remove : int; + inode_of_seq : int; + inode_of_raw : int; + inode_rec_add : int; + inode_rec_remove : int; + inode_to_binv : int; + inode_decode_bin : int; + inode_encode_bin : int; + } + [@@deriving repr] + (** Stats extracted from [Irmin_pack.Stats.get ()]. *) + + type commit = pack commit_base [@@deriving repr] + type bag_of_stats = pack bag_of_stats_base [@@deriving repr] + type row = pack row_base [@@deriving repr] + type header = pack header_base [@@deriving repr] + + (* [v0.cache_misses] is lost *) + let v1pack_of_v0pack (v0 : V0.pack) : pack = + { + finds = + { + total = v0.finds; + from_staging = 0; + from_lru = 0; + from_pack_direct = 0; + from_pack_indexed = 0; + }; + appended_hashes = v0.appended_hashes; + appended_offsets = v0.appended_offsets; + inode_add = 0; + inode_remove = 0; + inode_of_seq = 0; + inode_of_raw = 0; + inode_rec_add = 0; + inode_rec_remove = 0; + inode_to_binv = 0; + inode_decode_bin = 0; + inode_encode_bin = 0; + } + + let v1bos_of_v0bos (v0 : V0.bag_of_stats) : bag_of_stats = + { + pack = v1pack_of_v0pack v0.pack; + tree = v0.tree; + index = v0.index; + gc = v0.gc; + disk = v0.disk; + timestamp_wall = v0.timestamp_wall; + timestamp_cpu = v0.timestamp_cpu; + } + + let v1commit_of_v0commit (v0 : V0.commit) : commit = + { + duration = v0.duration; + before = v1bos_of_v0bos v0.before; + after = v1bos_of_v0bos v0.after; + store_before = v0.store_before; + store_after = v0.store_after; + } + + let v1row_of_v0row (v0 : V0.row) : row = + match v0 with + | `Commit payload -> `Commit (v1commit_of_v0commit payload) + | ( `Add _ | `Remove _ | `Find _ | `Mem _ | `Mem_tree _ | `Checkout _ + | `Copy _ ) as v0 -> + v0 + + let v1header_of_v0header (v0 : V0.header) : header = + { + config = v0.config; + hostname = v0.hostname; + timeofday = v0.timeofday; + word_size = v0.word_size; + initial_stats = v1bos_of_v0bos v0.initial_stats; + } + end + + module Latest = V1 + include Latest + + let watched_nodes : watched_node list = + List.init (max_watched_node + 1) (fun i -> + watched_node_of_enum i |> Option.get) + + let step_list_per_watched_node = + let aux = function + | `Contracts_index -> [ "data"; "contracts"; "index" ] + | `Big_maps_index -> [ "data"; "big_maps"; "index" ] + | `Rolls_index -> [ "data"; "rolls"; "index" ] + | `Rolls_owner_current -> [ "data"; "rolls"; "owner"; "current" ] + | `Commitments -> [ "data"; "commitments" ] + | `Lol -> [] + | `Contracts_index_ed25519 -> [ "data"; "contracts"; "index"; "ed25519" ] + | `Contracts_index_originated -> + [ "data"; "contracts"; "index"; "originated" ] + in + List.combine watched_nodes (List.map aux watched_nodes) + + let path_per_watched_node = + List.map + (fun (k, l) -> (k, "/" ^ String.concat "/" l)) + step_list_per_watched_node + + include Trace_common.Io (struct + module Latest = Latest + + (** Irmin's Stats Bootstrap Trace *) + let magic = Trace_common.Magic.of_string "IrmStaBT" + + let get_version_converter = function + | 0 -> + Trace_common.Version_converter + { + header_t = V0.header_t; + row_t = V0.row_t; + upgrade_header = v1header_of_v0header; + upgrade_row = v1row_of_v0row; + } + | 1 -> + Trace_common.Version_converter + { + header_t = V1.header_t; + row_t = V1.row_t; + upgrade_header = Fun.id; + upgrade_row = Fun.id; + } + | i -> Fmt.invalid_arg "Unknown Stat_trace version %d" i + end) +end diff --git a/vendors/irmin/bench/irmin-pack/trace_replay.ml b/vendors/irmin/bench/irmin-pack/trace_replay.ml new file mode 100644 index 000000000000..e0bed82ebcc8 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_replay.ml @@ -0,0 +1,524 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends +open Bench_common +include Trace_replay_intf +module Def = Trace_definitions.Replayable_trace +module Seq = Trace_common.Seq + +let is_hex_char = function + | '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' -> true + | _ -> false + +let is_2char_hex s = + if String.length s <> 2 then false + else s |> String.to_seq |> List.of_seq |> List.for_all is_hex_char + +let all_6_2char_hex a b c d e f = + is_2char_hex a + && is_2char_hex b + && is_2char_hex c + && is_2char_hex d + && is_2char_hex e + && is_2char_hex f + +let is_30char_hex s = + if String.length s <> 30 then false + else s |> String.to_seq |> List.of_seq |> List.for_all is_hex_char + +(** This function flattens all the 6 step-long chunks forming 40 byte-long + hashes to a single step. + + Those flattenings are performed during the trace replay, i.e. they count in + the total time. + + If a path contains 2 or more of those patterns, only the leftmost one is + converted. + + A chopped hash has this form + + {v ([0-9a-f]{2}/){5}[0-9a-f]{30} v} + + and is flattened to that form + + {v [0-9a-f]{40} v} *) +let flatten_v0 key = + let rec aux rev_prefix suffix = + match suffix with + | a :: b :: c :: d :: e :: f :: tl + when is_2char_hex a + && is_2char_hex b + && is_2char_hex c + && is_2char_hex d + && is_2char_hex e + && is_30char_hex f -> + let mid = a ^ b ^ c ^ d ^ e ^ f in + aux (mid :: rev_prefix) tl + | hd :: tl -> aux (hd :: rev_prefix) tl + | [] -> List.rev rev_prefix + in + aux [] key + +(** This function removes from the paths all the 6 step-long hashes of this form + + {v ([0-9a-f]{2}/){6} v} + + Those flattenings are performed during the trace replay, i.e. they count in + the total time. + + The paths in tezos: + https://www.dailambda.jp/blog/2020-05-11-plebeia/#tezos-path + + Tezos' PR introducing this flattening: + https://gitlab.com/tezos/tezos/-/merge_requests/2771 *) +let flatten_v1 = function + | "data" :: "contracts" :: "index" :: a :: b :: c :: d :: e :: f :: tl + when all_6_2char_hex a b c d e f -> ( + match tl with + | hd :: "delegated" :: a :: b :: c :: d :: e :: f :: tl + when all_6_2char_hex a b c d e f -> + "data" :: "contracts" :: "index" :: hd :: "delegated" :: tl + | _ -> "data" :: "contracts" :: "index" :: tl) + | "data" :: "big_maps" :: "index" :: a :: b :: c :: d :: e :: f :: tl + when all_6_2char_hex a b c d e f -> + "data" :: "big_maps" :: "index" :: tl + | "data" :: "rolls" :: "index" :: _ :: _ :: tl -> + "data" :: "rolls" :: "index" :: tl + | "data" :: "rolls" :: "owner" :: "current" :: _ :: _ :: tl -> + "data" :: "rolls" :: "owner" :: "current" :: tl + | "data" :: "rolls" :: "owner" :: "snapshot" :: a :: b :: _ :: _ :: tl -> + "data" :: "rolls" :: "owner" :: "snapshot" :: a :: b :: tl + | l -> l + +let flatten_op ~flatten_path = function + | Def.Checkout _ as op -> op + | Add op -> Add { op with key = flatten_path op.key } + | Remove (keys, in_ctx_id, out_ctx_id) -> + Remove (flatten_path keys, in_ctx_id, out_ctx_id) + | Copy op -> + Copy + { + op with + key_src = flatten_path op.key_src; + key_dst = flatten_path op.key_dst; + } + | Find (keys, b, ctx) -> Find (flatten_path keys, b, ctx) + | Mem (keys, b, ctx) -> Mem (flatten_path keys, b, ctx) + | Mem_tree (keys, b, ctx) -> Mem_tree (flatten_path keys, b, ctx) + | Commit _ as op -> op + +let open_commit_sequence max_ncommits path_conversion path : Def.row list Seq.t + = + let flatten_path = + match path_conversion with + | `None -> Fun.id + | `V1 -> flatten_v1 + | `V0 -> flatten_v0 + | `V0_and_v1 -> fun p -> flatten_v1 p |> flatten_v0 + in + + let rec aux (ops_seq, commits_sent, ops) = + if commits_sent >= max_ncommits then None + else + match ops_seq () with + | Seq.Nil -> None + | Cons ((Def.Commit _ as op), ops_seq) -> + let ops = op :: ops |> List.rev in + Some (ops, (ops_seq, commits_sent + 1, [])) + | Cons (op, ops_seq) -> + let op = flatten_op ~flatten_path op in + aux (ops_seq, commits_sent, op :: ops) + in + let _header, ops_seq = Def.open_reader path in + Seq.unfold aux (ops_seq, 0, []) + +module Make (Store : Store) = struct + include Config + module Stat_collector = Trace_collection.Make_stat (Store) + + type key = Store.contents_key [@@deriving irmin ~pp] + type context = { tree : Store.tree } + + type t = { + contexts : (int64, context) Hashtbl.t; + hash_corresps : (Def.hash, Store.commit_key) Hashtbl.t; + mutable commits_since_start_or_gc : int; + mutable latest_commit_idx : int; + (** the most recent commit idx to be replayed. initial value is -1 *) + mutable gc_count : int; + key_per_commit_idx : (int, Store.commit_key) Hashtbl.t; + } + + let error_find op k b n_op n_c in_ctx_id = + Fmt.failwith + "Cannot reproduce operation %d on ctx %Ld of commit %d %s @[k = %a@] \ + expected %b" + n_op in_ctx_id n_c op + Fmt.(list ~sep:comma string) + k b + + let unscope = function Def.Forget v -> v | Keep v -> v + + let maybe_forget_hash t = function + | Def.Forget h -> Hashtbl.remove t.hash_corresps h + | Keep _ -> () + + let maybe_forget_ctx t = function + | Def.Forget ctx -> Hashtbl.remove t.contexts ctx + | Keep _ -> () + + let exec_checkout t stats repo h_trace out_ctx_id = + let h_store = Hashtbl.find t.hash_corresps (unscope h_trace) in + maybe_forget_hash t h_trace; + Stat_collector.short_op_begin stats; + Store.Commit.of_key repo h_store >|= function + | None -> failwith "prev commit not found" + | Some commit -> + let tree = Store.Commit.tree commit in + Stat_collector.short_op_end stats `Checkout; + Hashtbl.add t.contexts (unscope out_ctx_id) { tree }; + maybe_forget_ctx t out_ctx_id + + let exec_add t stats key v in_ctx_id out_ctx_id empty_blobs = + let v = if empty_blobs then Bytes.empty else Bytes.of_string v in + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + Stat_collector.short_op_begin stats; + let+ tree = Store.Tree.add tree key v in + Stat_collector.short_op_end stats `Add; + Hashtbl.add t.contexts (unscope out_ctx_id) { tree }; + maybe_forget_ctx t out_ctx_id + + let exec_remove t stats keys in_ctx_id out_ctx_id = + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + Stat_collector.short_op_begin stats; + let+ tree = Store.Tree.remove tree keys in + Stat_collector.short_op_end stats `Remove; + Hashtbl.add t.contexts (unscope out_ctx_id) { tree }; + maybe_forget_ctx t out_ctx_id + + let exec_copy t stats from to_ in_ctx_id out_ctx_id = + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + Stat_collector.short_op_begin stats; + Store.Tree.find_tree tree from >>= function + | None -> failwith "Couldn't find tree in exec_copy" + | Some sub_tree -> + let* tree = Store.Tree.add_tree tree to_ sub_tree in + Stat_collector.short_op_end stats `Copy; + Hashtbl.add t.contexts (unscope out_ctx_id) { tree }; + maybe_forget_ctx t out_ctx_id; + Lwt.return_unit + + let exec_find t stats n i keys b in_ctx_id = + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + Stat_collector.short_op_begin stats; + let+ query = Store.Tree.find tree keys in + Stat_collector.short_op_end stats `Find; + if Option.is_some query <> b then + error_find "find" keys b i n (unscope in_ctx_id) + + let exec_mem t stats n i keys b in_ctx_id = + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + Stat_collector.short_op_begin stats; + let+ b' = Store.Tree.mem tree keys in + Stat_collector.short_op_end stats `Mem; + if b <> b' then error_find "mem" keys b i n (unscope in_ctx_id) + + let exec_mem_tree t stats n i keys b in_ctx_id = + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + Stat_collector.short_op_begin stats; + let+ b' = Store.Tree.mem_tree tree keys in + Stat_collector.short_op_end stats `Mem_tree; + if b <> b' then error_find "mem_tree" keys b i n (unscope in_ctx_id) + + let check_hash_trace h_trace h_store = + let h_store = Irmin.Type.(to_string Store.Hash.t) h_store in + if h_trace <> h_store then + Fmt.failwith "hash replay %s, hash trace %s" h_store h_trace + + let exec_commit t stats repo h_trace date message parents_trace in_ctx_id + check_hash = + let parents_store = + parents_trace + |> List.map unscope + |> List.map (Hashtbl.find t.hash_corresps) + in + List.iter (maybe_forget_hash t) parents_trace; + let { tree } = Hashtbl.find t.contexts (unscope in_ctx_id) in + maybe_forget_ctx t in_ctx_id; + let* () = Stat_collector.commit_begin stats tree in + let* _ = + (* in tezos commits call Tree.list first for the unshallow operation *) + Store.Tree.list tree [] + in + let info = Store.Info.v ~author:"Tezos" ~message date in + let* commit = Store.Commit.v repo ~info ~parents:parents_store tree in + let+ () = Stat_collector.commit_end stats tree in + Store.Tree.clear tree; + let k_store, h_store = Store.Commit.(key commit, hash commit) in + if check_hash then check_hash_trace (unscope h_trace) h_store; + (* It's okey to have [h_trace] already in history. It corresponds to + * re-commiting the same thing, hence the [.replace] below. *) + Hashtbl.replace t.hash_corresps (unscope h_trace) k_store; + maybe_forget_hash t h_trace; + let () = + let tbl = t.key_per_commit_idx in + Hashtbl.add tbl (Hashtbl.length tbl) k_store + in + () + + let add_operations t repo operations n stats check_hash empty_blobs = + let rec aux l i = + match l with + | Def.Checkout (h, out_ctx_id) :: tl -> + let* () = exec_checkout t stats repo h out_ctx_id in + aux tl (i + 1) + | Add op :: tl -> + let* () = + exec_add t stats op.key op.value op.in_ctx_id op.out_ctx_id + empty_blobs + in + aux tl (i + 1) + | Remove (keys, in_ctx_id, out_ctx_id) :: tl -> + let* () = exec_remove t stats keys in_ctx_id out_ctx_id in + aux tl (i + 1) + | Copy op :: tl -> + let* () = + exec_copy t stats op.key_src op.key_dst op.in_ctx_id op.out_ctx_id + in + aux tl (i + 1) + | Find (keys, b, in_ctx_id) :: tl -> + let* () = exec_find t stats n i keys b in_ctx_id in + aux tl (i + 1) + | Mem (keys, b, in_ctx_id) :: tl -> + let* () = exec_mem t stats n i keys b in_ctx_id in + aux tl (i + 1) + | Mem_tree (keys, b, in_ctx_id) :: tl -> + let* () = exec_mem_tree t stats n i keys b in_ctx_id in + aux tl (i + 1) + | [ Commit op ] -> + exec_commit t stats repo op.hash op.date op.message op.parents + op.in_ctx_id check_hash + | Commit _ :: _ | [] -> + failwith "A batch of operation should end with a commit" + in + aux operations 0 + + let gc_actions config i commits_since_start_or_gc gc_count = + let gc_enabled = + (* Is GC enabled at all? *) + config.gc_every > 0 + in + let gc_wait_enabled = + (* Will GC wait be called at all? *) + gc_enabled && config.gc_wait_after > 0 + in + + let first_gc_occured = i <> commits_since_start_or_gc in + + let time_to_split = commits_since_start_or_gc = config.gc_every in + + let time_to_start = + (* Is it time to start GC? *) + if first_gc_occured then time_to_split + else + let gc_commit_idx = + (* [i] is the replay step and also the commit index of the next + commit and also the number of commits replayed so far. + + [i - t.gc_distance_in_the_past - 1] is the index of the commit we + want to GC. *) + i - config.gc_distance_in_the_past - 1 + in + gc_commit_idx = 1 + in + + let time_to_wait = + (* Is it time to wait GC? *) + if first_gc_occured then commits_since_start_or_gc = config.gc_wait_after + else false + in + + let time_to_add_volume = + config.add_volume_every > 0 + && time_to_split + && gc_count > 0 + && gc_count mod config.add_volume_every = 0 + in + + let really_split = gc_enabled && time_to_split in + let really_start_gc = gc_enabled && time_to_start in + let really_wait_gc = gc_wait_enabled && time_to_wait in + let really_add_volume = time_to_add_volume in + (really_wait_gc, really_start_gc, really_split, really_add_volume) + + let add_commits config repo commit_seq on_commit on_end stats check_hash + empty_blobs = + let max_ncommits = config.number_of_commits_to_replay in + with_progress_bar ~message:"Replaying trace" ~n:max_ncommits ~unit:"commit" + @@ fun prog -> + let t = + { + contexts = Hashtbl.create 3; + hash_corresps = Hashtbl.create 3; + commits_since_start_or_gc = 0; + gc_count = 0; + latest_commit_idx = -1; + key_per_commit_idx = Hashtbl.create 3; + } + in + + (* Manually add genesis context *) + Hashtbl.add t.contexts 0L { tree = Store.Tree.empty () }; + + let rec aux commit_seq i = + match commit_seq () with + | Seq.Nil -> on_end () >|= fun () -> i + | Cons (ops, commit_seq) -> + let really_wait_gc, really_start_gc, really_split, really_add_volume = + gc_actions config i t.commits_since_start_or_gc t.gc_count + in + (* Split before GC to simulate how it is inteded to be used. *) + let () = if really_split then Store.split repo in + let () = if really_add_volume then Store.add_volume repo in + let* () = + if really_wait_gc then ( + [%logs.app + "Waiting gc while latest commit has idx %d" t.latest_commit_idx]; + Store.gc_wait repo) + else Lwt.return_unit + in + let* () = + if really_start_gc then ( + (* Starting GC. + + TODO: If the GC-commit is an orphan commit we will have + problems. *) + let gc_commit_idx = + t.latest_commit_idx - config.gc_distance_in_the_past + in + let gc_commit_key = + Hashtbl.find t.key_per_commit_idx gc_commit_idx + in + let gc_start_commit_idx = t.latest_commit_idx in + (* used in closure below to know start commit of gc process *) + t.commits_since_start_or_gc <- 0; + [%logs.app + "Starting gc on commit idx %d with key %a while latest commit \ + has idx %d with key %a" + gc_commit_idx pp_key gc_commit_key gc_start_commit_idx pp_key + (Hashtbl.find t.key_per_commit_idx t.latest_commit_idx)]; + let finished = function + | Ok stats -> + t.gc_count <- t.gc_count + 1; + let commit_idx = t.latest_commit_idx in + let commit_duration = commit_idx - gc_start_commit_idx in + let duration = + Irmin_pack_unix.Stats.Latest_gc.total_duration stats + in + let finalise_duration = + Irmin_pack_unix.Stats.Latest_gc.finalise_duration stats + in + [%logs.app + "Gc ended after %d commits; duration: %fs; \ + finalise_duration: %fs" + commit_duration duration finalise_duration]; + Lwt.return_unit + | Error s -> failwith s + in + Store.gc_run ~finished repo gc_commit_key) + else Lwt.return_unit + in + let* () = add_operations t repo ops i stats check_hash empty_blobs in + t.latest_commit_idx <- i; + let len0 = Hashtbl.length t.contexts in + let len1 = Hashtbl.length t.hash_corresps in + if (len0, len1) <> (0, 1) then + [%logs.app + "\nAfter commit %6d we have %d/%d history sizes" + t.latest_commit_idx len0 len1]; + let* () = + on_commit t.latest_commit_idx + (Hashtbl.find t.key_per_commit_idx t.latest_commit_idx + |> Store.Backend.Commit.Key.to_hash) + in + t.commits_since_start_or_gc <- t.commits_since_start_or_gc + 1; + prog 1; + aux commit_seq (t.latest_commit_idx + 1) + in + aux commit_seq 0 + + let run : type a. _ -> a config -> a Lwt.t = + fun ext_config config -> + let check_hash = + config.path_conversion = `None + && config.inode_config = (32, 256) + && config.empty_blobs = false + in + [%logs.app + "Will %scheck commit hashes against reference." + (if check_hash then "" else "NOT ")]; + let commit_seq = + open_commit_sequence config.number_of_commits_to_replay + config.path_conversion config.replay_trace_path + in + let root = Filename.concat config.artefacts_path "root" in + let* repo, on_commit, on_end = Store.create_repo ~root ext_config in + prepare_artefacts_dir config.artefacts_path; + let stat_path = Filename.concat config.artefacts_path "stat_trace.repr" in + let c = + let entries, stable_hash = config.inode_config in + Trace_definitions.Stat_trace. + { + setup = + `Replay + { + path_conversion = config.path_conversion; + artefacts_dir = config.artefacts_path; + }; + inode_config = (entries, entries, stable_hash); + store_type = config.store_type; + } + in + let stats = Stat_collector.create_file stat_path c root in + Irmin_pack.Stats.reset_stats (); + Lwt.finalize + (fun () -> + let* block_count = + add_commits config repo commit_seq on_commit on_end stats check_hash + config.empty_blobs + in + [%logs.app "Closing repo..."]; + let+ () = Store.Repo.close repo in + Stat_collector.close stats; + match config.return_type with + | Unit -> (() : a) + | Summary -> + [%logs.app "Computing summary..."]; + Trace_stat_summary.summarise ~block_count stat_path) + (fun () -> + if config.keep_stat_trace then ( + [%logs.app "Stat trace kept at %s" stat_path]; + Unix.chmod stat_path 0o444; + Lwt.return_unit) + else Lwt.return (Stat_collector.remove stats)) +end diff --git a/vendors/irmin/bench/irmin-pack/trace_replay.mli b/vendors/irmin/bench/irmin-pack/trace_replay.mli new file mode 100644 index 000000000000..e176c9f38710 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_replay.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Trace_replay_intf.Sigs diff --git a/vendors/irmin/bench/irmin-pack/trace_replay_intf.ml b/vendors/irmin/bench/irmin-pack/trace_replay_intf.ml new file mode 100644 index 000000000000..93d558d2be9b --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_replay_intf.ml @@ -0,0 +1,134 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Config = struct + type _ return_type = + | Unit : unit return_type + | Summary : Trace_stat_summary.t return_type + + type 'a config = { + number_of_commits_to_replay : int; + path_conversion : [ `None | `V1 | `V0_and_v1 | `V0 ]; + inode_config : int * int; + store_type : [ `Pack | `Pack_layered | `Pack_mem ]; + replay_trace_path : string; + artefacts_path : string; + keep_store : bool; + keep_stat_trace : bool; + empty_blobs : bool; + return_type : 'a return_type; + gc_every : int; + gc_distance_in_the_past : int; + gc_wait_after : int; + add_volume_every : int; + } + (** Replay configuration + + [replay_trace_path] points to a specific file that describes the sequence + of operations to replay. You may download one of the following URLs. The + smaller ones are prefix of the larger ones. + + - http://data.tarides.com/irmin/data4_10310commits.repr (0.3GB) + - http://data.tarides.com/irmin/data4_100066commits.repr (2.9GB) + - http://data.tarides.com/irmin/data_1343496commits.repr (102GB) + + [number_of_commits_to_replay] is the wished number of commits to replay. + If the value is too high, the replay will stop when reaching the end of + [replay_trace_path]. Pick a number of commits depending on the wished + runtime. Here are some reference runtimes that were true for irmin 3.0: + + - [60_457] commits take 3 minutes + - [500_000] commits take 1 hour + - [1_343_496] commits take 5 hours + + [artefacts_path] is the destination for the stats trace and the store. If + both [keep_store] and [keep_stat_trace] are false, the destination will be + emptied at the end of the replay. + + [path_conversion] is the strategy for shortening the paths while + replaying. Was useful when benchmarking irmin on flattened Tezos paths. + + [empty_blobs] make the replay to push the empty string as in all the + blobs, instead of their actual value read in the trace. + + [inode_config] is a pair of ints that will be stored in the results of the + replay. + + A GC is triggered every [gc_every] commits. When GC is triggered, we + select a previous commit that is [gc_distance_in_the_past] commits away + from the current head commit. + + The first GC will be started after [gc_distance_in_the_past + 1] commits + were replayed. [gc_distance_in_the_past] only makes sense if [gc_every] is + not [0]. + + [gc_wait_after] defines how many commits separate the start of a GC and + the moment we block to wait for it to finish. [0] means that we will only + block when the next gc starts or at the end of the replay. This parameter + only makes sense if [gc_every] is not [0]. *) +end + +module type Config = module type of Config + +include Config + +module type Store = sig + type store_config + type key + + include + Irmin.Generic_key.KV + with type Schema.Contents.t = bytes + and type commit_key = key + and type node_key = key + and type contents_key = key + + type on_commit := int -> Hash.t -> unit Lwt.t + type on_end := unit -> unit Lwt.t + + val create_repo : + root:string -> store_config -> (Repo.t * on_commit * on_end) Lwt.t + + val split : repo -> unit + val add_volume : repo -> unit + val gc_wait : repo -> unit Lwt.t + + type stats := Irmin_pack_unix.Stats.Latest_gc.stats + + val gc_run : + ?finished:((stats, string) result -> unit Lwt.t) -> + repo -> + commit_key -> + unit Lwt.t +end + +module type Sigs = sig + include + Config + with type 'a return_type = 'a return_type + and type 'a config = 'a config + + module type Store = Store + + module Make (Store : Store) : sig + include + Config + with type 'a return_type = 'a return_type + and type 'a config = 'a config + + val run : Store.store_config -> 'a config -> 'a Lwt.t + end +end diff --git a/vendors/irmin/bench/irmin-pack/trace_stat_summary.ml b/vendors/irmin/bench/irmin-pack/trace_stat_summary.ml new file mode 100644 index 000000000000..74ef2429b082 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stat_summary.ml @@ -0,0 +1,1106 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Conversion of a [Stat_trace] to a summary that is both pretty-printable and + exportable to JSON. + + The main type [t] here isn't versioned like a [Stat_trace.t] is. + + Computing a summary may take a long time if the input [Stat_trace] is long. + Count ~1000 commits per second. + + This file is NOT meant to be used from Tezos, as opposed to some other + "trace_*" files. *) + +module Def = Trace_definitions.Stat_trace +module Conf = Trace_stat_summary_conf +module Utils = Trace_stat_summary_utils +module Vs = Utils.Variable_summary +module Seq = Trace_common.Seq + +(* Section 1/4 - Type of a summary. *) + +type curve = Utils.curve [@@deriving repr] + +(** A stat trace can be chunked into {e blocks}. A {e blocks} is made of 2 + phases, first the {e buildup} and then the {e commit}. + + The duration of a {e buildup} can be split into 2 parts: 1. the time spend + in each operation and 2. the sum of the time spent between, before and after + all operations. The first being the {e seen buildup} and the second the + {e unseen buildup}. + + The total duration of a block is the sum of the durations of the {e commit}, + the {e seen buildup} and the {e unseen buildup}. + + Caveat: There isn't a one to one correspondance between summary blocks and + Tezos' blocks. A Tezos block is associated to a commit, but a commit is not + necessarily associated to a Tezos block. There are ~50 more commits than + Tezos blocks up to the Edo protocol. *) +module Span = struct + module Key = struct + type atom_seen = + [ `Add | `Remove | `Find | `Mem | `Mem_tree | `Checkout | `Copy | `Commit ] + [@@deriving repr, enum] + (** The unitary operations played. We recorded the length of all of these. *) + + type atom = [ atom_seen | `Unseen ] + (** [atom_seen] plus the time between operations. The sum of these is the + total time. *) + + type phase = [ `Buildup | `Commit ] + (** The two major phases. The sum of these is the total time *) + + type t = + [ `Add + | `Remove + | `Find + | `Mem + | `Mem_tree + | `Checkout + | `Copy + | `Commit + | `Unseen + | `Buildup + | `Block ] + [@@deriving repr, enum] + (** All spans. + + Redefined (i.e. no inheritance) for derivers. *) + + let all_atoms_seen : atom_seen list = + List.init (max_atom_seen + 1) (fun i -> atom_seen_of_enum i |> Option.get) + + let all : t list = List.init (max + 1) (fun i -> of_enum i |> Option.get) + + let to_string : [< t ] -> string = + fun v -> + match String.split_on_char '"' (Irmin.Type.to_string t v) with + | [ ""; s; "" ] -> s |> String.lowercase_ascii + | _ -> failwith "Could not encode span name to json" + + let of_string : string -> (t, [ `Msg of string ]) result = + fun s -> + let s = "\"" ^ String.capitalize_ascii s ^ "\"" in + match Irmin.Type.of_string t s with Ok v -> Ok v | Error _ as e -> e + end + + module Val = struct + type t = { + count : Vs.t; + cumu_count : Vs.t; + duration : Vs.t; + duration_log_scale : Vs.t; + cumu_duration : Vs.t; + } + [@@deriving repr] + (** The [count] variable is the number of occurences of a span per block and + [cumu_count] is the cumulative from the beginning. + + The [duration] variable is the length of a span occurence and + [cumu_duration] is the cumulative from the beginning. The x axis for the + [evolution] is the number of blocks. + + The [count] for [commit] and [unseen] is trivialy equal to 1. The same + is almost true for [checkout] too. *) + end + + module Map = Map.Make (struct + type t = Key.t + + let compare = compare + end) + + type map = Val.t Map.t + + let map_t : map Irmin.Type.t = + let encode map = + Map.bindings map |> List.map (fun (k, v) -> (Key.to_string k, v)) + in + let decode l = + let key_of_string k = + match Key.of_string k with + | Ok k -> k + | Error (`Msg msg) -> + Fmt.failwith "Could not convert string back to key: %s" msg + in + List.map (fun (k, v) -> (key_of_string k, v)) l + |> List.to_seq + |> Map.of_seq + in + Irmin.Type.(map (Json.assoc Val.t) decode encode) +end + +module Watched_node = struct + module Key = struct + type t = Def.watched_node [@@deriving repr] + + let to_string v = + match String.split_on_char '"' (Irmin.Type.to_string t v) with + | [ ""; s; "" ] -> s |> String.lowercase_ascii + | _ -> failwith "Could not encode node name to json" + + let of_string s = + let s = "\"" ^ String.capitalize_ascii s ^ "\"" in + match Irmin.Type.of_string t s with Ok v -> Ok v | Error _ as e -> e + end + + module Val = struct + type t = { value : Vs.t; diff_per_block : Vs.t } [@@deriving repr] + end + + module Map = Map.Make (struct + type t = Key.t + + let compare = compare + end) + + type map = Val.t Map.t + + let map_t : map Irmin.Type.t = + let encode map = + Map.bindings map |> List.map (fun (k, v) -> (Key.to_string k, v)) + in + let decode l = + let key_of_string k = + match Key.of_string k with + | Ok k -> k + | Error (`Msg msg) -> + Fmt.failwith "Could not convert string back to key: %s" msg + in + List.map (fun (k, v) -> (key_of_string k, v)) l + |> List.to_seq + |> Map.of_seq + in + Irmin.Type.(map (Json.assoc Val.t) decode encode) +end + +type bag_stat = { + value_before_commit : Vs.t; + value_after_commit : Vs.t; + diff_per_block : Vs.t; + diff_per_buildup : Vs.t; + diff_per_commit : Vs.t; +} +[@@deriving repr] +(** Summary of an entry contained in [Def.bag_of_stat]. + + Properties of such a variables: + + - Is sampled before each commit operation. + - Is sampled after each commit operation. + - Is sampled in header. + - Most of these entries are expected to grow linearly, it implies that no + smoothing is necessary for the downsampled curve in these cases, and that + the histogram is best viewed on a linear scale - as opposed to a log + scale. The other entries are summarised using + [~is_linearly_increasing:false]. + + The [value_after_commit] is initially fed with the value in the header (i.e. + the value recorded just before the start of the play). *) + +type finds = { + total : bag_stat; + from_staging : bag_stat; + from_lru : bag_stat; + from_pack_direct : bag_stat; + from_pack_indexed : bag_stat; + missing : bag_stat; + cache_miss : bag_stat; +} +[@@deriving repr] + +type pack = { + finds : finds; + appended_hashes : bag_stat; + appended_offsets : bag_stat; + inode_add : bag_stat; + inode_remove : bag_stat; + inode_of_seq : bag_stat; + inode_of_raw : bag_stat; + inode_rec_add : bag_stat; + inode_rec_remove : bag_stat; + inode_to_binv : bag_stat; + inode_decode_bin : bag_stat; + inode_encode_bin : bag_stat; +} +[@@deriving repr] + +type tree = { + contents_hash : bag_stat; + contents_find : bag_stat; + contents_add : bag_stat; + node_hash : bag_stat; + node_mem : bag_stat; + node_add : bag_stat; + node_find : bag_stat; + node_val_v : bag_stat; + node_val_find : bag_stat; + node_val_list : bag_stat; +} +[@@deriving repr] + +type index = { + bytes_read : bag_stat; + nb_reads : bag_stat; + bytes_written : bag_stat; + nb_writes : bag_stat; + bytes_both : bag_stat; + nb_both : bag_stat; + nb_merge : bag_stat; + cumu_data_bytes : bag_stat; + merge_durations : float list; +} +[@@deriving repr] + +type gc = { + minor_words : bag_stat; + promoted_words : bag_stat; + major_words : bag_stat; + minor_collections : bag_stat; + major_collections : bag_stat; + compactions : bag_stat; + major_heap_bytes : bag_stat; + major_heap_top_bytes : curve; +} +[@@deriving repr] + +type disk = { + index_data : bag_stat; + index_log : bag_stat; + index_log_async : bag_stat; + store_dict : bag_stat; + store_pack : bag_stat; +} +[@@deriving repr] + +type store = { watched_nodes : Watched_node.map } [@@deriving repr] + +type t = { + summary_timeofday : float; + summary_hostname : string; + curves_sample_count : int; + moving_average_half_life_ratio : float; + (* Stats from [Def.header]. *) + config : Def.config; + hostname : string; + word_size : int; + timeofday : float; + timestamp_wall0 : float; + timestamp_cpu0 : float; + (* Stats derived from [Def.row]s. *) + elapsed_wall : float; + elapsed_wall_over_blocks : Utils.curve; + elapsed_cpu : float; + elapsed_cpu_over_blocks : Utils.curve; + op_count : int; + span : Span.map; + block_count : int; + cpu_usage : Vs.t; + index : index; + pack : pack; + tree : tree; + gc : gc; + disk : disk; + store : store; +} +[@@deriving repr] + +(* Section 2/4 - Converters from stat_strace to element of summary. *) +let create_vs block_count = + Vs.create_acc ~distribution_bin_count:Conf.histo_bin_count + ~out_sample_count:Conf.curves_sample_count + ~in_period_count:(block_count + 1) ~evolution_resampling_mode:`Next_neighbor + +let create_vs_exact block_count = + create_vs block_count ~evolution_smoothing:`None ~scale:`Linear + +let create_vs_smooth block_count = + let hlr = Conf.moving_average_half_life_ratio in + let rt = Conf.moving_average_relevance_threshold in + create_vs block_count ~evolution_smoothing:(`Ema (hlr, rt)) ~scale:`Linear + +let create_vs_smooth_log block_count = + let hlr = Conf.moving_average_half_life_ratio in + let rt = Conf.moving_average_relevance_threshold in + create_vs block_count ~evolution_smoothing:(`Ema (hlr, rt)) ~scale:`Log + +(** Accumulator for the [span] field of [t]. *) +module Span_folder = struct + type span_acc = { + sum_count : int; + sum_duration : float; + count : Vs.acc; + cumu_count : Vs.acc; + duration : Vs.acc; + duration_log_scale : Vs.acc; + cumu_duration : Vs.acc; + } + + type acc = { + per_span : span_acc Span.Map.t; + seen_atoms_durations_in_block : float list Span.Map.t; + timestamp_before : float; + } + + let create timestamp_before block_count = + let seen_atoms_durations_in_block0 = + List.map + (fun atom_seen -> (atom_seen, [])) + (Span.Key.all_atoms_seen :> Span.Key.t list) + |> List.to_seq + |> Span.Map.of_seq + in + let acc0 = + let acc0_per_span = + let count = create_vs_smooth block_count in + let count = Vs.accumulate count [] in + let cumu_count = create_vs_exact block_count in + let cumu_count = Vs.accumulate cumu_count [ 0. ] in + let duration = create_vs_smooth block_count in + let duration = Vs.accumulate duration [] in + let duration_log_scale = create_vs_smooth_log block_count in + let duration_log_scale = Vs.accumulate duration_log_scale [] in + let cumu_duration = create_vs_exact block_count in + let cumu_duration = Vs.accumulate cumu_duration [ 0. ] in + { + sum_count = 0; + sum_duration = 0.; + count; + cumu_count; + duration; + duration_log_scale; + cumu_duration; + } + in + let per_span = + List.map (fun span -> (span, acc0_per_span)) Span.Key.all + |> List.to_seq + |> Span.Map.of_seq + in + { + per_span; + seen_atoms_durations_in_block = seen_atoms_durations_in_block0; + timestamp_before; + } + in + + let accumulate acc row = + let on_atom_seen_duration32 acc (span : Span.Key.atom_seen) (d : int32) = + let d = Int32.float_of_bits d in + let span = (span :> Span.Key.t) in + let seen_atoms_durations_in_block = + let m = acc.seen_atoms_durations_in_block in + let l = d :: Span.Map.find span m in + Span.Map.add span l m + in + { acc with seen_atoms_durations_in_block } + in + let on_durations (span : Span.Key.t) (new_durations : float list) acc = + let acc' = Span.Map.find span acc.per_span in + let new_count = List.length new_durations in + let sum_count = acc'.sum_count + new_count in + let sum_duration = + acc'.sum_duration +. List.fold_left ( +. ) 0. new_durations + in + let count = Vs.accumulate acc'.count [ float_of_int new_count ] in + let cumu_count = + Vs.accumulate acc'.cumu_count [ float_of_int sum_count ] + in + let duration = Vs.accumulate acc'.duration new_durations in + let duration_log_scale = + Vs.accumulate acc'.duration_log_scale new_durations + in + let cumu_duration = Vs.accumulate acc'.cumu_duration [ sum_duration ] in + let acc' = + { + sum_count; + sum_duration; + count; + cumu_count; + duration; + duration_log_scale; + cumu_duration; + } + in + { acc with per_span = Span.Map.add span acc' acc.per_span } + in + let on_commit (c : Def.commit) acc = + let list_one span = + Span.Map.find span acc.seen_atoms_durations_in_block + in + let sum_one span = List.fold_left ( +. ) 0. (list_one span) in + let sum_several spans = + let spans = (spans :> Span.Key.t list) in + List.fold_left (fun cumu span -> cumu +. sum_one span) 0. spans + in + let total_duration = c.after.timestamp_wall -. acc.timestamp_before in + let acc = + acc + |> on_durations `Add (list_one `Add) + |> on_durations `Remove (list_one `Remove) + |> on_durations `Find (list_one `Find) + |> on_durations `Mem (list_one `Mem) + |> on_durations `Mem_tree (list_one `Mem_tree) + |> on_durations `Checkout (list_one `Checkout) + |> on_durations `Copy (list_one `Copy) + |> on_durations `Commit (list_one `Commit) + |> on_durations `Unseen + [ total_duration -. sum_several Span.Key.all_atoms_seen ] + |> on_durations `Buildup [ total_duration -. sum_one `Commit ] + |> on_durations `Block [ total_duration ] + in + { + acc with + seen_atoms_durations_in_block = seen_atoms_durations_in_block0; + timestamp_before = c.after.timestamp_wall; + } + in + match row with + | `Add d -> on_atom_seen_duration32 acc `Add d + | `Remove d -> on_atom_seen_duration32 acc `Remove d + | `Find d -> on_atom_seen_duration32 acc `Find d + | `Mem d -> on_atom_seen_duration32 acc `Mem d + | `Mem_tree d -> on_atom_seen_duration32 acc `Mem_tree d + | `Checkout d -> on_atom_seen_duration32 acc `Checkout d + | `Copy d -> on_atom_seen_duration32 acc `Copy d + | `Commit c -> + on_atom_seen_duration32 acc `Commit c.Def.duration |> on_commit c + in + + let finalise { per_span; _ } = + Span.Map.map + (fun acc -> + { + Span.Val.count = Vs.finalise acc.count; + cumu_count = Vs.finalise acc.cumu_count; + duration = Vs.finalise acc.duration; + duration_log_scale = Vs.finalise acc.duration_log_scale; + cumu_duration = Vs.finalise acc.cumu_duration; + }) + per_span + in + + Utils.Parallel_folders.folder acc0 accumulate finalise +end + +(** Summary computation for statistics recorded in [Def.bag_of_stat]. *) +module Bag_stat_folder = struct + type acc = { + value_before_commit : Vs.acc; + value_after_commit : Vs.acc; + diff_per_block : Vs.acc; + diff_per_buildup : Vs.acc; + diff_per_commit : Vs.acc; + prev_value : float; + (* constants *) + value_of_bag : Def.bag_of_stats -> float; + should_cumulate_value : bool; + } + + let create_acc ?(is_linearly_increasing = true) + ?(should_cumulate_value = false) header block_count value_of_bag = + let value_in_header = value_of_bag header.Def.initial_stats in + let f = + if is_linearly_increasing then create_vs_exact else create_vs_smooth + in + let value_before_commit = f block_count in + let value_before_commit = Vs.accumulate value_before_commit [] in + let value_after_commit = f block_count in + let value_after_commit = + Vs.accumulate value_after_commit [ value_in_header ] + in + let diff_per_block = create_vs_smooth block_count in + let diff_per_block = Vs.accumulate diff_per_block [] in + let diff_per_buildup = create_vs_smooth block_count in + let diff_per_buildup = Vs.accumulate diff_per_buildup [] in + let diff_per_commit = create_vs_smooth block_count in + let diff_per_commit = Vs.accumulate diff_per_commit [] in + { + value_before_commit; + value_after_commit; + diff_per_block; + diff_per_buildup; + diff_per_commit; + prev_value = value_in_header; + value_of_bag; + should_cumulate_value; + } + + let accumulate acc row = + match row with + | `Commit c -> + let va = acc.value_of_bag c.Def.before in + let vb = acc.value_of_bag c.Def.after in + let va, vb = + if acc.should_cumulate_value then + (acc.prev_value +. va, acc.prev_value +. va +. vb) + else (va, vb) + in + let diff_block = vb -. acc.prev_value in + let diff_buildup = va -. acc.prev_value in + let diff_commit = vb -. va in + let value_before_commit = + Vs.accumulate acc.value_before_commit [ va ] + in + let value_after_commit = Vs.accumulate acc.value_after_commit [ vb ] in + let diff_per_block = Vs.accumulate acc.diff_per_block [ diff_block ] in + let diff_per_buildup = + Vs.accumulate acc.diff_per_buildup [ diff_buildup ] + in + let diff_per_commit = + Vs.accumulate acc.diff_per_commit [ diff_commit ] + in + { + acc with + value_before_commit; + value_after_commit; + diff_per_block; + diff_per_buildup; + diff_per_commit; + prev_value = vb; + } + | _ -> acc + + let finalise acc : bag_stat = + { + value_before_commit = Vs.finalise acc.value_before_commit; + value_after_commit = Vs.finalise acc.value_after_commit; + diff_per_block = Vs.finalise acc.diff_per_block; + diff_per_buildup = Vs.finalise acc.diff_per_buildup; + diff_per_commit = Vs.finalise acc.diff_per_commit; + } + + let create ?should_cumulate_value ?is_linearly_increasing header block_count + value_of_bag = + let acc0 = + create_acc ?should_cumulate_value ?is_linearly_increasing header + block_count value_of_bag + in + Utils.Parallel_folders.folder acc0 accumulate finalise +end + +(** Accumulator for the [store] field of [t]. *) +module Store_watched_nodes_folder = struct + type acc_per_node = { + value : Vs.acc; + diff_per_block : Vs.acc; + prev_value : float; + } + + type acc = acc_per_node list + + let create_acc block_count = + let acc0_per_node = + let value = create_vs_exact block_count in + let value = Vs.accumulate value [] in + let diff_per_block = create_vs_smooth block_count in + let diff_per_block = Vs.accumulate diff_per_block [] in + { value; diff_per_block; prev_value = Float.nan } + in + List.map (Fun.const acc0_per_node) Def.watched_nodes + + let accumulate acc row = + match row with + | `Commit c -> + let accumulate_per_node v acc = + let v = float_of_int v in + let diff_block = v -. acc.prev_value in + let value = Vs.accumulate acc.value [ v ] in + let diff_per_block = + Vs.accumulate acc.diff_per_block [ diff_block ] + in + { value; diff_per_block; prev_value = v } + in + List.map2 accumulate_per_node c.Def.store_after.watched_nodes_length acc + | _ -> acc + + let finalise acc : Watched_node.map = + List.map2 + (fun k acc -> + let v = + { + Watched_node.Val.value = Vs.finalise acc.value; + diff_per_block = Vs.finalise acc.diff_per_block; + } + in + (k, v)) + Def.watched_nodes acc + |> List.to_seq + |> Watched_node.Map.of_seq + + let create block_count = + let acc0 = create_acc block_count in + Utils.Parallel_folders.folder acc0 accumulate finalise +end + +(** Build a resampled curve of [gc.top_heap_words] *) +let major_heap_top_bytes_folder header block_count = + let ws = header.Def.word_size / 8 |> float_of_int in + let len0 = block_count + 1 in + let len1 = Conf.curves_sample_count in + let v0 = float_of_int header.Def.initial_stats.gc.top_heap_words *. ws in + let acc0 = Utils.Resample.create_acc `Next_neighbor ~len0 ~len1 ~v00:v0 in + let accumulate acc = function + | `Commit c -> + Utils.Resample.accumulate acc + (float_of_int c.Def.after.gc.top_heap_words *. ws) + | _ -> acc + in + let finalise = Utils.Resample.finalise in + Utils.Parallel_folders.folder acc0 accumulate finalise + +(** Build a resampled curve of timestamps. *) +let elapsed_wall_over_blocks_folder header block_count = + let open Def in + let len0 = block_count + 1 in + let len1 = Conf.curves_sample_count in + let v0 = header.initial_stats.timestamp_wall in + let acc0 = Utils.Resample.create_acc `Interpolate ~len0 ~len1 ~v00:v0 in + let accumulate acc = function + | `Commit c -> Utils.Resample.accumulate acc c.after.timestamp_wall + | _ -> acc + in + let finalise acc = + Utils.Resample.finalise acc |> List.map (fun t -> t -. v0) + in + Utils.Parallel_folders.folder acc0 accumulate finalise + +(** Build a resampled curve of timestamps. *) +let elapsed_cpu_over_blocks_folder header block_count = + let open Def in + let len0 = block_count + 1 in + let len1 = Conf.curves_sample_count in + let v0 = header.initial_stats.timestamp_cpu in + let acc0 = Utils.Resample.create_acc `Interpolate ~len0 ~len1 ~v00:v0 in + let accumulate acc = function + | `Commit c -> Utils.Resample.accumulate acc c.after.timestamp_cpu + | _ -> acc + in + let finalise acc = + Utils.Resample.finalise acc |> List.map (fun t -> t -. v0) + in + Utils.Parallel_folders.folder acc0 accumulate finalise + +(** Build a list of all the merge durations. *) +let merge_durations_folder = + let acc0 = [] in + let accumulate l = function + | `Commit c -> + let l = List.rev_append c.Def.before.index.new_merge_durations l in + let l = List.rev_append c.Def.after.index.new_merge_durations l in + l + | _ -> l + in + let finalise = List.rev in + Utils.Parallel_folders.folder acc0 accumulate finalise + +let cpu_usage_folder header block_count = + let acc0 = + let vs = create_vs_smooth block_count in + let vs = Vs.accumulate vs [] in + ( header.Def.initial_stats.timestamp_wall, + header.Def.initial_stats.timestamp_cpu, + vs ) + in + let accumulate ((prev_wall, prev_cpu, vs) as acc) = function + | `Commit c -> + let span_wall = c.Def.after.timestamp_wall -. prev_wall in + let span_cpu = c.Def.after.timestamp_cpu -. prev_cpu in + ( c.Def.after.timestamp_wall, + c.Def.after.timestamp_cpu, + Vs.accumulate vs [ span_cpu /. span_wall ] ) + | _ -> acc + in + let finalise (_, _, vs) = Vs.finalise vs in + Utils.Parallel_folders.folder acc0 accumulate finalise + +(** Substract the first and the last timestamps and count the number of span. *) +let misc_stats_folder header = + let open Def in + let acc0 = (0., 0., 0) in + let accumulate (t, t', count) = function + | `Commit c -> (c.after.timestamp_wall, c.after.timestamp_cpu, count + 1) + | _ -> (t, t', count + 1) + in + let finalise (t, t', count) = + ( t -. header.initial_stats.timestamp_wall, + t' -. header.initial_stats.timestamp_cpu, + count ) + in + Utils.Parallel_folders.folder acc0 accumulate finalise + +(* Section 3/4 - Converter from stat_strace to summary *) + +(** Fold over [row_seq] and produce the summary. + + {3 Parallel Folders} + + Almost all entries in [t] require to independently fold over the rows of the + stat trace, but we want: + + - not to fully load the trace in memory, + - not to reread the trace from disk once for each entry, + - this current file to be verbose and simple, + - to have fun with GADTs and avoid mutability. + + All the boilerplate is hidden behind [Utils.Parallel_folders], a + datastructure that holds all folder functions, takes care of feeding the + rows to those folders, and preseves the types. + + In the code below, [pf0] is the initial parallel folder, before the first + accumulation. Each [|+ ...] statement declares a [acc, accumulate, finalise] + triplet, i.e. a folder. + + [val acc : acc] is the initial empty accumulation of a folder. + + [val accumulate : acc -> row -> acc] needs to be folded over all rows of the + stat trace. Calling [Parallel_folders.accumulate pf row] will feed [row] to + every folders. + + [val finalise : acc -> v] has to be applied on the final [acc] of a folder + in order to produce the final value of that folder - which value is meant to + be stored in [Trace_stat_summary.t]. Calling [Parallel_folders.finalise pf] + will finalise all folders and pass their result to [construct]. *) +let summarise' header block_count (row_seq : Def.row Seq.t) = + let bs_folder_of_bag_getter ?should_cumulate_value ?is_linearly_increasing + value_of_bag = + Bag_stat_folder.create ?should_cumulate_value ?is_linearly_increasing header + block_count value_of_bag + in + + let finds_folder = + let construct total from_staging from_lru from_pack_direct from_pack_indexed + missing cache_miss = + { + total; + from_staging; + from_lru; + from_pack_direct; + from_pack_indexed; + missing; + cache_miss; + } + in + let acc0 = + let open Utils.Parallel_folders in + let ofi = float_of_int in + open_ construct + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.finds.total) + |+ bs_folder_of_bag_getter (fun bag -> + ofi bag.Def.pack.finds.from_staging) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.finds.from_lru) + |+ bs_folder_of_bag_getter (fun bag -> + ofi bag.Def.pack.finds.from_pack_direct) + |+ bs_folder_of_bag_getter (fun bag -> + ofi bag.Def.pack.finds.from_pack_indexed) + |+ bs_folder_of_bag_getter (fun bag -> + let open Def in + let v = bag.pack.finds in + v.total + - v.from_staging + - v.from_lru + - v.from_pack_direct + - v.from_pack_indexed + |> ofi) + |+ bs_folder_of_bag_getter (fun bag -> + let open Def in + let v = bag.pack.finds in + v.total - v.from_staging - v.from_lru |> ofi) + |> seal + in + Utils.Parallel_folders.folder acc0 Utils.Parallel_folders.accumulate + Utils.Parallel_folders.finalise + in + + let pack_folder = + let construct finds appended_hashes appended_offsets inode_add inode_remove + inode_of_seq inode_of_raw inode_rec_add inode_rec_remove inode_to_binv + inode_decode_bin inode_encode_bin = + { + finds; + appended_hashes; + appended_offsets; + inode_add; + inode_remove; + inode_of_seq; + inode_of_raw; + inode_rec_add; + inode_rec_remove; + inode_to_binv; + inode_decode_bin; + inode_encode_bin; + } + in + let acc0 = + let open Utils.Parallel_folders in + let ofi = float_of_int in + open_ construct + |+ finds_folder + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.appended_hashes) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.appended_offsets) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_add) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_remove) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_of_seq) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_of_raw) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_rec_add) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_rec_remove) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_to_binv) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_decode_bin) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.pack.inode_encode_bin) + |> seal + in + Utils.Parallel_folders.folder acc0 Utils.Parallel_folders.accumulate + Utils.Parallel_folders.finalise + in + + let tree_folder = + let construct contents_hash contents_find contents_add node_hash node_mem + node_add node_find node_val_v node_val_find node_val_list = + { + contents_hash; + contents_find; + contents_add; + node_hash; + node_mem; + node_add; + node_find; + node_val_v; + node_val_find; + node_val_list; + } + in + let acc0 = + let open Utils.Parallel_folders in + let ofi = float_of_int in + open_ construct + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.contents_hash) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.contents_find) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.contents_add) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_hash) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_mem) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_add) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_find) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_val_v) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_val_find) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.tree.node_val_list) + |> seal + in + Utils.Parallel_folders.folder acc0 Utils.Parallel_folders.accumulate + Utils.Parallel_folders.finalise + in + + let index_folder = + let construct bytes_read nb_reads bytes_written nb_writes bytes_both nb_both + nb_merge cumu_data_bytes merge_durations = + { + bytes_read; + nb_reads; + bytes_written; + nb_writes; + bytes_both; + nb_both; + nb_merge; + cumu_data_bytes; + merge_durations; + } + in + let acc0 = + let open Utils.Parallel_folders in + let ofi = float_of_int in + open_ construct + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.index.bytes_read) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.index.nb_reads) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.index.bytes_written) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.index.nb_writes) + |+ bs_folder_of_bag_getter (fun bag -> + ofi (bag.Def.index.bytes_read + bag.Def.index.bytes_written)) + |+ bs_folder_of_bag_getter (fun bag -> + ofi (bag.Def.index.nb_reads + bag.Def.index.nb_writes)) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.index.nb_merge) + |+ bs_folder_of_bag_getter ~should_cumulate_value:true (fun bag -> + (* When 1 merge occured, [data_size] bytes were written. + + When 2 merge occured, [data_size * 2 - log_size] bytes were + written. But here we just count [data_size * 2]. *) + let merge_count = + List.length bag.Def.index.new_merge_durations |> Int64.of_int + in + let data_size = bag.Def.disk.index_data in + Int64.to_float (Int64.mul merge_count data_size)) + |+ merge_durations_folder + |> seal + in + Utils.Parallel_folders.folder acc0 Utils.Parallel_folders.accumulate + Utils.Parallel_folders.finalise + in + + let gc_folder = + let construct minor_words promoted_words major_words minor_collections + major_collections compactions major_heap_bytes major_heap_top_bytes = + { + minor_words; + promoted_words; + major_words; + minor_collections; + major_collections; + compactions; + major_heap_bytes; + major_heap_top_bytes; + } + in + let acc0 = + let open Utils.Parallel_folders in + let ofi = float_of_int in + let ws = header.Def.word_size / 8 |> float_of_int in + open_ construct + |+ bs_folder_of_bag_getter (fun bag -> bag.Def.gc.minor_words) + |+ bs_folder_of_bag_getter (fun bag -> bag.Def.gc.promoted_words) + |+ bs_folder_of_bag_getter (fun bag -> bag.Def.gc.major_words) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.gc.minor_collections) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.gc.major_collections) + |+ bs_folder_of_bag_getter (fun bag -> ofi bag.Def.gc.compactions) + |+ bs_folder_of_bag_getter ~is_linearly_increasing:false (fun bag -> + ofi bag.Def.gc.heap_words *. ws) + |+ major_heap_top_bytes_folder header block_count + |> seal + in + Utils.Parallel_folders.folder acc0 Utils.Parallel_folders.accumulate + Utils.Parallel_folders.finalise + in + + let disk_folder = + let construct index_data index_log index_log_async store_dict store_pack = + { index_data; index_log; index_log_async; store_dict; store_pack } + in + let acc0 = + let open Utils.Parallel_folders in + let ofi64 = Int64.to_float in + open_ construct + |+ bs_folder_of_bag_getter (fun bag -> ofi64 bag.Def.disk.index_data) + |+ bs_folder_of_bag_getter ~is_linearly_increasing:false (fun bag -> + ofi64 bag.Def.disk.index_log) + |+ bs_folder_of_bag_getter ~is_linearly_increasing:false (fun bag -> + ofi64 bag.Def.disk.index_log_async) + |+ bs_folder_of_bag_getter (fun bag -> ofi64 bag.Def.disk.store_dict) + |+ bs_folder_of_bag_getter (fun bag -> + (* This would not be linearly increasing with irmin layers *) + ofi64 bag.Def.disk.store_pack) + |> seal + in + Utils.Parallel_folders.folder acc0 Utils.Parallel_folders.accumulate + Utils.Parallel_folders.finalise + in + + let construct (elapsed_wall, elapsed_cpu, op_count) elapsed_wall_over_blocks + elapsed_cpu_over_blocks span cpu_usage_variable pack tree index gc disk + watched_nodes = + { + summary_hostname = Unix.gethostname (); + summary_timeofday = Unix.gettimeofday (); + elapsed_wall; + elapsed_cpu; + op_count; + block_count; + curves_sample_count = Conf.curves_sample_count; + moving_average_half_life_ratio = Conf.moving_average_half_life_ratio; + config = header.config; + hostname = header.hostname; + word_size = header.word_size; + timeofday = header.timeofday; + timestamp_wall0 = header.initial_stats.timestamp_wall; + timestamp_cpu0 = header.initial_stats.timestamp_cpu; + elapsed_wall_over_blocks; + elapsed_cpu_over_blocks; + span; + pack; + tree; + cpu_usage = cpu_usage_variable; + index; + gc; + disk; + store = { watched_nodes }; + } + in + + let pf0 = + let open Utils.Parallel_folders in + open_ construct + |+ misc_stats_folder header + |+ elapsed_wall_over_blocks_folder header block_count + |+ elapsed_cpu_over_blocks_folder header block_count + |+ Span_folder.create header.initial_stats.timestamp_wall block_count + |+ cpu_usage_folder header block_count + |+ pack_folder + |+ tree_folder + |+ index_folder + |+ gc_folder + |+ disk_folder + |+ Store_watched_nodes_folder.create block_count + |> seal + in + Seq.fold_left Utils.Parallel_folders.accumulate pf0 row_seq + |> Utils.Parallel_folders.finalise + +(** Turn a stat trace into a summary. + + The number of blocks to consider may be provided in order to truncate the + summary. *) +let summarise ?block_count trace_stat_path = + let block_count = + match block_count with + | Some block_count -> block_count + | None -> + (* The trace has to be iterated a first time in order to retrieve the + * number of blocks. This is needed to: + * - define the moving average momentum, + * - stop the row sequence immediately after the last commit. *) + Trace_definitions.Stat_trace.open_reader trace_stat_path + |> snd + |> Seq.fold_left + (fun count op -> + match op with `Commit _ -> count + 1 | _ -> count) + 0 + in + if block_count <= 0 then invalid_arg "Can't summarise an empty stat trace"; + let header, row_seq = + Trace_definitions.Stat_trace.open_reader trace_stat_path + in + let row_seq = + let aux (seq, commit_count) = + if commit_count >= block_count then None + else + match seq () with + | Seq.Nil -> + failwith + "summarise reached the end of the stat trace before \ + 'block_count' commits were seen" + | Seq.Cons ((`Commit _ as op), seq) -> Some (op, (seq, commit_count + 1)) + | Seq.Cons (op, seq) -> Some (op, (seq, commit_count)) + in + Seq.unfold aux (row_seq, 0) + in + summarise' header block_count row_seq + +(* Section 4/4 - Conversion from summary to json file *) + +let save_to_json v path = + let j = Fmt.str "%a\n" (Irmin.Type.pp_json t) v in + let chan = open_out path in + output_string chan j; + [%logs.app "Summary saved to %s" path]; + close_out chan; + Unix.chmod path 0o444 diff --git a/vendors/irmin/bench/irmin-pack/trace_stat_summary_cb.ml b/vendors/irmin/bench/irmin-pack/trace_stat_summary_cb.ml new file mode 100644 index 000000000000..da86d33454b4 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stat_summary_cb.ml @@ -0,0 +1,247 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Summary = Trace_stat_summary +module Utils = Trace_stat_summary_utils + +type metrics = (string * float list) list [@@deriving repr] + +let metrics_t = Irmin.Type.(Json.assoc (list float)) + +type result = { name : string; metrics : metrics } [@@deriving repr] +type t = { results : (result[@nobuiltin]) list } [@@deriving repr] + +(** As of may 2021, outputing "nan" strings in place of numbers crashes the CB. + Let's just filter those out since this is functionally identical. *) +let filter_nans_out results = + List.map + (fun { name; metrics } -> + let metrics = + List.map + (fun (name, l) -> + (name, match l with [ v ] when Float.is_nan v -> [] | l -> l)) + metrics + in + { name; metrics }) + results + +let create_raw_results0 s : result list = + let open Summary in + [ + { + name = "Trace Replay - main metrics"; + metrics = + [ + ("CPU time elapsed (s)", [ s.elapsed_cpu ]); + ( "TZ-transactions per sec", + [ + (Utils.approx_transaction_count_of_block_count s.block_count + |> float_of_int) + /. s.elapsed_cpu; + ] ); + ( "TZ-operations per sec", + [ + (Utils.approx_operation_count_of_block_count s.block_count + |> float_of_int) + /. s.elapsed_cpu; + ] ); + ( "Context.set per sec", + [ + fst (Span.Map.find `Add s.span).cumu_count.max_value + /. s.elapsed_cpu; + ] ); + ( "tail latency (s)", + [ fst (Span.Map.find `Commit s.span).duration.max_value ] ); + ]; + }; + { + name = "Trace Replay - resource usage - disk IO (total)"; + metrics = + [ + ( "IOPS (op/s)", + [ s.index.nb_both.value_after_commit.diff /. s.elapsed_cpu ] ); + ( "throughput (MB/s)", + [ + s.index.bytes_both.value_after_commit.diff /. s.elapsed_cpu /. 1e6; + ] ); + ("total (MB)", [ s.index.bytes_both.value_after_commit.diff /. 1e6 ]); + ]; + }; + { + name = "Trace Replay - resource usage - disk IO (read)"; + metrics = + [ + ( "IOPS (op/s)", + [ s.index.nb_reads.value_after_commit.diff /. s.elapsed_cpu ] ); + ( "throughput (MB/s)", + [ + s.index.bytes_read.value_after_commit.diff /. s.elapsed_cpu /. 1e6; + ] ); + ("total (MB)", [ s.index.bytes_read.value_after_commit.diff /. 1e6 ]); + ]; + }; + { + name = "Trace Replay - resource usage - disk IO (write)"; + metrics = + [ + ( "IOPS (op/s)", + [ s.index.nb_writes.value_after_commit.diff /. s.elapsed_cpu ] ); + ( "throughput (MB/s)", + [ + s.index.bytes_written.value_after_commit.diff + /. s.elapsed_cpu + /. 1e6; + ] ); + ( "total (MB)", + [ s.index.bytes_written.value_after_commit.diff /. 1e6 ] ); + ]; + }; + { + name = "Trace Replay - resource usage - misc."; + metrics = + [ + ( "max memory usage (GB)", + [ List.fold_left max 0. s.gc.major_heap_top_bytes /. 1e9 ] ); + ("mean CPU usage", [ s.elapsed_cpu /. s.elapsed_wall ]); + ]; + }; + ] + +let create_raw_results1 s : result list = + let a = + let name = "Trace Replay - Context Phases Length" in + let open Trace_stat_summary in + let metrics = + [ `Block; `Buildup; `Commit ] + |> List.map @@ fun k -> + let vs = Span.(Map.find k s.span).duration in + ( Printf.sprintf "%s (ms)" (Span.Key.to_string k), + [ + vs.mean *. 1000. + (* TODO: {min / max / avg}, maybe on a log scale? *); + ] ) + in + { name; metrics } + in + let b = + let name = "Trace Replay - Context Buildup Lengths" in + let open Trace_stat_summary in + let metrics = + [ `Add; `Remove; `Find; `Mem; `Mem_tree; `Copy; `Unseen ] + |> List.map @@ fun k -> + let vs = Span.(Map.find k s.span).duration in + ( Printf.sprintf "%s (\xc2\xb5s)" (Span.Key.to_string k), + [ + vs.mean *. 1e6 (* TODO: {min / max / avg}, maybe on a log scale? *); + ] ) + in + { name; metrics } + in + [ a; b ] + +let create_raw_results2 s : result list = + let name = "Trace Replay - irmin-pack Global Stats" in + let metrics = + let open Summary in + [ + ("finds", s.pack.finds.total); + ("finds.from_staging", s.pack.finds.from_staging); + ("finds.from_lru", s.pack.finds.from_lru); + ("finds.from_pack_direct", s.pack.finds.from_pack_direct); + ("finds.from_pack_indexed", s.pack.finds.from_pack_indexed); + ("finds.missing", s.pack.finds.missing); + ("finds.cache_miss", s.pack.finds.cache_miss); + ("appended_hashes", s.pack.appended_hashes); + ("appended_offsets", s.pack.appended_offsets); + ("inode_add", s.pack.inode_add); + ("inode_remove", s.pack.inode_remove); + ("inode_of_seq", s.pack.inode_of_seq); + ("inode_of_raw", s.pack.inode_of_raw); + ("inode_rec_add", s.pack.inode_rec_add); + ("inode_rec_remove", s.pack.inode_rec_remove); + ("inode_to_binv", s.pack.inode_to_binv); + ("inode_decode_bin", s.pack.inode_decode_bin); + ("inode_encode_bin", s.pack.inode_encode_bin); + ] + |> List.map @@ fun (name, lbs) -> (name, [ lbs.value_after_commit.diff ]) + in + [ { name; metrics } ] + +let create_raw_results3 s : result list = + let name = "Trace Replay - irmin.tree Global Stats" in + let open Trace_stat_summary in + let metrics = + [ + ("contents_hash", s.tree.contents_hash); + ("contents_find", s.tree.contents_find); + ("contents_add", s.tree.contents_add); + ("node_hash", s.tree.node_hash); + ("node_mem", s.tree.node_mem); + ("node_add", s.tree.node_add); + ("node_find", s.tree.node_find); + ("node_val_v", s.tree.node_val_v); + ("node_val_find", s.tree.node_val_find); + ("node_val_list", s.tree.node_val_list); + ] + |> List.map @@ fun (name, lbs) -> (name, [ lbs.value_after_commit.diff ]) + in + [ { name; metrics } ] + +let create_raw_results4 s : result list = + let name = "Trace Replay - index Stats" in + let open Trace_stat_summary in + let metrics = + [ + ( "cumu data MB", + [ fst s.index.cumu_data_bytes.value_after_commit.max_value *. 1e-6 ] ); + ("merge count", [ s.index.nb_merge.value_after_commit.diff ]); + ] + in + [ { name; metrics } ] + +let create_raw_results5 s : result list = + let name = "Trace Replay - GC Stats" in + let open Trace_stat_summary in + let metrics = + [ + ("minor words allocated", s.gc.minor_words); + ("major words allocated", s.gc.major_words); + ("minor collections", s.gc.minor_collections); + ("major collections", s.gc.major_collections); + ("promoted words", s.gc.promoted_words); + ("compactions", s.gc.compactions); + ] + |> List.map @@ fun (name, lbs) -> (name, [ lbs.value_after_commit.diff ]) + in + let metrics' = + [ + ( "avg major heap MB after commit", + [ s.gc.major_heap_bytes.value_after_commit.mean /. 1e6 ] ); + ] + in + [ { name; metrics = metrics @ metrics' } ] + +let of_summary s = + { + results = + create_raw_results0 s + @ create_raw_results1 s + @ create_raw_results2 s + @ create_raw_results3 s + @ create_raw_results4 s + @ create_raw_results5 s + |> filter_nans_out; + } diff --git a/vendors/irmin/bench/irmin-pack/trace_stat_summary_conf.ml b/vendors/irmin/bench/irmin-pack/trace_stat_summary_conf.ml new file mode 100644 index 000000000000..f6afd1912d10 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stat_summary_conf.ml @@ -0,0 +1,42 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Summary configuration. + + This file is NOT meant to be used from Tezos, as opposed to some other + "trace_*" files. *) + +let histo_bin_count = 16 +let curves_sample_count = 201 + +(** Parameter to control the width of the moving average window. + + This width is expressed as a fraction of the width of the final plot images, + (i.e. the number of played blocks). This implies that the amount of + smoothing remains visually the same, no matter [curves_sample_count] and the + number of blocks in the stat trace. + + Justification of the current value: + + The 2nd commit of the full replay trace is a massive one, it contains ~1000x + more operations than an average one, it takes ~10 half lives to fully get + rid of it from the EMAs. With [moving_average_half_life_ratio = 1. /. 80.], + that 2nd commit will only poluate [1 / 8] of the width of the smoothed + curves. *) +let moving_average_half_life_ratio = 1. /. 80. + +(** See [Exponential_moving_average] *) +let moving_average_relevance_threshold = 0.999 diff --git a/vendors/irmin/bench/irmin-pack/trace_stat_summary_pp.ml b/vendors/irmin/bench/irmin-pack/trace_stat_summary_pp.ml new file mode 100644 index 000000000000..2e4ec97cf430 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stat_summary_pp.ml @@ -0,0 +1,1114 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Pretty printing of one or more summaries. + + This file is NOT meant to be used from Tezos, as opposed to some other + "trace_*" files. + + This file contains A LOT of uninteresting boilerplate in order to build the + pretty-printable table. Doing this using pandas-like multi-level dataframes + would make the thing much more simpler. *) + +open Trace_stat_summary +module Utils = Trace_stat_summary_utils +module Summary = Trace_stat_summary + +module Pb = struct + include PrintBox + + (* Some utilities to work with lists instead of array *) + + let transpose_matrix l = + l + |> List.map Array.of_list + |> Array.of_list + |> PrintBox.transpose + |> Array.to_list + |> List.map Array.to_list + + let matrix_to_text m = List.map (List.map PrintBox.text) m + let align_matrix where = List.map (List.map (PrintBox.align ~h:where ~v:`Top)) + + (** Dirty trick to only have vertical bars, and not the horizontal ones *) + let matrix_with_column_spacers = + let rec interleave sep = function + | ([ _ ] | []) as l -> l + | hd :: tl -> hd :: sep :: interleave sep tl + in + List.map (fun l -> + PrintBox.text " | " :: interleave (PrintBox.text " | ") l) +end + +let fprintf_result ppf = + Format.fprintf ppf + {|
+ Setups + +%s +
+ + +%s + + - (1) Longest Context.commit. + - The "per sec" stats are calculated over CPU time. + - "TZ-transactions" and "TZ-operations" are approximations. + - "max memory usage" is the max size of OCaml's major heap. + - "mean CPU usage" is inexact. + +-- global -- +%s + +%s + +-- evolution through blocks -- +%s + +Types of curves: + *C: Cumulative. No smoothing. + *LA: Local Average. Smoothed using a weighted sum of the value in the + block and the exponentially decayed values of the previous blocks. + Every %.2f blocks, half of the past is forgotten. + *S: Size. E.g. directory entries, file bytes. No smoothing. + *N: Very noisy.|} + +type summary = Summary.t + +type scalar_format_fixed = [ `SM | `S3 | `Sm | `Su | `RG | `RM | `Ri | `R3 | `P ] +(** Seconds minutes, Seconds 3 digits, Seconds milli, Seconds micro, Real giga, + Real mega, Real as integer, Real 3 digits, Percent *) + +let pp_scalar_fixed ppf (format, v) = + if Float.is_nan v then Format.fprintf ppf "n/a" + else if Float.is_infinite v then Format.fprintf ppf "%f" v + else if v = 0. then Format.fprintf ppf "0" + else + match format with + | `SM -> + let m = Float.floor (v /. 60.) in + let s = v -. (m *. 60.) in + Format.fprintf ppf "%.0fm%02.0fs" m s + | `S3 -> Format.fprintf ppf "%.3f s" v + | `Sm -> Format.fprintf ppf "%.3f ms" (v *. 1e3) + | `Su -> Format.fprintf ppf "%.3f \xc2\xb5s" (v *. 1e6) + | `RG -> Format.fprintf ppf "%.3f G" (v /. 1e9) + | `RM -> Format.fprintf ppf "%.3f M" (v /. 1e6) + | `Ri -> Format.fprintf ppf "%#d" (Float.round v |> int_of_float) + | `R3 -> Format.fprintf ppf "%.3f" v + | `P -> Format.fprintf ppf "%.0f%%" (v *. 100.) + +(** Summary *) +module Table0 = struct + let summary_config_entries = + [ + `Hostname; + `Word_size; + `Timeofday; + `Inode_config; + `Store_type; + `Replay_path_conversion; + ] + + let name_of_summary_config_entry = function + | `Hostname -> "Hostname" + | `Word_size -> "Word Size" + | `Timeofday -> "Start Time" + | `Inode_config -> "Inode Config" + | `Store_type -> "Store Type" + | `Replay_path_conversion -> "Path Conversion" + + let cell_of_summary_config (s : summary) = function + | `Hostname -> s.hostname + | `Word_size -> Printf.sprintf "%d bits" s.word_size + | `Timeofday -> + let open Unix in + let t = gmtime s.timeofday in + Printf.sprintf "%04d/%02d/%02d %02d:%02d:%02d (GMT)" (1900 + t.tm_year) + (t.tm_mon + 1) t.tm_mday t.tm_hour t.tm_min t.tm_sec + | `Inode_config -> + let a, b, c = s.config.inode_config in + Printf.sprintf "mls:%d bf:%d sh:%d" a b c + | `Store_type -> ( + match s.config.store_type with + | `Pack -> "pack" + | `Pack_layered -> "pack-layered" + | `Pack_mem -> "pack-mem") + | `Replay_path_conversion -> ( + match s.config.setup with + | `Play _ -> "n/a" + | `Replay s -> ( + match s.path_conversion with + | `None -> "none" + | `V1 -> "v1" + | `V0_and_v1 -> "v0+v1" + | `V0 -> "v0")) + + let box_of_summaries_config summary_names (summaries : summary list) = + let summary_name_length = List.length summary_names in + let row0 = [ "" :: summary_names ] in + let separator_row = + [ List.init (summary_name_length + 1) (Fun.const "--") ] + in + let rows = + List.map + (fun e -> + let n = name_of_summary_config_entry e in + let l = List.map (fun s -> cell_of_summary_config s e) summaries in + n :: l) + summary_config_entries + in + row0 @ separator_row @ rows |> Pb.matrix_to_text +end + +(** Highlights *) +module Table1 = struct + let rows_of_summaries summaries = + let cpu_time_elapsed = List.map (fun s -> s.elapsed_cpu) summaries in + let wall_time_elapsed = List.map (fun s -> s.elapsed_wall) summaries in + let add_per_sec = + List.map + (fun s -> + fst Summary.(Span.Map.find `Add s.span).cumu_count.max_value + /. s.elapsed_cpu) + summaries + in + let tail_latency = + List.map + (fun s -> fst Summary.(Span.Map.find `Commit s.span).duration.max_value) + summaries + in + let tx_per_sec = + (* TODO: When replaying on a middle section of the chain, set + [~first_block_idx] *) + List.map + (fun s -> + (Utils.approx_transaction_count_of_block_count s.block_count + |> float_of_int) + /. s.elapsed_cpu) + summaries + in + let tz_ops_per_sec = + (* TODO: When replaying on a middle section of the chain, set + [~first_block_idx] *) + List.map + (fun s -> + (Utils.approx_operation_count_of_block_count s.block_count + |> float_of_int) + /. s.elapsed_cpu) + summaries + in + let bytes = + List.map (fun s -> s.index.bytes_both.value_after_commit.diff) summaries + in + let read_bytes = + List.map (fun s -> s.index.bytes_read.value_after_commit.diff) summaries + in + let written_bytes = + List.map + (fun s -> s.index.bytes_written.value_after_commit.diff) + summaries + in + let throughput = + List.map + (fun s -> s.index.bytes_both.value_after_commit.diff /. s.elapsed_cpu) + summaries + in + let read_throughput = + List.map + (fun s -> s.index.bytes_read.value_after_commit.diff /. s.elapsed_cpu) + summaries + in + let write_throughput = + List.map + (fun s -> + s.index.bytes_written.value_after_commit.diff /. s.elapsed_cpu) + summaries + in + let iops = + List.map + (fun s -> s.index.nb_both.value_after_commit.diff /. s.elapsed_cpu) + summaries + in + let read_iops = + List.map + (fun s -> s.index.nb_reads.value_after_commit.diff /. s.elapsed_cpu) + summaries + in + let write_iops = + List.map + (fun s -> s.index.nb_writes.value_after_commit.diff /. s.elapsed_cpu) + summaries + in + let max_ram = + List.map + (fun s -> List.fold_left max 0. s.gc.major_heap_top_bytes) + summaries + in + let mean_cpu_usage = + List.map (fun s -> s.elapsed_cpu /. s.elapsed_wall) summaries + in + [ + `Section "-- main metrics --"; + `Data (`SM, "CPU time elapsed", cpu_time_elapsed); + `Data (`SM, "Wall time elapsed", wall_time_elapsed); + `Data (`R3, "TZ-transactions per sec", tx_per_sec); + `Data (`R3, "TZ-operations per sec", tz_ops_per_sec); + `Data (`R3, "Context.set per sec", add_per_sec); + `Data (`S3, "tail latency (1)", tail_latency); + `Section ""; + `Section "-- resource usage --"; + `Section "disk IO (total)"; + `Data (`Ri, " IOPS (op/sec)", iops); + `Data (`RM, " throughput (bytes/sec)", throughput); + `Data (`RG, " total (bytes)", bytes); + `Section "disk IO (read)"; + `Data (`Ri, " IOPS (op/sec)", read_iops); + `Data (`RM, " throughput (bytes/sec)", read_throughput); + `Data (`RG, " total (bytes)", read_bytes); + `Section "disk IO (write)"; + `Data (`Ri, " IOPS (op/sec)", write_iops); + `Data (`RM, " throughput (bytes/sec)", write_throughput); + `Data (`RG, " total (bytes)", written_bytes); + `Section ""; + `Data (`RG, "max memory usage", max_ram); + `Data (`P, "mean CPU usage", mean_cpu_usage); + ] + + type data_row = [ `Data of scalar_format_fixed * string * float list ] + type section_row = [ `Section of string ] + + let cells_of_data_row (`Data (scalar_format, row_name, scalars) : data_row) = + let v0 = List.hd scalars in + let pp_cell i v = + let percent ppf = + if i = 0 then () + else if scalar_format = `P then Format.fprintf ppf " " + else Format.fprintf ppf " %a" Utils.pp_percent (v /. v0) + in + Fmt.str "%a%t" pp_scalar_fixed (scalar_format, v) percent + in + + Pb.text row_name + :: (List.mapi pp_cell scalars + |> List.map Pb.text + |> List.map (Pb.align ~h:`Right ~v:`Top)) + + let cells_of_section_row col_count (`Section name : section_row) = + Pb.text name + :: (List.init (col_count - 1) (Fun.const "") |> List.map Pb.text) + + let cells_of_row col_count = function + | `Data _ as row -> cells_of_data_row row + | `Section _ as row -> (cells_of_section_row col_count) row + + let matrix_of_rows col_count rows = List.map (cells_of_row col_count) rows +end + +module Table2 = struct + type variable = float * float * float * float + (** min, max, avg, avg per sec *) + + type summary_floor = + [ `Spacer + | `Data of + (scalar_format_fixed * scalar_format_fixed) + * string + * (string * variable) list ] + + let create_header_rows summaries = + let only_one_summary = List.length summaries = 1 in + [ + ("" :: (if only_one_summary then [] else [ "" ])) + @ [ "min per block"; "max per block"; "avg per block"; "avg per sec" ]; + ] + |> Pb.matrix_to_text + |> Pb.align_matrix `Center + + let floors_of_summaries : string list -> summary list -> summary_floor list = + fun summary_names summaries -> + let zip : (summary -> variable) -> (string * variable) list = + fun variable_of_summary -> + List.map2 + (fun sname s -> (sname, variable_of_summary s)) + summary_names summaries + in + let pb : ?f:_ -> string -> (summary -> Summary.bag_stat) -> summary_floor = + fun ?(f = (`Ri, `R3)) stat_name lbs_of_summary -> + let variables = + zip (fun s -> + let vs = (lbs_of_summary s).diff_per_block in + ( fst vs.min_value, + fst vs.max_value, + vs.mean, + vs.mean *. float_of_int s.block_count /. s.elapsed_wall )) + in + `Data (f, stat_name, variables) + in + let span_occu_per_block : string -> Span.Key.t -> summary_floor = + fun name op -> + let variables = + let open Summary in + zip (fun s -> + let vs = Span.(Map.find op s.span).count in + ( fst vs.min_value, + fst vs.max_value, + vs.mean, + vs.mean *. float_of_int s.block_count /. s.elapsed_wall )) + in + `Data ((`Ri, `R3), name, variables) + in + [ + `Spacer; + span_occu_per_block "Add count" `Add; + span_occu_per_block "Remove count" `Remove; + span_occu_per_block "Find count" `Find; + span_occu_per_block "Mem count" `Mem; + span_occu_per_block "Mem_tree count" `Mem_tree; + span_occu_per_block "Copy count" `Copy; + span_occu_per_block "Commit count" `Commit; + `Spacer; + pb ~f:(`RM, `RM) "Disk bytes read" (fun s -> s.index.bytes_read); + pb ~f:(`RM, `RM) "Disk bytes written" (fun s -> s.index.bytes_written); + pb ~f:(`RM, `RM) "Disk bytes both" (fun s -> s.index.bytes_both); + `Spacer; + pb "Disk reads" (fun s -> s.index.nb_reads); + pb "Disk writes" (fun s -> s.index.nb_writes); + pb "Disk both" (fun s -> s.index.nb_both); + `Spacer; + pb "pack.finds" (fun s -> s.pack.finds.total); + pb "pack.finds.from_staging" (fun s -> s.pack.finds.from_staging); + pb "pack.finds.from_lru" (fun s -> s.pack.finds.from_lru); + pb "pack.finds.from_pack_direct" (fun s -> s.pack.finds.from_pack_direct); + pb "pack.finds.from_pack_indexed" (fun s -> + s.pack.finds.from_pack_indexed); + pb "pack.finds.missing" (fun s -> s.pack.finds.missing); + pb "pack.finds.cache_miss" (fun s -> s.pack.finds.cache_miss); + pb "pack.appended_hashes" (fun s -> s.pack.appended_hashes); + pb "pack.appended_offsets" (fun s -> s.pack.appended_offsets); + pb "pack.inode_add" (fun s -> s.pack.inode_add); + pb "pack.inode_remove" (fun s -> s.pack.inode_remove); + pb "pack.inode_of_seq" (fun s -> s.pack.inode_of_seq); + pb "pack.inode_of_raw" (fun s -> s.pack.inode_of_raw); + pb "pack.inode_rec_add" (fun s -> s.pack.inode_rec_add); + pb "pack.inode_rec_remove" (fun s -> s.pack.inode_rec_remove); + pb "pack.inode_to_binv" (fun s -> s.pack.inode_to_binv); + pb "pack.inode_decode_bin" (fun s -> s.pack.inode_decode_bin); + pb "pack.inode_encode_bin" (fun s -> s.pack.inode_encode_bin); + `Spacer; + pb "tree.contents_hash" (fun s -> s.tree.contents_hash); + pb "tree.contents_find" (fun s -> s.tree.contents_find); + pb "tree.contents_add" (fun s -> s.tree.contents_add); + pb "tree.node_hash" (fun s -> s.tree.node_hash); + pb "tree.node_mem" (fun s -> s.tree.node_mem); + pb "tree.node_add" (fun s -> s.tree.node_add); + pb "tree.node_find" (fun s -> s.tree.node_find); + pb "tree.node_val_v" (fun s -> s.tree.node_val_v); + pb "tree.node_val_find" (fun s -> s.tree.node_val_find); + pb "tree.node_val_list" (fun s -> s.tree.node_val_list); + `Spacer; + pb ~f:(`RM, `Ri) "index.cumu_data_bytes" (fun s -> + s.index.cumu_data_bytes); + `Spacer; + pb ~f:(`RM, `RM) "gc.minor_words allocated" (fun s -> s.gc.minor_words); + pb ~f:(`RM, `RM) "gc.major_words allocated" (fun s -> s.gc.major_words); + pb "gc.minor_collections" (fun s -> s.gc.minor_collections); + pb "gc.major_collections" (fun s -> s.gc.major_collections); + ] + + let matrix_of_data_floor + (`Data + ((scalar_format_a, scalar_format_b), floor_name, names_and_variables)) = + let only_one_summary = List.length names_and_variables = 1 in + let _, variables = List.split names_and_variables in + let min0, max0, avg0, avg_ps0 = List.hd variables in + + let box_of_scalar scalar_format row_idx v0 v = + let ratio = v /. v0 in + let show_percent = + if only_one_summary then + (* Percents are only needed for comparisons between summaries. *) + `No + else if Float.is_finite ratio = false then + (* Nan and infinite percents are ugly. *) + `Shadow + else if row_idx = 0 then + (* The first row of a floor is always 100%, it is prettier without + displaying it. *) + `Shadow + else `Yes + in + let pp_percent ppf = + match show_percent with + | `Yes -> Format.fprintf ppf " %a" Utils.pp_percent ratio + | `Shadow -> Format.fprintf ppf " " + | `No -> () + in + let pp_scalar ppf = pp_scalar_fixed ppf (scalar_format, v) in + Fmt.str "%t%t" pp_scalar pp_percent + |> Pb.text + |> Pb.align ~h:`Right ~v:`Top + in + let rows = + List.mapi + (fun row_idx (summary_name, variable) -> + let a = Pb.text (if row_idx = 0 then floor_name else "") in + let b = if only_one_summary then [] else [ Pb.text summary_name ] in + let c = + let min, max, avg, avg_ps = variable in + [ + box_of_scalar scalar_format_a row_idx min0 min; + box_of_scalar scalar_format_a row_idx max0 max; + box_of_scalar scalar_format_b row_idx avg0 avg; + box_of_scalar scalar_format_b row_idx avg_ps0 avg_ps; + ] + in + (a :: b) @ c) + names_and_variables + in + rows + + let matrix_of_floor col_count = function + | `Spacer -> [ List.init col_count (Fun.const "") ] |> Pb.matrix_to_text + | `Data _ as floor -> matrix_of_data_floor floor +end + +module Table3 = struct + type variable = float * float * float + (** min, max, avg *) + + type summary_floor = + [ `Spacer + | `Data of + (scalar_format_fixed * scalar_format_fixed) + * string + * (string * variable) list ] + + let create_header_rows summaries = + let only_one_summary = List.length summaries = 1 in + [ + ("" :: (if only_one_summary then [] else [ "" ])) + @ [ "min"; "max"; "avg" ]; + ] + |> Pb.matrix_to_text + |> Pb.align_matrix `Center + + let floors_of_summaries : string list -> summary list -> summary_floor list = + fun summary_names summaries -> + let zip : (summary -> variable) -> (string * variable) list = + fun variable_of_summary -> + List.map2 + (fun sname s -> (sname, variable_of_summary s)) + summary_names summaries + in + + let v : ?f:_ -> string -> (summary -> Summary.bag_stat) -> summary_floor = + fun ?(f = (`RM, `RM)) stat_name lbs_of_summary -> + let variables = + zip (fun s -> + let vs = (lbs_of_summary s).value_after_commit in + (fst vs.min_value, fst vs.max_value, vs.mean)) + in + `Data (f, stat_name, variables) + in + let cpu_usage_variables = + zip (fun s -> + let vs = s.cpu_usage in + (fst vs.min_value, fst vs.max_value, vs.mean)) + in + let span_durations : ?f:_ -> string -> Span.Key.t -> summary_floor = + fun ?(f = (`Sm, `Su)) name op -> + let variables = + let open Summary in + zip (fun s -> + let vs = Span.(Map.find op s.span).duration in + (fst vs.min_value, fst vs.max_value, vs.mean)) + in + `Data (f, name, variables) + in + [ + `Spacer; + span_durations ~f:(`S3, `Sm) "Block duration (s)" `Block; + span_durations ~f:(`S3, `Sm) "Buildup duration (s)" `Buildup; + span_durations ~f:(`S3, `Sm) "Commit duration (s)" `Commit; + `Spacer; + span_durations "Add duration (s)" `Add; + span_durations "Remove duration (s)" `Remove; + span_durations "Find duration (s)" `Find; + span_durations "Mem duration (s)" `Mem; + span_durations "Mem_tree duration (s)" `Mem_tree; + span_durations "Copy duration (s)" `Copy; + span_durations ~f:(`S3, `Sm) "Unseen duration (s)" `Unseen; + `Spacer; + v "Major heap bytes after commit" (fun s -> s.gc.major_heap_bytes); + `Spacer; + `Data ((`P, `P), "CPU Usage", cpu_usage_variables); + ] + + let matrix_of_data_floor + (`Data + ((scalar_format_a, scalar_format_b), floor_name, names_and_variables)) = + let only_one_summary = List.length names_and_variables = 1 in + let _, variables = List.split names_and_variables in + let min0, max0, avg0 = List.hd variables in + + let box_of_scalar scalar_format row_idx v0 v = + let ratio = v /. v0 in + let show_percent = + if only_one_summary then + (* Percents are only needed for comparisons between summaries. *) + `No + else if Float.is_finite ratio = false then + (* Nan and infinite percents are ugly. *) + `Shadow + else if row_idx = 0 then + (* The first row of a floor is always 100%, it is prettier without + displaying it. *) + `Shadow + else if scalar_format = `P then `Shadow + else `Yes + in + let pp_percent ppf = + match show_percent with + | `Yes -> Format.fprintf ppf " %a" Utils.pp_percent ratio + | `Shadow -> Format.fprintf ppf " " + | `No -> () + in + let pp_scalar ppf = pp_scalar_fixed ppf (scalar_format, v) in + + Fmt.str "%t%t" pp_scalar pp_percent + |> Pb.text + |> Pb.align ~h:`Right ~v:`Top + in + let rows = + List.mapi + (fun row_idx (summary_name, variable) -> + let a = Pb.text (if row_idx = 0 then floor_name else "") in + let b = if only_one_summary then [] else [ Pb.text summary_name ] in + let c = + let min, max, avg = variable in + [ + box_of_scalar scalar_format_b row_idx min0 min; + box_of_scalar scalar_format_a row_idx max0 max; + box_of_scalar scalar_format_b row_idx avg0 avg; + ] + in + (a :: b) @ c) + names_and_variables + in + rows + + let matrix_of_floor col_count = function + | `Spacer -> [ List.init col_count (Fun.const "") ] |> Pb.matrix_to_text + | `Data _ as floor -> matrix_of_data_floor floor +end + +(** Curves *) +module Table4 = struct + type scalar_format_auto = [ `R | `S ] + (** Real / Seconds *) + + type scalar_format = [ scalar_format_auto | scalar_format_fixed ] + + type summary_floor = + [ `Spacer | `Data of scalar_format * string * (string * curve) list ] + (** A [summary_floor] of tag [`Data] contains all the data necessary in order + to print a bunch of rows, 1 per summary, all displaying the same summary + entry. *) + + let sum_curves curves = + curves + |> Pb.transpose_matrix + |> List.map + (List.fold_left + (fun acc v -> if Float.is_nan v then acc else acc +. v) + 0.) + + let div_curves a b = List.map2 ( /. ) a b + let mul_curves a b = List.map2 ( *. ) a b + let mul_curve_scalar a v = List.map (( *. ) v) a + + let create_header_rows sample_count summaries = + let only_one_summary = List.length summaries = 1 in + let s = List.hd summaries in + let played_count_curve = + List.init s.curves_sample_count (fun i -> + float_of_int i + /. float_of_int (s.curves_sample_count - 1) + *. float_of_int s.block_count) + in + let played_count_curve = + Utils.Resample.resample_vector `Next_neighbor played_count_curve + sample_count + |> Array.of_list + in + let header_cells_per_col_idx col_idx = + let played_count = played_count_curve.(col_idx) in + let progress_blocks = played_count /. float_of_int s.block_count in + let h0 = + if progress_blocks = 0. then "0 (before)" + else if progress_blocks = 1. then + Printf.sprintf "%.0f (end)" played_count + else if Float.is_integer played_count then + Printf.sprintf "%.0f" played_count + else Printf.sprintf "%.1f" played_count + in + let h1 = Printf.sprintf "%.0f%%" (progress_blocks *. 100.) in + [ h0; h1 ] + in + let col_a = + [ [ "Block played count *C"; "Blocks progress *C" ] ] |> Pb.matrix_to_text + in + let col_b = + (if only_one_summary then [] else [ [ ""; "" ] ]) + |> Pb.matrix_to_text + |> Pb.align_matrix `Center + in + let cols_c = + List.init sample_count header_cells_per_col_idx + |> Pb.matrix_to_text + |> Pb.align_matrix `Center + in + col_a @ col_b @ cols_c |> Pb.transpose_matrix + + let floors_of_summaries : string list -> summary list -> summary_floor list = + fun summary_names summaries -> + (* Step 1/3 - Prepare the "/data/..." directories floors *) + let floor_per_node : summary_floor list = + List.map + (fun key -> + let path = List.assoc key Def.path_per_watched_node in + let name = Printf.sprintf "%s *S" path in + let curves = + List.map + (fun s -> + (Summary.Watched_node.Map.find key s.store.watched_nodes).value + .evolution) + summaries + in + let l = List.combine summary_names curves in + `Data (`R, name, l)) + Def.watched_nodes + in + + (* Step 2/3 - Prepare the functions to build all the simple floors *) + let zip : (summary -> curve) -> (string * curve) list = + fun curve_of_summary -> + List.map2 + (fun sname s -> (sname, curve_of_summary s)) + summary_names summaries + in + let zip_per_block_to_per_sec : (summary -> curve) -> (string * curve) list = + let sec_per_block = + List.map + (fun s -> Summary.(Span.Map.find `Block s.span).duration.evolution) + summaries + in + fun curve_of_summary -> + List.map2 + (fun (sname, sec_per_block) s -> + (sname, div_curves (curve_of_summary s) sec_per_block)) + (List.combine summary_names sec_per_block) + summaries + in + + let v : ?f:_ -> string -> (summary -> Summary.bag_stat) -> summary_floor = + fun ?(f = `R) stat_name lbs_of_summary -> + let curves = + zip (fun s -> (lbs_of_summary s).value_after_commit.evolution) + in + `Data (f, stat_name, curves) + in + let pb : ?f:_ -> string -> (summary -> Summary.bag_stat) -> summary_floor = + fun ?(f = `R) stat_name lbs_of_summary -> + let curves = zip (fun s -> (lbs_of_summary s).diff_per_block.evolution) in + `Data (f, stat_name, curves) + in + let ps : ?f:_ -> string -> (summary -> Summary.bag_stat) -> summary_floor = + fun ?(f = `R) stat_name lbs_of_summary -> + let curves = + zip_per_block_to_per_sec (fun s -> + (lbs_of_summary s).diff_per_block.evolution) + in + `Data (f, stat_name, curves) + in + + let span_occu_count : string -> Span.Key.t -> summary_floor = + fun name op -> + let curves = + zip (fun s -> Summary.(Span.Map.find op s.span).count.evolution) + in + `Data (`R3, name, curves) + in + let span_duration : _ -> string -> Span.Key.t -> summary_floor = + fun f name op -> + let curves = + zip (fun s -> Summary.(Span.Map.find op s.span).duration.evolution) + in + `Data (f, name, curves) + in + let span_occu_every_sec : string -> Span.Key.t -> summary_floor = + fun name op -> + let curves = + zip_per_block_to_per_sec (fun s -> + Summary.(Span.Map.find op s.span).count.evolution) + in + `Data (`R3, name, curves) + in + + let all_ops_cumu_count = + zip (fun s -> + Summary.Span.Key.((all_atoms_seen :> t list)) + |> List.map (fun op -> + Summary.(Span.Map.find op s.span).cumu_count.evolution) + |> sum_curves) + in + + let tz_tx_count = + (* TODO: When replaying on a middle section of the chain, set + [~first_block_idx] *) + zip (fun s -> + let played_count_curve = + List.init s.curves_sample_count (fun i -> + float_of_int i + /. float_of_int (s.curves_sample_count - 1) + *. float_of_int s.block_count) + |> List.map (fun v -> + Utils.approx_transaction_count_of_block_count + (int_of_float v) + |> float_of_int) + in + played_count_curve) + in + let tz_ops_count = + (* TODO: When replaying on a middle section of the chain, set + [~first_block_idx] *) + zip (fun s -> + let played_count_curve = + List.init s.curves_sample_count (fun i -> + float_of_int i + /. float_of_int (s.curves_sample_count - 1) + *. float_of_int s.block_count) + |> List.map (fun v -> + Utils.approx_operation_count_of_block_count (int_of_float v) + |> float_of_int) + in + played_count_curve) + in + + (* Step 3/3 - Build the final list of floors *) + [ + `Spacer; + `Data + (`S, "Wall time elapsed *C", zip (fun s -> s.elapsed_wall_over_blocks)); + `Data (`S, "CPU time elapsed *C", zip (fun s -> s.elapsed_cpu_over_blocks)); + `Data (`P, "CPU Usage *LA", zip (fun s -> s.cpu_usage.evolution)); + (* ops counts *) + `Spacer; + `Data (`R, "Approx. TZ-transaction count *C", tz_tx_count); + `Data (`R, "Approx. TZ-operations count *C", tz_ops_count); + `Data (`R, "Op count *C", all_ops_cumu_count); + (* per sec *) + `Spacer; + span_occu_every_sec "Commit per sec *LA *N" `Commit; + span_occu_every_sec "Add per sec *LA *N" `Add; + span_occu_every_sec "Remove per sec *LA *N" `Remove; + span_occu_every_sec "Find per sec *LA *N" `Find; + span_occu_every_sec "Mem per sec *LA *N" `Mem; + span_occu_every_sec "Mem_tree per sec *LA *N" `Mem_tree; + span_occu_every_sec "Copy per sec *LA *N" `Copy; + (* per block *) + `Spacer; + span_occu_count "Add count per block *LA" `Add; + span_occu_count "Remove count per block *LA" `Remove; + span_occu_count "Find count per block *LA" `Find; + span_occu_count "Mem count per block *LA" `Mem; + span_occu_count "Mem_tree count per block *LA" `Mem_tree; + span_occu_count "Copy count per block *LA" `Copy; + (* duration *) + `Spacer; + span_duration `Sm "Block duration *LA" `Block; + span_duration `Sm "Buildup duration *LA" `Buildup; + span_duration `Sm "Commit duration *LA" `Commit; + `Spacer; + (* duration *) + span_duration `Su "Add duration *LA" `Add; + span_duration `Su "Remove duration *LA" `Remove; + span_duration `Su "Find duration *LA" `Find; + span_duration `Su "Mem duration *LA" `Mem; + span_duration `Su "Mem_tree duration *LA" `Mem_tree; + span_duration `Su "Copy duration *LA" `Copy; + span_duration `Su "Checkout duration *LA" `Checkout; + (* derived from bag_of_stat *) + `Spacer; + v "Disk bytes read *C" (fun s -> s.index.bytes_read); + v "Disk bytes written *C" (fun s -> s.index.bytes_written); + v "Disk bytes both *C" (fun s -> s.index.bytes_both); + pb ~f:`Ri "Disk bytes read per block *LA" (fun s -> s.index.bytes_read); + pb ~f:`Ri "Disk bytes written per block *LA" (fun s -> + s.index.bytes_written); + pb ~f:`Ri "Disk bytes both per block *LA" (fun s -> s.index.bytes_both); + ps ~f:`RM "Disk bytes read per sec *LA *N" (fun s -> + s.index.bytes_read); + ps ~f:`RM "Disk bytes written per sec *LA *N" (fun s -> + s.index.bytes_written); + ps ~f:`RM "Disk bytes both per sec *LA *N" (fun s -> + s.index.bytes_both); + `Spacer; + v "Disk read count *C" (fun s -> s.index.nb_reads); + v "Disk write count *C" (fun s -> s.index.nb_writes); + v "Disk both count *C" (fun s -> s.index.nb_both); + pb ~f:`R3 "Disk read count per block *LA" (fun s -> s.index.nb_reads); + pb ~f:`R3 "Disk write count per block *LA" (fun s -> s.index.nb_writes); + pb ~f:`R3 "Disk both count per block *LA" (fun s -> s.index.nb_both); + ps ~f:`Ri "Disk read count per sec *LA *N" (fun s -> s.index.nb_reads); + ps ~f:`Ri "Disk write count per sec *LA *N" (fun s -> s.index.nb_writes); + ps ~f:`Ri "Disk both count per sec *LA *N" (fun s -> s.index.nb_both); + `Spacer; + pb "pack.appended_hashes per block *LA" (fun s -> s.pack.appended_hashes); + pb "pack.appended_offsets per block *LA" (fun s -> + s.pack.appended_offsets); + pb "pack.finds per block *LA" (fun s -> s.pack.finds.total); + pb "pack.finds.from_staging per block *LA" (fun s -> + s.pack.finds.from_staging); + pb "pack.finds.from_lru per block *LA" (fun s -> s.pack.finds.from_lru); + pb "pack.finds.from_pack_direct per block *LA" (fun s -> + s.pack.finds.from_pack_direct); + pb "pack.finds.from_pack_indexed per block *LA" (fun s -> + s.pack.finds.from_pack_indexed); + pb "pack.finds.missing per block *LA" (fun s -> s.pack.finds.missing); + pb "pack.finds.cache_miss per block *LA" (fun s -> + s.pack.finds.cache_miss); + pb "pack.inode_add per block *LA" (fun s -> s.pack.inode_add); + pb "pack.inode_remove per block *LA" (fun s -> s.pack.inode_remove); + pb "pack.inode_of_seq per block *LA" (fun s -> s.pack.inode_of_seq); + pb "pack.inode_of_raw per block *LA" (fun s -> s.pack.inode_of_raw); + pb "pack.inode_rec_add per block *LA" (fun s -> s.pack.inode_rec_add); + pb "pack.inode_rec_remove per block *LA" (fun s -> + s.pack.inode_rec_remove); + pb "pack.inode_to_binv per block *LA" (fun s -> s.pack.inode_to_binv); + pb "pack.inode_decode_bin per block *LA" (fun s -> + s.pack.inode_decode_bin); + pb "pack.inode_encode_bin per block *LA" (fun s -> + s.pack.inode_encode_bin); + `Spacer; + pb "tree.contents_hash per block *LA" (fun s -> s.tree.contents_hash); + pb "tree.contents_find per block *LA" (fun s -> s.tree.contents_find); + pb "tree.contents_add per block *LA" (fun s -> s.tree.contents_add); + pb "tree.node_hash per block *LA" (fun s -> s.tree.node_hash); + pb "tree.node_mem per block *LA" (fun s -> s.tree.node_mem); + pb "tree.node_add per block *LA" (fun s -> s.tree.node_add); + pb "tree.node_find per block *LA" (fun s -> s.tree.node_find); + pb "tree.node_val_v per block *LA" (fun s -> s.tree.node_val_v); + pb "tree.node_val_find per block *LA" (fun s -> s.tree.node_val_find); + pb "tree.node_val_list per block *LA" (fun s -> s.tree.node_val_list); + `Spacer; + v "index.nb_merge *C" (fun s -> s.index.nb_merge); + v "index.cumu_data_bytes *C" (fun s -> s.index.cumu_data_bytes); + pb "index.cumu_data_bytes per block *LA" (fun s -> + s.index.cumu_data_bytes); + `Spacer; + v "gc.minor_words allocated *C" (fun s -> s.gc.minor_words); + pb "gc.minor_words allocated per block *LA" (fun s -> s.gc.minor_words); + v "gc.promoted_words *C" (fun s -> s.gc.promoted_words); + v "gc.major_words allocated *C" (fun s -> s.gc.major_words); + pb "gc.major_words allocated per block *LA" (fun s -> s.gc.major_words); + v "gc.minor_collections *C" (fun s -> s.gc.minor_collections); + pb "gc.minor_collections per block *LA" (fun s -> s.gc.minor_collections); + v "gc.major_collections *C" (fun s -> s.gc.major_collections); + pb "gc.major_collections per block *LA" (fun s -> s.gc.major_collections); + v "gc.compactions *C" (fun s -> s.gc.compactions); + `Spacer; + `Data + ( `RM, + "gc.major heap bytes top *C", + zip (fun s -> s.gc.major_heap_top_bytes) ); + v ~f:`RM "gc.major heap bytes *LA" (fun s -> s.gc.major_heap_bytes); + `Spacer; + v "index_data bytes *S" (fun s -> s.disk.index_data); + pb "index_data bytes per block *LA" (fun s -> s.disk.index_data); + v "store_pack bytes *S" (fun s -> s.disk.store_pack); + pb "store_pack bytes per block *LA" (fun s -> s.disk.store_pack); + v "index_log bytes *S" (fun s -> s.disk.index_log); + v "index_log_async *S" (fun s -> s.disk.index_log_async); + v "store_dict bytes *S" (fun s -> s.disk.store_dict); + `Spacer; + ] + @ floor_per_node + + let resample_curves_of_floor sample_count = function + | `Data (a, b, names_and_curves) -> + let names, curves = List.split names_and_curves in + let curves = + List.map + (fun curve -> + Utils.Resample.resample_vector `Next_neighbor curve sample_count) + curves + in + `Data (a, b, List.combine names curves) + | `Spacer -> `Spacer + + let matrix_of_data_floor (`Data (scalar_format, floor_name, names_and_curves)) + = + let only_one_summary = List.length names_and_curves = 1 in + let _, curves = List.split names_and_curves in + let pp_real = Utils.create_pp_real (List.concat curves) in + let pp_seconds = Utils.create_pp_seconds (List.concat curves) in + let curve0 = List.hd curves in + let box_of_scalar row_idx col_idx (v0, v) = + let ratio = v /. v0 in + let show_percent = + if only_one_summary then + (* Percents are only needed for comparisons between summaries. *) + `No + else if col_idx = 0 then + (* The first columns is usually full of NaNs, showing percents there + is a waste of space. *) + `No + else if Float.is_finite ratio = false then + (* Nan and infinite percents are ugly. *) + `Shadow + else if row_idx = 0 then + (* The first row of a floor is always 100%, it is prettier without + displaying it. *) + `Shadow + else if scalar_format = `P then `Shadow + else `Yes + in + let pp_percent ppf = + match show_percent with + | `Yes -> Format.fprintf ppf " %a" Utils.pp_percent ratio + | `Shadow -> Format.fprintf ppf " " + | `No -> () + in + let pp_scalar ppf = + match scalar_format with + | `R -> Format.fprintf ppf "%a" pp_real v + | `S -> Format.fprintf ppf "%a" pp_seconds v + | #scalar_format_fixed as scalar_format -> + pp_scalar_fixed ppf (scalar_format, v) + in + Fmt.str "%t%t" pp_scalar pp_percent + |> Pb.text + |> Pb.align ~h:`Right ~v:`Top + in + let rows = + List.mapi + (fun row_idx (summary_name, curve) -> + let a = Pb.text (if row_idx = 0 then floor_name else "") in + let b = if only_one_summary then [] else [ Pb.text summary_name ] in + let c = + List.mapi (box_of_scalar row_idx) (List.combine curve0 curve) + in + (a :: b) @ c) + names_and_curves + in + rows + + let matrix_of_floor col_count = function + | `Spacer -> [ List.init col_count (Fun.const "") ] |> Pb.matrix_to_text + | `Data _ as floor -> matrix_of_data_floor floor +end + +let unsafe_pp sample_count ppf summary_names (summaries : Summary.t list) = + let block_count = + let l = List.map (fun s -> s.block_count) summaries in + let v = List.hd l in + if List.exists (fun v' -> v' <> v) l then + failwith "Can't pp together summaries with a different `block_count`"; + v + in + let moving_average_half_life_ratio = + let l = List.map (fun s -> s.moving_average_half_life_ratio) summaries in + let v = List.hd l in + if List.exists (fun v' -> v' <> v) l then + failwith + "Can't pp together summaries with a different \ + `moving_average_half_life_ratio`"; + v + in + let table0 = + Table0.box_of_summaries_config summary_names summaries + |> Pb.matrix_with_column_spacers + |> Pb.grid_l ~bars:false + |> PrintBox_text.to_string + in + let table1 = + let summary_length = List.length summaries in + let header_rows = + [ "" :: summary_names ] |> Pb.matrix_to_text |> Pb.align_matrix `Center + in + let col_count = summary_length + 1 in + let separator = + ([ List.init (summary_length + 1) (Fun.const "--") ] : string list list) + in + let separator_row = Pb.matrix_to_text separator in + let body_rows = + Table1.rows_of_summaries summaries |> Table1.matrix_of_rows col_count + in + header_rows @ separator_row @ body_rows + |> Pb.matrix_with_column_spacers + |> Pb.grid_l ~bars:false + |> PrintBox_text.to_string + in + let table2 = + let header_rows = Table2.create_header_rows summaries in + let body_rows = + let col_count = 4 + 1 + if List.length summaries = 1 then 0 else 1 in + Table2.floors_of_summaries summary_names summaries + |> List.map (Table2.matrix_of_floor col_count) + |> List.concat + in + header_rows @ body_rows + |> Pb.matrix_with_column_spacers + |> Pb.grid_l ~bars:false + |> PrintBox_text.to_string + in + let table3 = + let header_rows = Table3.create_header_rows summaries in + let body_rows = + let col_count = 4 + 1 + if List.length summaries = 1 then 0 else 1 in + Table3.floors_of_summaries summary_names summaries + |> List.map (Table3.matrix_of_floor col_count) + |> List.concat + in + header_rows @ body_rows + |> Pb.matrix_with_column_spacers + |> Pb.grid_l ~bars:false + |> PrintBox_text.to_string + in + let table4 = + let header_rows = Table4.create_header_rows sample_count summaries in + let body_rows = + let col_count = + sample_count + 1 + if List.length summaries = 1 then 0 else 1 + in + Table4.floors_of_summaries summary_names summaries + |> List.map (Table4.resample_curves_of_floor sample_count) + |> List.map (Table4.matrix_of_floor col_count) + |> List.concat + in + header_rows @ body_rows + |> Pb.matrix_with_column_spacers + |> Pb.grid_l ~bars:false + |> PrintBox_text.to_string + in + fprintf_result ppf table0 table1 table2 table3 table4 + (moving_average_half_life_ratio *. float_of_int (block_count + 1)) + +let pp sample_count ppf (summary_names, summaries) = + if List.length summaries = 0 then () + else unsafe_pp sample_count ppf summary_names summaries diff --git a/vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.ml b/vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.ml new file mode 100644 index 000000000000..e35846aed403 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.ml @@ -0,0 +1,636 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type histo = (float * int) list [@@deriving repr] +type curve = float list [@@deriving repr] + +let snap_to_integer ~significant_digits v = + if significant_digits < 0 then + invalid_arg "significant_digits should be greater or equal to zero."; + if not @@ Float.is_finite v then v + else if Float.is_integer v then v + else + (* This scope is about choosing between [v] and [Float.round v]. *) + let significant_digits = float_of_int significant_digits in + let v' = Float.round v in + if v' = 0. then (* Do not snap numbers close to 0. *) + v + else + let round_distance = Float.abs (v -. v') in + assert (round_distance <= 0.5); + (* The smaller [round_distance], the greater [significant_digits']. *) + let significant_digits' = -.Float.log10 round_distance in + assert (significant_digits' > 0.); + if significant_digits' >= significant_digits then v' else v + +let pp_six_digits_with_spacer ppf v = + let s = Printf.sprintf "%.6f" v in + let len = String.length s in + let a = String.sub s 0 (len - 3) in + let b = String.sub s (len - 3) 3 in + Format.fprintf ppf "%s_%s" a b + +let create_pp_real ?(significant_digits = 7) examples = + let examples = List.map (snap_to_integer ~significant_digits) examples in + let all_integer = + List.for_all + (fun v -> Float.is_integer v || not (Float.is_finite v)) + examples + in + let absmax = + List.fold_left + (fun acc v -> + if not @@ Float.is_finite acc then v + else if not @@ Float.is_finite v then acc + else Float.abs v |> max acc) + Float.neg_infinity examples + in + let finite_pp = + if absmax /. 1e12 >= 10. then fun ppf v -> + Format.fprintf ppf "%.3f T" (v /. 1e12) + else if absmax /. 1e9 >= 10. then fun ppf v -> + Format.fprintf ppf "%.3f G" (v /. 1e9) + else if absmax /. 1e6 >= 10. then fun ppf v -> + Format.fprintf ppf "%.3f M" (v /. 1e6) + else if absmax /. 1e3 >= 10. then fun ppf v -> + Format.fprintf ppf "%#d" (Float.round v |> int_of_float) + else if all_integer then fun ppf v -> + Format.fprintf ppf "%#d" (Float.round v |> int_of_float) + else if absmax /. 1. >= 10. then fun ppf v -> Format.fprintf ppf "%.3f" v + else if absmax /. 1e-3 >= 10. then pp_six_digits_with_spacer + else fun ppf v -> Format.fprintf ppf "%.3e" v + in + fun ppf v -> + if Float.is_nan v then Format.fprintf ppf "n/a" + else if Float.is_infinite v then Format.fprintf ppf "%f" v + else finite_pp ppf v + +let create_pp_seconds examples = + let absmax = + List.fold_left + (fun acc v -> + if not @@ Float.is_finite acc then v + else if not @@ Float.is_finite v then acc + else Float.abs v |> max acc) + Float.neg_infinity examples + in + let finite_pp = + if absmax >= 60. then fun ppf v -> Mtime.Span.pp_float_s ppf v + else if absmax < 100. *. 1e-12 then fun ppf v -> + Format.fprintf ppf "%.3e s" v + else if absmax < 100. *. 1e-9 then fun ppf v -> + Format.fprintf ppf "%.3f ns" (v *. 1e9) + else if absmax < 100. *. 1e-6 then fun ppf v -> + Format.fprintf ppf "%.3f \xc2\xb5s" (v *. 1e6) + else if absmax < 100. *. 1e-3 then fun ppf v -> + Format.fprintf ppf "%.3f ms" (v *. 1e3) + else fun ppf v -> Format.fprintf ppf "%.3f s" v + in + fun ppf v -> + if Float.is_nan v then Format.fprintf ppf "n/a" + else if Float.is_infinite v then Format.fprintf ppf "%f" v + else finite_pp ppf v + +let pp_percent ppf v = + if not @@ Float.is_finite v then Format.fprintf ppf "%4f" v + else if v = 0. then Format.fprintf ppf " 0%%" + else if v < 10. /. 100. then Format.fprintf ppf "%3.1f%%" (v *. 100.) + else if v < 1000. /. 100. then Format.fprintf ppf "%3.0f%%" (v *. 100.) + else if v < 1000. then Format.fprintf ppf "%3.0fx" v + else if v < 9.5e9 then ( + let long_repr = Printf.sprintf "%.0e" v in + assert (String.length long_repr = 5); + Format.fprintf ppf "%ce%cx" long_repr.[0] long_repr.[4]) + else Format.fprintf ppf "++++" + +let weekly_stats = Tezos_history_metrics.weekly_stats + +let approx_value_count_of_block_count value_of_row ?(first_block_idx = 0) + wished_block_count = + let end_block_idx = first_block_idx + wished_block_count in + let blocks_of_row (_, _, _, v) = v in + let fold (week_block0_idx, acc_value, acc_blocks) row = + let week_blocks = blocks_of_row row in + let week_value = value_of_row row in + assert (acc_blocks <= wished_block_count); + let nextweek_block0_idx = week_block0_idx + week_blocks in + let kept_block_count = + let left = + if first_block_idx >= nextweek_block0_idx then `After + else if first_block_idx <= week_block0_idx then `Before + else `Inside + in + let right = + if end_block_idx >= nextweek_block0_idx then `After + else if end_block_idx <= week_block0_idx then `Before + else `Inside + in + match (left, right) with + | `After, `After -> 0 + | `Before, `Before -> 0 + | `Before, `After -> week_blocks + | `Inside, `After -> first_block_idx - week_block0_idx + | `Inside, `Inside -> end_block_idx - first_block_idx + | `Before, `Inside -> wished_block_count - acc_blocks + | `Inside, `Before -> assert false + | `After, (`Before | `Inside) -> assert false + in + assert (kept_block_count >= 0); + assert (kept_block_count <= week_blocks); + let kept_tx_count = + let f = float_of_int in + f week_value /. f week_blocks *. f kept_block_count + |> Float.round + |> int_of_float + in + assert (kept_tx_count >= 0); + assert (kept_tx_count <= week_value); + let acc_blocks' = acc_blocks + kept_block_count in + let acc_value' = acc_value + kept_tx_count in + (nextweek_block0_idx, acc_value', acc_blocks') + in + let _, acc_value, acc_blocks = List.fold_left fold (0, 0, 0) weekly_stats in + assert (acc_blocks <= wished_block_count); + if acc_blocks = wished_block_count then acc_value + else + (* Extrapolate for the following weeks *) + let latest_weeks_tx_count, latest_weeks_block_count = + match List.rev weekly_stats with + | rowa :: rowb :: rowc :: _ -> + let value = + List.map value_of_row [ rowa; rowb; rowc ] |> List.fold_left ( + ) 0 + in + let blocks = + List.map blocks_of_row [ rowa; rowb; rowc ] + |> List.fold_left ( + ) 0 + in + (value, blocks) + | _ -> assert false + in + let missing_blocks = wished_block_count - acc_blocks in + let missing_value = + let f = float_of_int in + f latest_weeks_tx_count /. f latest_weeks_block_count *. f missing_blocks + |> Float.round + |> int_of_float + in + acc_value + missing_value + +let approx_transaction_count_of_block_count = + approx_value_count_of_block_count (fun (_, txs, _, _) -> txs) + +let approx_operation_count_of_block_count = + approx_value_count_of_block_count (fun (_, _, ops, _) -> ops) + +module Exponential_moving_average = struct + type t = { + momentum : float; + relevance_threshold : float; + opp_momentum : float; + hidden_state : float; + void_fraction : float; + } + + let create ?(relevance_threshold = 1.) momentum = + if momentum < 0. || momentum >= 1. then invalid_arg "Wrong momentum"; + if relevance_threshold < 0. || relevance_threshold > 1. then + invalid_arg "Wrong relevance_threshold"; + { + momentum; + relevance_threshold; + opp_momentum = 1. -. momentum; + hidden_state = 0.; + void_fraction = 1.; + } + + let from_half_life ?relevance_threshold hl = + if hl < 0. then invalid_arg "Wrong half life"; + create ?relevance_threshold (if hl = 0. then 0. else log 0.5 /. hl |> exp) + + let from_half_life_ratio ?relevance_threshold hl_ratio step_count = + if hl_ratio < 0. then invalid_arg "Wrong half life ratio"; + if step_count < 0. then invalid_arg "Wront step count"; + step_count *. hl_ratio |> from_half_life ?relevance_threshold + + let momentum ema = ema.momentum + let hidden_state ema = ema.hidden_state + let void_fraction ema = ema.void_fraction + let is_relevant ema = ema.void_fraction < ema.relevance_threshold + + let peek_exn ema = + if is_relevant ema then ema.hidden_state /. (1. -. ema.void_fraction) + else failwith "Can't peek an irrelevant EMA" + + let peek_or_nan ema = + if is_relevant ema then ema.hidden_state /. (1. -. ema.void_fraction) + else Float.nan + + let update ema sample = + let hidden_state = + (* The first term is the "forget" term, the second one is the "remember" + term. *) + (ema.momentum *. ema.hidden_state) +. (ema.opp_momentum *. sample) + in + let void_fraction = + (* [update] decreases the quantity of "void". *) + ema.momentum *. ema.void_fraction + in + { ema with hidden_state; void_fraction } + + let update_batch ema sample sample_size = + if sample_size <= 0. then invalid_arg "Wrong sample_size"; + let momentum = ema.momentum ** sample_size in + let opp_momentum = 1. -. momentum in + (* From this point, the code is identical to [update]. *) + let hidden_state = + (ema.hidden_state *. momentum) +. (sample *. opp_momentum) + in + let void_fraction = ema.void_fraction *. momentum in + { ema with hidden_state; void_fraction } + + (** [peek ema] is equal to [forget ema |> peek]. Modulo floating point + imprecisions and relevance changes. + + Proof: + + {v + v0 = hs0 / (1 - vf0) + v1 = hs1 / (1 - vf1) + hs1 = mom * hs0 + vf1 = mom * vf0 + (1 - mom) + hs0 / (1 - vf0) = hs1 / (1 - vf1) + hs0 / (1 - vf0) = (mom * hs0) / (1 - (mom * vf0 + (1 - mom))) + hs0 / (1 - vf0) = (mom * hs0) / (1 - (mom * vf0 + 1 - mom)) + hs0 / (1 - vf0) = (mom * hs0) / (1 + (-mom * vf0 - 1 + mom)) + hs0 / (1 - vf0) = (mom * hs0) / (1 - mom * vf0 - 1 + mom) + hs0 / (1 - vf0) = (mom * hs0) / ( -mom * vf0 + mom) + hs0 / (1 - vf0) = (hs0) / ( -1 * vf0 + 1) + hs0 / (1 - vf0) = hs0 / (1 - vf0) + v0 = v1 + v} *) + let forget ema = + let hidden_state = ema.momentum *. ema.hidden_state in + let void_fraction = + (* [forget] increases the quantity of "void". + + Where [update] does: [ema.m * ema.vf + ema.opp_m * 0], + [forget] does: [ema.m * ema.vf + ema.opp_m * 1]. *) + (ema.momentum *. ema.void_fraction) +. ema.opp_momentum + in + { ema with hidden_state; void_fraction } + + let forget_batch ema sample_size = + if sample_size <= 0. then invalid_arg "Wrong sample_size"; + let momentum = ema.momentum ** sample_size in + let opp_momentum = 1. -. momentum in + (* From this point, the code is identical to [forget]. *) + let hidden_state = ema.hidden_state *. momentum in + let void_fraction = (ema.void_fraction *. momentum) +. opp_momentum in + { ema with hidden_state; void_fraction } + + let map ?relevance_threshold momentum vec0 = + List.fold_left + (fun (ema, rev_result) v0 -> + let ema = update ema v0 in + let v1 = peek_or_nan ema in + (ema, v1 :: rev_result)) + (create ?relevance_threshold momentum, []) + vec0 + |> snd + |> List.rev +end + +module Resample = struct + let should_sample ~i0 ~len0 ~i1 ~len1 = + assert (len0 >= 2); + assert (len1 >= 2); + assert (i0 < len0); + assert (i0 >= 0); + assert (i1 >= 0); + if i1 >= len1 then `Out_of_bounds + else + let i0 = float_of_int i0 in + let len0 = float_of_int len0 in + let i1 = float_of_int i1 in + let len1 = float_of_int len1 in + let progress0_left = (i0 -. 1.) /. (len0 -. 1.) in + let progress0_right = i0 /. (len0 -. 1.) in + let progress1 = i1 /. (len1 -. 1.) in + if progress1 <= progress0_left then `Before + else if progress1 <= progress0_right then ( + let where_in_interval = + (progress1 -. progress0_left) /. (progress0_right -. progress0_left) + in + assert (where_in_interval > 0.); + assert (where_in_interval <= 1.); + `Inside where_in_interval) + else `After + + type acc = { + mode : [ `Interpolate | `Next_neighbor ]; + len0 : int; + len1 : int; + i0 : int; + i1 : int; + prev_v0 : float; + rev_samples : curve; + } + + let create_acc mode ~len0 ~len1 ~v00 = + let mode = (mode :> [ `Interpolate | `Next_neighbor ]) in + if len0 < 2 then invalid_arg "Can't resample curves below 2 points"; + if len1 < 2 then invalid_arg "Can't resample curves below 2 points"; + { mode; len0; len1; i0 = 1; i1 = 1; prev_v0 = v00; rev_samples = [ v00 ] } + + let accumulate ({ mode; len0; len1; i0; i1; prev_v0; rev_samples } as acc) v0 + = + assert (i0 >= 1); + assert (i1 >= 1); + if i0 >= len0 then failwith "Accumulate called to much"; + if i1 >= len1 then failwith "Accumulate called to much"; + let rec aux i1 rev_samples = + match should_sample ~len1 ~i0 ~len0 ~i1 with + | `Inside where_inside -> + if i1 = len1 - 1 then ( + assert (i0 = len0 - 1); + assert (where_inside = 1.)); + let v1 = + match mode with + | `Next_neighbor -> v0 + | `Interpolate when where_inside = 1. -> + (* Optimisation in case of nan *) + v0 + | `Interpolate -> prev_v0 +. (where_inside *. (v0 -. prev_v0)) + in + aux (i1 + 1) (v1 :: rev_samples) + | `After -> (i1, rev_samples) + | `Before -> assert false + | `Out_of_bounds -> + assert (i0 = len0 - 1); + assert (i1 = len1); + (i1, rev_samples) + in + let i1, rev_samples = aux i1 rev_samples in + { acc with i0 = i0 + 1; i1; prev_v0 = v0; rev_samples } + + let finalise { len1; rev_samples; _ } = + if List.length rev_samples <> len1 then failwith "Finalise called too soon"; + List.rev rev_samples + + let resample_vector mode vec0 len1 = + let len0 = List.length vec0 in + if len0 < 2 then invalid_arg "Can't resample curves below 2 points"; + let v00, vec0 = + match vec0 with hd :: tl -> (hd, tl) | _ -> assert false + in + let acc = create_acc mode ~len0 ~len1 ~v00 in + List.fold_left accumulate acc vec0 |> finalise +end + +module Variable_summary = struct + type t = { + max_value : float * int; + min_value : float * int; + mean : float; + diff : float; + distribution : histo; + evolution : curve; + } + [@@deriving repr] + + type acc = { + (* Accumulators *) + first_value : float; + last_value : float; + max_value : float * int; + min_value : float * int; + sum_value : float; + value_count : int; + distribution : Bentov.histogram; + rev_evolution : curve; + ma : Exponential_moving_average.t; + next_in_idx : int; + next_out_idx : int; + (* Constants *) + in_period_count : int; + out_sample_count : int; + evolution_resampling_mode : + [ `Interpolate | `Prev_neighbor | `Next_neighbor ]; + scale : [ `Linear | `Log ]; + } + + let create_acc ~evolution_smoothing ~evolution_resampling_mode + ~distribution_bin_count ~scale ~in_period_count ~out_sample_count = + if in_period_count < 2 then + invalid_arg "in_period_count should be greater than 1"; + if out_sample_count < 2 then + invalid_arg "out_sample_count should be greater than 1"; + { + first_value = Float.nan; + last_value = Float.nan; + max_value = (Float.nan, 0); + min_value = (Float.nan, 0); + sum_value = 0.; + value_count = 0; + distribution = Bentov.create distribution_bin_count; + rev_evolution = []; + ma = + (match evolution_smoothing with + | `None -> Exponential_moving_average.create 0. + | `Ema (half_life_ratio, relevance_threshold) -> + Exponential_moving_average.from_half_life_ratio ~relevance_threshold + half_life_ratio + (float_of_int in_period_count)); + next_in_idx = 0; + next_out_idx = 0; + in_period_count; + out_sample_count; + evolution_resampling_mode; + scale; + } + + let accumulate acc occurences_of_variable_in_period = + let xs = occurences_of_variable_in_period in + let xs = List.filter (fun v -> not (Float.is_nan v)) xs in + let i = acc.next_in_idx in + let sample_count = List.length xs |> float_of_int in + assert (i < acc.in_period_count); + + let accumulate_in_sample + (first, last, ((topv, _) as top), ((botv, _) as bot), histo, ma) v = + let first = if Float.is_nan first then v else first in + let last = if Float.is_nan v then last else v in + let top = if Float.is_nan topv || topv < v then (v, i) else top in + let bot = if Float.is_nan botv || botv > v then (v, i) else bot in + let v = + match acc.scale with + | `Linear -> v + | `Log -> + if Float.is_infinite v then v + else if v <= 0. then + failwith + "Input samples to a Variable_summary should be > 0. when \ + scale=`Log." + else Float.log v + in + let histo = Bentov.add v histo in + let ma = + Exponential_moving_average.update_batch ma v (1. /. sample_count) + in + (first, last, top, bot, histo, ma) + in + let first_value, last_value, max_value, min_value, distribution, ma = + List.fold_left accumulate_in_sample + ( acc.first_value, + acc.last_value, + acc.max_value, + acc.min_value, + acc.distribution, + acc.ma ) + xs + in + let ma = + if sample_count = 0. then Exponential_moving_average.forget ma else ma + in + let rev_evolution, next_out_idx = + let rec aux rev_samples next_out_idx = + match + Resample.should_sample ~i0:i ~len0:acc.in_period_count + ~i1:next_out_idx ~len1:acc.out_sample_count + with + | `Before -> assert false + | `Inside where_in_block -> + let out_sample = + let v_after = Exponential_moving_average.peek_or_nan ma in + if where_in_block = 1. then v_after + else ( + assert (where_in_block > 0.); + assert (next_out_idx > 0); + let v_before = Exponential_moving_average.peek_or_nan acc.ma in + match acc.evolution_resampling_mode with + | `Prev_neighbor -> v_before + | `Next_neighbor -> v_after + | `Interpolate -> + v_before +. ((v_after -. v_before) *. where_in_block)) + in + aux (out_sample :: rev_samples) (next_out_idx + 1) + | `After | `Out_of_bounds -> (rev_samples, next_out_idx) + in + aux acc.rev_evolution acc.next_out_idx + in + + { + acc with + first_value; + last_value; + max_value; + min_value; + sum_value = List.fold_left ( +. ) acc.sum_value xs; + value_count = acc.value_count + List.length xs; + distribution; + rev_evolution; + ma; + next_in_idx = acc.next_in_idx + 1; + next_out_idx; + } + + let finalise acc = + assert (acc.next_out_idx = acc.out_sample_count); + assert (acc.next_out_idx = List.length acc.rev_evolution); + assert (acc.next_in_idx = acc.in_period_count); + let f = match acc.scale with `Linear -> Fun.id | `Log -> Float.exp in + let distribution = + let open Bentov in + bins acc.distribution |> List.map (fun b -> (f b.center, b.count)) + in + let evolution = List.rev_map f acc.rev_evolution in + { + max_value = acc.max_value; + min_value = acc.min_value; + mean = acc.sum_value /. float_of_int acc.value_count; + diff = acc.last_value -. acc.first_value; + distribution; + evolution; + } +end + +module Parallel_folders = struct + type ('row, 'acc, 'v) folder = { + acc : 'acc; + accumulate : 'acc -> 'row -> 'acc; + finalise : 'acc -> 'v; + } + + let folder acc accumulate finalise = { acc; accumulate; finalise } + + type ('res, 'row, 'v) folders = + | F0 : ('res, 'row, 'res) folders + | F1 : + ('row, 'acc, 'v) folder * ('res, 'row, 'rest) folders + -> ('res, 'row, 'v -> 'rest) folders + + type ('res, 'row, 'f, 'rest) open_t = + ('res, 'row, 'rest) folders -> 'f * ('res, 'row, 'f) folders + + let open_ : 'f -> ('res, 'row, 'f, 'f) open_t = + fun constructor folders -> (constructor, folders) + + let app : + type res f v rest acc row. + (res, row, f, v -> rest) open_t -> + (row, acc, v) folder -> + (res, row, f, rest) open_t = + fun open_t folder folders -> open_t (F1 (folder, folders)) + + let ( |+ ) = app + + type ('res, 'row) t = T : 'f * ('res, 'row, 'f) folders -> ('res, 'row) t + + let seal : type res row f. (res, row, f, res) open_t -> (res, row) t = + fun open_t -> + let constructor, folders = open_t F0 in + T (constructor, folders) + + let accumulate : type res row. (res, row) t -> row -> (res, row) t = + fun (T (constructor, folders)) row -> + let rec aux : type v. (res, row, v) folders -> (res, row, v) folders = + function + | F0 -> F0 + | F1 (folder, t) as f -> ( + let acc = folder.acc in + let acc' = folder.accumulate acc row in + let t' = aux t in + (* Avoid reallocating [F1] and [folder] when possible. *) + match (acc == acc', t == t') with + | true, true -> f + | true, false -> F1 (folder, t') + | false, (true | false) -> F1 ({ folder with acc = acc' }, t')) + in + let folders = aux folders in + T (constructor, folders) + + let finalise : type res row. (res, row) t -> res = + let rec aux : type c. (res, row, c) folders -> c -> res = function + | F0 -> Fun.id + | F1 (f, fs) -> + fun constructor -> + let v = f.finalise f.acc in + let finalise_remaining = aux fs in + let constructor = constructor v in + finalise_remaining constructor + in + fun (T (constructor, folders)) -> aux folders constructor +end diff --git a/vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.mli b/vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.mli new file mode 100644 index 000000000000..72609faeb3fe --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stat_summary_utils.mli @@ -0,0 +1,398 @@ +(** Utilities to summarise data. + + This file is NOT meant to be used from Tezos, as opposed to some other + "trace_*" files. *) + +type histo = (float * int) list [@@deriving repr] +type curve = float list [@@deriving repr] + +val snap_to_integer : significant_digits:int -> float -> float +(** [snap_to_integer ~significant_digits v] is [Float.round v] if [v] is close + to [Float.round v], otherwise the result is [v]. [significant_digits] + defines how close things are. + + Examples: + + When [significant_digits] is [4] and [v] is [42.00001], [snap_to_integer v] + is [42.]. + + When [significant_digits] is [4] and [v] is [42.001], [snap_to_integer v] is + [v]. *) + +val create_pp_real : + ?significant_digits:int -> float list -> Format.formatter -> float -> unit +(** [create_pp_real examples] is [pp_real], a float pretty-printer that adapts + to the [examples] shown to it. + + It is highly recommended, but not mandatory, for all the numbers passed to + [pp_real] to be included in [examples]. + + When all the [examples] are integers, the display may be different. The + examples that aren't integer, but that are very close to be a integers are + counted as integers. [significant_digits] is used internally to snap the + examples to integers. *) + +val create_pp_seconds : float list -> Format.formatter -> float -> unit +(** [create_pp_seconds examples] is [pp_seconds], a time span pretty-printer + that adapts to the [examples] shown to it. + + It is highly recommended, but not mandatory, for all the numbers passed to + [pp_seconds] to be included in [examples]. *) + +val pp_percent : Format.formatter -> float -> unit +(** Pretty prints a percent in a way that always takes 4 chars. + + Examples: [0.] is [" 0%"], [0.00001] is ["0.0%"], [0.003] is ["0.3%"], + [0.15] is [" 15%"], [9.0] is [900%], [700.] is [700x], [410_000.0] is + ["4e6x"] and [1e100] is ["++++"]. + + Negative inputs are undefined. *) + +val approx_transaction_count_of_block_count : ?first_block_idx:int -> int -> int +val approx_operation_count_of_block_count : ?first_block_idx:int -> int -> int + +(** Functional Exponential Moving Average (EMA). *) +module Exponential_moving_average : sig + type t + + val create : ?relevance_threshold:float -> float -> t + (** [create ?relevance_threshold m] is [ema], a functional exponential moving + average. [1. -. m] is the fraction of what's forgotten of the past during + each [update]. + + The value represented by [ema] can be retrieved using [peek_exn ema] or + [peek_or_nan ema]. + + When [m = 0.], all the past is forgotten on each update and each forget. + [peek_exn ema] is either the latest sample fed to an update function or + [nan]. + + When [m] approaches [1.], [peek_exn ema] tends to be the mean of all the + samples seen in the past. + + See + https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + + {3 Relevance} + + The value represented by [ema] is built from the {e history} of samples + shown through [update(_batch)]. When that history is empty, the value + can't be calculated, and when the history is too small, or too distant + because of calls to [forget(_batch)], the represented value is very noisy. + + [relevance_threshold] is a threshold on [ema]'s inner [void_fraction], + below which the represented value should be considered relevant, i.e. + [peek_or_nan ema] is not NaN. + + Before any call to [update(_batch)], the represented value is always + irrelevant. + + After a sufficient number of updates (e.g. 1 update in general), the + represented value gets relevant. + + After a sufficient number of forgets, the represented value gets + irrelevant again. + + A good value for [relevance_threshold] is between [momentum] and [1.], so + that right after a call to [update], the value is always relevant. + + {3 Commutativity} + + Adding together two curves independently built with an EMA, is equivalent + to adding the samples beforehand, and using a single EMA. + + In a more more formal way: + + Let [a], [b] be vectors of real values of similar length. + + Let [ema(x)] be the [Exponential_moving_average.map momentum] function + ([float list -> float list]); + + Let [*], [+] and [/] be the element-wise vector multiplication, addition + and division. + + Then [ema(a + b)] is [ema(a) + ema(b)]. + + The same is not true for multiplication and division, [ema(a * b)] is not + [ema(a) * ema(b)], but [exp(ema(log(a * b)))] is + [exp(ema(log(a))) * exp(ema(log(b)))] when all values in [a] and [b] are + strictly greater than 0. *) + + val from_half_life : ?relevance_threshold:float -> float -> t + (** [from_half_life hl] is [ema], a functional exponential moving average. + After [hl] calls to [update], half of the past is forgotten. *) + + val from_half_life_ratio : ?relevance_threshold:float -> float -> float -> t + (** [from_half_life_ratio hl_ratio step_count] is [ema], a functional + exponential moving average. After [hl_ratio * step_count] calls to + [update], half of the past is forgotten. *) + + val map : ?relevance_threshold:float -> float -> float list -> float list + (** [map momentum vec0] is [vec1], a list of float with the same length as + [vec0], where the values have been locally averaged. + + The first element of [vec1] is also the first element of [vec0]. *) + + val update : t -> float -> t + (** Feed a new sample to the EMA. If the sample is not finite (i.e., NaN or + infinite), the represented won't be either. *) + + val update_batch : t -> float -> float -> t + (** [update_batch ema p s] is equivalent to calling [update] [s] times. Modulo + floating point errors. *) + + val forget : t -> t + (** [forget ema] forgets some of the past without the need for samples. The + represented value doesn't change. *) + + val forget_batch : t -> float -> t + (** [forget_batch ema s] is equivalent to calling [forget] [s] times. Modulo + floating point errors.*) + + val is_relevant : t -> bool + (** Indicates whether or not [peek_exn] can be called without raising an + exception. *) + + val peek_exn : t -> float + (** Read the EMA value. *) + + val peek_or_nan : t -> float + (** Read the EMA value. *) + + val momentum : t -> float + val hidden_state : t -> float + val void_fraction : t -> float +end + +(** This [Resample] module offers 3 ways to resample a 1d vector: + + - At the lowest level, using [should_sample]. + - Using [create_acc] / [accumulate] / [finalise]. + - At the highest level, using [resample_vector]. + + Both downsampling and upsampling are possible: + + {v + > upsampling + vec0: | | | | (len0:4) + vec1: | | | | | | (len1:6) + > identity + vec0: | | | | (len0:4) + vec1: | | | | (len1:4) + > downsampling + vec0: | | | | | | (len0:6) + vec1: | | | | (len1:4) + v} + + The first and last point of the input and output sequences are always equal. *) +module Resample : sig + val should_sample : + i0:int -> + len0:int -> + i1:int -> + len1:int -> + [ `After | `Before | `Inside of float | `Out_of_bounds ] + (** When resampling a 1d vector from [len0] to [len1], this function locates a + destination point with index [i1] relative to the range [i0 - 1] excluded + and [i0] included. + + When both [i0] and [i1] equal [0], the result is [`Inside 1.]. + + [len0] and [len1] should be greater or equal to 2. *) + + type acc + + val create_acc : + [ `Interpolate | `Next_neighbor ] -> + len0:int -> + len1:int -> + v00:float -> + acc + (** Creates a resampling accumulator. + + Requires the first point of vec0. *) + + val accumulate : acc -> float -> acc + val finalise : acc -> curve + + val resample_vector : + [< `Interpolate | `Next_neighbor ] -> curve -> int -> curve + (** [resample_vector mode vec0 len1] is [vec1], a curve of length [len1], + created by resampling [vec0]. + + It internally relies on the [should_sample] function. *) +end + +(** Functional summary for a variable that has zero or more occurences per + period. [accumulate] is expected to be called [in_period_count] times before + [finalise] is. + + {3 Stats Gathered} + + - Global (non-nan) max, argmax, min, argmin and mean of the variable. + - The very last non-nan sample encountered minus the very first non-nan + sample encountered. + - Global histogram made of [distribution_bin_count] bins. Option: + [distribution_scale] to control the spreading scale of the bins, either on + a linear or a log scale. Computed using Bentov. + - A curve made of [out_sample_count] points. Options: [evolution_smoothing] + to control the smoothing, either using EMA, or no smoothing at all. + + {3 Histograms} + + The histograms are all computed using https://github.com/barko/bentov. + + [Bentov] computes dynamic histograms without the need for a priori + informations on the distributions, while maintaining a constant memory space + and a marginal CPU footprint. + + The implementation of that library is pretty straightforward, but not + perfect; the CPU footprint doesn't scale well with the number of bins. + + The computed histograms depend on the order of the operations, some marginal + unsabilities are to be expected. + + [Bentov] is good at spreading the bins on the input space. Since some + histograms will be shown on a log plot, the log10 of those values is passed + to [Bentov] instead, but the json will store real seconds. + + {3 Log Scale} + + When a variable has to be displayed on a log scale, the [scale] option can + be set to [`Log] in order for some adjustments to be made. + + In the histogram, the bins have to spread on a log scale. + + When smoothing the evolution, the EMA decay has to be calculated on a log + scale. + + Gotcha: All the input samples should be strictly greater than 0, so that + they don't fail their conversion to log. + + {3 Periods are Decoupled from Samples} + + When a [Variable_summary] ([vs]) is created, the number of periods has to be + declared right away through the [in_period_count] parameter, but [vs] is + very flexible when it comes to the number of samples shown to it on each + period. + + The simplest use case of [vs] is when there is exactly one sample for each + period. In that case, [accumulate acc samples] is called using a list of + length 1. For example: when a period corresponds to a cycle of an algorithm, + and the variable is a timestamp. + + The more advanced use case of [vs] is when there are a varying number a + samples for each period. For example: when a period corresponds to a cycle + of an algorithm, and the variable is the time taken by a buffer flush that + may happen 0, 1 or more times per cycle. + + In that later case, the [evolution] curve may contain NaNs before and after + sample points. + + {3 Possible Future Evolutions} + + - A period-wise histogram, similar to Grafana's heatmaps: "A heatmap is like + a histogram, but over time where each time slice represents its own + histogram.". + + - Variance evolution. Either without smoothing or using exponential moving + variance (see wikipedia). + + - Global variance. + + - Quantile evolution. *) +module Variable_summary : sig + type t = { + max_value : float * int; + min_value : float * int; + mean : float; + diff : float; + distribution : histo; + evolution : curve; + } + [@@deriving repr] + + type acc + + val create_acc : + evolution_smoothing:[ `Ema of float * float | `None ] -> + evolution_resampling_mode:[ `Interpolate | `Next_neighbor | `Prev_neighbor ] -> + distribution_bin_count:int -> + scale:[ `Linear | `Log ] -> + in_period_count:int -> + out_sample_count:int -> + acc + + val accumulate : acc -> float list -> acc + val finalise : acc -> t +end + +(** See [Trace_stat_summary] for an explanation and an example. + + Heavily inspired by the "repr" library. + + Type parameters: + + - ['res] is the output of [finalise]. + - ['f] is the full contructor that creates a ['res]. + - ['v] is the output of [folder.finalise], one parameter of ['f]. + - ['rest] is ['f] or ['res] or somewhere in between. + - ['acc] is the accumulator of one folder. + - ['row] is what needs to be fed to all [folder.accumulate]. + + Typical use case: + + {[ + let pf = + open_ (fun res_a res_b -> my_constructor res_a res_b) + |+ folder my_acc_a my_accumulate_a my_finalise_a + |+ folder my_acc_b my_accumulate_b my_finalise_b + |> seal + in + let res = my_row_sequence |> Seq.fold_left accumulate pf |> finalise in + ]} *) +module Parallel_folders : sig + (** Section 1/3 - Individual folders *) + + type ('row, 'acc, 'v) folder + + val folder : + 'acc -> ('acc -> 'row -> 'acc) -> ('acc -> 'v) -> ('row, 'acc, 'v) folder + (** Create one folder to be passed to an open parallel folder using [|+]. *) + + (** Section 2/3 - Open parallel folder *) + + type ('res, 'row, 'v) folders + type ('res, 'row, 'f, 'rest) open_t + + val open_ : 'f -> ('res, 'row, 'f, 'f) open_t + (** Start building a parallel folder. *) + + val app : + ('res, 'row, 'f, 'v -> 'rest) open_t -> + ('row, 'acc, 'v) folder -> + ('res, 'row, 'f, 'rest) open_t + (** Add a folder to an open parallel folder. *) + + val ( |+ ) : + ('res, 'row, 'f, 'v -> 'rest) open_t -> + ('row, 'acc, 'v) folder -> + ('res, 'row, 'f, 'rest) open_t + (** Alias for [app]. *) + + (** Section 3/3 - Closed parallel folder *) + + type ('res, 'row) t + + val seal : ('res, 'row, 'f, 'res) open_t -> ('res, 'row) t + (** Stop building a parallel folder. + + Gotcha: It may seal a partially applied [f]. *) + + val accumulate : ('res, 'row) t -> 'row -> ('res, 'row) t + (** Forward a row to all registered functional folders. *) + + val finalise : ('res, 'row) t -> 'res + (** Finalise all folders and pass their result to the user-defined function + provided to [open_]. *) +end diff --git a/vendors/irmin/bench/irmin-pack/trace_stats.ml b/vendors/irmin/bench/irmin-pack/trace_stats.ml new file mode 100644 index 000000000000..6ad6d5359868 --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/trace_stats.ml @@ -0,0 +1,213 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [trace_stats.exe]. + + This file is NOT meant to be used from Tezos, as opposed to some other + "trace_*" files. *) + +open Irmin_traces +module Def = Trace_definitions.Stat_trace +module Summary = Trace_stat_summary + +let is_trace_magic s = Trace_common.Magic.to_string Def.magic = s + +let summarise path = + Summary.(summarise path |> Fmt.pr "%a\n" (Irmin.Type.pp_json t)) + +let class_of_path p = + let chan = open_in_bin p in + if in_channel_length chan < 8 then + Fmt.invalid_arg "File \"%s\" should be a stat trace or a json." p; + let magic = really_input_string chan 8 in + close_in chan; + if is_trace_magic magic then + let block_count = + Def.open_reader p + |> snd + |> Seq.fold_left + (fun count op -> match op with `Commit _ -> count + 1 | _ -> count) + 0 + in + `Trace block_count + else + let chan = open_in_bin p in + let raw = really_input_string chan (in_channel_length chan) in + close_in chan; + match Irmin.Type.of_json_string Summary.t raw with + | Error (`Msg msg) -> + Fmt.invalid_arg + "File \"%s\" should be a stat trace or a json.\nError: %s" p msg + | Ok s -> `Summary s + +let pp name_per_path paths cols_opt = + let class_per_path = List.map class_of_path paths in + let block_count = + (* When pretty printing, all the summaries will have to have the same number of + blocks, i.e. the smallest of all inputs. *) + let trace_lengths = + List.filter_map + (function `Trace v -> Some v | `Summary _ -> None) + class_per_path + in + let summary_lengths = + List.filter_map + (function `Trace _ -> None | `Summary s -> Some s.Summary.block_count) + class_per_path + in + let s = List.length summary_lengths > 0 in + let t = List.length trace_lengths > 0 in + let min_trace_length = List.fold_left min max_int trace_lengths in + let min_summary_length = List.fold_left min max_int summary_lengths in + let max_summary_length = List.fold_left max 0 summary_lengths in + if s && min_summary_length <> max_summary_length then + invalid_arg + "Can't pretty print 2 summaries with a different number of blocks."; + if s && t && min_summary_length > min_trace_length then + invalid_arg + "Can't pretty print a trace alongside a summary that has a higher \ + block count."; + min min_trace_length min_summary_length + in + let summaries = + List.map2 + (fun path -> function + | `Summary s -> s + | `Trace _ -> Summary.summarise ~block_count path) + paths class_per_path + in + let col_count = + match cols_opt with + | Some v -> v + | None -> if List.length summaries > 1 then 4 else 5 + in + Fmt.pr "%a\n" (Trace_stat_summary_pp.pp col_count) (name_per_path, summaries) + +let pp paths named_paths cols_opt = + let name_per_path, paths = + List.mapi (fun i v -> (string_of_int i, v)) paths @ named_paths + |> List.split + in + if List.length paths = 0 then + invalid_arg "trace_stats.exe pp: At least one path should be provided"; + pp name_per_path paths cols_opt + +let summary_to_cb path = + let chan = open_in_bin path in + let raw = really_input_string chan (in_channel_length chan) in + close_in chan; + let s = + match Irmin.Type.of_json_string Summary.t raw with + | Error (`Msg msg) -> + Fmt.invalid_arg "File \"%s\" should be a summary json.\nError: %s" path + msg + | Ok s -> s + in + Trace_stat_summary_cb.(of_summary s |> Fmt.pr "%a\n" (Irmin.Type.pp_json t)) + +open Cmdliner + +let term_summarise = + let stat_trace_file = + let doc = Arg.info ~docv:"PATH" ~doc:"A stat trace file" [] in + Arg.(required @@ pos 0 (some string) None doc) + in + Term.(const summarise $ stat_trace_file) + +let term_pp = + let arg_indexed_files = + let open Arg in + let a = pos_all non_dir_file [] (info [] ~docv:"FILE") in + value a + in + let arg_named_files = + let open Arg in + let a = + opt_all (pair string non_dir_file) [] + (info [ "f"; "named-file" ] + ~doc: + "A comma-separated pair of short name / path to trace or summary. \ + The short name is used to tag the rows inside the pretty printed \ + table.") + in + value a + in + let arg_columns = + let open Arg in + let doc = + Arg.info ~doc:"Number of sample columns to show." [ "c"; "columns" ] + in + let a = opt (some int) None doc in + value a + in + Term.(const pp $ arg_indexed_files $ arg_named_files $ arg_columns) + +let term_cb = + let summary_file = + let doc = Arg.info ~docv:"PATH" ~doc:"A stat trace summary file" [] in + Arg.(required @@ pos 0 (some string) None doc) + in + Term.(const summary_to_cb $ summary_file) + +let deprecated_info = (Term.info [@alert "-deprecated"]) +let deprecated_exit = (Term.exit [@alert "-deprecated"]) +let deprecated_eval_choice = (Term.eval_choice [@alert "-deprecated"]) + +let () = + let man = [] in + let i = + deprecated_info ~man + ~doc:"Processing of stat traces and stat trace summaries." "trace_stats" + in + + let man = + [ + `P "From stat trace (repr) to summary (json)."; + `S "EXAMPLE"; + `P "trace_stats.exe summarise run0.repr > run0.json"; + ] + in + let j = deprecated_info ~man ~doc:"Stat Trace to Summary" "summarise" in + + let man = + [ + `P + "Accepts both stat traces (repr) and summaries (json). The file type \ + is automatically infered."; + `P + "When a single file is provided, a subset of the summary of that file \ + is computed and shown."; + `P + "When multiple files are provided, a subset of the summary of each \ + file is computed and shown in a way that makes comparisons between \ + files easy."; + `S "EXAMPLES"; + `P "trace_stats.exe pp run0.json"; + `Noblank; + `P "trace_stats.exe pp run1.repr"; + `Noblank; + `P "trace_stats.exe pp run0.json run1.repr run3.json"; + `Noblank; + `P "trace_stats.exe pp -f r0,run0.json -f r1,run1.repr"; + ] + in + let k = deprecated_info ~man ~doc:"Comparative Pretty Printing" "pp" in + let l = + deprecated_info ~man ~doc:"Summary JSON to Continous Benchmarks JSON" "cb" + in + deprecated_exit + @@ deprecated_eval_choice (term_summarise, i) + [ (term_summarise, j); (term_pp, k); (term_cb, l) ] diff --git a/vendors/irmin/bench/irmin-pack/tree.ml b/vendors/irmin/bench/irmin-pack/tree.ml new file mode 100644 index 000000000000..4430fe45a9df --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/tree.ml @@ -0,0 +1,672 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Bench_common +open Irmin.Export_for_backends +open Irmin_traces + +type config = { + ncommits : int; + number_of_commits_to_replay : int; + depth : int; + nchain_trees : int; + width : int; + nlarge_trees : int; + store_dir : string; + path_conversion : [ `None | `V1 | `V0_and_v1 | `V0 ]; + inode_config : int * int; + store_type : [ `Pack | `Pack_mem ]; + freeze_commit : int; + replay_trace_path : string; + artefacts_path : string; + keep_store : bool; + keep_stat_trace : bool; + no_summary : bool; + empty_blobs : bool; + gc_every : int; + gc_distance_in_the_past : int; + gc_wait_after : int; + add_volume_every : int; +} + +module type Store = sig + type store_config = config + type key + + include + Irmin.Generic_key.KV + with type Schema.Contents.t = bytes + and type commit_key = key + and type node_key = key + and type contents_key = key + + type on_commit := int -> Hash.t -> unit Lwt.t + type on_end := unit -> unit Lwt.t + + val create_repo : + root:string -> store_config -> (Repo.t * on_commit * on_end) Lwt.t + + type stats := Irmin_pack_unix.Stats.Latest_gc.stats + + val split : repo -> unit + val add_volume : repo -> unit + + val gc_run : + ?finished:((stats, string) result -> unit Lwt.t) -> + repo -> + commit_key -> + unit Lwt.t + + val gc_wait : repo -> unit Lwt.t +end + +let pp_inode_config ppf (entries, stable_hash) = + Format.fprintf ppf "[%d, %d]" entries stable_hash + +let pp_store_type ppf = function + | `Pack -> Format.fprintf ppf "[pack store]" + | `Pack_mem -> Format.fprintf ppf "[pack-mem store]" + +module Benchmark = struct + type result = { time : float; size : int } + + let run config f = + let+ time, res = with_timer f in + let size = FSHelper.get_size config.store_dir in + ({ time; size }, res) + + let pp_results ppf result = + Format.fprintf ppf "Total time: %f@\nSize on disk: %d M" result.time + result.size +end + +module Bench_suite (Store : Store) = struct + module Info = Info (Store.Info) + module Key = Store.Backend.Commit.Key + module Trees = Generate_trees (Store) + module Trace_replay = Trace_replay.Make (Store) + + let checkout_and_commit repo prev_commit f = + match prev_commit with + | None -> + let tree = Store.Tree.empty () in + let* tree = f tree in + Store.Commit.v repo ~info:(Info.f ()) ~parents:[] tree + | Some prev_commit -> ( + let prev_commit = Store.Commit.key prev_commit in + Store.Commit.of_key repo prev_commit >>= function + | None -> Lwt.fail_with "commit not found" + | Some commit -> + let tree = Store.Commit.tree commit in + let* tree = f tree in + Store.Commit.v repo ~info:(Info.f ()) ~parents:[ prev_commit ] tree) + + let add_commits ~message repo ncommits on_commit on_end f () = + with_progress_bar ~message ~n:ncommits ~unit:"commit" @@ fun prog -> + let rec aux c i = + if i >= ncommits then on_end () + else + let* c' = checkout_and_commit repo c f in + let* () = on_commit i (Store.Commit.hash c') in + prog 1; + aux (Some c') (i + 1) + in + aux None 0 + + let run_large config = + reset_stats (); + let root = config.store_dir in + let* repo, on_commit, on_end = Store.create_repo ~root config in + let* result, () = + Trees.add_large_trees config.width config.nlarge_trees + |> add_commits ~message:"Playing large mode" repo config.ncommits + on_commit on_end + |> Benchmark.run config + in + let+ () = Store.Repo.close repo in + fun ppf -> + Format.fprintf ppf + "Large trees mode on inode config %a, %a: %d commits, each consisting \ + of %d large trees of %d entries@\n\ + %a" + pp_inode_config config.inode_config pp_store_type config.store_type + config.ncommits config.nlarge_trees config.width Benchmark.pp_results + result + + let run_chains config = + reset_stats (); + let root = config.store_dir in + let* repo, on_commit, on_end = Store.create_repo ~root config in + let* result, () = + Trees.add_chain_trees config.depth config.nchain_trees + |> add_commits ~message:"Playing chain mode" repo config.ncommits + on_commit on_end + |> Benchmark.run config + in + let+ () = Store.Repo.close repo in + fun ppf -> + Format.fprintf ppf + "Chain trees mode on inode config %a, %a: %d commits, each consisting \ + of %d chains of depth %d@\n\ + %a" + pp_inode_config config.inode_config pp_store_type config.store_type + config.ncommits config.nchain_trees config.depth Benchmark.pp_results + result + + let run_read_trace config = + let replay_config : _ Irmin_traces.Trace_replay.config = + { + number_of_commits_to_replay = config.number_of_commits_to_replay; + path_conversion = config.path_conversion; + inode_config = config.inode_config; + store_type = + (config.store_type :> [ `Pack | `Pack_layered | `Pack_mem ]); + replay_trace_path = config.replay_trace_path; + artefacts_path = config.artefacts_path; + keep_store = config.keep_store; + keep_stat_trace = config.keep_stat_trace; + empty_blobs = config.empty_blobs; + return_type = Summary; + gc_every = config.gc_every; + gc_distance_in_the_past = config.gc_distance_in_the_past; + gc_wait_after = config.gc_wait_after; + add_volume_every = config.add_volume_every; + } + in + if config.no_summary then + let+ () = + Trace_replay.run config { replay_config with return_type = Unit } + in + fun _ppf -> () + else + let+ summary = Trace_replay.run config replay_config in + fun ppf -> + if not config.no_summary then ( + let p = Filename.concat config.artefacts_path "stat_summary.json" in + Trace_stat_summary.save_to_json summary p; + Format.fprintf ppf "%a" + (Trace_stat_summary_pp.pp 5) + ([ "" ], [ summary ])) +end + +module Make_store_mem (Conf : Irmin_pack.Conf.S) = struct + type store_config = config + + module Store = struct + open Irmin_pack_mem.Maker (Conf) + include Make (Irmin_tezos.Schema) + end + + include Store + + type key = commit_key + + let indexing_strategy = Irmin_pack.Indexing_strategy.minimal + + let create_repo ~root _config = + let conf = + Irmin_pack.config ~readonly:false ~fresh:true ~indexing_strategy root + in + prepare_artefacts_dir root; + let* repo = Store.Repo.v conf in + let on_commit _ _ = Lwt.return_unit in + let on_end () = Lwt.return_unit in + Lwt.return (repo, on_commit, on_end) + + let split _repo = () + let add_volume _repo = () + let gc_wait _repo = Lwt.return_unit + let gc_run ?finished:_ _repo _key = Lwt.return_unit +end + +module Make_store_pack (Conf : Irmin_pack.Conf.S) = struct + type store_config = config + + module Store = struct + open Irmin_pack_unix.Maker (Conf) + include Make (Irmin_tezos.Schema) + end + + include Store + + type key = commit_key + + let indexing_strategy = Irmin_pack.Indexing_strategy.minimal + + let create_repo ~root (config : store_config) = + let lower_root = + if config.add_volume_every > 0 then Some (Filename.concat root "lower") + else None + in + let conf = + Irmin_pack.config ~readonly:false ~fresh:true ~indexing_strategy + ~lower_root root + in + prepare_artefacts_dir root; + let* repo = Store.Repo.v conf in + let on_commit _ _ = Lwt.return_unit in + let on_end () = Lwt.return_unit in + Lwt.return (repo, on_commit, on_end) + + let split = Store.split + let add_volume = Store.add_volume + + let gc_wait repo = + let* r = Store.Gc.wait repo in + match r with Ok _ -> Lwt.return_unit | Error (`Msg err) -> failwith err + + let gc_run ?(finished = fun _ -> Lwt.return_unit) repo key = + let f (result : (_, Store.Gc.msg) result) = + match result with + | Error (`Msg err) -> finished @@ Error err + | Ok stats -> finished @@ Ok stats + in + let* launched = Store.Gc.run ~finished:f repo key in + match launched with + | Ok true -> Lwt.return_unit + | Ok false -> [%logs.app "GC skipped"] |> Lwt.return + | Error (`Msg err) -> failwith err +end + +module type B = sig + val run_large : config -> (Format.formatter -> unit) Lwt.t + val run_chains : config -> (Format.formatter -> unit) Lwt.t + val run_read_trace : config -> (Format.formatter -> unit) Lwt.t +end + +let store_of_config config = + let entries', stable_hash' = config.inode_config in + let module Conf = struct + include Irmin_tezos.Conf + + let entries = entries' + let stable_hash = stable_hash' + end in + match config.store_type with + | `Pack -> (module Bench_suite (Make_store_pack (Conf)) : B) + | `Pack_mem -> (module Bench_suite (Make_store_mem (Conf)) : B) + +type suite_elt = { + mode : [ `Read_trace | `Chains | `Large ]; + speed : [ `Quick | `Slow | `Custom ]; + run : config -> (Format.formatter -> unit) Lwt.t; +} + +let suite : suite_elt list = + [ + { + mode = `Read_trace; + speed = `Quick; + run = + (fun config -> + let config = + { config with inode_config = (32, 256); store_type = `Pack } + in + let (module Store) = store_of_config config in + Store.run_read_trace config); + }; + { + mode = `Read_trace; + speed = `Slow; + run = + (fun config -> + let config = + { config with inode_config = (32, 256); store_type = `Pack } + in + let (module Store) = store_of_config config in + Store.run_read_trace config); + }; + { + mode = `Chains; + speed = `Quick; + run = + (fun config -> + let config = + { config with inode_config = (32, 256); store_type = `Pack } + in + let (module Store) = store_of_config config in + Store.run_chains config); + }; + { + mode = `Chains; + speed = `Slow; + run = + (fun config -> + let config = + { config with inode_config = (2, 5); store_type = `Pack } + in + let (module Store) = store_of_config config in + Store.run_chains config); + }; + { + mode = `Large; + speed = `Quick; + run = + (fun config -> + let config = + { config with inode_config = (32, 256); store_type = `Pack } + in + let (module Store) = store_of_config config in + Store.run_large config); + }; + { + mode = `Large; + speed = `Slow; + run = + (fun config -> + let config = + { config with inode_config = (2, 5); store_type = `Pack } + in + let (module Store) = store_of_config config in + Store.run_large config); + }; + { + mode = `Read_trace; + speed = `Custom; + run = + (fun config -> + let (module Store) = store_of_config config in + Store.run_read_trace config); + }; + ] + +let get_suite suite_filter = + List.filter + (fun { mode; speed; _ } -> + match (suite_filter, speed, mode) with + | `Slow, `Slow, `Read_trace -> + (* The suite contains several `Read_trace benchmarks, let's keep the + slow one only *) + true + | `Slow, _, `Read_trace -> false + | `Slow, (`Slow | `Quick), _ -> true + | `Quick, `Quick, _ -> true + | `Custom_trace, `Custom, `Read_trace -> true + | `Custom_chains, `Custom, `Chains -> true + | `Custom_large, `Custom, `Large -> true + | (`Slow | `Quick | `Custom_trace | `Custom_chains | `Custom_large), _, _ + -> + false) + suite + +let main () ncommits number_of_commits_to_replay suite_filter inode_config + store_type freeze_commit path_conversion depth width nchain_trees + nlarge_trees replay_trace_path artefacts_path keep_store keep_stat_trace + no_summary empty_blobs gc_every gc_distance_in_the_past gc_wait_after + add_volume_every = + let default = match suite_filter with `Quick -> 10000 | _ -> 13315 in + let number_of_commits_to_replay = + Option.value ~default number_of_commits_to_replay + in + let config = + { + ncommits; + number_of_commits_to_replay; + store_dir = Filename.concat artefacts_path "store"; + path_conversion; + depth; + width; + nchain_trees; + nlarge_trees; + replay_trace_path; + inode_config; + store_type; + freeze_commit; + artefacts_path; + keep_store; + keep_stat_trace; + no_summary; + empty_blobs; + gc_every; + gc_distance_in_the_past; + gc_wait_after; + add_volume_every; + } + in + Printexc.record_backtrace true; + Random.self_init (); + (* Enforce the older allocation policy, for consistency of the existing + results. *) + Gc.set { (Gc.get ()) with Gc.allocation_policy = 0 }; + FSHelper.rm_dir config.store_dir; + let suite = get_suite suite_filter in + let run_benchmarks () = Lwt_list.map_s (fun b -> b.run config) suite in + let results = + Lwt_main.run + (Lwt.finalize run_benchmarks (fun () -> + if keep_store then ( + [%logs.app "Store kept at %s" config.store_dir]; + let ( / ) = Filename.concat in + let ro p = if Sys.file_exists p then Unix.chmod p 0o444 in + ro (config.store_dir / "store.branches"); + ro (config.store_dir / "store.dict"); + ro (config.store_dir / "store.pack"); + ro (config.store_dir / "index" / "data"); + ro (config.store_dir / "index" / "log"); + ro (config.store_dir / "index" / "log_async")) + else FSHelper.rm_dir config.store_dir; + Lwt.return_unit)) + in + [%logs.app "%a@." Fmt.(list ~sep:(any "@\n@\n") (fun ppf f -> f ppf)) results] + +open Cmdliner + +let mode = + let mode = + [ + ("slow", `Slow); + ("quick", `Quick); + ("trace", `Custom_trace); + ("chains", `Custom_chains); + ("large", `Custom_large); + ] + in + let doc = Arg.info ~doc:(Arg.doc_alts_enum mode) [ "mode" ] in + Arg.(value @@ opt (Arg.enum mode) `Slow doc) + +let inode_config = + let doc = Arg.info ~doc:"Inode config" [ "inode-config" ] in + Arg.(value @@ opt (pair int int) (32, 256) doc) + +let store_type = + let mode = [ ("pack", `Pack); ("pack-mem", `Pack_mem) ] in + let doc = Arg.info ~doc:(Arg.doc_alts_enum mode) [ "store-type" ] in + Arg.(value @@ opt (Arg.enum mode) `Pack doc) + +let freeze_commit = + let doc = + Arg.info + ~doc:"Index of the commit after which to start the layered store freeze." + [ "freeze-commit" ] + in + Arg.(value @@ opt int 1664 doc) + +let path_conversion = + let mode = + [ ("none", `None); ("v0", `V0); ("v1", `V1); ("v0+v1", `V0_and_v1) ] + in + let doc = Arg.info ~doc:(Arg.doc_alts_enum mode) [ "p"; "path-conversion" ] in + Arg.(value @@ opt (Arg.enum mode) `None doc) + +let ncommits = + let doc = + Arg.info ~doc:"Number of commits for the large and chain modes." + [ "n"; "ncommits" ] + in + Arg.(value @@ opt int 2 doc) + +let number_of_commits_to_replay = + let doc = + Arg.info ~doc:"Number of commits to read from trace." [ "ncommits-trace" ] + in + Arg.(value @@ opt (some int) None doc) + +let keep_store = + let doc = + Arg.info ~doc:"Whether or not the irmin store on disk should be kept." + [ "keep-store" ] + in + Arg.(value @@ flag doc) + +let no_summary = + let doc = + Arg.info + ~doc: + "Whether or not the stat trace should be converted to a summary at the \ + end of a replay." + [ "no-summary" ] + in + Arg.(value @@ flag doc) + +let keep_stat_trace = + let doc = + Arg.info + ~doc: + "Whether or not the stat trace should be discarded are the end, after \ + the summary has been saved the disk." + [ "keep-stat-trace" ] + in + Arg.(value @@ flag doc) + +let empty_blobs = + let doc = + Arg.info + ~doc: + "Whether or not the blobs added to the store should be the empty \ + string, during trace replay. This greatly increases the replay speed." + [ "empty-blobs" ] + in + Arg.(value @@ flag doc) + +let depth = + let doc = + Arg.info ~doc:"Depth of a commit's tree in chains-mode." [ "d"; "depth" ] + in + Arg.(value @@ opt int 1000 doc) + +let nchain_trees = + let doc = + Arg.info ~doc:"Number of chain trees per commit in chains-mode." + [ "c"; "nchain" ] + in + Arg.(value @@ opt int 1 doc) + +let width = + let doc = + Arg.info ~doc:"Width of a commit's tree in large-mode." [ "w"; "width" ] + in + Arg.(value @@ opt int 1000000 doc) + +let nlarge_trees = + let doc = + Arg.info ~doc:"Number of large trees per commit in large-mode." + [ "l"; "nlarge" ] + in + Arg.(value @@ opt int 1 doc) + +let replay_trace_path = + let doc = + Arg.info ~docv:"PATH" ~doc:"Trace of Tezos operations to be replayed." [] + in + Arg.(required @@ pos 0 (some string) None doc) + +let artefacts_path = + let doc = + Arg.info ~docv:"PATH" ~doc:"Destination of the bench artefacts." + [ "artefacts" ] + in + Arg.(value @@ opt string default_artefacts_dir doc) + +let setup_log = + Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ()) + +let gc_every = + let doc = Arg.info ~doc:"Distance between calls to GC" [ "gc-every" ] in + Arg.(value @@ opt int 1000 doc) + +let gc_distance_in_the_past = + let doc = + Arg.info ~doc:"Distance between the GC commit and the latest commit" + [ "gc-distance-in-the-past" ] + in + Arg.(value @@ opt int 5000 doc) + +let gc_wait_after = + let doc = + Arg.info + ~doc: + "How many commits separate the start of a GC and the moment we wait \ + for the end of it" + [ "gc-wait-after" ] + in + Arg.(value @@ opt int 0 doc) + +let add_volume_every = + let doc = Arg.info ~doc:"Add volume ever N GCs" [ "add-volume-every" ] in + Arg.(value @@ opt int 0 doc) + +let main_term = + Term.( + const main + $ setup_log + $ ncommits + $ number_of_commits_to_replay + $ mode + $ inode_config + $ store_type + $ freeze_commit + $ path_conversion + $ depth + $ width + $ nchain_trees + $ nlarge_trees + $ replay_trace_path + $ artefacts_path + $ keep_store + $ keep_stat_trace + $ no_summary + $ empty_blobs + $ gc_every + $ gc_distance_in_the_past + $ gc_wait_after + $ add_volume_every) + +let deprecated_info = (Term.info [@alert "-deprecated"]) +let deprecated_exit = (Term.exit [@alert "-deprecated"]) +let deprecated_eval = (Term.eval [@alert "-deprecated"]) + +let () = + let man = + [ + `S "DESCRIPTION"; + `P + "Benchmarks for tree operations. Requires traces of operations, \ + download them (`wget trace.repr`) from:"; + `P + "Trace with $(b,10310) commits \ + http://data.tarides.com/irmin/data4_10310commits.repr"; + `P + "Trace with $(b,100066) commits \ + http://data.tarides.com/irmin/data4_100066commits.repr"; + `P + "Trace with $(b,1343496) commits \ + http://data.tarides.com/irmin/data_1343496commits.repr"; + ] + in + let info = + deprecated_info ~man ~doc:"Benchmarks for tree operations" "tree" + in + deprecated_exit @@ deprecated_eval (main_term, info) diff --git a/vendors/irmin/bench/irmin-pack/tree.mli b/vendors/irmin/bench/irmin-pack/tree.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/bench/irmin-pack/tree.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/bench/irmin/data/bench_fixed_size_string_set.ml b/vendors/irmin/bench/irmin/data/bench_fixed_size_string_set.ml new file mode 100644 index 000000000000..29f29dfb38f5 --- /dev/null +++ b/vendors/irmin/bench/irmin/data/bench_fixed_size_string_set.ml @@ -0,0 +1,124 @@ +let stabilize_garbage_collector () = + let rec go fail last_heap_live_words = + if fail <= 0 then + failwith "Unable to stabilize the number of live words in the major heap"; + Gc.compact (); + let stat = Gc.stat () in + if stat.Gc.live_words <> last_heap_live_words then + go (fail - 1) stat.Gc.live_words + in + go 10 0 + +let allocated_words () = + let s = Gc.quick_stat () in + s.minor_words +. s.major_words -. s.promoted_words + +let open_stat_file name = + let stat_file = + let rnd = Random.bits () land 0xFFFFFF in + let ( / ) = Filename.concat in + "_build" / Printf.sprintf "%s-%06x.csv" name rnd + in + Printf.printf "Sending stats to '%s'\n%!" stat_file; + let out = open_out stat_file in + Printf.fprintf out + "entries,implementation,reachable_words,allocated_words,time(ns)\n"; + out + +(** Compute metrics of various hashset implementations, as a function of the + number of entries: + + - total size in memory + - extra allocations per entry + - cost of [add] per entry + + Stats are emitted to a trace file to be interpreted by scripts in + [./analysis]. *) + +module type S = sig + type t + type elt := string + + val implementation_name : string + val create : unit -> t + val add : t -> elt -> unit + val reachable_words : t -> int +end + +module Elt = struct + type t = string + + let equal = String.equal + let elt_length = 32 + let hash elt = Int64.to_int Bytes.(get_int64_be (unsafe_of_string elt) 0) + + let hash_substring t ~off ~len:_ = + Int64.to_int (Bigstringaf.get_int64_be t off) +end + +module Stringset_irmin : S = struct + module T = Irmin_data.Fixed_size_string_set + + type t = T.t + + let implementation_name = "irmin" + + let create () = + let open Elt in + T.create ~elt_length ~hash ~hash_substring ~initial_slots:0 () + + let add = T.add_exn + let reachable_words = T.reachable_words +end + +module Stringset_stdlib : S = struct + module T = Stdlib.Hashtbl.Make (Elt) + + type t = unit T.t + + let implementation_name = "stdlib" + let create () = T.create 0 + let add t k = T.add t k () + let reachable_words (t : t) = Obj.reachable_words (Obj.repr t) +end + +let random_string state = + let b = Bytes.create Elt.elt_length in + for i = 0 to Elt.elt_length - 1 do + Bytes.set b i (Char.chr (Random.State.int state 256)) + done; + Bytes.unsafe_to_string b + +let run_loop ~random_state ~out (module Hashset : S) = + let t = Hashset.create () + and iterations = 300_000 + and start_time = Mtime_clock.counter () + and last = ref Mtime.Span.zero + and initial_allocations = allocated_words () in + stabilize_garbage_collector (); + for i = 1 to iterations do + Hashset.add t (random_string random_state); + if i mod 1_000 = 0 then ( + let time = Mtime_clock.count start_time in + let diff = Mtime.Span.abs_diff time !last in + let reachable_words = Hashset.reachable_words t in + Printf.eprintf "\r%s : %#d / %#d%!" Hashset.implementation_name i + iterations; + Printf.fprintf out "%d,%s,%d,%f,%Ld\n%!" i Hashset.implementation_name + reachable_words + (allocated_words () -. initial_allocations) + (Int64.div (Mtime.Span.to_uint64_ns diff) 1_000L); + last := Mtime_clock.count start_time) + done; + Printf.eprintf "\r%s : done\x1b[K\n%!" Hashset.implementation_name + +let () = + Random.self_init (); + let seed = Random.int 0x3fff_ffff in + let random_state = Random.State.make [| seed |] in + Printf.eprintf "Random seed: %d\n%!" seed; + let out = open_stat_file "hashset-memory-usage" in + List.iter + (run_loop ~random_state ~out) + [ (module Stringset_irmin); (module Stringset_stdlib) ]; + Printf.printf "\nDone\n" diff --git a/vendors/irmin/bench/irmin/data/dune b/vendors/irmin/bench/irmin/data/dune new file mode 100644 index 000000000000..0d116268a7bc --- /dev/null +++ b/vendors/irmin/bench/irmin/data/dune @@ -0,0 +1,3 @@ +(executable + (name bench_fixed_size_string_set) + (libraries irmin.data mtime mtime.clock.os)) diff --git a/vendors/irmin/codecov.yml b/vendors/irmin/codecov.yml new file mode 100644 index 000000000000..714a8ae74641 --- /dev/null +++ b/vendors/irmin/codecov.yml @@ -0,0 +1,4 @@ +comment: + layout: diff + behaviour: default + require_changes: true diff --git a/vendors/irmin/doc/irmin-pack/design/README.md b/vendors/irmin/doc/irmin-pack/design/README.md new file mode 100644 index 000000000000..adf6758472a5 --- /dev/null +++ b/vendors/irmin/doc/irmin-pack/design/README.md @@ -0,0 +1,5 @@ +# Irmin-pack design docs + +- [Layered store](./layered_store.md), the design document for the first version of garbage collection (GC) that shipped with [Irmin 3.4](https://github.com/mirage/irmin/releases/tag/3.4.0). +- [Chunked suffix](./chunked_suffix.md), the design document for the second version of GC that introduced a chunked suffix for disk space saving during a GC. Introduced in [Irmin 3.5](https://github.com/mirage/irmin/releases/tag/3.5.0). +- [Lower layer](./lower_layer.md), the design document for the third phase of GC that extended it to work for unlimited history stores by archiving instead of deleting data. Will be introduced in Irmin 3.7. diff --git a/vendors/irmin/doc/irmin-pack/design/chunked_suffix.md b/vendors/irmin/doc/irmin-pack/design/chunked_suffix.md new file mode 100644 index 000000000000..a7158ea6cd07 --- /dev/null +++ b/vendors/irmin/doc/irmin-pack/design/chunked_suffix.md @@ -0,0 +1,210 @@ +# Improve GC disk space usage + +## Problem: GC disk spikes + +The latest release of `irmin-pack` (3.4) adds a new "Garbage Collection" (GC) feature that is able to reclaim disk space by deleting old data. This cleaning operation can be called by the user who specifies which data should be considered "old" and deleted. In practice, we observe huge spikes of disk space usage when the GC is called: + +![](./imgs/chunked_suffix/hgbTwYv.png) + + +To understand and correct this behavior, we will focus on the two files involved: + +- The **control file** is the entry point into the database. It is a very small file that contains relevant information to interpret the other files used by `irmin-pack`. +- The **suffix file** is an append-only file where new objects are stored by Irmin. This is a file that grows very large and from which the GC reclaims disk space by deleting old objects. +- There are other files used by `irmin-pack`, notably the prefix which plays a role in the GC, but in this document we will ignore them for as long as they are not relevant to the issue and the proposed solution. + +We can visualize the relation between the control and the suffix file as: + +![](./imgs/chunked_suffix/j4O6FSd.png) + + +When an irmin-pack store is opened, the first step consists of reading the control file to discover the name of the suffix file and how big that file is supposed to be. A single store can be opened by multiple instances running at the same time: +- A single read-write instance, which is the only one allowed to make modifications to the files. +- And multiple read-only instances. + +These read-only instances severely limits the operations that the read-write instance can do: It should expect at all time that the read-only instances might be looking anywhere in the suffix file, so any changes to it must be non-observable by them. As an appetizer, let's look at how the read-write instance supports the simple operation of appending new data at the end of the `suffix` file: + +![](./imgs/chunked_suffix/2bSEzad.png) + + +This write operation is not instantaneous! It will take some time proportional to the amount of new data to append. Under no circumstances should the read-only instances attempt to read this "write-in-progress" data, as it is most likely incomplete at this stage. The trick is that the read-only instances can only look at the portion of the `suffix` file that they know of, as defined by the "How big is it?" field in the control file. As such, the write-in-progress is outside of the section of the file that they are allowed to look at and the file mutation is actually safe. + +After some time, the write is completed but still invisible: + +![](./imgs/chunked_suffix/Yg65T4T.png) + + +In order to make this new data visible to the read-only instances, the control file must be updated **atomically** in one shot to reflect the new suffix length: + +![](./imgs/chunked_suffix/sQX4H8b.png) + + +The read-only instances will periodically reload the control file and discover the new "allowed read size" of the suffix. The update of the control file is supposed to be atomic, meaning that a read-only instance won't see an incomplete update due to an in-progress write of the control file... This is only possible because the control file is so small that we expect the disk and filesystem not to break up its update into multiple partial writes. + +We can now talk about the disk space spikes. When the user calls the GC to delete data past a certain age, a bunch of operations happen, culminating in the need to truncate the beginning of the suffix file: + +![](./imgs/chunked_suffix/aVtdXI3.png) + + +However, due to the readers potentially looking at the "to-be-deleted" data, we can't easily get rid of it. The current strategy is to create a new suffix file, in which all the to-be-kept data is copied: + +![](./imgs/chunked_suffix/n9FqctU.png) + + +Once the copy of all the "to keep" data is completed, we can once again atomically update the control file to point to the new (truncated) suffix file. This time we will need to update the "generation" field of the control file in order to point the right suffix filename: + +![](./imgs/chunked_suffix/s0HCu2y.png) + + +And finally, the previous suffix file can be deleted. This doesn't interfere with the read-only instances looking at the old suffix file, because the operating system is smart enough to delay the deletion of this file as long as it is in use. But as soon as all the read-only instances have reloaded the updated control file and switched to the new suffix, the old file is cleared! + +![](./imgs/chunked_suffix/2OQmmez.png) + + +**The huge disk space spikes are then explained by the creation of the new suffix while the old suffix still exists.** In Tezos, since the suffix is the largest file of all and since the GC is called to truncate only 1/5 of it, the disk space nearly doubles during the copying of the live data. To paraphrase capitalist investors, you need space to make space. + +A small precision to make the picture complete, the control file also remembers the total amount of deleted data from the truncated suffix file: + +![](./imgs/chunked_suffix/0dXEkNs.png) + + +If further GC calls remove more data, this number gets increased to always reflect the total amount of reclaimed disk space. During normal read operations on the database, Irmin needs to be able to fetch data from the truncated suffix at specific offsets: These offsets are defined as if the GC never ran, so the "total deleted" number must be subtracted before reading at the corresponding offset in the truncated suffix file. + +Even though we will not mention again the read-only instances, their presence is assumed behind every change! To maintain data consistency, the control file is the only synchronization point between the read-write instance and the read-only nodes: +- Either a read-only instance is uptodate with the latest control file and all the files mentionned by the control file are ready for consumption, +- Or the read-only instance lags behind with an old version of the control file, yet its expired files are still usable with no observable defect. + + +## Proposed solution: chunking the suffix file + +In order to avoid copying the live data in a new suffix file, we propose to cut the suffix file into multiple "chunk" files. Conceptually, the suffix file is the concatenation of all the chunk files. The new layout of the control and chunk files would then be: + +![](./imgs/chunked_suffix/nyr4DMY.png) + +Besides breaking up the suffix file, we also need to add some new fields in the control file, while keeping it small for atomic updates: + +- The "name" of the first chunk : in practice, only the integer identifier and not the real filename as the rest is static +- The "number of chunks" : also just integer, which can be combined with the "name" to recover the filenames of all the chunks + +We emulate the functionalities of the (now virtual) suffix file by: + +- When reading at a specific offset, we can check the filesize of the chunks to discover which specific chunk should be read (all chunks except the last one are read-only so their filesize is statically cached.) +- When appending new data, we write them at the end of the last chunk (as all the previous chunks are read-only.) + + +### Chunked suffix GC + +The truncate operation is now much easier than before and involves no data copying. In the following example, we just have to update the control file to get rid of all the chunks on the left of the GC request point (and then delete them from the filesystem): + +![](./imgs/chunked_suffix/PUTfEkm.png) + +This leads to an optimal disk usage during GC with almost no spike since we do not need to copy several cycles of data for the truncation (the remaining small spikes are related to the prefix file): + +![](./imgs/chunked_suffix/c9RmxfR.png) + +### Optimal GC + +However, the chosen point of truncation becomes important to get the claimed disk space usage depicted in the above graph! In the previous example, the truncation happened on the boundary of a chunk which permitted its easy removal. In practice, the user could choose a less optimal point by requesting a GC in the middle of a chunk: + +![](./imgs/chunked_suffix/NQVgpqN.png) + +To handle this situation, another field is added to the control file: The amount of space in the first chunk that should be considered deleted (even though it still exists on the disk). This new field allows us to maintain the invariant that "garbage collected" data is unaccessible. When a GC happens on a less optimal point, it becomes less able to release disk space... but a future GC will eventually get rid of the partial chunk. + +This situation should not happen in Tezos. The GC calls and the point of truncation will happen at the end of Tezos cycles. We will expose a new API function in `irmin-pack` and `lib_context`, allowing the manual creation of the chunks to align them with Tezos cycles. This function will be called at the spot of future GC points, which will guarantee an optimal layout of the chunks and no wasted disk space after a GC. + +Even if the new chunks were created non-optimally, the wasted space would be at most one chunk (which can be made relatively small by calling the chunks creation function more frequently than necessary). + +### Enabling optimal GC: manual chunk creation + +In Irmin API, the GC is called on a user-chosen commit. All the reachable objects from that commit are copied into another file, called the `prefix`. Finally, the GC gets rid of all the old data preceding that commit by using the truncation routine described above. + +In order to minimize disk waste, the chosen GC commit should be the last object of a chunk. The GC will copy this commit and its reachable data into the prefix, and then get rid of its chunk. + +Since the GC frequency is user dependent, we propose to expose the manual creation of chunks with a new function. In Tezos the GC commits are the first commit of a cycle: it means that the Tezos shell will need to call for the creation of a new chunk right after persisting the first commit of a cycle. + + +## Migration + +### Control file + +To switch to the new chunked layout of the suffix file, we will have to migrate the control file from the current left side to the right version with the new fields: + +![](./imgs/chunked_suffix/uAGz0tE.png) + +We would like to make this transition as seamless as possible: + +- The existing suffix file will implicitly become the first chunk. +- The migration of the control file version to add the new fields will be done on the first update operation to the store (typically a new commit, or a GC call). If no updates are made, the store will remain compatible with the previous releases of irmin in order to facilitate rollback. + +After the migration with only a small update to the control file, the new layout will be active. New chunks will be created regularly and the data layout will start to look like expected: + +![](./imgs/chunked_suffix/Av5J4Zb.png) + +### Original suffix as the first chunk + +In the case where the existing original suffix file was large before the migration, it might take some time to get rid of the first chunk: + +![](./imgs/chunked_suffix/uFBENIj.png) + +In Tezos situation, we expect this big chunk to be 5 or 6 cycles worth of data (while a normal chunk would only be one cycle). After 5-6 calls to the GC (= 5 or 6 Tezos cycles), this chunk will finally be removed. The expected disk space usage showing the transition period is: + +![](./imgs/chunked_suffix/uwzqD0x.png) + +It should be noted that this disk space peak is strictly equivalent to the disk space peaks produced by all the GCs of irmin 3.4. + +We recommend starting from a snapshot if this the disk space usage depicted above is an issue, but present alternatives next that can be added as evolutions to the above design. + + +### Additional GC migration strategies + +Overall, we consider the proposed GC migration strategy a safer compromise, and a required first step before other evolutions, but we acknowledge that the initial disk space consumption of the GC during the transition period might not be desirable. + +We have two possible solutions that can be added as evolutions of the proposed design presented above: + +**Apply Irmin 3.4 GC to existing suffix** + +First, the Irmin 3.4 strategy "truncate by copying live data" could be applied to the partially garbage collected chunks (rather than keeping their inaccessible data on disk). + +- This would guarantee maximal reclamation even with non-optimal chunking, at the cost of a spike in disk space during GC and increased disk I/O as data gets copied. +- For the transitional migration, the very first GC would produce a disk space peak equivalent to the largest disk space peak produced by the first design. Further GCs would keep on copying a progressively smaller first chunk, and it would also take 5 or 6 Tezos cycles to reach "normal behaviour" with no abnormal disk space overhead. + +**Chunk existing suffix** + +Another solution would be to split the initial big suffix into multiple chunks when opening the store in read-write mode for the first time. + +- When the read-write instance starts, the read-only instances are not yet active, which allows to use a migration algorithm that doesn't have to ensure that the store supports the _Single Writer Multiple Readers_ paradigm. As such, we would be able to split the existing suffix file "in place" without doubling the disk space usage (only "one chunk" worth of disk overhead). +- It is however not clear where to split the suffix file: We don't know where the user is going to call the GC in the future, so the resulting chunks wouldn't be optimal for some time. +- Any crash / interruption / power outage during this migration would leave the store in an unrecoverable state. + + +-------------------------------------------------- + +# Appendix / WIP :) + +## Risks & mitigations + +### File descriptor limits + +The proposed design will likely open a file descriptor for every chunk (for easier management). If the ratio of split to GC is high, this could lead to hitting file descriptor limits. In practice for Tezos, it should be low (less than 20), but if it is an issue, we can implement a file descriptor pool for the chunks to maintain an upper limit. + +### Crash consistency + +The guarantees are the same as before, as we do stricly less disk operations. + +## Automatic vs Manual chunking + +We have considered the following alternative chunking strategies, before deciding to expose a new public function to manually trigger the creation of new chunks from the user side: + +- **Fixed physical size:** This could potentially split an object data between two chunks at the boundary, leading to more code complexity. The chunk physical size would have to be decided when creating the store and never change after that. +- **Fixed number of objects:** We expect a Tezos cycle to contain roughly 8'192 commit objects, but we can't detect when a cycle starts/ends on Irmin's side. Automatically creating a new chunk after seeing a given number of commits/objects is unlikely to yield an optimal alignment of the chunks with the GC commits, resulting in wasted disk space. + +We believe the manual creation of chunks will better align with the needs of Tezos. In practice, since a chunk will correspond with one Tezos cycle, the chunks will have roughly the same number of objects and nearly the same physical size on disk. Furthermore, it bounds the number of file descriptors opened for the chunks to the number of kept cycles. + +In the future, it would still be possible to extend Irmin's logic with automatic chunking, for non-Tezos users. + +## Other GC optimization, unrelated to chunks + + +Before the truncation of the suffix, the GC traverses the object DAG to save reachable data into the `prefix` file. Currently, this traversal traverses the disk in a random order and uses temporary files to remember the live data later. + +We believe that this step could be optimized by traversing the disk in order and by writing less data to the temporary files, hence reducing disk I/O and improving the reactivity of the Tezos node during a GC. Benchmarking will be required to validate that the improvements are not outweighted by an increased RAM consumption. diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/0dXEkNs.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/0dXEkNs.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff8efd9ae32f7732738a0401f1899a1eb6a972a GIT binary patch literal 35949 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

S~fKWo^ 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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/2bSEzad.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/2bSEzad.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f2d177684f572817f09f61b1a9a7a4329bdbfa GIT binary patch literal 23614 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%0AD5~V9CDd{uM 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 N!PC{xWt~$(696SuJ^lay literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/Av5J4Zb.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/Av5J4Zb.png new file mode 100644 index 0000000000000000000000000000000000000000..09a35f6ff4a11b9adb7ac613f523d532408c76bc GIT binary patch literal 43602 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 i|^CrIoSU`J2SKR)bZfp;PWe{Ej*f( z`0mcmz}rf}huFP*d}O|vDtmc*YwGICe%kou%NJv-V*$UPJbij{)n#RkDY1Bk_GZy4By`=@6PE)eBnhFYxG5;P$TPkqcZ1g+^t>APgtL}?Er75_-J(H)`f$w#JBa77`ybm$k@pLyCOUJ zdB?Zyo&2hcStdn%|7147;<4)bwL7za9G7<6w!ibnrE4aCe)@7K9$C8b`s2krx8*LG z?RY9e`PY()d)3A4=^HI}?>Mo=tc34(g?o4GvE`5UWahq*c&RpL8jF;^v)^v+<#$al zofVkgnYX+9UH5|hTi-~%6zkw#xcjv0_j429=Yzboqk{FX;~ZIA<-0r#F>V%{R#z{X zt!U?9%g5hd9@bl8+_EE~WYsFKdEZhO-G2SR;qbSKd2Jnmm%W}%7N{?3J=VQ+f9=0{ z{}*jtI=6oP&*KwT+jevM^8!4!hfR6`jcw@ZJC(YCg9Z3J!8pt4#lLX;$q`QhlWX$CPDVF z6go;i=Gkx{;r*p5C;aKt-1`6TsV4bYpi-*|p2+PM&#TVWIL} z8PLA1CQZ57?SA?Pxj+7^tlG2XO6(u)xp7(R_I`^3U1xnaPu|CM-=>Rzg_`n zk8{?Z9|fI`Y%#xA(foXVeO%amP}ibGKzyqC{hG~UnbYvE~FDOzh9sK`jG+8VK8D)P*-OU4Gn$q zBB3#Ox!=~(LW#D-c@kk4PZ*pD)>c$xe5=bLw&KV^=HIt=SwQtLJBTm0iYnUhWXX;F z<^Iv)?THf4Iuk{Ec@Eob{r2u2Yj!8kTV0bI`|In$a&3tcZHWvF)pd6{wF6CW&CZ@U zVFrUz)@vn0p2IeRYZgsRoUuG8H&=I3u-@T=KHS>EPQ7cSzQ4Ph{W{4IV≠ucboi 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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/Yg65T4T.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/Yg65T4T.png new file mode 100644 index 0000000000000000000000000000000000000000..e739b53573bce4f6f0aecc11684750119c71cccb GIT binary patch literal 23017 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 E07&3bS^xk5 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/c9RmxfR.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/c9RmxfR.png new file mode 100644 index 0000000000000000000000000000000000000000..343c29b309e726105128bba042d559d2b5bb3362 GIT binary patch literal 29550 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 V%uI*~U|?Wi@O1TaS?83{1OVC(U?u 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 SJ~1#bFnGH9xvX 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 T=k75uFfe$!`njxgN@xNAsj-?f literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uAGz0tE.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uAGz0tE.png new file mode 100644 index 0000000000000000000000000000000000000000..292e15e0dd8f8a15a830c4eea1993e019d1f141b GIT binary patch literal 66045 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 E01PNo9{>OV literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uFBENIj.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uFBENIj.png new file mode 100644 index 0000000000000000000000000000000000000000..de34dba7352d458e164e494e39e24f49415e0fba GIT binary patch literal 98529 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

%4W-KlqHU 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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uwzqD0x.png b/vendors/irmin/doc/irmin-pack/design/imgs/chunked_suffix/uwzqD0x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed918f082505891b9936bedaf9e1203193e6f058 GIT binary patch literal 49670 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 A8vpiU=!XDMM*M;Gdv0iMbz} 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%0AGX!Xv)y`GnpZTiqy#Z(?gnDJa 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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/jqAbf7o.png b/vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/jqAbf7o.png new file mode 100644 index 0000000000000000000000000000000000000000..df75a4c8dc27453428cac95ec269e35d91bc7271 GIT binary patch literal 25855 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 z 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 R(Hc~idb;|#taD0e0ss&qe1ZS~ literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/ywNyqGa.png b/vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/ywNyqGa.png new file mode 100644 index 0000000000000000000000000000000000000000..bb288f9c97da929a3cfb83cc6a1f53d31cec8008 GIT binary patch literal 51818 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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/suffix.png b/vendors/irmin/doc/irmin-pack/design/imgs/suffix.png new file mode 100644 index 0000000000000000000000000000000000000000..ced3d0a56711220f966ecf5d9a8c4de70eeb1bc1 GIT binary patch literal 7139 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 S?VJn@3=E#GelF{r5}E)|Vctjp literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/layered_store.md b/vendors/irmin/doc/irmin-pack/design/layered_store.md new file mode 100644 index 000000000000..3218b1fa3e0c --- /dev/null +++ b/vendors/irmin/doc/irmin-pack/design/layered_store.md @@ -0,0 +1,545 @@ +# Irmin-pack layered-store/GC design document + +Date: 2022-02-03 + +## Introduction + +This is a short document to describe the design of a garbage +collection mechanism for irmin-pack (the variant of Irmin currently +used by Tezos). + +**TL;DR** + +The irmin pack file stores objects. References from one object to +another are stored using the position of the referred-to object in the +pack file. Currently, objects are never deleted, so disk usage grows +indefinitely; this is the problem we want to solve. In order to delete +old objects and reclaim disk space, whilst still referencing objects +by their "position in the pack file", we replace an initial segment of +the pack file -- up to a particular "garbage collection root commit" +-- with an "object store", which essentially stores the live objects +from the initial segment, indexed by their original position in the +pack file. Every so often, we choose a new GC root commit and +reconstruct the object store from scratch. In this way, disk usage is +required only for recent objects and those reachable from the last GC +root commit. + +## Background + +The Tezos blockchain uses irmin-pack as the main storage +component. Roughly speaking, irmin-pack is a git-like object store, +optimized for the Tezos usecase. Irmin-pack has several components +(including an "index", and a "dictionary"), but we focus on the main +file used to store object data: the store pack file. + +**Pack file:** The pack file stores marshalled objects one after the + other. An object can contain pointers to earlier (but not later!) + objects in the file. Pointers to an earlier object are typically + represented by the offset (position) of the earlier object in the + pack file. The pack file is append-only: existing objects are never + updated. + +``` +Pack file as a sequence of objects: [obj][obj][obj]... +``` + +Aside: Previously, every object was identified by hash, and there was +another structure -- the index -- that translated hashes to offsets; +however, this indirection was inefficient compared with directly +addressing objects by their offset. Now, most objects are referenced +using the offset in the pack file. + +**Commit objects:** Some of the objects in the pack file are "commit + objects"; a commit, together with the objects reachable from that + commit, represents "the state of the tezos node at a point in + time". (It is possible for the state to split in two temporarily, + but we will ignore this for the time being.) The Tezos node only + needs the "latest" commits in order to process new blocks. Thus, any + objects not reachable from the latest commits can be considered + "garbage". + +**Archive nodes and rolling nodes:** There are different types of + Tezos node. An "archive node" stores the complete history of the + blockchain from the genesis block. Currently this is over 2 million + blocks. Roughly speaking, a block corresponds to a commit. A + "rolling node" stores only the last blocks (where is chosen to keep + the total disk usage within some bound - _n_ may be as small as 5 or + even less, or as large as 40,000 or more). Another type of node is + the "full node", which is somewhere between an archive node and a + rolling node. + +**Rolling nodes, disk space usage:** The purpose of the rolling node + is to keep resource usage, particularly of disk space, bounded by + only storing the last blocks. However, the current implementation + does not achieve this aim: as rolling nodes execute, the pack file + grows larger and larger, and no old data is discarded. To get around + this problem, node owners periodically "snapshot export" the current + state of the blockchain from the node, delete the old data, and then + "snapshot import" the state back again, in a form of manual garbage + collection. + +**Problem summary:** The main problem we want to avoid is Tezos users + having to periodically export and import the blockchain state in + order to keep the disk usage of the Tezos node bounded. Instead, we + want to perform garbage collection of unreachable objects + automatically: Periodically, a commit should be chosen as the GC + root, and objects constructed before the commit that are not + reachable from the commit should be considered garbage, removed from + the pack store, and the disk space reclaimed. The problem is that + with the current implementation of the pack file, which is just an + ordinary file, it is not possible to "delete" regions corresponding + to dead objects, and "reclaim" the space. + +## Proposed solution + +Consider the following pack file, where the commit object has been +selected as the GC root: + +``` +Pack file: [obj1][obj2]...[obj3][obj4][obj5][commit]... +``` + +Objects that precede the commit are either reachable from the commit +(by following object references from the commit), or not. For the +unreachable objects, we want to reclaim the disk space. For reachable +objects, we need to be able to continue to access them via their +"offset in the pack file". + +The straightforward solution is to implement the pack file using two +other data-structures: + +- The "suffix file" contains the commit object, and all bytes + following in the pack file. +- The "object store" contains all the objects reachable from the + commit, indexed by their offset. (Recall: these objects all appear + earlier in the pack file than the commit object.) + +``` +Pack file : [obj1][obj2]...[obj3][obj4][obj5][commit]... +Object reachable? : Y N Y N Y + +...is implemented by... + +Object store : a map for reachable objs: off1->obj1, ... off3->obj3, off5->obj5 + where off1 is the offset of obj1 etc. + +and + +Suffix file : [commit]... +``` + +Attempting to read from the pack file is then simulated in the obvious +way: if the offset is for the commit, or later, we read from the +suffix file, and otherwise we lookup the offset in the object store +and return the appropriate object. It is assumed that we only ever +access the reachable objects in the object store, and that we do so +via their offset. + +![](./imgs/suffix.png) + +We replace the irmin pack file with these two datastructures. Every +time we perform garbage collection from a given commit, we create the +next versions of the object store and suffix file, and switch from the +current version to the next version, deleting the old suffix file and +object store to reclaim disk space. Creating the next versions of the +object store and suffix file is potentially expensive, so we implement +these steps in a separate process with minimal impact on the running +Tezos node. + +Aside: Following git, a commit will typically reference its parent +commit, which will then reference its parent, and so on. Clearly, if +we used these references to calculate object reachability, all objects +would remain reachable forever. This is not what we want, so when +calculating the set of reachable objects for a given commit, we ignore +the references from a commit to its parent commit. + +### Object store + +The object store is a persistent datastructure that implements a map +from key (offset in pack file) to data (the marshalled bytes +representing an object). In our scenario, the worker creates the +object store, which is then read-only for the main process: objects +are never mutated, or deleted from the object store. In this setting, +a very simple implementation of an object store suffices: we store +live objects in a data file, and maintain a persistent (int → int) map +from "offset in the original pack file" to "offset in the object store +data file". + +**Terminology:** We introduce the term "virtual offset" for "offset in + the original pack file", and the term "real offset" for "offset in + the object store data file". Thus, the object store map is from + virtual offset to real offset. + +**Example:** Consider the following, where the pack file contains + reachable objects _o1_, _o3_, _o5_, (with virtual offsets _v1, ...) + +``` +Pack store : ...[o1]...[o3]...[o5]... +Virtual offset : ^v1 ^v3 ^v5 + +Object store data file : [o3][o5][o1] +Real offset : ^r3 ^r5 ^r1 +``` + +The object store data file contains the same objects, but with +different "real" offsets _r1, _r3,_, _r5_. + +The persistent map needs to contain an entry _v1 -> r1_ (and similarly +for the other objects) to relate the virtual offset in the pack file +with the real offset in the data file. + +To read from "virtual offset v3" (say), we use the map to retrieve the +real offset _r3_ in the object store data file, and then read the object +data from that position. + +### Asynchronous implementation + +Garbage collection is performed periodically. We want each round of +garbage collection to take place asynchronously, with minimal impact +on the main Tezos node. For this reason, when a commit is chosen as +the GC root, we fork a worker process to construct the next +object-store and next suffix-file. When the worker terminates, the +main process "handles worker termination": it switches from the +current object-store+suffix-file to the next, and continues +operation. This switch takes place almost instantaneously. The hard +work is done in the worker process. + +**Read-only Tezos nodes:** In addition to the main Tezos read/write + node that accesses the pack store, there are a number of read-only + nodes, which also access the pack store (and other irmin data files) + in read-only mode. It is important that these are synchronised when + the switch is made from the current object-store+suffix to the next + object-store+suffix. This synchronisation makes use of a "control + file". + +**Control file:** In order to coordinate between the main process and + the worker process (and also any read-only processes), we introduce + a control file. The control file is a single file which includes the + following fields: + +- generation: an integer which is bumped every time a switch occurs; + processes can detect that a switch has occurred by observing changes + in the generation number +- object-store: a pointer to the object store (actually, the name of + the directory containing the object store) +- suffix-file: a pointer to the suffix file (actually, the name of the + directory containing the suffix file) +- other metadata (not relevant for this document) + +The current control file has filename `control`. In order to switch +state from one object-store+suffix to the next, we can create a new +control file and atomically rename it over the old control file. + +**Steps taken by the worker:** Given a GC root commit, the worker + proceeds as follows: + +- Calculate the reachable objects from the commit, recording their + offset and length information. +- Construct the new object store, a map from offset to object (really, + the marshalled bytes representing the object). +- Construct the new suffix file, by copying the contents of the + current suffix file from the GC root commit onwards. +- Finally, construct the next control file `control.nnnn` where `nnnn` + is the next generation number, and terminate. + +Aside: For efficiency, some of these steps may be combined. For +example, the worker could construct the object store at the same time +that it calculates the reachable objects, thereby avoiding having to +visit locations in the file twice. + +**Steps taken by the main process on worker termination:** When the + main process detects the worker has terminated, it does the + following: + +- Read the next control file `control.nnnn` to find the next + object-store and next suffix file. +- Copy any further data that has been added to the current suffix to + the end of next suffix. +- Rename `control.nnnn` over `control` ; read-only processes detect that + the generation number has changed, and synchronise with the new + state. +- Delete the old object-store and suffix file to reclaim disk space. + +## Worker efficiency concerns + +We want the worker process to execute with minimal impact on the main +Tezos node. For this reason, we take the following steps: + +- The worker runs as a separate process. If needed, the process can be + "nice"-ed to reduce its impact, for example, when running on a + single core. +- The worker uses `fadvise` to inform the operating system that it + should preferentially **not** devote resources to caching **worker** + disk IO. The OS caches should instead remain allocated to the main + Tezos node. In particular, the worker should not disturb the caches + for the main process, when the worker calculates the reachable + objects for the given commit. +- With the exception of the calculation of the reachable objects from + a commit, the worker is **simply copying bytes between files.** This + makes the worker very simple, and hopefully makes it easy to + optimize performance and ensure correctness of operation. + +### Crash correctness + +We now describe what happens in the event of a system crash. The +interesting cases are when the worker is active, or has just +terminated. + +If the worker process is active, then it may have created part or all +of the next object-store and next suffix. However, the control file +will still point to the current object store and suffix. On restart, +the main process opens the control file, at which point it knows which +files are the "real" object-store and suffix (those listed in the +control file), and can delete any other files it finds (which will be +the partial files the worker was creating). + +If the worker process has just terminated and a crash occurs, then the +critical point is whether the rename of the next + +`control.nnnn` over the current `control` was recorded persistently on +disk or not. If it was, then the main process restarts, reads +`control` (which was successfully renamed from `control.nnnn` ), and +starts operating with the next object-store and suffix file (and +deletes the old versions). If not, the main process reads the old +`control` file (the rename of `control.nnnn` was not successful), and +starts with the old object-store and suffix file (and deletes the new +ones that the worker created). In either case, the system restarts in +a correct state. + +This correctness argument uses the "atomic rename" property of +filesystems: when renaming a file within a directory, and a crash +occurs, on restart the file is found either under the old name or +under the new name. + +### Summary + +The above gives an overview of the design. Further detailed comments +on particular aspects are included in the appendix below. + +## Appendix + +The following sections provide further detail on particular aspects of +the design. They can be skipped on first reading. + +### Scaling + +It is worth noting that several computations (finding the set of +reachable objects; constructing the object store) scale as "the number +of reachable objects per commit". However, we might want to scale as +"the number of actively changed objects per commit". In this case, a +completely different design would be required (see the Alternative +design section below). + +### Object store overhead + +**Object store overhead and the number of reachable objects:** The + object store consists of a data file, and a persistent map. The use + of a persistent map introduces overhead compared to the space needed + to store the raw objects. For each object, we need at least two + integers (or 16 bytes) for each map entry. Thus, 1M reachable + objects requires at least 16MB of overhead for the map, 10M requires + 160MB and 100M requires 1.6GB. + +A snapshot of the current Tezos state contains 30M objects, which +corresponds to an overhead of 480MB for the map. This is significant, +so we would like to reduce the map size if possible. + +**Extents:** Consider adjacent reachable objects in the pack file + between two offsets: + +``` +Pack file: ...[obj1][obj2][obj3]... + ^off1 ^off2 ^off3 + \________________/ + A single "extent" +``` + +Instead of storing (virtual offset → real offset) entries for each +object, we can consider adjacent objects in the pack file as an +"extent" (an extent is just a region in a file between two offsets), +and instead store (virtual offset →real offset) entries for each +extent. It is still possible to locate individual objects via their +virtual offset, but hopefully a map based on extents would have +significantly fewer entries. + +Thus, the proposal would be to work with a map from "virtual extent +offset" to "real extent offset". + +**Summary:** The prototype implementation of the object store will use + a map with an entry for each object. For production, we will replace + this implementation with one based on extents. The sequence of + operations for the worker, when calculating reachablility using + extents, is as follows: + +- Traverse reachable objects and store unsorted (off,len) information + in a file (30M objects, approx 1GB) +- Sort on-disk object (off,len) data by offset (another 1GB file) +- Calculate (off,len) extents corresponding to adjacent objects and + store on disk (size unknown) + +Whether extents reduce the size of the map is currently unknown. The +worst case is if each reachable object is separated from all others, +so the number of extents is the same as the number of objects, and the +map remains the same size. If there are many adjacent reachable +objects (the expected case), then using extents should result in a +much reduced size for the persistent map. + +We hope the use of extents will make the persistent map sufficently +small. If the extent-based map file is still "too large", we will then +consider further ways to reduce its size. + +### Possible optimisations + +We expect the above design will perform well. However, it is possible +to make further efficiency improvements, at the cost of increased +complexity in the implementation. We now describe some potential +optimisations. + +**Reduce persistent map size further:** The persistent map, from + virtual extent offset to real offset, is far from arbitrary (it is + monotonic, for example). This should make it easy to compress, if + the size of the map is considered too large. + +**Reuse object ancestor information:** When we select a commit as the + GC root, we calculate the objects reachable from that commit. This + requires that for each object, we (implicitly or explicitly) + calculate the reachable ancestors of that object. When it comes to + the next GC iteration, we select a later commit. However, if one of + the objects reachable before, is still reachable, we know that all + that object's ancestors are also reachable. Rather than repeatedly + traverse those ancestors on each GC, we could remember the (offsets + of ) ancestors of each object, and reuse this information for the + next GC cycle. + +**Prefer sequential object traversal:** Traversing the object graph + during GC involves accessing earlier objects, typically in "random + access" fashion. We might want to be smarter about this, so that + objects are visited (as far as possible) in order of increasing + offset on disk. This takes advantage of the fact that sequential + file access is often much quicker than accessing the file randomly. + +**Prefer sequential object traversal for new objects:** Between two GC + commits, the pack file contains new objects: + +``` +Pack file: ...[commit][obj][obj]...[obj][commit]... + \ / + This region may also contain non-GC commits +``` + +When calculating the reachable objects for the later commit, we +already noted that we can reuse ancestor information from the earlier +commit. In addition, when calculating reachability information, we can +process the objects between the two commits in the order they appear +in the pack file. With these two optimisations, we only ever access +the pack file sequentially, from the previous GC commit to the next. + +One possible downside is that by processing each of the objects +between the two commits, we potentially do extra work when very few of +these intervening objects are reachable (and so very few of these +objects need to be touched when computing reachability from the later +commit). However, we expect that the benefit to processing these +objects in the order they appear in the file outweighs this possible +downside. + +### Prototype + +A prototype of the proposed design can be found at: +https://github.com/tomjridge/sparse-file (the object store is referred +to as a "sparse file" in that repository). The code for the worker, +for example, looks like the following (modulo some renaming of +functions): + +```ocaml +let run\_worker ~dir ~commit\_offset = + (* load the control, obj-store, suffix; calculate reachability from + commit_offset and store objs in new obj-store; create new suffix file; + create new control file; terminate *) + let io = Io.open_ dir in + let dreach = Dr.disk_calc_reachable ~io ~off:commit_offset in + create_object_store ~io ~dreach; + create_suffix_file ~io ~off:commit_offset; + create_control_file ~io; + log "worker: terminating"; + () +``` + +This code matches exactly the informal description of the steps taken +by the worker, described earlier. + +### Retaining older objects for archive nodes + +Archive nodes contain the complete blockchain history, starting from +the genesis block. This results in a huge store pack file, many times +larger than main memory. Live objects are distributed throughout this +huge file, which makes it difficult for OS caching to work +effectively, and as a result, as the store becomes larger, the archive +node becomes slower. + +In previous versions of the layered store, the design also included a +"lower" layer. For archive nodes, the lower layer contained all the +objects before the most recent GC commit, whether they were reachable +or not - the lower layer was effectively the full + +prefix of the pack file before the GC commit. + +One possibility with the new design proposed above is to retain the +lower layer, whilst still sticking with the object store + sparse file +approach, and preferentially reading from the object store where +possible. The advantage (compared with just keeping the full pack +file) is that the object store is a dense store of live objects (much +denser than the full pack file), which improves + +OS disk caching, thereby improving performance of snapshot export for +recent commits. In addition, the OS can preferentially cache the +object store, which improves general archive node performance compared +with trying to cache the huge pack file, providing we mostly access +objects in the object store+suffix rather than the lower +layer. However, some uses of the archive node, such as responding to +RPC requests concerning arbitrary blocks, would still use the lower +layer, and no performance improvement can be expected in these cases. + +The goal of improving archive node performance for arbitrary blocks +(not just those corresponding to recent commits) still remains, and is +not addressed by this proposal. + +### Alternative design + +The design proposed above scales with "the number of objects reachable +from a commit". If this grows increasingly large over time, the +proposed design may become unsuitable. An alternative is to use a +fully-fledged object store as the storage layer, and implement GC in +that layer. This would avoid having to recreate the +object-store+suffix file each time. This approach would scale as "the +number of objects mutated on each commit". + +The pack file stores objects, which reference each other via their +position in the pack file. Clearly there is nothing particularly +special about the position of an object in a pack file - it is just a +way of uniquely identifying the objects. + +In the design proposed above, when we build the object store, we +construct a map from key (offset in pack file) to object, and we +construct a new object store each time we perform garbage collection. + +One alternative design would be to replace the pack file completely, +and instead use a "real" object store (with no suffix file) to store +objects. This "real" object store would be far more sophisticated than +the object store outlined above. For example, the real object store +should also support a "delete" operation, with asynchronous garbage +collection, so we can delete unreachable objects and reclaim the disk +space. This would provide a clean interface for the bottom-most +storage layer, based on the notions of object and object id, rather +than file offsets and byte strings we currently manipulate. Garbage +collection could be implemented cleanly in this layer. With such an +approach, and using the "ancestor optimisation" above, GC could scale +as "the number of objects mutated on each commit" (although we do not +spell out the details here). + +The problem is that existing databases and object stores do not +provide the performance needed for the Tezos usecase. This is partly +the reason Tezos uses Irmin (the other main reason is that Irmin +provides efficient tree-like operations). However, we have developed a +prototype object store "kv-hash", as part of work on optimising +another part of Irmin, that could potentially be used as an object +store if this alternative design were pursued. diff --git a/vendors/irmin/doc/irmin-pack/design/lower_layer.md b/vendors/irmin/doc/irmin-pack/design/lower_layer.md new file mode 100644 index 000000000000..04258010471d --- /dev/null +++ b/vendors/irmin/doc/irmin-pack/design/lower_layer.md @@ -0,0 +1,458 @@ +# Improving performance for unlimited history stores + + +Irmin 3.4 introduced a garbage collection (GC) feature, giving users of `irmin-pack` the capability to trim a store's commit history by removing data older than a specified commit hash. Irmin 3.5 and 3.6 build on this feature by decreasing the size of volatile and non-volatile memory needed to perform the operation. + +This is a useful feature for stores that only need recent history, but some stores are designed to keep an unlimited number of commits in their histories and cannot take advantage of this feature. Irmin 3.7 will extend GC support to these stores and address a longstanding performance problem for them in the process. + +## Problem: performance degradation when storing unlimited history + +Stores that keep an unlimited history decrease in overall performance over time due to two primary reasons: + +1. they store their data in a single file (called the suffix), and +1. this file grows unbounded over time. + +Each time a commit tree is stored in `irmin-pack`, its unchanged data is not stored again but rather referenced by its previously stored offset location. As more commits are accumulated over time, these offsets can be located farther and farther apart in the suffix file. This results in reads potentially happening in more disparate locations in the file, which puts pressure on the OSes page cache and results in less reads happening from memory. In essence, [data locality](https://en.wikipedia.org/wiki/Locality_of_reference) suffers in these larger files. + +## Solution: split an `irmin-pack` store into two layers + +To reduce the loss of data locality, an `irmin-pack` store must compose of smaller, self-contained files or sets of files. This is already achieved with limited history stores that use GC, primarily through the introduction of the prefix file. The prefix file works together with the suffix file(s) to store the data of an `irmin-pack` store. The prefix contains all data for offset references in the suffix that are not included in the suffix itself. In essence, it takes objects that used to be spread across the offset space of the store and places them next to each other, thereby improving data locality. + +For unlimited history stores, we can reduce the loss of data locality for recent history by adding a new location for storing GCed history and extending the GC feature to utilize this new location. + +The new location is called the **lower layer**. When it is present, GC will put discarded history in the lower layer instead of deleting it, and thus enable unlimited history stores to keep all of their history. The area of data that is the target of GC is called the **upper layer**. + +![](./imgs/lower_layer/gYsLcmj.png) + + +Another way to think about it is that the upper layer is equivalent to what a store is today and that GC will either delete history on disk, for limited history stores, or move it to the lower layer, for unlimited history stores. The upper layer is the area for recent history and new data being written to the store, and the lower layer is the archival area for GCed data that might be read later. + +With this new structure in place, unlimited history stores will benefit from an upper layer that has the same data locality properties as limited history stores and so should have similar performance characteristics, at least for recent history. Data locality can be improved in the lower layer as well through subdividing its data into self-contained segments. + +## Design overview + +To implement the splitting of an unlimited history `irmin-pack` store into an upper layer and lower layer, the following high-level changes need to be made: + +1. Introduce on-disk layout (collection of diretories and files) for the lower layer +1. Introduce on-disk layout for self-contained segments of the lower layer +1. Add any store configuration values so that `irmin-pack` has all the knowledge it needs for using a lower layer +1. Introduce migration for existing unlimited history stores +1. Modify GC API and process to allow unlimited history stores to move history into the lower layer instead of discarding it +1. Modify data reading process to use lower layer when data is not found in the upper layer + +These changes and related ones are discussed in the following sections. + +### New terms + +The following new terms are introduced: + +- **upper layer**: the area of of a store that contains recent history and receives new commits: the "recent" area. +- **lower layer**: the area of an unlimited history store that holds history that has been discarded by GC from the upper layer: the "archive" area. +- **volume**: a sub-area of the **lower layer** for storing a contiguous portion of a store's history. Multiple volumes can be created to reduce loss of data locality. + - **appendable volume**: the read-write volume in the **lower layer** + +## New store configuration values + +Currenlty, an `irmin-pack` store uses a configuration value named `root` to know the path on disk to use for reading and writing its files. To support a lower layer, the configuration is extended by adding a value named `lower_root`. This is a path on disk for reading and writing volumes. + + +## Lower layer + +The lower layer is the archive area for an unlimited history store. It stores the commit history that has been discared from the upper layer through a GC process. + +### On-disk layout + +The on-disk representation for the lower layer is a directory that contains volume data. + + +## Volumes + +A volume is a self-contained area of contiguous commit history. + +It is self-contained in so far as all the data needed to read a commit and its tree is in the volume. This is achieved through the usage of a prefix-like area that contains all the data that is needed for reading any commit in the volume. + +Since it contains a contiguous commit history, there are no gaps of commits from its beginning commit to its ending commit. + +From this definition, it can be seen that the upper layer can also be considered a volume, but for the current discussion, we are only considering volumes in the lower layer. + +**Multiple volumes** + +The lower layer can contain 0 or more volumes. If it contains only 1 volume, it will eventually suffer from similar performance characteristics of today's unlimited history stores, so the design supports multiple volumes. This will be discussed more in the following sections. + + +### On-disk layout + +![](./imgs/lower_layer/DBAFgWu.png) + +A volume is a directory in the lower root that contains the following files that make it a volume. + +**volume.data** + +This file stores the actual data (commits, contents, nodes). It can contain either sparse or dense data, but all of it is covered by entries in the mapping file. + +**volume.mapping** + +This file holds a sorted list of mappings from global offset to physical offset in **volume.data**. It works like the mapping file in the upper layer. + +**volume.control** + +This is the control file for the volume. It stores fields that are used for reading, writing, and generally understanding the contents of a volume. + +| Field | Description | +| -------- | -------- | +| start_offset | The global offset for the start of `volume.data`. The volume is expected to have offset data `>= start_offset`. Used for routing reads to a volume. | +| end_offset | The global offset for the start of `volume.data`. The volume is expected to have offset data `>= start_offset`. Used for routing reads to a volume. | +| mapping_end_poff | The physical offset of `volume.mapping` that corresponds to the end of the file. Under normal circumstances it should be equal to the length of the file, but can be less if a flush fails. Used when writing data. **Note:** we do not need to store the end phyical offset of the data file since it can be determined by looking at the mapping file's data. | +| checksum | A checksum of the payload. | + +These fields will be discussed more later within the contexts they are used. + +### CRUD operations + +**Create** +New volumes are created during the initial migration process and by an explicit call to an `add_volume` function. See subsequent sections for more details. + +**Read** +See subsequent section on the data reading process for more details. + +**Update** +Volumes have the following invariants for writes: + +1. Only the last volume (as sorted ascending by `start_offset`) is read-write. This is called the **appendable volume**. +1. It is illegal to write to any volume other than the appendable volume. +1. Writes to the data file or the mapping file only occur in the GC worker process. +1. The control file can be written in the main or GC worker process, as needed. + +Additionally, it is intended that volumes, once created, are never migrated: whatever version of layout and data they have at time of creation will always be supported. + +See subsequent sections for more details. + +**Delete** +Volumes are never deleted. + +## Upper layer control file + +One new field, `volume_num`, is added to the upper layer's control file to track the number of volumes in the lower layer. + +## Migrating existing stores + +Since unlimited history stores can have large upper layers (> 500 GB for Tezos), we want to minimize the amount of extra disk space used during a migration for these stores. We also want the migration to be quick enough to happen when the store is first opened as read-write. To accomplish both goals, we simply move the existing suffix into the first volume. This is a fast operation if the lower layer is on the same disk and incurs no extra disk usage overhead. + +If a store is opened with a `lower_layer` configured and its upper layer control file's `volume_num` is 0, the following migration is performed: + +1. Create first volume in lower layer, `volume.0` +1. Move upper suffix chunk to the first volume's `volume.data` file +1. Create `volume.mapping` with an entry for the entire data file +1. Write `volume.control` + - `start_offset` is 0 + - `end_offset` is length of the data file + - `mapping_end_poff` is length of mapping file +1. Create empty `store.1.suffix` in upper layer +1. Create empty prefix and mapping in upper layer +1. Update upper layer control file + - `status` is `Gced` + - `suffix_start_offset` is length of `volume.data` + - `generation` is 1 + - `latest_gc_target_offset` is `suffix_start_offset` + - `suffix_dead_bytes` is 0 + - `appendable_chunk_poff` is 0 + - `volume_num` is 1 + - `chunk_start_idx` is 1 + - other fields are unchanged +1. The `store.branches`, `index/*`, and `store.dict` files are left as-is in the upper + +## Updates to GC API and process + +### Recap of Irmin 3.5 + +As a recap, the GC process introduced in Irmin 3.5 proceeds in two phases. The first is to create new data in the asynchronous worker process. The second is to finalize the GC in the main process. + +**1. Creating new data in worker** +1. Create new mapping file +1. Create new prefix file +1. Calculate chunks for deletion, new chunk starting index, and new dead bytes for the suffix + +**2. Finalization in main** +1. Reload prefix, suffix, and mapping +1. Write new control file +1. Purge LRUs +1. Unlink files + +### Updates to API + +There are two addtions to the API related to the lower layer. + +The first is a function on the store to add a new volume: `add_volume`. This functions is used by clients to create a new empty volume in the lower. Note: an empty volume is created automatically when creating a store for the first time. + +The second function is to check GC behavior: `Gc.behaviour`. This function returns either `Delete` for stores that do not have a lower layer and support deletion during GC or `Archive` for stores that have a lower layer. Note: `Archive` is supported by all stores, but `Delete` is not supported by stores that were created before version 3 of `irmin-pack` or that have non-minimally indexed data. + +### Updates to GC process + +![](./imgs/lower_layer/gYQPmLU.png) + +The new GC process retains the existing steps and adds some new ones. The circled letters represent possible moments of failure for discussion in the subsequent section on handling failure. + +The appendable volume is used for writing data from the upper to the lower. + +The following is a description of the timeline of steps in the updated GC process. + +**1. Existing GC steps (worker)** + +No changes from Irmin 3.5. + +**2. Handle empty volumes (worker)** + +If the appendable volume is empty and it is not the first volume, we copy the existing (pre-GC) prefix and mapping files from the upper layer into the volume. This is what creates a self-contained volume. + +This step is not needed for the first empty volume since no GC has happened yet and so there is not a prefix or mapping file at that time. + +**3. Process new mappings (worker)** + +If orphaned commits are removed, the process must traverse commit history **in the suffix**, starting from the target GC commit. During this traversal, new mapping data is created that will subsequently be appended to the volume's mapping file. + +In the case that orphaned commits are not removed, an entry will be appended to the mapping file that corresponds with the range of data that is appended to the data file. + +Data is appended starting at the end of the mapping file or `mapping_end_poff`, depending on if the volume was empty at the beginning of GC or not. + +**4. Append discarded suffix data (worker)** + +The data from the upper suffix that will be discarded is instead moved to the target volume by appending to its data file. Prefix data is never appended to a volume's data file. + +If orphaned commits are removed, appends must follow in the order of the data appended to the mapping file. If they are not removed, data can be simply appended in a blit-like manner from the upper suffix to the volume's data file. + +Data is appended starting at the end of the data file or the last physical offset contained in the mapping file, depending on if the volume was empty at the beginning of GC or not. + +**5. Write volume.gen.control (worker)** + +The last new step in the worker process is to write the new control file values. The purpose of writing a new control file is to enable clean up in the presence of a failure that results in an incomplete GC process. The `gen` part of the name corresponds with the next generation of the upper (that is, after GC completes). + +The values of the control file are: + +- `start_offset` is the current - ie before GC - value of `suffix_start_offset` of the upper (unchanged if not a empty volume) +- `end_offset` is the end offset of the data file +- `mapping_end_poff` is the length of `volume.mapping` + +**6. Write store.control (main)** + +No changes from Irmin 3.5. + +**7. Rename volume.gen.control to volume.control (main)** + +After the upper control file is written, the volume's control file is updated by renaming `volume.gen.control` to `volume.control`, making the new data in the volume readable. Close `volume.control` file descriptor, if open. + +**7. Unlink files (main)** + +No changes from Irmin 3.5. + +### Handling crashes during GC + +Three moments are indicated by red circles in the previous diagram of the new GC process. Here is how we maintain consistency if a crash occurs at any of them. + +**Moment A** +![](./imgs/lower_layer/ywNyqGa.png) + +This moment is anytime during the worker's execution (or after it has finished) but before the new upper control file has been written. + +Nothing changes from the current behavior. All remnant files (in both upper and the appendable volume) will be unlinked on node restart: + +- `store.gen.prefix` +- `store.gen.mapping` +- `volume.gen.control` + +**Moment B** +![](./imgs/lower_layer/jqAbf7o.png) + + +This moment is after the new upper control file has been written but before the appendable volume's control file has been renamed. + +This scenario is detected by comparing the generation number (the `gen` part of the name) of the volume's control file and the generation in the upper control file. If they are the same then this is resolved by swapping the appendable volume's control file on restart via a file rename. If they are not, it is unlinked. + +This scenario highlights a motivating reason for `volume.gen.control`. It gives us a way to coordinate the control files of the volume and the upper layer and to recover in the scenarios where one or the other fails to update. + +**Moment C** +![](./imgs/lower_layer/bXuEjOi.png) + + +This moment is after the volume's control file has been renamed but before files have been unlinked (in the upper). + +Nothing changes from current behavior. Files are unlinked on node restart. + + +### Validations + +The following validations are performed as a part of the new GC process: + +- The `end_offset` of the appendable volume should be less than or equal to the `suffix_start_offset` of the upper before appending data to the volume. This should never happen in pracitce, but this validation protects against writing offsets that have already been written to the volume. + +### GC API usage + +The new APIs are intended to make using a lower layer with multiple volumes as straightforward as possible. Since every store will start with an empty volume in its lower layer, a client only needs to run a GC as in previous versions of `irmin-pack` by calling `Gc.run`. Data will be moved to the volume in the lower layer automatically. + +If a client ever wants to have multiple volumes in their lower layer, they can call `Store.add_volume` after they have run at least one GC for the curent volume (only one empty volume an exist at a time). + +If a client wants precise control over the data in each volume, they will have to make sure they call `Gc.run` on the last commit they want in a volume before calling `Store.add_volume`. + + +## Updates to data read process + +When reading from an `irmin-pack` store, the first step is to get a tree based on a commit hash. Once you have this tree, you can find data at particular paths within it. There are two reasons why this is the entry point for reading: + +1. Keys are not intended to be used across stores or even across restarts of the process +1. With minimal indexing, only commits are addressable by their hash + +For a given commit hash, reading from the lower layer only happens if the corresponding commit is not in the upper layer. + +To successfully go from commit hash to data, we need to answer the following questions: + +- How do we know a commit is not in the upper layer? +- How do we determine which volume contains a commit hash? +- Once we have loaded a commit, how do we continue reading its data (nodes and contents) from its volume? + +### Finding a commit + +**Upper layer** + +The starting point for finding a commit in `irmin-pack` is to lookup its key in the index. Assuming the store has a record in its index of the commit hash, the key will provide a global offset for finding the commit. Lets call this simply `offset`. + +In Irmin 3.5, the control file value `suffix_start_offset` is used to determine whether the offset should be looked up in the prefix (`offset < suffix_start_offset`) or the suffix (`offset >= suffix_start_offset`). We only need to consider the prefix case when considering how to route reads to the lower layer. + +To determine if `offset` is in the prefix or not, we can use the upper mapping to lookup the offset. If it is found we know the data is in the prefix; otherwise, we need to look in the lower layer. + +One caveat is the dangling parent commit in the prefix. This is created as a part of the GC process. The offset for this key exists in the mapping and so it will still be read from the prefix. All other data for this commit will be read from the lower layer since it does not exist in the prefix. + +**Lower layer** + +The simplest way to find which volume contains `offset` is to create an in-memory data structure based on the control files of volumes at the time of opening the store that can be used to map `offset` to volume `identifier`. We expect the number of volumes to be small (say, less than 100), so a list that is created at store open (and not persisted to disk) will likely perform acceptably, but more complex options can be explored as needed. + + +```ocaml +(* data read from lower volumes at time of opening the store *) +type volume_meta = { + start_off : int63; + end_off : int63; + identifier : volume_identifier +} + +(* volume lookup *) +let find_volume (volumes : volume_meta list) offset = + let contains_offset v = + v.start_off <= offset && offset < v.end_off + in + List.find contains_offset volumes +``` + +Once we have a volume, we need to map `offset` to a physical offset in `volume.data`. Since all of the data file is covered by the mapping file, it looks something like: + +```ocaml +(* Lookup using volume.mapping *) +let poff = Mapping.poff_from_off mapping offset +``` + +Now that we have a physical offset in `volume.data`, we can proceed as normal to read/decode the key. **Note**: if a `poff` cannot be determined, for whatever reason, an exception or error will be raised at this point. + +**Other lookup strategies** + +We have also discussed adding an index to each volume that maps from hash to offset or adding a global index that maps from hash to volume. To reduce complexity of the GC process and data synchronization, these are excluded from the current design. + +Another reason for choosing offsets as the basis of looking up volumes is that `irmin-pack` already routes internally based on offsets. Therefore, using offsets to find volumes fits this current architecture with a minimal amount of change. + +### Reading commit data within a volume + +Once we have the commit key read correctly from a volume, we would like to continue reading its data from this volume without needing to do another pass of lookups. + +This context can be remembered by storing `volume_identifier` in the commit key that is decoded. + +```ocaml +type key = Direct of { + hash : 'hash; + offset : int63; + length : int; + volume : volume_identifier option; +} +``` + +This volume information can then be set for keys decoded in the commit data, namely the parent commit keys and the node key. This volume information would then also be set when decoding children nodes. In this way, the volume information is propagated down the tree of data as it is read and decoded. + +**Dangling parent commits** + +The exception to this propagation is dangling parent commit keys. These keys are created as a part of the GC process when constructing the prefix, so are present in the volume, but they need to be read from the prior volume. Volume information is not added to these so that they are read from the correct volume. + +### Resource management + +Since the number of volumes could be large, we do not plan to open all volumes and their files when opening the store since that could present an issue of too many file descriptors open. The current plan is to open volume files when needed and to close them after they are used. The lifecycle of volumes and their file descriptors could be managed by a simple cache. This is an area to be determined during implementation. + +### Performance analysis + +The updates to the data reading process adds a few steps when compared to the current way data is read in unlimited history stores. Currently, all data can be read from the single suffix file using global offsets. The addtion of the lower layer, volumes, and the self-contained upper layer, add several steps, as outlined above. + +Reading from the new self-contained upper layer is expected to perform similarly to current limited history stores, which should be an improvement for unlimited history stores due to improvements to data locality. + +The performance of reading from a volume should not come with any surprises. It is simple arithmetic to discover offsets, and the performance of the mapping file technique has been acceptable so far. + +When reading from the lower layer, there are spots that could add too much overhead: + +1. Opening files that have been closed because of file descriptor management +1. Mapping an offset to a volume if the number of volumes is large + +The primary way to address the first issue is to not close file descriptors. We can simply leave some number of recently accessed volumes open through an LRU mechanism. However, we do not know the access patterns of this older data, so this might not help that much if volumes are not accessed in a way the utilizes an LRU effectively. + +Another way to mitigate the first issue, which is included in the design, is to decrease the number of files that need to be opened to read from a volume. If desired, the control file data can be stored in-memory on store open and never opened again. The mapping file can likewise be `mmap`ed on open and then its file descriptor closed (the overhead of leaving all volume mappings `mmap`ed needs consideration). That leaves only the data file (`volume.data`) that would need to be re-opened. The overhead of a single file open is the best we can have if we need to manage file descriptors. + +For the second issue, the overhead of mapping offset to volume comes mostly down to the data structure used for doing this lookup. As proposed, we can iterate over a list to find the volume that corresponds to a particular global offset in $O(n)$ time, but we can switch to a process/data structure that gives $O(\log n)$ time, if needed. + + +### Handling data races for volumes + +`irmin-pack` supports single-writer, multi-reader concurrency. This means it is only supported to have one read-write instance for a store at any given time. There can be as many read-only instances as desired. + +**Writes** + +Only the read-write instance can perform write operations for volumes. More precisely, only the GC worker process can write data to files of a volume, but the main process of the read-write instance is allowed to rename the volume's control file. Since only one GC process is allowed to run at a time, there are no data races when writing data to a volume. Renaming the volume's control file only happens after a GC is finished or on node restart, so it cannot interfere with a running GC's writes. + +**Reads** + +A control file is used as a mechanism to update readers of new data, in both the appendable volume and the upper layer. + +When the appendable volume's control file is renamed from `volume.gen.control` to `volume.control`, readers see the new end bounds of a volume at the last readable offset of `end_offset`, and the mapping file is extended to contain all entries to the new `mapping_end_poff`. Until this happens, readers read the data as it was before GC. + +The control file of the volume is renamed after the control file of the upper layer is written to maintain consistency between upper and lower layers. This ordering allows for consistency recovery during crashes, and maintains the authority of the upper's control file in coordinating the overall store. + + +## Handling failure scenarios + +See previous section on the updated GC process for a discussion on handling failures. + +## Benchmarking + +The main areas of benchmarking: + +- time added to GC process (recognizing it is dependent on performance characteristics of the lower layer's storage) +- memory usage deltas +- disk usage deltas +- reading from recent history: current unlimited history store vs new unlimited history store with upper layer +- reading from archived history: current vs new + +## Security considerations + +Since these changes do not touch the core data encoding/decoding properties, it does not appear that the changes will affect the security of `irmin-pack` from a data payload perspective. + +## Other features + +### Sharing volumes between nodes + +The possibility of interchanging volumes between nodes (for instance, in the situation of data corruption) has been discussed. However, the nature of `irmin-pack`'s offset-based addressing makes this not automatically possible since offsets can be different across nodes. + +The current design works for a single authoring node, but we have discussed and can imagine ways to export and import volumes that would make them interchangeable. For now, we are postponing a design specifically for this until there is a concrete use case / need. + +The addition of `last_commit_off` to the volume control file is looking ahead to needing a way to index the commits that are inside of a volume. + +### Removing orphaned commits + +As mentioned in the section on the updated GC process, orphaned commits can be removed through a traversal of suffix data that is to be moved to the appendable volume. + +The design supports these commits being removed or not being removed. The store will even work with a mixture of volumes that do or do not have them removed. This is a useful property, but it is also needed for store migration to work correctly. + +The implementation steps are: + +1. Implement without removing orphaned commits +1. Add removal of orphaned commits after stabilization of core features diff --git a/vendors/irmin/doc/irmin-pack/dune b/vendors/irmin/doc/irmin-pack/dune new file mode 100644 index 000000000000..4ad7c453cb66 --- /dev/null +++ b/vendors/irmin/doc/irmin-pack/dune @@ -0,0 +1,3 @@ +(documentation + (package irmin-pack) + (mld_files index)) diff --git a/vendors/irmin/doc/irmin-pack/index.mld b/vendors/irmin/doc/irmin-pack/index.mld new file mode 100644 index 000000000000..3bef53795021 --- /dev/null +++ b/vendors/irmin/doc/irmin-pack/index.mld @@ -0,0 +1,19 @@ +{0 irmin-pack} + +The [irmin-pack] package provides a space-optimized, on-disk backend inspired by {{:https://git-scm.com/book/en/v2/Git-Internals-Packfiles} Git Packfiles}. + +[irmin-pack] is designed and developed for a specific use-case and requires more in-depth backend configuration from applications. It offers additional functionality through extensions to the core Irmin API, but users interested in a more general Irmin backend with simpler configuration are recommended to use other backend such as {!Irmin_fs} or {!Irmin_git}. + +See [examples/irmin-pack] for examples of how to configure and use some of the additional functionality. + +The entry point of this library is the module {!module:Irmin_pack}. + +{1 Implementations} + +{2 [irmin-pack.mem]} + +The entry point of this library is the module {!module:Irmin_pack_mem}. + +{2 [irmin-pack.unix]} + +The entry point of this library is the module {!module:Irmin_pack_unix}. \ No newline at end of file diff --git a/vendors/irmin/doc/irmin/dune b/vendors/irmin/doc/irmin/dune new file mode 100644 index 000000000000..bf130ddf9506 --- /dev/null +++ b/vendors/irmin/doc/irmin/dune @@ -0,0 +1,3 @@ +(documentation + (package irmin) + (mld_files index)) diff --git a/vendors/irmin/doc/irmin/index.mld b/vendors/irmin/doc/irmin/index.mld new file mode 100644 index 000000000000..03273c220b12 --- /dev/null +++ b/vendors/irmin/doc/irmin/index.mld @@ -0,0 +1,32 @@ +{0 Irmin} + +[Irmin] is a distributed database built on the same principles as {{:https://git-scm.com} Git}. It can be used as an OCaml library that provides persistent stores with built-in snapshot, branching and reverting mechanisms. + +{e Release %%VERSION%% - %%HOMEPAGE%%} + +{1 Irmin API} + +The [irmin] package defines the public API of [Irmin]. The entry point of the library is the module {!Irmin}. + +{1 Backends} + +Irmin is designed to use a large variety of backends. Various backends are provided: + +- {!module:Irmin_mem}: An in-memory store provided in the [irmin] package (this package). +- {!Irmin_git}: A backend that exposes a bi-directional bridge to a Git repository proivded by the [irmin-git] package. +- {!Irmin_pack}: A space-optimiezed, on-disk store inspired by {{:https://git-scm.com/book/en/v2/Git-Internals-Packfiles} Git Packfiles} is provided in the [irmin-pack] package. +- {!Irmin_mirage}: A {{:https://mirage.io/} MirageOS} compatible store is provided in the [irmin-mirage] package. + +{1 Helpers and Internal Utilities} + +{2 irmin.unix} + +The [irmin.unix] package provides [Irmin] related utilities for Unix applications. + +The entry point of this library is the module {!Irmin_unix}. + +{2 irmin.data} + +This package contains data structure implementations used in the implementation of Irmin. It is exposed only for internal use, and does not provide a stable API. + +The entry point of this library is the module {!Irmin_data}. \ No newline at end of file diff --git a/vendors/irmin/dune b/vendors/irmin/dune new file mode 100644 index 000000000000..fe7d302bca28 --- /dev/null +++ b/vendors/irmin/dune @@ -0,0 +1,6 @@ +(vendored_dirs vendors) + +(mdx + (files README.md) + (package irmin-cli) + (packages irmin-cli)) diff --git a/vendors/irmin/dune-project b/vendors/irmin/dune-project new file mode 100644 index 000000000000..f9600ff68f48 --- /dev/null +++ b/vendors/irmin/dune-project @@ -0,0 +1,4 @@ +(lang dune 2.9) +(name irmin) +(cram enable) +(using mdx 0.1) diff --git a/vendors/irmin/examples/config.ml b/vendors/irmin/examples/config.ml new file mode 100644 index 000000000000..6f05a73d31da --- /dev/null +++ b/vendors/irmin/examples/config.ml @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let root = "/tmp/irmin/test" + +let init () = + let _ = Sys.command (Printf.sprintf "rm -rf %s" root) in + let _ = Sys.command (Printf.sprintf "mkdir -p %s" root) in + Irmin.Backend.Watch.set_listen_dir_hook Irmin_watcher.hook diff --git a/vendors/irmin/examples/custom_graphql.ml b/vendors/irmin/examples/custom_graphql.ml new file mode 100644 index 000000000000..244cafd51f1b --- /dev/null +++ b/vendors/irmin/examples/custom_graphql.ml @@ -0,0 +1,122 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* Example of using irmin-graphql with custom types *) + +open Lwt.Syntax + +module Car = struct + type color = Black | White | Other of string [@@deriving irmin] + + type t = { + license : string; + year : int32; + make_and_model : string * string; + color : color; + owner : string; + } + [@@deriving irmin] + + let merge = Irmin.Merge.(option (idempotent t)) +end + +module Store = Irmin_git_unix.Mem.KV (Car) + +module Custom_types = struct + module Defaults = Irmin_graphql.Server.Default_types (Store) + module Path = Defaults.Path + module Metadata = Defaults.Metadata + module Hash = Defaults.Hash + module Branch = Defaults.Branch + module Commit_key = Defaults.Commit_key + module Contents_key = Defaults.Contents_key + module Node_key = Defaults.Node_key + + module Contents = struct + open Graphql_lwt + + let color_values = + Schema. + [ + enum_value "BLACK" ~value:Car.Black; + enum_value "WHITE" ~value:Car.White; + ] + + let schema_typ = + Schema.( + obj "Car" + ~fields: + [ + field "license" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ car -> car.Car.license); + field "year" ~typ:(non_null int) ~args:[] ~resolve:(fun _ car -> + Int32.to_int car.Car.year); + field "make" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ car -> fst car.Car.make_and_model); + field "model" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ car -> snd car.Car.make_and_model); + field "color" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ car -> car.Car.license); + field "owner" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ car -> car.Car.owner); + ]) + + let color = Schema.Arg.enum "Color" ~values:color_values + + let arg_typ = + Schema.Arg.( + obj "CarInput" + ~fields: + [ + arg "license" ~typ:(non_null string); + arg "year" ~typ:(non_null int); + arg "make" ~typ:(non_null string); + arg "model" ~typ:(non_null string); + arg "color" ~typ:(non_null color); + arg "owner" ~typ:(non_null string); + ] + ~coerce:(fun license year make model color owner -> + { + Car.license; + year = Int32.of_int year; + make_and_model = (make, model); + color; + owner; + })) + end +end + +module Remote = struct + let remote = Some Store.remote +end + +module Server = + Irmin_graphql_unix.Server.Make_ext (Store) (Remote) (Custom_types) + +let main () = + Config.init (); + let config = Irmin_git.config Config.root in + let* repo = Store.Repo.v config in + let server = Server.v repo in + let src = "localhost" in + let port = 9876 in + let* ctx = Conduit_lwt_unix.init ~src () in + let ctx = Cohttp_lwt_unix.Net.init ~ctx () in + let on_exn exn = Printf.printf "on_exn: %s" (Printexc.to_string exn) in + Printf.printf "Visit GraphiQL @ http://%s:%d/graphql\n%!" src port; + Cohttp_lwt_unix.Server.create ~on_exn ~ctx ~mode:(`TCP (`Port port)) server + +let () = Lwt_main.run (main ()) diff --git a/vendors/irmin/examples/custom_merge.ml b/vendors/irmin/examples/custom_merge.ml new file mode 100644 index 000000000000..af70d47ae7d4 --- /dev/null +++ b/vendors/irmin/examples/custom_merge.ml @@ -0,0 +1,165 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) +open Lwt.Syntax +open Astring + +let what = + "This example demonstrates custom merges on Irmin datastructures.\n\n\ + It models log files as a sequence of lines, ordered by timestamps.\n\n\ + The log files of `branch 1` and `branch 2` are merged by using the following \n\ + strategy:\n\ + \ - find the log file corresponding the lowest common ancestor: `lca`\n\ + \ - remove the prefix `lca` from `branch 1`; this gives `l1`;\n\ + \ - remove the prefix `lca` from `branch 2`; this gives `l2`;\n\ + \ - interleave `l1` and `l2` by ordering the timestamps; This gives `l3`;\n\ + \ - concatenate `lca` and `l3`; This gives the final result." + +let time = ref 0L +let failure fmt = Fmt.kstr failwith fmt + +(* A log entry *) +module Entry : sig + include Irmin.Type.S + + val v : string -> t + val timestamp : t -> int64 +end = struct + type t = { timestamp : int64; message : string } [@@deriving irmin] + + let compare x y = Int64.compare x.timestamp y.timestamp + + let v message = + time := Int64.add 1L !time; + { timestamp = !time; message } + + let timestamp t = t.timestamp + let pp ppf { timestamp; message } = Fmt.pf ppf "%04Ld: %s" timestamp message + + let of_string str = + match String.cut ~sep:": " str with + | None -> Error (`Msg ("invalid entry: " ^ str)) + | Some (x, message) -> ( + try Ok { timestamp = Int64.of_string x; message } + with Failure e -> Error (`Msg e)) + + let t = Irmin.Type.like ~pp ~of_string ~compare t +end + +(* A log file *) +module Log : sig + include Irmin.Contents.S + + val add : t -> Entry.t -> t + val empty : t +end = struct + type t = Entry.t list [@@deriving irmin] + + let empty = [] + let pp_entry = Irmin.Type.pp Entry.t + let lines ppf l = List.iter (Fmt.pf ppf "%a\n" pp_entry) (List.rev l) + + let of_string str = + let lines = String.cuts ~empty:false ~sep:"\n" str in + try + List.fold_left + (fun acc l -> + match Irmin.Type.of_string Entry.t l with + | Ok x -> x :: acc + | Error (`Msg e) -> failwith e) + [] lines + |> fun l -> Ok l + with Failure e -> Error (`Msg e) + + let t = Irmin.Type.like ~pp:lines ~of_string t + let timestamp = function [] -> 0L | e :: _ -> Entry.timestamp e + + let newer_than timestamp file = + let rec aux acc = function + | [] -> List.rev acc + | h :: _ when Entry.timestamp h <= timestamp -> List.rev acc + | h :: t -> aux (h :: acc) t + in + aux [] file + + let compare_entry = Irmin.Type.(unstage (compare Entry.t)) + + let merge ~old t1 t2 = + let open Irmin.Merge.Infix in + old () >>=* fun old -> + let old = match old with None -> [] | Some o -> o in + let ts = timestamp old in + let t1 = newer_than ts t1 in + let t2 = newer_than ts t2 in + let t3 = List.sort compare_entry (List.rev_append t1 t2) in + Irmin.Merge.ok (List.rev_append t3 old) + + let merge = Irmin.Merge.(option (v t merge)) + let add t e = e :: t +end + +(* Build an Irmin store containing log files. *) +module Store = Irmin_git_unix.FS.KV (Log) + +(* Set-up the local configuration of the Git repository. *) +let config = Irmin_git.config ~bare:true Config.root + +(* Convenient alias for the info function for commit messages *) +let info = Irmin_git_unix.info +let log_file = [ "local"; "debug" ] + +let all_logs t = + let+ logs = Store.find t log_file in + match logs with None -> Log.empty | Some l -> l + +(** Persist a new entry in the log. Pretty inefficient as it reads/writes the + whole file every time. *) +let log t fmt = + Printf.ksprintf + (fun message -> + let* logs = all_logs t in + let logs = Log.add logs (Entry.v message) in + Store.set_exn t ~info:(info "Adding a new entry") log_file logs) + fmt + +let print_logs name t = + let+ logs = all_logs t in + Fmt.pr "-----------\n%s:\n-----------\n%a%!" name (Irmin.Type.pp Log.t) logs + +let main () = + Config.init (); + let* repo = Store.Repo.v config in + let* t = Store.main repo in + + (* populate the log with some random messages *) + let* () = + Lwt_list.iter_s + (fun msg -> log t "This is my %s " msg) + [ "first"; "second"; "third" ] + in + Printf.printf "%s\n\n" what; + let* () = print_logs "lca" t in + let* x = Store.clone ~src:t ~dst:"test" in + let* () = log x "Adding new stuff to x" in + let* () = log x "Adding more stuff to x" in + let* () = log x "More. Stuff. To x." in + let* () = print_logs "branch 1" x in + let* () = log t "I can add stuff on t also" in + let* () = log t "Yes. On t!" in + let* () = print_logs "branch 2" t in + let* r = Store.merge_into ~info:(info "Merging x into t") x ~into:t in + match r with Ok () -> print_logs "merge" t | Error _ -> failwith "conflict!" + +let () = Lwt_main.run (main ()) diff --git a/vendors/irmin/examples/custom_storage.ml b/vendors/irmin/examples/custom_storage.ml new file mode 100644 index 000000000000..d749e0679cae --- /dev/null +++ b/vendors/irmin/examples/custom_storage.ml @@ -0,0 +1,101 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Syntax + +(** Create a configuration module for our storage. Here we demonstrate a simple + configuration for setting the initial size of the hash table. *) + +module Hashtbl_config = struct + module Conf = Irmin.Backend.Conf + + let spec = Conf.Spec.v "hashtbl" + let init_size = Conf.key ~spec "init-size" Irmin.Type.int 8 + let empty = Conf.empty spec +end + +(** Create a {!Irmin.Storage.Make} functor for our hash table storage. *) + +module Hashtbl_storage : Irmin.Storage.Make = +functor + (Key : Irmin.Type.S) + (Value : Irmin.Type.S) + -> + struct + module Tbl = Hashtbl.Make (struct + type t = Key.t + + let equal a b = Irmin.Type.(unstage (equal Key.t)) a b + let hash k = Irmin.Type.(unstage (short_hash Key.t)) k + end) + + (** Types *) + + type t = { t : Value.t Tbl.t; l : Mutex.t } + type key = Key.t + type value = Value.t + + (** Initialisation / Closing *) + + let v config = + let init_size = Irmin.Backend.Conf.get config Hashtbl_config.init_size in + { t = Tbl.create init_size; l = Mutex.create () } |> Lwt.return + + let close _t = Lwt.return_unit + + (** Operations *) + + let set { t; _ } key value = Tbl.replace t key value |> Lwt.return + let mem { t; _ } key = Tbl.mem t key |> Lwt.return + let find { t; _ } key = Tbl.find_opt t key |> Lwt.return + let keys { t; _ } = Tbl.to_seq_keys t |> List.of_seq |> Lwt.return + let remove { t; _ } key = Tbl.remove t key |> Lwt.return + let clear { t; _ } = Tbl.clear t |> Lwt.return + + let batch t f = + Mutex.lock t.l; + let+ x = + Lwt.catch + (fun () -> f t) + (fun exn -> + Mutex.unlock t.l; + raise exn) + in + Mutex.unlock t.l; + x + end + +(** Create an Irmin store using our hash table with a specified hash type and + content type. Irmin will create one {!Irmin.Content_addressable} store for + storing data (keys, content, commits) and one {!Irmin.Atomic_write} store + for storing branches. Each store will have its own hash table. *) + +module Store = + Irmin.Of_storage (Hashtbl_storage) (Irmin.Hash.SHA256) (Irmin.Contents.String) + +let config ?(config = Hashtbl_config.empty) ?(init_size = 42) () = + Irmin.Backend.Conf.add config Hashtbl_config.init_size init_size + +let main () = + let* repo = Store.Repo.v (config ()) in + let* main = Store.main repo in + let info () = Store.Info.v 0L in + let key = "Hello" in + let* () = Store.set_exn main [ key ] ~info "world!" in + let* v = Store.get main [ key ] in + Printf.printf "%s, %s" key v |> Lwt.return + +let () = Lwt_main.run @@ main () diff --git a/vendors/irmin/examples/deploy.ml b/vendors/irmin/examples/deploy.ml new file mode 100644 index 000000000000..384db9c071e5 --- /dev/null +++ b/vendors/irmin/examples/deploy.ml @@ -0,0 +1,142 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) +open Lwt.Syntax +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) + +let config = + let head = Git.Reference.v "refs/heads/upstream" in + Irmin_git.config ~head ~bare:false Config.root + +let info ~user message () = + let date = Int64.of_float (Unix.gettimeofday ()) in + let author = user in + Store.Info.v ~author ~message date + +(* 1. Cloning the gold image. *) +let provision repo = + Config.init (); + let provision = info ~user:"Automatic VM provisioning" in + let* t = Store.of_branch repo "upstream" in + let v = + Store.Tree.singleton [ "etc"; "manpath" ] + "/usr/share/man\n/usr/local/share/man" + in + let* v = + Store.Tree.add v [ "bin"; "sh" ] + "�����XpN ������� H__PAGEZERO(__TEXT__text__TEXT [...]" + in + Store.set_tree_exn t ~info:(provision "Cloning Ubuntu 14.04 Gold Image.") [] v + +(* 2. VM configuration. *) +let sysadmin = info ~user:"Bob the sysadmin" + +let configure repo = + let* t = Store.of_branch repo "upstream" in + let* () = Lwt_unix.sleep 2. in + let* t = Store.clone ~src:t ~dst:"dev" in + let* () = Lwt_unix.sleep 2. in + let* () = + Store.set_exn t + ~info:(sysadmin "DNS configuration") + [ "etc"; "resolv.conf" ] "domain mydomain.com\nnameserver 128.221.130.23" + in + let* () = Lwt_unix.sleep 2. in + let+ _ = Store.clone ~src:t ~dst:"prod" in + () + +let attack repo = + let info = info ~user:"Remote connection from 132.443.12.444" in + (* 3. Attacker. *) + let* t = Store.of_branch repo "prod" in + let* () = Lwt_unix.sleep 2. in + let* () = + Store.set_exn t + ~info:(info "$ vim /etc/resolv.conf") + [ "etc"; "resolv.conf" ] "domain mydomain.com\nnameserver 12.221.130.23" + in + let* () = Lwt_unix.sleep 2. in + Store.set_exn t + ~info:(info "$ gcc -c /tmp/sh.c -o /bin/sh") + [ "bin"; "sh" ] "�����XpNx ������� H__PAGEZERO(__TEXT__text__TEXT [...]" + +let revert repo = + let* prod = Store.of_branch repo "prod" in + let* dev = Store.of_branch repo "dev" in + let* h1 = Store.Head.get prod in + let* h2 = Store.Head.get dev in + if h1 <> h2 then ( + Printf.printf + "WARNING: the filesystem is different in dev and prod, intrusion detected!\n\ + Reverting the production system to the dev environment.\n\ + %!"; + let* () = Lwt_unix.sleep 2. in + Store.Head.set prod h2) + else Lwt.return_unit + +let () = + let cmd = Sys.argv.(0) in + let help () = + Printf.eprintf + "This demo models a simple deployment scenario in three phases:\n\n\ + \ - [%s provision] first a VM is provisioned;\n\ + \ - [%s configure] then a sysadmin connects to the machine \n\ + \ and install some software packages;\n\ + \ - [%s attack] an attacker connects to the machine and \n\ + \ injects random code.\n\ + \ - [%s revert] the sysadmin revert the VM in a consistent state.\n\n\ + Run `irmin init -d --root=%s` and Connect your browser \n\ + to http://127.0.0.1:8080/graph to see the system state evolving in \n\ + real-time during the different phases.\n\n\ + Using a VCS-style filesystem allows file modifications to be tracked, \ + with \n\ + user origin and dates. It also supports quickly reverting to a \ + consistent \n\ + state when needed.\n" + cmd cmd cmd cmd Config.root + in + if Array.length Sys.argv <> 2 then help () + else + match Sys.argv.(1) with + | "provision" -> + Lwt_main.run + (let* repo = Store.Repo.v config in + provision repo); + Printf.printf + "The VM is now provisioned. Run `%s configure` to simulate a sysadmin \n\ + configuration.\n" + cmd + | "configure" -> + Lwt_main.run + (let* repo = Store.Repo.v config in + configure repo); + Printf.printf + "The VM is now configured. Run `%s attack` to simulate an attack by \ + an \n\ + intruder.\n" + cmd + | "attack" -> + Lwt_main.run + (let* repo = Store.Repo.v config in + attack repo); + Printf.printf + "The VM has been attacked. Run `%s revert` to revert the VM state to \ + a safe one.\n" + cmd + | "revert" -> + Lwt_main.run + (let* repo = Store.Repo.v config in + revert repo) + | _ -> help () diff --git a/vendors/irmin/examples/dune b/vendors/irmin/examples/dune new file mode 100644 index 000000000000..59dc3ea3baf7 --- /dev/null +++ b/vendors/irmin/examples/dune @@ -0,0 +1,62 @@ +(executables + (names + readme + trees + sync + process + deploy + irmin_git_store + custom_merge + push + custom_graphql + custom_storage + fold) + (libraries + astring + cohttp + fmt + irmin.unix + irmin-git.unix + irmin-graphql.unix + irmin-pack.unix + irmin-watcher + lwt + lwt.unix) + (preprocess + (pps ppx_irmin))) + +(alias + (name examples) + (deps + readme.exe + trees.exe + sync.exe + process.exe + deploy.exe + push.exe + irmin_git_store.exe + custom_merge.exe + custom_graphql.exe + fold.exe + gc.exe + custom_storage.exe)) + +(alias + (name runtest) + (package irmin-cli) + (deps + readme.exe + trees.exe + sync.exe + process.exe + deploy.exe + push.exe + irmin_git_store.exe + custom_merge.exe + fold.exe)) + +(mdx + (files merkle_proofs.md) + ; (preludes merkle_proofs_prelude.ml) + (package irmin-cli) + (packages irmin-cli)) diff --git a/vendors/irmin/examples/fold.ml b/vendors/irmin/examples/fold.ml new file mode 100644 index 000000000000..152c98544512 --- /dev/null +++ b/vendors/irmin/examples/fold.ml @@ -0,0 +1,100 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* example of using tree fold *) + +open Lwt.Syntax +module Store = Irmin_mem.KV.Make (Irmin.Contents.String) +module Tree = Store.Tree + +let config = Irmin_mem.config () + +let info = + let counter = ref 0L in + let inc () = + let c = !counter in + counter := Int64.add c 1L; + c + in + fun message () -> Store.Info.v ~author:"fold.exe" ~message (inc ()) + +module Folder : sig + (* Not accumulating anything so use unit as accumulator type *) + val pre : (unit, Store.step list) Tree.folder + val post : (unit, Store.step list) Tree.folder + val node : (unit, Store.node) Tree.folder + val contents : (unit, Store.contents) Tree.folder + val tree : (unit, Store.tree) Tree.folder +end = struct + let print_path newline path _ _ = + let format : ('a, Format.formatter, unit) format = + "Visit [%s]" ^^ if newline then "\n" else "" + in + Fmt.(pf stdout format (String.concat ";" path)) |> Lwt.return + + let pre = print_path true + let post = print_path true + let node = print_path true + + let contents path c acc = + let* () = print_path false path c acc in + Fmt.(pf stdout " = '%s'\n" c) |> Lwt.return + + let tree path t acc = + let* () = print_path false path t acc in + let* k = Tree.kind t [] in + match k with + | Some k' -> + (match k' with + | `Node -> Fmt.(string stdout ", with `Node kind\n") + | `Contents -> Fmt.(string stdout ", with `Contents kind\n")) + |> Lwt.return + | None -> failwith "no kind" +end + +let main = + let ps name = Fmt.(pf stdout "\n%s\n" name) in + ps "Demo of how tree folders visit nodes."; + let* repo = Store.Repo.v config in + let* main_b = Store.main repo in + let* () = Store.set_exn ~info:(info "add c1") main_b [ "c1" ] "c1" in + let* () = Store.set_exn ~info:(info "add c2") main_b [ "c2" ] "c2" in + let* () = + Store.set_exn ~info:(info "add n1/c1") main_b [ "n1"; "c1" ] "n1/c1" + in + let* () = + Store.set_exn ~info:(info "add n1/n1/c1") main_b [ "n1"; "n1"; "c1" ] + "n1/n1/c1" + in + let* () = + Store.set_exn ~info:(info "add n2/c1") main_b [ "n2"; "c1" ] "n2/c1" + in + let* t = Store.tree main_b in + (* let order = `Random (Random.State.make_self_init ()) in *) + let order = `Sorted in + ps "pre folder: preorder traversal of `Node kinds"; + let* () = Tree.fold ~order ~pre:Folder.pre t () in + ps "post folder: postorder traversal of `Node kinds"; + let* () = Tree.fold ~order ~post:Folder.post t () in + ps "node folder: visit all `Node kinds"; + let* () = Tree.fold ~order ~node:Folder.node t () in + ps "contents folder: visit all `Contents kinds"; + let* () = Tree.fold ~order ~contents:Folder.contents t () in + ps "tree folder: visit both `Node and `Contents kinds"; + let* () = Tree.fold ~order ~tree:Folder.tree t () in + Lwt.return_unit + +let () = Lwt_main.run main diff --git a/vendors/irmin/examples/irmin-pack/dune b/vendors/irmin/examples/irmin-pack/dune new file mode 100644 index 000000000000..b054502f197f --- /dev/null +++ b/vendors/irmin/examples/irmin-pack/dune @@ -0,0 +1,3 @@ +(executables + (names gc kv) + (libraries irmin irmin.unix irmin-pack.unix logs)) diff --git a/vendors/irmin/examples/irmin-pack/gc.ml b/vendors/irmin/examples/irmin-pack/gc.ml new file mode 100644 index 000000000000..a5bafe4b8335 --- /dev/null +++ b/vendors/irmin/examples/irmin-pack/gc.ml @@ -0,0 +1,204 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Syntax + +module Schema = Irmin.Schema.KV (Irmin.Contents.String) +(** Make schema *) + +(** Define configuration parameters for pack store *) +module Store_conf : Irmin_pack.Conf.S = struct + (** The branching factor of the inode tree. 32 performs well *) + let entries = 32 + + (** Set this to 0 to only use inode hashing (this parameter exists for + particular backwards compatibility applications with Irmin 1.0 data) *) + let stable_hash = 0 + + (** GC only supports minimal indexing strategy so [contents_length_header] + must be [Some `Varint]. [None] requires an always indexing strategy *) + let contents_length_header = Some `Varint + + (** This is the recommended sorting algorithm for new stores *) + let inode_child_order = `Hash_bits + + (** Throw an error (or not) if an empty tree is persisted *) + let forbid_empty_dir_persistence = true +end + +(** Make pack store *) + +module Maker = Irmin_pack_unix.Maker (Store_conf) +module Store = Maker.Make (Schema) + +(** Define configuration for repo *) +module Repo_config = struct + (** The number of entries to cache in the index log (an in-memory and on-disk + data store). Default is [2_500_000] *) + let index_log_size = 2_500_000 + + (** Choose what to do when the index log is full and a merge is in-progress. + + - [Block_writes] (the default) will block writing until the merge is + complete + - [Overcommit_memory] will increase the in-memory cache indefinitely *) + let merge_throttle = `Block_writes + + (** Must use minimal indexing strategy to use GC *) + let indexing_strategy = Irmin_pack.Indexing_strategy.minimal + + (** Buffer size that triggers auto flushing to disk *) + let dict_auto_flush_threshold = 1_000_000 + + (** Buffer size that triggers auto flushing to disk *) + let suffix_auto_flush_threshold = 1_000_000 + + (** Location on disk to save the repository + + Note: irmin-pack will not create the entire path, only the final directory *) + let root = "./irmin-pack-example" + + (** See {!Irmin_pack.Conf} for more keys that can be used when initialising + the repository config *) + + (** Create new repository every time. Use [false] (the defalut) to use + existing repository. *) + let fresh = true + + (** Create config for our repository *) + let config = + Irmin_pack.config ~fresh ~index_log_size ~merge_throttle ~indexing_strategy + ~dict_auto_flush_threshold ~suffix_auto_flush_threshold root + + (** We can add an optional lower layer to our repository. Data discarded by + the GC will be stored there and still be accessible instead of being + deleted. *) + let lower_root = Some "./irmin-pack-example-lower" + + (** Create a copy of the previous configuration, now with a lower layer *) + let config_with_lower = + Irmin_pack.config ~fresh ~index_log_size ~merge_throttle ~indexing_strategy + ~dict_auto_flush_threshold ~suffix_auto_flush_threshold ~lower_root root +end + +(** Utility for creating commit info *) +let info fmt key value = Irmin_unix.info ~author:"pack example" fmt key value () + +(** Utility for computing the size of a directory *) +let rec megabytes_of_path path = + if Sys.is_directory path then + Array.fold_left + (fun acc p -> megabytes_of_path (Filename.concat path p) +. acc) + 0. (Sys.readdir path) + else float_of_int Unix.((stat path).st_size) /. 1e6 + +(** A utility module for tracking the latest commit and the commit we will want + to run GC for. *) +module Tracker = struct + type t = { + mutable latest_commit : Store.commit option; + mutable next_gc_commit : Store.commit option; + } + + let v () = { latest_commit = None; next_gc_commit = None } + let update_latest_commit t commit = t.latest_commit <- Some commit + + let latest_parents t = + match t.latest_commit with None -> [] | Some c -> Store.Commit.parents c + + let latest_tree t = + match t.latest_commit with + | None -> Store.Tree.empty () + | Some c -> Store.Commit.tree c + + let mark_next_gc_commit t = t.next_gc_commit <- t.latest_commit +end + +(** Demonstrate running GC on a previous commit aligned to the end of a chunk + for ideal GC space reclamation. *) +let run_gc config repo tracker = + let* () = + match Tracker.(tracker.next_gc_commit) with + | None -> Lwt.return_unit + | Some commit -> ( + let finished = function + | Ok stats -> + let duration = + Irmin_pack_unix.Stats.Latest_gc.total_duration stats + in + let finalise_duration = + Irmin_pack_unix.Stats.Latest_gc.finalise_duration stats + in + Printf.printf + "GC finished in %.4fs. Finalise took %.4fs. Size of repo: \ + %.2fMB." + duration finalise_duration + (megabytes_of_path @@ Irmin_pack.Conf.root config); + (match Irmin_pack.Conf.lower_root config with + | None -> Printf.printf "\n%!" + | Some lower -> + Printf.printf " Size of lower layer: %.2fMB.\n" + (megabytes_of_path lower)); + Lwt.return_unit + | Error (`Msg err) -> print_endline err |> Lwt.return + in + (* Launch GC *) + let commit_key = Store.Commit.key commit in + let+ launched = Store.Gc.run ~finished repo commit_key in + match launched with + | Ok false -> () + | Ok true -> + Printf.printf "GC started. Size of repo: %.2fMB\n" + (megabytes_of_path @@ Irmin_pack.Conf.root config) + | Error (`Msg err) -> print_endline err) + in + (* Create new split and mark the latest commit to be the next GC commit. *) + let () = Store.split repo in + Tracker.mark_next_gc_commit tracker |> Lwt.return + +let run_experiment config = + let num_of_commits = 200_000 in + let gc_every = 1_000 in + let* repo = Store.Repo.v config in + let tracker = Tracker.v () in + (* Create commits *) + let* _ = + let rec loop i n = + let key = "hello" in + let value = Printf.sprintf "packfile%d" i in + let* tree = Store.Tree.add (Tracker.latest_tree tracker) [ key ] value in + let parents = Tracker.latest_parents tracker in + let* commit = + Store.Commit.v repo ~info:(info "add %s = %s" key value) ~parents tree + in + Tracker.update_latest_commit tracker commit; + let* _ = + if i mod gc_every = 0 then run_gc config repo tracker + else Lwt.return_unit + in + if i >= n then Lwt.return_unit else loop (i + 1) n + in + loop 1 num_of_commits + in + (* A GC may still be running. Wait for GC to finish before ending the process *) + let* _ = Store.Gc.wait repo in + Lwt.return_unit + +let () = + Printf.printf "== RUN 1: deleting discarded data ==\n"; + Lwt_main.run (run_experiment Repo_config.config); + Printf.printf "== RUN 2: archiving discarded data ==\n"; + Lwt_main.run (run_experiment Repo_config.config_with_lower) diff --git a/vendors/irmin/examples/irmin-pack/kv.ml b/vendors/irmin/examples/irmin-pack/kv.ml new file mode 100644 index 000000000000..f7fe378ecf81 --- /dev/null +++ b/vendors/irmin/examples/irmin-pack/kv.ml @@ -0,0 +1,108 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* A minimal example of instantiating a `irmin-pack.unix` key-value store. *) + +open Lwt +open Lwt.Syntax + +let src = + Logs.Src.create "irmin-pack.unix/examples/kv" + ~doc:"irmin-pack.unix/examples/kv" + +module Log = (val Logs.src_log src : Logs.LOG) + +(* Compile-time configurations passed to a functor. *) +module Conf = struct + let entries = 32 + let stable_hash = 256 + let contents_length_header = Some `Varint + let inode_child_order = `Seeded_hash + let forbid_empty_dir_persistence = true +end + +(* Run-time configurations passed when instantiating a repository. *) +module Repo_config = struct + (** The number of entries to cache in the index log (an in-memory and on-disk + data store). Default is [2_500_000] *) + let index_log_size = 2_500_000 + + (** Choose what to do when the index log is full and a merge is in-progress. + + - [Block_writes] (the default) will block writing until the merge is + complete + - [Overcommit_memory] will increase the in-memory cache indefinitely *) + let merge_throttle = `Block_writes + + (** Must use minimal indexing strategy to use GC *) + let indexing_strategy = Irmin_pack.Indexing_strategy.minimal + + (** Buffer size that triggers auto flushing to disk *) + let dict_auto_flush_threshold = 1_000_000 + + (** Buffer size that triggers auto flushing to disk *) + let suffix_auto_flush_threshold = 1_000_000 + + (** Location on disk to save the repository + + Note: irmin-pack will not create the entire path, only the final directory *) + let root = "./irmin-pack-example" + + (** See {!Irmin_pack.Conf} for more keys that can be used when initialising + the repository config *) + + (** Create new repository every time. Use [false] (the defalut) to use + existing repository. *) + let fresh = true + + (** Create config for our repository *) + let config = + Irmin_pack.config ~fresh ~index_log_size ~merge_throttle ~indexing_strategy + ~dict_auto_flush_threshold ~suffix_auto_flush_threshold root +end + +module StoreMaker = Irmin_pack_unix.KV (Conf) +module Store = StoreMaker.Make (Irmin.Contents.String) + +let main () = + (* Instantiate a repository *) + let* repo = Store.Repo.v Repo_config.config in + + (* Get the store from the main branch. *) + let* store = Store.main repo in + + (* Set a value. *) + let* () = + Store.set_exn + ~info:(fun () -> Store.Info.empty) + store [ "hello" ] "irmin-pack.unix!" + in + + (* Get the value *) + let* content = Store.get store [ "hello" ] in + + Log.app (fun m -> m "hello: %s" content); + + return () + +let setup_logs () = + Fmt_tty.setup_std_outputs (); + Logs.set_reporter (Logs_fmt.reporter ()); + Logs.(set_level @@ Some Debug) + +let () = + setup_logs (); + Lwt_main.run @@ main () diff --git a/vendors/irmin/examples/irmin_git_store.ml b/vendors/irmin/examples/irmin_git_store.ml new file mode 100644 index 000000000000..965042953452 --- /dev/null +++ b/vendors/irmin/examples/irmin_git_store.ml @@ -0,0 +1,65 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* Simple example of reading and writing in a Git repository *) + +open Lwt.Syntax + +let info = Irmin_git_unix.info + +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) + +let update t k v = + let msg = Fmt.str "Updating /%s" (String.concat "/" k) in + print_endline msg; + Store.set_exn t ~info:(info "%s" msg) k v + +let read_exn t k = + let msg = Fmt.str "Reading /%s" (String.concat "/" k) in + print_endline msg; + Store.get t k + +let main () = + Config.init (); + let config = Irmin_git.config ~bare:true Config.root in + let* repo = Store.Repo.v config in + let* t = Store.main repo in + let* () = update t [ "root"; "misc"; "1.txt" ] "Hello world!" in + let* () = update t [ "root"; "misc"; "2.txt" ] "Hi!" in + let* () = update t [ "root"; "misc"; "3.txt" ] "How are you ?" in + let* _ = read_exn t [ "root"; "misc"; "2.txt" ] in + let* x = Store.clone ~src:t ~dst:"test" in + print_endline "cloning ..."; + let* () = update t [ "root"; "misc"; "3.txt" ] "Hohoho" in + let* () = update x [ "root"; "misc"; "2.txt" ] "Cool!" in + let* r = Store.merge_into ~info:(info "t: Merge with 'x'") x ~into:t in + match r with + | Error _ -> failwith "conflict!" + | Ok () -> + print_endline "merging ..."; + let* _ = read_exn t [ "root"; "misc"; "2.txt" ] in + let+ _ = read_exn t [ "root"; "misc"; "3.txt" ] in + () + +let () = + Printf.printf + "This example creates a Git repository in %s and use it to read \n\ + and write data:\n" + Config.root; + let _ = Sys.command (Printf.sprintf "rm -rf %s" Config.root) in + Lwt_main.run (main ()); + Printf.printf "You can now run `cd %s && tig` to inspect the store.\n" + Config.root diff --git a/vendors/irmin/examples/merkle_proof_1.jpg b/vendors/irmin/examples/merkle_proof_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..672480ebfc5bd4644d8a2b954ef515414706f45f GIT binary patch literal 46268 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

J83tiKg{*p_U%PywLSmM>)!QO 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 z�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 a(>PpyHB5! +val repo : Store.repo = +``` + +Create a tree which contains the accounts and their balance for 3 customers: Ben, Bob and Eve. + +Instead of using `[ "eve" ]` as a path (which whould have been valid too), this example splits the names char by char. This is better in order to highlight how proofs work. + +```ocaml +# let tree = Lwt_main.run ( + let tree = Store.Tree.empty () in + let* tree = Store.Tree.add tree [ "b"; "e"; "n" ] 10 in + let* tree = Store.Tree.add tree [ "b"; "o"; "b" ] 20 in + let+ tree = Store.Tree.add tree [ "e"; "v"; "e" ] 30 in + tree + );; +val tree : Store.tree = +``` + +In order to produce a Merkle proof, Irmin requires that the tree on which the proof will be based is persisted inside a `repo`. The following code block does so. + +`tree_key` is a value that encodes where `tree` has been persisted inside the store's backend. + +```ocaml +# let tree_key = Lwt_main.run ( + (* [batch] exposes [repo] stores in read-write mode *) + let+ kinded_key = Store.Backend.Repo.batch repo + (fun rw_contents_store rw_node_store _rw_commit_store -> + Store.save_tree repo rw_contents_store rw_node_store tree) + in + (* As the root of [tree] is a node, refining the type is safe *) + match kinded_key with + | `Node key -> key + | `Contents _ -> assert false + );; +val tree_key : Store.node_key = +``` + +The bank is ready. `repo` contains the data, which was persisted on disk. `tree_key` acts as a pointer to the root of the accounts tree. + +Since this example only cares about account statements, there is no need to worry about modifying the account balances, this would be well expressed using Irmin's commit and branches abstraction, but this is out of the scope of this example. + +![The bank's data](./merkle_proof_1.jpg) + +### Producing Acccount Statements + +Let's produce an account statement for Eve. + +```ocaml +let visit_tree tree = + (* [tree] is shallow. Let's only load the parts we are interested in *) + let+ (_ : int option) = Store.Tree.find tree [ "e"; "v"; "e" ] in + (Store.Tree.empty (), `Success) + +let proof, `Success = Lwt_main.run ( + Store.Tree.produce_proof repo (`Node tree_key) visit_tree) + +let pp_merkle_proof = Irmin.Type.pp Store.Tree.Proof.tree_t +``` + +```ocaml +# let () = Fmt.pr "proof: %a\n" pp_merkle_proof (Store.Tree.Proof.state proof);; +proof: {"Node":[["b",{"Blinded_node":"584ba234368730ce6cea56d93433a7a777cad2a0"}],["e",{"Node":[["v",{"Node":[["e",{"Contents":[30,"normal"]}]]}]]}]]} +``` + +The proof of Eve's balance is a Merkle proof. It is a path in the tree of all the accounts in the bank, it doesn't leaks Bob and Ben's balance, it only reveals the hash and the name of their subtree (i.e. `["b",{"Blinded_node":"584ba234368730ce6cea56d93433a7a777cad2a0"}]`). + +![The Merkle proof](./merkle_proof_2.jpg) + +The reason why this statement is tamper proof is because it hashes the same way as the full account tree of the bank. The bank could make public the hash in a trusted place and anyone could produce the hash of the statement and make sure that it is identical to the hash published by the bank. + +```ocaml +let pp_hash = Irmin.Type.pp Store.hash_t +``` + +```ocaml +# let () = + let bank_hash = Store.Tree.hash tree in + Fmt.pr " bank hash: %a\n" pp_hash bank_hash + + let () = + let proof_hash = + match Store.Tree.(Proof.state proof |> hash_of_proof_state) with + | `Node h -> h + | `Contents _ -> assert false + in + Fmt.pr "proof hash: %a\n" pp_hash proof_hash + ;; + bank hash: 8e2d5291a09b98725e8525807d189eb7d9eb66d5 +proof hash: 8e2d5291a09b98725e8525807d189eb7d9eb66d5 +``` + +### `produce_proof` in details + +Here is the signature of `produce_proof`: + +```ocaml +# let produce_proof = Store.Tree.produce_proof;; +val produce_proof : + Store.repo -> + Store.Tree.kinded_key -> + (Store.tree -> (Store.tree * 'a) Lwt.t) -> + (Store.Tree.Proof.tree Store.Tree.Proof.t * 'a) Lwt.t = +``` + +`produce_proof repo key_before f` is `(proof = { state; hash_before; hash_after }, f_res)`. `f` is invoked once per call to `produce_proof` and `f tree_before` is `(tree_after, f_res)`. + +`produce_proof` invokes `f`, passing it `tree_before` which is the tree at `key_before` in `repo`. In the preceding example, `tree_before` is the tree of all the bank accounts and `key_before` is the pointer in `repo` to the root of all the bank accounts. + +`f` is expected to perform operations on `tree_before`. Irmin will record all these operations and remember which paths were loaded and which paths weren't. All operations in `Store.Tree` work! All of this is thread safe: behind the scene, instead of using global variables, `tree_before` is decorated with a local cache. + +When `f` is done, Irmin computes `state`, which is the Merkle proof. The paths that were visited during `f` are exposed in `state`, and the paths that were not visited are blinded. + +### Other use cases + +The goal of the above example is to share `state` while `hash_before` is publically known, so that anyone can verify that both match, without knowing `repo`. `hash_after` and `tree_after` are unimportant for this task. + +`hash_after` and `tree_after` are useful in tasks where the goal is to share `proof` and `f` while `hash_before` is publically known, so that anyone can verify that `f` applied on a tree that hashes to `hash_before` produces a tree that hashes to `hash_after`, without knowing `repo`. The `Store.Tree.verify_proof` function exists to support that use case. + +Irmin's Merkle proofs are used in Tezos' _rollups_ where some peers need to verify what some other peers did in other blockchains. diff --git a/vendors/irmin/examples/plugin/README.md b/vendors/irmin/examples/plugin/README.md new file mode 100644 index 000000000000..016a11d4ffaa --- /dev/null +++ b/vendors/irmin/examples/plugin/README.md @@ -0,0 +1,33 @@ +# Example plugin + +## Building + +From the root of the irmin repository: + +```sh +$ dune build ./examples/plugin/plugin.cmxs +``` + +## Usage + +To load this plugin you can use the `--plugin` flag when using `irmin` (or +`dune exec ./src/irmin-cli/bin/main.exe` from the root of the irmin repo): + +```sh +$ dune exec ./src/irmin-cli/bin/main.exe -- set --plugin _build/default/examples/plugin/plugin.cmxs a/b/c 123 +``` + +By default this will use the `mem-int` store defined in [plugin.ml](https://github.com/mirage/irmin/blob/main/examples/plugin/plugin.ml) +since the `default` parameter is `true` when calling `Irmin_cli.Resolver.Store.add`. + +It is still possible to select the store and content type after a plugin has +been loaded. To use the `int` content type with a git store you can run: + +```sh +$ echo 'plugin: _build/default/examples/plugin/plugin.cmxs' > irmin.yml # Set the plugin in config file +$ dune exec ./src/irmin-cli/bin/main.exe -- set --root /tmp/irmin-plugin -s git -c int a/b/c 123 +``` + +Since the `default` parameter is `true` when registering the content type using +`Irmin_cli.Resolver.Contents.add`, `int` contents will already be the default, +which means `-c int` could be left out. diff --git a/vendors/irmin/examples/plugin/dune b/vendors/irmin/examples/plugin/dune new file mode 100644 index 000000000000..d729afa5505d --- /dev/null +++ b/vendors/irmin/examples/plugin/dune @@ -0,0 +1,14 @@ +(executable + (name plugin) + (modes plugin) + (modules plugin) + (libraries irmin-cli)) + +(alias + (name runtest) + (package irmin-cli) + (deps plugin.cmxs)) + +(cram + (package irmin-cli) + (deps %{bin:irmin} plugin.cmxs)) diff --git a/vendors/irmin/examples/plugin/plugin.ml b/vendors/irmin/examples/plugin/plugin.ml new file mode 100644 index 000000000000..05b7cff8664e --- /dev/null +++ b/vendors/irmin/examples/plugin/plugin.ml @@ -0,0 +1,28 @@ +open Irmin_cli + +(* Adding a new content type *) + +module Int = struct + type t = int + + let t = Irmin.Type.int + let merge = Irmin.Merge.(option (idempotent t)) +end + +let () = Resolver.Contents.add ~default:true "int" (module Int) + +module Schema = struct + module Contents = Int + module Hash = Irmin.Hash.BLAKE2B + module Branch = Irmin.Branch.String + module Path = Irmin.Path.String_list + module Info = Irmin.Info.Default + module Metadata = Irmin.Metadata.None +end + +(* Adding a new store type *) + +module Store = Irmin_mem.Make (Schema) + +let store = Resolver.Store.v Irmin_mem.Conf.spec (module Store) +let () = Resolver.Store.add ~default:true "mem-int" (Fixed store) diff --git a/vendors/irmin/examples/plugin/plugin.t b/vendors/irmin/examples/plugin/plugin.t new file mode 100644 index 000000000000..66ddb4aee56f --- /dev/null +++ b/vendors/irmin/examples/plugin/plugin.t @@ -0,0 +1,9 @@ + $ irmin set --plugin ./plugin.cmxs a/b/c 123 + $ echo 'plugin: plugin.cmxs' > irmin.yml # Set the plugin in config file + $ irmin set --root ./irmin-plugin -s git -c int a/b/c 123 + $ irmin get --root ./irmin-plugin -s git -c int a/b/c + 123 + $ irmin set --root ./irmin-plugin -s git -c int a/b/c "AAA" + ERROR: int_of_string + [1] + diff --git a/vendors/irmin/examples/process.ml b/vendors/irmin/examples/process.ml new file mode 100644 index 000000000000..04ce82b2352d --- /dev/null +++ b/vendors/irmin/examples/process.ml @@ -0,0 +1,179 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* Simple UI example: connect to http://localhost:8080/dump *) + +open Lwt.Syntax + +let fin () = + let _ = Fmt.kstr Sys.command "cd %s && git reset HEAD --hard" Config.root in + Lwt.return_unit + +type action = { + message : string; + files : (string list * (unit -> string)) list; +} + +type image = { name : string; actions : action list } + +let ubuntu = + { + name = "official-images/ubuntu:14.04"; + actions = + [ + { + message = "Updating source lists"; + files = + [ + ( [ "etc"; "source.list" ], + fun () -> Fmt.str "deb %d" (Random.int 10) ); + ]; + }; + { message = "grep -v '^#' /etc/apt/sources.list"; files = [] }; + { message = "cat /etc/issue"; files = [] }; + ]; + } + +let wordpress = + { + name = "official-images/wordpress:latest"; + actions = + [ + { + message = "user logging"; + files = + [ + ( [ "wordpress"; "wp-users.php" ], + fun () -> Fmt.str " Fmt.str " Fmt.str "X%duYYt" (Random.int 10) ); + ]; + }; + { message = "Reading table wp_posts"; files = [] }; + { + message = "Writing table wp_posts"; + files = + [ + ( [ "var"; "lib"; "mysql" ], + fun () -> Fmt.str "X%dxYYt" (Random.int 10) ); + ]; + }; + ]; + } + +let branch image = String.map (function ':' -> '/' | c -> c) image.name +let images = [| (*ubuntu; *) wordpress; mysql |] + +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) + +let head = Git.Reference.v ("refs/heads/" ^ branch images.(0)) +let config = Irmin_git.config ~bare:true ~head Config.root + +let info image message () = + let date = Int64.of_float (Unix.gettimeofday ()) in + let author = image.name in + Store.Info.v ~author ~message date + +let main = branch images.(0) + +let init () = + Config.init (); + let* repo = Store.Repo.v config in + let* t = Store.of_branch repo main in + let* () = Store.set_exn t ~info:(info images.(0) "init") [ "0" ] "0" in + Lwt_list.iter_s + (fun i -> + let* _ = Store.clone ~src:t ~dst:(branch i) in + Lwt.return_unit) + (Array.to_list images) + +let random_array a = a.(Random.int (Array.length a)) +let random_list l = random_array (Array.of_list l) + +let rec process image = + let id = branch image in + Printf.printf "Processing %s\n%!" id; + let actions = random_list image.actions in + let key, value = + try random_list actions.files + with _ -> + ([ "log"; id; "0" ], fun () -> id ^ string_of_int (Random.int 10)) + in + let* repo = Store.Repo.v config in + let* t = Store.of_branch repo id in + let* () = Store.set_exn t ~info:(info image actions.message) key (value ()) in + let* () = + if Random.int 3 = 0 then + let branch = branch (random_array images) in + if branch <> id then ( + Printf.printf "Merging ...%!"; + let* r = + Store.merge_with_branch t + ~info:(info image @@ Fmt.str "Merging with %s" branch) + branch + in + match r with + | Ok () -> + Printf.printf "ok!\n%!"; + Lwt.return_unit + | Error _ -> Lwt.fail_with "conflict!") + else Lwt.return_unit + else Lwt.return_unit + in + let* () = Lwt_unix.sleep (max 0.1 (Random.float 0.3)) in + process image + +let rec protect fn x = + Lwt.catch + (fun () -> fn x) + (fun e -> + Printf.eprintf "error: %s" (Printexc.to_string e); + protect fn x) + +let rec watchdog () = + Printf.printf "I'm alive!\n%!"; + let* () = Lwt_unix.sleep 1. in + watchdog () + +let () = + let aux () = + let* () = init () in + Lwt.choose (watchdog () :: List.map (protect process) (Array.to_list images)) + in + Lwt_main.run (aux ()) diff --git a/vendors/irmin/examples/push.ml b/vendors/irmin/examples/push.ml new file mode 100644 index 000000000000..68c9252de6ba --- /dev/null +++ b/vendors/irmin/examples/push.ml @@ -0,0 +1,54 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* Simple example of Git push *) + +open Lwt.Syntax + +let info = Irmin_git_unix.info + +let url, user, token = + if Array.length Sys.argv = 4 then (Sys.argv.(1), Sys.argv.(2), Sys.argv.(3)) + else failwith "usage: push.exe url user token" + +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) +module Sync = Irmin.Sync.Make (Store) + +let headers = + let e = Cohttp.Header.of_list [] in + Cohttp.Header.add_authorization e (`Basic (user, token)) + +let test () = + Config.init (); + let config = Irmin_git.config Config.root in + let* repo = Store.Repo.v config in + let* t = Store.main repo in + let* remote = Store.remote ~headers url in + let* _ = Sync.pull_exn t remote `Set in + let* readme = Store.get t [ "README.md" ] in + let* tree = Store.get_tree t [] in + let* tree = Store.Tree.add tree [ "BAR.md" ] "Hoho!" in + let* tree = Store.Tree.add tree [ "FOO.md" ] "Hihi!" in + let* () = Store.set_tree_exn t ~info:(info "merge") [] tree in + Printf.printf "%s\n%!" readme; + let* bar = Store.get t [ "BAR.md" ] in + Printf.printf "%s\n%!" bar; + let* foo = Store.get t [ "FOO.md" ] in + Printf.printf "%s\n%!" foo; + let+ _ = Sync.push_exn t remote in + () + +let () = Lwt_main.run (test ()) diff --git a/vendors/irmin/examples/readme.ml b/vendors/irmin/examples/readme.ml new file mode 100644 index 000000000000..e8c0f33a2155 --- /dev/null +++ b/vendors/irmin/examples/readme.ml @@ -0,0 +1,33 @@ +open Lwt.Syntax + +(* Irmin store with string contents *) +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) + +(* Database configuration *) +let config = Irmin_git.config ~bare:true "/tmp/irmin/test" + +(* Commit author *) +let author = "Example " + +(* Commit information *) +let info fmt = Irmin_git_unix.info ~author fmt + +let main = + (* Open the repo *) + let* repo = Store.Repo.v config in + + (* Load the main branch *) + let* t = Store.main repo in + + (* Set key "foo/bar" to "testing 123" *) + let* () = + Store.set_exn t ~info:(info "Updating foo/bar") [ "foo"; "bar" ] + "testing 123" + in + + (* Get key "foo/bar" and print it to stdout *) + let+ x = Store.get t [ "foo"; "bar" ] in + Printf.printf "foo/bar => '%s'\n" x + +(* Run the program *) +let () = Lwt_main.run main diff --git a/vendors/irmin/examples/sync.ml b/vendors/irmin/examples/sync.ml new file mode 100644 index 000000000000..4f206b02cc7e --- /dev/null +++ b/vendors/irmin/examples/sync.ml @@ -0,0 +1,42 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Syntax + +let info = Irmin_git_unix.info + +let path = + if Array.length Sys.argv = 2 then Sys.argv.(1) + else "git://github.com/mirage/ocaml-git.git" + +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) +module Sync = Irmin.Sync.Make (Store) + +let test () = + Config.init (); + let config = Irmin_git.config Config.root in + let* repo = Store.Repo.v config in + let* t = Store.of_branch repo "master" in + let* upstream = Store.remote path in + let* _ = Sync.pull_exn t upstream `Set in + let* readme = Store.get t [ "README.md" ] in + let* tree = Store.get_tree t [] in + let* tree = Store.Tree.add tree [ "BAR.md" ] "Hoho!" in + let* tree = Store.Tree.add tree [ "FOO.md" ] "Hihi!" in + let+ () = Store.set_tree_exn t ~info:(info "merge") [] tree in + Printf.printf "%s\n%!" readme + +let () = Lwt_main.run (test ()) diff --git a/vendors/irmin/examples/trees.ml b/vendors/irmin/examples/trees.ml new file mode 100644 index 000000000000..07a1a2bad50c --- /dev/null +++ b/vendors/irmin/examples/trees.ml @@ -0,0 +1,71 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* example of using the tree API *) + +open Lwt.Syntax +module Store = Irmin_git_unix.FS.KV (Irmin.Contents.String) +module Tree = Store.Tree + +let info = Irmin_git_unix.info + +type t1 = int +type t2 = { x : string; y : t1 } +type t = t2 list + +let tree_of_t t = + let+ tree, _ = + Lwt_list.fold_left_s + (fun (v, i) t2 -> + let si = string_of_int i in + let* v = Tree.add v [ si; "x" ] t2.x in + let+ v = Tree.add v [ si; "y" ] (string_of_int t2.y) in + (v, i + 1)) + (Tree.empty (), 0) + t + in + tree + +let t_of_tree v = + let aux acc i = + let i = string_of_int i in + let* x = Tree.get v [ i; "x" ] in + let+ y = Tree.get v [ i; "y" ] in + { x; y = int_of_string y } :: acc + in + let* t2s = Tree.list v [] in + let t2s = List.map (fun (i, _) -> int_of_string i) t2s in + let t2s = List.rev (List.sort compare t2s) in + Lwt_list.fold_left_s aux [] t2s + +let main () = + Config.init (); + let config = Irmin_git.config ~bare:false Config.root in + let t = + [ { x = "foo"; y = 3 }; { x = "bar"; y = 5 }; { x = "too"; y = 10 } ] + in + let* v = tree_of_t t in + let* repo = Store.Repo.v config in + let* t = Store.main repo in + let* () = Store.set_tree_exn t ~info:(info "update a/b") [ "a"; "b" ] v in + let* v = Store.get_tree t [ "a"; "b" ] in + let* tt = t_of_tree v in + let* () = Store.set_tree_exn t ~info:(info "update a/c") [ "a"; "c" ] v in + let tt = tt @ [ { x = "ggg"; y = 4 } ] in + let* vv = tree_of_t tt in + Store.set_tree_exn t ~info:(info "merge tree into a/b") [ "a"; "b" ] vv + +let () = Lwt_main.run (main ()) diff --git a/vendors/irmin/irmin-bench.opam b/vendors/irmin/irmin-bench.opam new file mode 100644 index 000000000000..aa60de96936c --- /dev/null +++ b/vendors/irmin/irmin-bench.opam @@ -0,0 +1,50 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] +] + +depends: [ + "dune" {>= "2.9.0"} + "irmin-pack" {= version} + "irmin-test" {= version} + "irmin-tezos" {= version} + "cmdliner" + "logs" + "lwt" {>= "5.3.0"} + "repr" {>= "0.3.0"} + "ppx_repr" + "re" {>= "1.9.0"} + "fmt" + "uuidm" + "progress" {>="0.2.1"} + "fpath" {with-test} + "bentov" + "mtime" {< "2.0.0"} + "ppx_deriving" + "alcotest" {with-test} + "rusage" + "uutf" + "uucp" + "printbox" {>= "0.6"} + "printbox-text" +] + +available: [ + # Disabled on 32-bit platforms due to an overly-large int literal in the source + arch != "arm32" & arch != "x86_32" +] + +synopsis: "Irmin benchmarking suite" +description: """ +`irmin-bench` provides access to the Irmin suite for benchmarking storage backend +implementations. +""" diff --git a/vendors/irmin/irmin-chunk.opam b/vendors/irmin/irmin-chunk.opam new file mode 100644 index 000000000000..63812ee2a1e8 --- /dev/null +++ b/vendors/irmin/irmin-chunk.opam @@ -0,0 +1,26 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Mounir Nasr Allah" "Thomas Gazagnaire"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +depends: [ + "ocaml" {>= "4.02.3"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "fmt" + "logs" + "lwt" {>= "5.3.0"} + "irmin-test" {with-test & = version} + "alcotest" {with-test} +] + +synopsis: "Irmin backend which allow to store values into chunks" diff --git a/vendors/irmin/irmin-cli.opam b/vendors/irmin/irmin-cli.opam new file mode 100644 index 000000000000..c72f14541a32 --- /dev/null +++ b/vendors/irmin/irmin-cli.opam @@ -0,0 +1,56 @@ +opam-version: "2.0" +maintainer: "Tarides " +authors: ["Tarides"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test & os != "macos"} +] + +available: arch != "arm32" & arch != "x86_32" + +depends: [ + "ocaml" {>= "4.01.0"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "irmin-git" {= version} + "irmin-http" {= version} + "irmin-fs" {= version} + "irmin-pack" {= version} + "irmin-graphql" {= version} + "irmin-tezos" {= version} + "git-unix" {>= "3.7.0"} + "digestif" {>= "0.9.0"} + "irmin-watcher" {>= "0.2.0"} + "yaml" {>= "3.0.0"} + "astring" + "astring" + "cohttp" + "cohttp-lwt" + "cohttp-lwt-unix" + "conduit" + "conduit-lwt" + "conduit-lwt-unix" + "logs" + "uri" + "cmdliner" + "cohttp-lwt-unix" + "fmt" + "git" {>= "3.7.0"} + "happy-eyeballs-lwt" + "lwt" {>= "5.3.0"} + "irmin-test" {with-test & = version} + "alcotest" {with-test} + "mdx" {>= "2.0.0" & with-test} +] + +synopsis: "CLI for Irmin" +description: """ +A simple CLI tool (called `irmin`) to manipulate and inspect Irmin stores. +""" diff --git a/vendors/irmin/irmin-containers.opam b/vendors/irmin/irmin-containers.opam new file mode 100644 index 000000000000..672c2acd8fdf --- /dev/null +++ b/vendors/irmin/irmin-containers.opam @@ -0,0 +1,33 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["KC Sivaramakrishnan" "Anirudh Sunder Raj"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +depends: [ + "ocaml" {>= "4.03.0"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "irmin-fs" {= version} + "ppx_irmin" {= version} + "lwt" {>= "5.3.0"} + "mtime" {< "2.0.0"} + "alcotest" {with-test} + "alcotest-lwt" {with-test} +] + +synopsis: "Mergeable Irmin data structures" +description: """ +A collection of simple, ready-to-use mergeable data structures built using +Irmin. Each data structure works with an arbitrary Irmin backend and is +customisable in a variety of ways. +""" diff --git a/vendors/irmin/irmin-fs.opam b/vendors/irmin/irmin-fs.opam new file mode 100644 index 000000000000..e88d8f9070fe --- /dev/null +++ b/vendors/irmin/irmin-fs.opam @@ -0,0 +1,28 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire" "Thomas Leonard"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +depends: [ + "ocaml" {>= "4.03.0"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "astring" + "logs" + "lwt" {>= "5.3.0"} + "alcotest" {with-test} + "irmin-test" {with-test & = version} + "irmin-watcher" {with-test & >= "0.2.0"} +] + +synopsis: "Generic file-system backend for Irmin" diff --git a/vendors/irmin/irmin-git.opam b/vendors/irmin/irmin-git.opam new file mode 100644 index 000000000000..5d892b47be60 --- /dev/null +++ b/vendors/irmin/irmin-git.opam @@ -0,0 +1,44 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire" "Thomas Leonard"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + # Tests disabled on 32-bit platforms as the Dune build fails in CI: + ["dune" "runtest" "-p" name "-j" jobs] {with-test & arch != "arm32" & arch != "x86_32"} +] + +depends: [ + "ocaml" {>= "4.02.3"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "ppx_irmin" {= version} + "git" {>= "3.7.0"} + "git-unix" {>= "3.7.0"} + "digestif" {>= "0.9.0"} + "cstruct" + "fmt" + "astring" + "cohttp-lwt-unix" + "fpath" + "logs" + "lwt" {>= "5.3.0"} + "uri" + "mimic" + "irmin-test" {with-test & = version} + "mtime" {with-test & >= "1.0.0" & < "2.0.0"} + "alcotest" {with-test} + "irmin-watcher" {>= "0.2.0"} +] + +synopsis: "Git backend for Irmin" +description: """ +`Irmin_git` expose a bi-directional bridge between Git repositories and +Irmin stores. +""" diff --git a/vendors/irmin/irmin-graphql.opam b/vendors/irmin/irmin-graphql.opam new file mode 100644 index 000000000000..7d6e9e1c482d --- /dev/null +++ b/vendors/irmin/irmin-graphql.opam @@ -0,0 +1,36 @@ +opam-version: "2.0" +maintainer: "Andreas Garnaes " +authors: "Andreas Garnaes " +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test & os != "macos"} +] + +depends: [ + "ocaml" {>= "4.03.0"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "graphql" {>= "0.14.0"} + "graphql-lwt" {>= "0.14.0"} + "graphql-cohttp" {>= "0.14.0"} + "graphql_parser" {>= "0.14.0"} + "cohttp" + "cohttp-lwt" + "cohttp-lwt-unix" + "git-unix" {>= "3.7.0"} + "fmt" + "lwt" {>= "5.3.0"} + "alcotest-lwt" {with-test & >= "1.1.0"} + "yojson" {with-test} + "alcotest" {with-test & >= "1.2.3"} + "logs" {with-test} +] + +synopsis: "GraphQL server for Irmin" diff --git a/vendors/irmin/irmin-http.opam b/vendors/irmin/irmin-http.opam new file mode 100644 index 000000000000..a04b8a931e5e --- /dev/null +++ b/vendors/irmin/irmin-http.opam @@ -0,0 +1,39 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire" "Thomas Leonard"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test & os != "macos"} +] + +depends: [ + "ocaml" {>= "4.02.3"} + "dune" {>= "2.9.0"} + "crunch" {>= "2.2.0"} + "webmachine" {>= "0.6.0"} + "irmin" {= version} + "ppx_irmin" {= version} + "cohttp-lwt" {>= "1.0.0"} + "cohttp-lwt-unix" {>= "1.0.0"} + "astring" + "cohttp" + "fmt" + "jsonm" + "logs" + "lwt" {>= "5.3.0"} + "uri" + "irmin-git" {with-test & = version} + "irmin-fs" {with-test & = version} + "irmin-test" {with-test & = version} + "git-unix" {with-test & >= "3.5.0"} + "digestif" {with-test & >= "0.9.0"} +] + +synopsis: "HTTP client and server for Irmin" diff --git a/vendors/irmin/irmin-mirage-git.opam b/vendors/irmin/irmin-mirage-git.opam new file mode 100644 index 000000000000..78246be9a88d --- /dev/null +++ b/vendors/irmin/irmin-mirage-git.opam @@ -0,0 +1,27 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: "Thomas Gazagnaire" +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] +] + +depends: [ + "dune" {>= "2.9.0"} + "irmin-mirage" {= version} + "irmin-git" {= version} + "mirage-kv" {>= "3.0.0" & < "5.0.0"} + "fmt" + "git" {>= "3.7.0"} + "lwt" {>= "5.3.0"} + "mirage-clock" + "uri" +] + +synopsis: "MirageOS-compatible Irmin stores" diff --git a/vendors/irmin/irmin-mirage-graphql.opam b/vendors/irmin/irmin-mirage-graphql.opam new file mode 100644 index 000000000000..da6926a61806 --- /dev/null +++ b/vendors/irmin/irmin-mirage-graphql.opam @@ -0,0 +1,26 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: "Thomas Gazagnaire" +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] +] + +depends: [ + "dune" {>= "2.9.0"} + "irmin-mirage" {= version} + "irmin-graphql" {= version} + "mirage-clock" + "cohttp-lwt" + "lwt" {>= "5.3.0"} + "uri" + "git" {>= "3.4.0"} +] + +synopsis: "MirageOS-compatible Irmin stores" diff --git a/vendors/irmin/irmin-mirage.opam b/vendors/irmin/irmin-mirage.opam new file mode 100644 index 000000000000..710d97af26a8 --- /dev/null +++ b/vendors/irmin/irmin-mirage.opam @@ -0,0 +1,23 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: "Thomas Gazagnaire" +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] +] + +depends: [ + "dune" {>= "2.9.0"} + "irmin" {= version} + "fmt" + "ptime" + "mirage-clock" {>= "3.0.0"} +] + +synopsis: "MirageOS-compatible Irmin stores" diff --git a/vendors/irmin/irmin-pack-tools.opam b/vendors/irmin/irmin-pack-tools.opam new file mode 100644 index 000000000000..89794983ca99 --- /dev/null +++ b/vendors/irmin/irmin-pack-tools.opam @@ -0,0 +1,38 @@ +opam-version: "2.0" +maintainer: "Gwenaelle@tarides.com" +authors: ["Gwenaëlle Lecat"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +available: arch != "arm32" & arch != "x86_32" + +depends: [ + "ocaml" {>= "4.01.0"} + "dune" {>= "2.9.0"} + "irmin-tezos" {= version} + "irmin-pack" {= version} + "irmin-pack" {= version} + "cmdliner" {>= "1.1.0"} + "cmdliner" {>= "1.1.0"} + "notty" {>= "0.2.3"} + "ptime" + "hex" + "irmin-test" {with-test & = version} + "alcotest" {with-test} +] + +synopsis: "Utils for Irmin-pack" +description: """ +`Irmin-pack-tools` defines useful binaries and libraries for +an internal use of irmin-pack, like dumping control files in +a readable json format and such. +""" diff --git a/vendors/irmin/irmin-pack.opam b/vendors/irmin/irmin-pack.opam new file mode 100644 index 000000000000..cc2483e17d2b --- /dev/null +++ b/vendors/irmin/irmin-pack.opam @@ -0,0 +1,35 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +depends: [ + "ocaml" {>= "4.12.0"} + "dune" {>= "2.9.0"} + "irmin" {= version} + "ppx_irmin" {= version} + "index" {>= "1.6.0"} + "fmt" + "logs" + "lwt" {>= "5.4.0"} + "mtime" {< "2.0.0"} + "cmdliner" + "optint" {>= "0.1.0"} + "checkseum" + "rusage" + "irmin-test" {with-test & = version} + "alcotest-lwt" {with-test} + "astring" {with-test} + "alcotest" {with-test} +] + +synopsis: "Irmin backend which stores values in a pack file" diff --git a/vendors/irmin/irmin-test.opam b/vendors/irmin/irmin-test.opam new file mode 100644 index 000000000000..58e423b572cc --- /dev/null +++ b/vendors/irmin/irmin-test.opam @@ -0,0 +1,39 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire" "Thomas Leonard"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] +] + +depends: [ + "irmin" {= version} + "ppx_irmin" {= version} + "ocaml" {>= "4.02.3"} + "dune" {>= "2.9.0"} + "alcotest-lwt" {>= "1.5.0"} + "mtime" {>= "1.0.0" & < "2.0.0"} + "astring" + "fmt" + "jsonm" + "logs" + "lwt" {>= "5.3.0"} + "metrics-unix" + "ocaml-syntax-shims" + "cmdliner" + "metrics" {>= "0.2.0"} + "hex" {with-test & >= "1.4.0"} + "vector" {with-test & >= "1.0.0"} +] + +synopsis: "Irmin test suite" +description: """ +`irmin-test` provides access to the Irmin test suite for testing storage backend +implementations. +""" diff --git a/vendors/irmin/irmin-tezos.opam b/vendors/irmin/irmin-tezos.opam new file mode 100644 index 000000000000..740f749e6b4f --- /dev/null +++ b/vendors/irmin/irmin-tezos.opam @@ -0,0 +1,29 @@ +opam-version: "2.0" +synopsis: "Irmin implementation of the Tezos context hash specification" +description: "Irmin implementation of the Tezos context hash specification" +maintainer: "Tarides " +authors: ["Thomas Gazagnaire "] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +depends: [ + "dune" {>= "2.9.0"} + "irmin" {>= version} + "irmin-pack" {= version} + "ppx_irmin" {= version} + "tezos-base58" + "digestif" {>= "0.7"} + "cmdliner" + "fmt" + "yojson" + "alcotest" {with-test} + "hex" {with-test & >= "1.4.0"} + "fpath" {with-test} + "irmin-test" {with-test & = version} +] +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test & arch != "arm32" & arch != "x86_32"}] + +] +dev-repo: "git+https://github.com/mirage/irmin.git" diff --git a/vendors/irmin/irmin.opam b/vendors/irmin/irmin.opam new file mode 100644 index 000000000000..fe3bf05a5ede --- /dev/null +++ b/vendors/irmin/irmin.opam @@ -0,0 +1,55 @@ +opam-version: "2.0" +maintainer: "thomas@gazagnaire.org" +authors: ["Thomas Gazagnaire" "Thomas Leonard"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +dev-repo: "git+https://github.com/mirage/irmin.git" +doc: "https://mirage.github.io/irmin/" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +depends: [ + "ocaml" {>= "4.08.0"} + "dune" {>= "2.9.0"} + "repr" {>= "0.6.0"} + "fmt" {>= "0.8.5"} + "uri" {>= "1.3.12"} + "uutf" + "jsonm" {>= "1.0.0"} + "lwt" {>= "5.3.0"} + "digestif" {>= "0.9.0"} + "ocamlgraph" + "logs" {>= "0.5.0"} + "bheap" {>= "2.0.0"} + "astring" + "mtime" {>= "1.0.0" & < "2.0.0"} + "bigstringaf" { >= "0.2.0" } + "ppx_irmin" {= version} + "hex" {with-test} + "alcotest" {>= "1.1.0" & with-test} + "alcotest-lwt" {with-test} + "qcheck-alcotest" {with-test} + "vector" {with-test} + "odoc" {(< "2.0.1" | > "2.0.2") & with-doc} # See https://github.com/ocaml/odoc/issues/793 + "bisect_ppx" {dev & >= "2.5.0"} +] + +conflicts: [ + "result" {< "1.5"} # Requires `Result = Stdlib.Result` +] + +synopsis: """ +Irmin, a distributed database that follows the same design principles as Git +""" +description: """ +Irmin is a library for persistent stores with built-in snapshot, +branching and reverting mechanisms. It is designed to use a large +variety of backends. Irmin is written in pure OCaml and does not +depend on external C stubs; it aims to run everywhere, from Linux, +to browsers and Xen unikernels. +""" diff --git a/vendors/irmin/libirmin.opam b/vendors/irmin/libirmin.opam new file mode 100644 index 000000000000..76c709512c98 --- /dev/null +++ b/vendors/irmin/libirmin.opam @@ -0,0 +1,25 @@ +opam-version: "2.0" +synopsis: "C bindings for irmin" +description: "C bindings for irmin using Ctypes inverted stubs" +maintainer: ["zachshipko@gmail.com"] +authors: ["Zach Shipko"] +license: "ISC" +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +depends: [ + "dune" {>= "2.9"} + "ctypes" {>= "0.19"} + "ctypes-foreign" {>= "0.18"} + "irmin" {= version} + "irmin-cli" {= version} +] +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +dev-repo: "git+https://github.com/mirage/irmin.git" + +# Disabled on arm64 linux and s390x because of a SEGFAULT in tests +# Disabled on macOS because of https://github.com/mirage/ca-certs/issues/20 +available: [ arch != "arm64" & arch != "s390x" & os != "macos" ] diff --git a/vendors/irmin/logo.svg b/vendors/irmin/logo.svg new file mode 100644 index 000000000000..48d85bf88e77 --- /dev/null +++ b/vendors/irmin/logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/vendors/irmin/ppx_irmin.opam b/vendors/irmin/ppx_irmin.opam new file mode 100644 index 000000000000..ed6b33542c7a --- /dev/null +++ b/vendors/irmin/ppx_irmin.opam @@ -0,0 +1,25 @@ +opam-version: "2.0" +maintainer: "Craig Ferguson " +author: "Craig Ferguson " +homepage: "https://github.com/mirage/irmin" +bug-reports: "https://github.com/mirage/irmin/issues" +license: "ISC" +dev-repo: "git+https://github.com/mirage/irmin.git" + +build: [ + ["dune" "subst"] {dev} + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] + +depends: [ + "ocaml" {>= "4.10.0"} + "dune" {>= "2.9.0"} + "ppx_repr" {>= "0.2.0"} + "ppxlib" {>= "0.12.0"} + "logs" {>= "0.5.0"} + "fmt" {with-test & >= "0.8.0"} + "bisect_ppx" {dev & >= "2.5.0"} +] + +synopsis: "PPX deriver for Irmin type representations" diff --git a/vendors/irmin/src/irmin-chunk/dune b/vendors/irmin/src/irmin-chunk/dune new file mode 100644 index 000000000000..0b16010d73d7 --- /dev/null +++ b/vendors/irmin/src/irmin-chunk/dune @@ -0,0 +1,8 @@ +(library + (name irmin_chunk) + (public_name irmin-chunk) + (libraries irmin fmt logs lwt) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-chunk/import.ml b/vendors/irmin/src/irmin-chunk/import.ml new file mode 100644 index 000000000000..71053e21ba54 --- /dev/null +++ b/vendors/irmin/src/irmin-chunk/import.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin-chunk/irmin_chunk.ml b/vendors/irmin/src/irmin-chunk/irmin_chunk.ml new file mode 100644 index 000000000000..eb3a286086b5 --- /dev/null +++ b/vendors/irmin/src/irmin-chunk/irmin_chunk.ml @@ -0,0 +1,259 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2015 Mounir Nasr Allah + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +let src = Logs.Src.create "irmin.chunk" ~doc:"Irmin chunks" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Conf = struct + include Irmin.Backend.Conf + + let spec = Spec.v "chunk" + + module Key = struct + let min_size = + key ~spec ~doc:"Minimal chunk size" "min-size" Irmin.Type.int 4000 + + let chunk_size = key ~spec ~doc:"Size of chunk" "size" Irmin.Type.int 4096 + + let chunk_type_t = + Irmin.Type.(enum "chunk_type" [ ("max", `Max); ("best-fit", `Best_fit) ]) + + let chunking = + key ~spec ~doc:"Chunking algorithm" "chunking" chunk_type_t `Best_fit + end +end + +let err_too_small ~min size = + Printf.ksprintf invalid_arg + "Chunks of %d bytes are too small. Size should at least be %d bytes." size + min + +let config ?size ?min_size ?(chunking = `Best_fit) config = + let min_size = + match min_size with None -> Conf.default Conf.Key.min_size | Some v -> v + in + let size = + match size with + | None -> Conf.default Conf.Key.chunk_size + | Some v -> if v < min_size then err_too_small ~min:min_size v else v + in + let add x y c = Conf.add c x y in + let cfg = + Conf.empty Conf.spec + |> add Conf.Key.min_size min_size + |> add Conf.Key.chunk_size size + |> add Conf.Key.chunking chunking + in + Conf.(verify (union cfg config)) + +module Chunk (H : Irmin.Hash.S) = struct + type v = Data of string | Index of H.t list + + let v_t = + let open Irmin.Type in + variant "chunk" (fun d i -> function + | Data data -> d data | Index index -> i index) + |~ case1 "Data" string (fun d -> Data d) + |~ case1 "Index" (list ~len:`Int16 H.t) (fun i -> Index i) + |> sealv + + type value = v + [@@deriving irmin ~size_of ~to_bin_string ~decode_bin ~encode_bin] + + type t = { len : int; v : v } + + let size_of_v t = + match size_of_value t with + | Some n -> n + | None -> String.length (value_to_bin_string t) + + let size_of_data_header = size_of_v (Data "") + let size_of_index_header = size_of_v (Index []) + + let of_string b = + let len = String.length b in + let pos_ref = ref 0 in + let v = decode_bin_value b pos_ref in + if !pos_ref = len then { len; v } + else Fmt.invalid_arg "invalid length: got %d, expecting %d" !pos_ref len + + let to_string t = + let buf = Bytes.make t.len '\000' in + let b = Buffer.create t.len in + encode_bin_value t.v (Buffer.add_string b); + let s = Buffer.contents b in + Bytes.blit_string s 0 buf 0 (String.length s); + Bytes.unsafe_to_string buf + + let t = Irmin.Type.(map string) of_string to_string +end + +module Content_addressable + (Make_append_only : Irmin.Append_only.Maker) + (H : Irmin.Hash.S) + (V : Irmin.Type.S) = +struct + module Chunk = Chunk (H) + module AO = Make_append_only (H) (Chunk) + module CA = Irmin.Content_addressable.Make (Make_append_only) (H) (Chunk) + + type key = H.t [@@deriving irmin ~pp ~equal] + type value = V.t [@@deriving irmin ~of_bin_string ~to_bin_string ~pre_hash] + + type 'a t = { + chunking : [ `Max | `Best_fit ]; + db : 'a CA.t; + (* An handler to the underlying database. *) + chunk_size : int; + (* the size of chunks. *) + max_children : int; + (* the maximum number of children a node can have. *) + max_data : int; + (* the maximum length (in bytes) of data stored in one + chunk. *) + } + + let index t i = + let v = Chunk.Index i in + match t.chunking with + | `Max -> { Chunk.v; len = t.chunk_size } + | `Best_fit -> { Chunk.v; len = Chunk.size_of_v v } + + let data t s = + let v = Chunk.Data s in + match t.chunking with + | `Max -> { Chunk.v; len = t.chunk_size } + | `Best_fit -> { Chunk.v; len = Chunk.size_of_v v } + + module Tree = struct + (* return all the tree leaves *) + let find_leaves t root = + let rec aux acc { Chunk.v; _ } = + match v with + | Chunk.Data d -> Lwt.return (d :: acc) + | Chunk.Index i -> + Lwt_list.fold_left_s + (fun acc key -> + CA.find t.db key >>= function + | None -> Lwt.return acc + | Some v -> aux acc v) + acc i + in + aux [] root >|= List.rev + + (* partition a list into a list of elements of at most size [n] *) + let list_partition n l = + let rec aux done_ i acc = function + | [] -> List.rev (List.rev acc :: done_) + | h :: t -> + if i >= n then aux (List.rev acc :: done_) 1 [ h ] t + else aux done_ (i + 1) (h :: acc) t + in + aux [] 0 [] l + + let add t ~key l = + let rec aux = function + | [] -> invalid_arg "Irmin_chunk.Tree.add" + | [ k ] -> Lwt.return k + | l -> ( + let n = + if List.length l >= t.max_children then t.max_children + else List.length l + in + match list_partition n l with + | [ i ] -> AO.add t.db key (index t i) >|= fun () -> key + | l -> Lwt_list.map_p (fun i -> CA.add t.db (index t i)) l >>= aux) + in + aux l + end + + let v config = + let chunk_size = Conf.get config Conf.Key.chunk_size in + let max_data = chunk_size - Chunk.size_of_data_header in + let max_children = + (chunk_size - Chunk.size_of_index_header) / H.hash_size + in + let chunking = Conf.get config Conf.Key.chunking in + (if max_children <= 1 then + let min = Chunk.size_of_index_header + (H.hash_size * 2) in + err_too_small ~min chunk_size); + [%log.debug + "config: chunk-size=%d digest-size=%d max-data=%d max-children=%d" + chunk_size H.hash_size max_data max_children]; + let+ db = CA.v config in + { chunking; db; chunk_size; max_children; max_data } + + let close _ = Lwt.return_unit + let batch t f = CA.batch t.db (fun db -> f { t with db }) + + let find_leaves t key = + AO.find t.db key >>= function + | None -> Lwt.return_none (* shallow objects *) + | Some x -> Tree.find_leaves t x >|= Option.some + + let check_hash k v = + let k' = H.hash (pre_hash_value v) in + if equal_key k k' then Lwt.return_unit + else + Fmt.kstr Lwt.fail_invalid_arg "corrupted value: got %a, expecting %a" + pp_key k' pp_key k + + let find t key = + find_leaves t key >>= function + | None -> Lwt.return_none + | Some bufs -> ( + let buf = String.concat "" bufs in + match value_of_bin_string buf with + | Ok va -> check_hash key va >|= fun () -> Some va + | Error _ -> Lwt.return_none) + + let list_range ~init ~stop ~step = + let rec aux acc n = + if n >= stop then List.rev acc else aux (n :: acc) (n + step) + in + aux [] init + + let unsafe_add_buffer t key buf = + let len = String.length buf in + if len <= t.max_data then + AO.add t.db key (data t buf) >|= fun () -> + [%log.debug "add -> %a (no split)" pp_key key] + else + let offs = list_range ~init:0 ~stop:len ~step:t.max_data in + let aux off = + let len = min t.max_data (String.length buf - off) in + let payload = String.sub buf off len in + CA.add t.db (data t payload) + in + let+ k = Lwt_list.map_s aux offs >>= Tree.add ~key t in + [%log.debug "add -> %a (split)" pp_key k] + + let add t v = + let buf = value_to_bin_string v in + let key = H.hash (pre_hash_value v) in + let+ () = unsafe_add_buffer t key buf in + key + + let unsafe_add t key v = + let buf = value_to_bin_string v in + unsafe_add_buffer t key buf + + let mem t key = CA.mem t.db key +end diff --git a/vendors/irmin/src/irmin-chunk/irmin_chunk.mli b/vendors/irmin/src/irmin-chunk/irmin_chunk.mli new file mode 100644 index 000000000000..338a09427f5b --- /dev/null +++ b/vendors/irmin/src/irmin-chunk/irmin_chunk.mli @@ -0,0 +1,91 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2015 Mounir Nasr Allah + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** This package provides an Irmin backend to cut raw contents into blocks of + the same size, while preserving the keys used in the store. It can be used + to optimize space usage when dealing with large files or as an intermediate + layer for a raw block device backend. *) + +(** {1 Managing Chunks} + + This module exposes functors to store raw contents into append-only stores + as chunks of same size. It exposes the {{!AO} AO} functor which split the + raw contents into [Data] blocks, addressed by [Node] blocks. That's the + usual rope-like representation of strings, but chunk trees are always built + as perfectly well-balanced and blocks are addressed by their hash (or by the + stable keys returned by the underlying store). + + A chunk has the following structure: + + {v + -------------------------- -------------------------- + | uint8_t type | | uint8_t type | + --------------------------- --------------------------- + | uint16_t | | uint64_t | + --------------------------- --------------------------- + | key children[length] | | byte data[length] | + --------------------------- --------------------------- + v} + + [type] is either [Data] (0) or [Index] (1). If the chunk contains data, + [length] is the payload length. Otherwise it is the number of children that + the node has. + + It also exposes {{!AO_stable} AO_stable} which -- as {{!AO} AO} does -- + stores raw contents into chunks of same size. But it also preserves the nice + property that values are addressed by their hash, instead of by the hash of + the root chunk node as is the case for {{!AO} AO}. *) + +module Conf : sig + open Irmin.Backend.Conf + + val spec : Spec.t + + module Key : sig + val chunk_size : int key + (** [chunk_size] is the configuration key to configure chunk size. By + default, it is set to 4666, so that payload and metadata can be stored + in a 4K block. *) + + val min_size : int key + val chunking : [ `Best_fit | `Max ] key + end +end + +val config : + ?size:int -> + ?min_size:int -> + ?chunking:[ `Max | `Best_fit ] -> + Irmin.config -> + Irmin.config +(** [config ?config ?size ?min_size ()] is the configuration value extending the + optional [config] with bindings associating {{!Conf.Key.chunk_size} + chunk_size} to [size]. + + If [chunking] is [Best_fit] (the default), the size of new chunks will be of + maximum [max_size] but could be smaller if they don't need to be chunked. If + [chunking] is [Max], all the new chunks will be of size [max_size]. + + Fail with [Invalid_argument] if [size] is smaller than [min_size]. + [min_size] is, by default, set to 4000 (to avoid hash collisions on smaller + sizes) but can be tweaked for testing purposes. {i Notes:} the smaller + [size] is, the bigger the risk of hash collisions, so use reasonable values. *) + +(** [Content_addressable(X)] is a content-addressable store which store values + cut into chunks into the underlying store [X]. *) +module Content_addressable (S : Irmin.Append_only.Maker) : + Irmin.Content_addressable.Maker diff --git a/vendors/irmin/src/irmin-cli/bin/dune b/vendors/irmin/src/irmin-cli/bin/dune new file mode 100644 index 000000000000..f4073837cceb --- /dev/null +++ b/vendors/irmin/src/irmin-cli/bin/dune @@ -0,0 +1,5 @@ +(executable + (name main) + (public_name irmin) + (package irmin-cli) + (libraries irmin-cli)) diff --git a/vendors/irmin/src/irmin-cli/bin/main.ml b/vendors/irmin/src/irmin-cli/bin/main.ml new file mode 100644 index 000000000000..2ba8b5d33369 --- /dev/null +++ b/vendors/irmin/src/irmin-cli/bin/main.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = Irmin_cli.(run ~default commands) diff --git a/vendors/irmin/src/irmin-cli/cli.ml b/vendors/irmin/src/irmin-cli/cli.ml new file mode 100644 index 000000000000..8e36a2a6bf52 --- /dev/null +++ b/vendors/irmin/src/irmin-cli/cli.ml @@ -0,0 +1,1058 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Cmdliner +open Resolver +module Http = Irmin_http_unix +module Graphql = Irmin_graphql_unix + +let deprecated_info = (Term.info [@alert "-deprecated"]) +let deprecated_man_format = (Term.man_format [@alert "-deprecated"]) +let deprecated_eval_choice = (Term.eval_choice [@alert "-deprecated"]) +let () = Irmin.Backend.Watch.set_listen_dir_hook Irmin_watcher.hook + +let info (type a) (module S : Irmin.Generic_key.S with type Schema.Info.t = a) + ?(author = "irmin") fmt = + let module Info = Info.Make (S.Info) in + Info.v ~author fmt + +(* Help sections common to all commands *) +let help_sections = + [ + `S global_option_section; + `P "These options can be passed to any command"; + `S "AUTHORS"; + `P "Thomas Gazagnaire "; + `S "BUGS"; + `P "Check bug reports at https://github.com/mirage/irmin/issues."; + ] + +let setup_log style_renderer level = + Fmt_tty.setup_std_outputs ?style_renderer (); + Logs.set_level level; + Logs.set_reporter (Logs_fmt.reporter ()); + () + +let setup_log = + Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ()) + +let term_info title ~doc ~man = + let man = man @ help_sections in + deprecated_info ~sdocs:global_option_section ~docs:global_option_section ~doc + ~man title + +type command = (unit Term.t * Term.info[@alert "-deprecated"]) + +type sub = { + name : string; + doc : string; + man : Manpage.block list; + term : unit Term.t; +} + +let create_command c = + let man = [ `S "DESCRIPTION"; `P c.doc ] @ c.man in + (c.term, term_info c.name ~doc:c.doc ~man) + +(* Converters *) + +let pr_str = Format.pp_print_string + +let path = + let path_conv = + let parse str = `Ok str in + let print ppf path = pr_str ppf path in + (parse, print) + in + let doc = Arg.info ~docv:"PATH" ~doc:"Key to lookup or modify." [] in + Arg.(required & pos 0 (some path_conv) None & doc) + +type path_or_empty = Empty | Path of string + +let path_or_empty = + let path_conv = + let parse str = `Ok (Path str) in + let print = Fmt.of_to_string (function Path str -> str | Empty -> "/") in + (parse, print) + in + let doc = + Arg.info [] ~docv:"PATH" + ~doc: + "Path to lookup or modify. Defaults to the empty path (which queries \ + the root tree of a store)." + in + Arg.(value & pos 0 path_conv Empty & doc) + +let depth = + let doc = + Arg.info ~docv:"DEPTH" ~doc:"Limit the history depth." [ "d"; "depth" ] + in + Arg.(value & opt (some int) None & doc) + +let print_exc exc = + (match exc with + | Failure f -> Fmt.epr "ERROR: %s\n%!" f + | e -> Fmt.epr "ERROR: %a\n%!" Fmt.exn e); + exit 1 + +let run t = Lwt_main.run (Lwt.catch (fun () -> t) print_exc) +let mk (fn : 'a) : 'a Term.t = Term.(const (fun () -> fn) $ setup_log) + +(* INIT *) +let init = + { + name = "init"; + doc = "Initialize a store."; + man = []; + term = + (let init (S (_, _store, _)) = run Lwt.return_unit in + Term.(mk init $ store ())); + } + +(* HTTP *) +let http = + { + name = "http"; + doc = "Run http server"; + man = []; + term = + (let uri = + let doc = + Arg.info ~docv:"URI" [ "a"; "address" ] + ~doc: + "Start the Irmin server on the given socket address. Examples \ + include http://localhost:8080 and launchd://Listener." + in + Arg.(value & opt string "http://localhost:8080" & doc) + in + let init (S (impl, store, _)) uri = + let (module S) = + match Store.Impl.hash_keyed impl with + | Some x -> x + | None -> + Fmt.failwith + "Unsupported backend: can't start an HTTP server with a store \ + that is not keyed by hashes" + in + run + (let* t = store in + let module HTTP = Http.Server (S) in + let uri = Uri.of_string uri in + let spec = HTTP.v (S.repo t) in + match Uri.scheme uri with + | Some "launchd" -> + let uri, name = + match Uri.host uri with + | None -> (Uri.with_host uri (Some "Listener"), "Listener") + | Some name -> (uri, name) + in + [%logs.info "daemon: %s" (Uri.to_string uri)]; + Cohttp_lwt_unix.Server.create ~timeout:3600 + ~mode:(`Launchd name) spec + | _ -> + let uri = + match Uri.host uri with + | None -> Uri.with_host uri (Some "localhost") + | Some _ -> uri + in + let port, uri = + match Uri.port uri with + | None -> (8080, Uri.with_port uri (Some 8080)) + | Some p -> (p, uri) + in + [%logs.info "daemon: %s" (Uri.to_string uri)]; + Printf.printf "Server starting on port %d.\n%!" port; + Cohttp_lwt_unix.Server.create ~timeout:3600 + ~mode:(`TCP (`Port port)) + spec) + in + Term.(mk init $ store () $ uri)); + } + +let print fmt = Fmt.kstr print_endline fmt + +let get name f x = + match Irmin.Type.of_string f x with + | Ok x -> x + | Error (`Msg e) -> Fmt.kstr invalid_arg "invalid %s: %s" name e + +let key f x = get "key" f x +let value f x = get "value" f x +let branch f x = get "branch" f x +let commit f x = get "commit" f x + +(* GET *) +let get = + { + name = "get"; + doc = "Read the value associated with a key."; + man = []; + term = + (let get (S (impl, store, _)) path = + let (module S) = Store.Impl.generic_keyed impl in + run + (let* t = store in + S.find t (key S.Path.t path) >>= function + | None -> + print ""; + exit 1 + | Some v -> + print "%a" (Irmin.Type.pp S.Contents.t) v; + Lwt.return_unit) + in + Term.(mk get $ store () $ path)); + } + +(* LIST *) +let list = + { + name = "list"; + doc = "List subdirectories."; + man = []; + term = + (let list (S (impl, store, _)) path_or_empty = + let (module S) = Store.Impl.generic_keyed impl in + let path = + match path_or_empty with + | Empty -> S.Path.empty + | Path str -> key S.Path.t str + in + run + (let* t = store in + let* paths = S.list t path in + let pp_step = Irmin.Type.pp S.Path.step_t in + let pp ppf (s, k) = + match S.Tree.destruct k with + | `Contents _ -> Fmt.pf ppf "FILE %a" pp_step s + | `Node _ -> Fmt.pf ppf "DIR %a" pp_step s + in + List.iter (print "%a" pp) paths; + Lwt.return_unit) + in + Term.(mk list $ store () $ path_or_empty)); + } + +(* TREE *) +let tree = + { + name = "tree"; + doc = "List the store contents."; + man = []; + term = + (let tree (S (impl, store, _)) = + let (module S) = Store.Impl.generic_keyed impl in + run + (let* t = store in + let all = ref [] in + let todo = ref [ S.Path.empty ] in + let rec walk () = + match !todo with + | [] -> Lwt.return_unit + | k :: rest -> + todo := rest; + let* childs = S.list t k in + Lwt_list.iter_p + (fun (s, c) -> + let k = S.Path.rcons k s in + match S.Tree.destruct c with + | `Node _ -> + todo := k :: !todo; + Lwt.return_unit + | `Contents _ -> + let+ v = S.get t k in + all := (k, v) :: !all) + childs + >>= walk + in + walk () >>= fun () -> + let all = !all in + let all = + List.map + (fun (k, v) -> + ( Irmin.Type.to_string S.Path.t k, + Irmin.Type.to_string S.Contents.t v )) + all + in + let max_length l = + List.fold_left (fun len s -> max len (String.length s)) 0 l + in + let k_max = max_length (List.map fst all) in + let v_max = max_length (List.map snd all) in + let pad = 79 + k_max + v_max in + List.iter + (fun (k, v) -> + let dots = + String.make (pad - String.length k - String.length v) '.' + in + print "%s%s%s" k dots v) + all; + Lwt.return_unit) + in + Term.(mk tree $ store ())); + } + +let author = + let doc = Arg.info ~docv:"NAME" ~doc:"Commit author name." [ "author" ] in + Arg.(value & opt (some string) None & doc) + +let message = + let doc = Arg.info ~docv:"MESSAGE" ~doc:"Commit message." [ "message" ] in + Arg.(value & opt (some string) None & doc) + +(* SET *) +let set = + { + name = "set"; + doc = "Update the value associated with a key."; + man = []; + term = + (let v = + let doc = Arg.info ~docv:"VALUE" ~doc:"Value to add." [] in + Arg.(required & pos 1 (some string) None & doc) + in + let set (S (impl, store, _)) author message path v = + let (module S) = Store.Impl.generic_keyed impl in + run + (let message = match message with Some s -> s | None -> "set" in + let* t = store in + let path = key S.Path.t path in + let value = value S.Contents.t v in + S.set_exn t ~info:(info (module S) ?author "%s" message) path value) + in + Term.(mk set $ store () $ author $ message $ path $ v)); + } + +(* REMOVE *) +let remove = + { + name = "remove"; + doc = "Delete a key."; + man = []; + term = + (let remove (S (impl, store, _)) author message path = + let (module S) = Store.Impl.generic_keyed impl in + run + (let message = + match message with Some s -> s | None -> "remove " ^ path + in + let* t = store in + S.remove_exn t + ~info:(info (module S) ?author "%s" message) + (key S.Path.t path)) + in + Term.(mk remove $ store () $ author $ message $ path)); + } + +let apply e f = + match (e, f) with + | R (h, e), Some f -> f ?ctx:None ?headers:h e + | R _, None -> Fmt.failwith "invalid remote for that kind of store" + | r, _ -> Lwt.return r + +(* CLONE *) +let clone = + { + name = "clone"; + doc = "Copy a remote respository to a local store"; + man = []; + term = + (let clone (S (impl, store, f), remote) depth = + let (module S) = Store.Impl.generic_keyed impl in + let module Sync = Irmin.Sync.Make (S) in + run + (let* t = store in + let* r = remote in + let* x = apply r f in + Sync.fetch t ?depth x >>= function + | Ok (`Head d) -> S.Head.set t d + | Ok `Empty -> Lwt.return_unit + | Error (`Msg e) -> failwith e) + in + Term.(mk clone $ remote () $ depth)); + } + +(* FETCH *) +let fetch = + { + name = "fetch"; + doc = "Download objects and refs from another repository."; + man = []; + term = + (let fetch (S (impl, store, f), remote) = + let (module S) = Store.Impl.generic_keyed impl in + let module Sync = Irmin.Sync.Make (S) in + run + (let* t = store in + let* r = remote in + let branch = branch S.Branch.t "import" in + let* t = S.of_branch (S.repo t) branch in + let* x = apply r f in + let* _ = Sync.pull_exn t x `Set in + Lwt.return_unit) + in + Term.(mk fetch $ remote ())); + } + +(* MERGE *) +let merge = + { + name = "merge"; + doc = "Merge branches."; + man = []; + term = + (let merge (S (impl, store, _)) author message branch = + let (module S) = Store.Impl.generic_keyed impl in + run + (let message = match message with Some s -> s | None -> "merge" in + let branch = + match Irmin.Type.of_string S.Branch.t branch with + | Ok b -> b + | Error (`Msg msg) -> failwith msg + in + let* t = store in + S.merge_with_branch t branch + ~info:(info (module S) ?author "%s" message) + >|= function + | Ok () -> () + | Error conflict -> + let fmt = Irmin.Type.pp_json Irmin.Merge.conflict_t in + Fmt.epr "CONFLICT: %a\n%!" fmt conflict) + in + let branch_name = + let doc = Arg.info ~docv:"BRANCH" ~doc:"Branch to merge from." [] in + Arg.(required & pos 0 (some string) None & doc) + in + Term.(mk merge $ store () $ author $ message $ branch_name)); + } + +(* PULL *) +let pull = + { + name = "pull"; + doc = "Fetch and merge with another repository."; + man = []; + term = + (let pull (S (impl, store, f), remote) author message = + let (module S) = Store.Impl.generic_keyed impl in + let message = match message with Some s -> s | None -> "pull" in + let module Sync = Irmin.Sync.Make (S) in + run + (let* t = store in + let* r = remote in + let* x = apply r f in + let* _ = + Sync.pull_exn t x (`Merge (info (module S) ?author "%s" message)) + in + Lwt.return_unit) + in + Term.(mk pull $ remote () $ author $ message)); + } + +(* PUSH *) +let push = + { + name = "push"; + doc = "Update remote references along with associated objects."; + man = []; + term = + (let push (S (impl, store, f), remote) = + let (module S) = Store.Impl.generic_keyed impl in + let module Sync = Irmin.Sync.Make (S) in + run + (let* t = store in + let* r = remote in + let* x = apply r f in + let* _ = Sync.push_exn t x in + Lwt.return_unit) + in + Term.(mk push $ remote ())); + } + +(* SNAPSHOT *) +let snapshot = + { + name = "snapshot"; + doc = "Return a snapshot for the current state of the database."; + man = []; + term = + (let snapshot (S (impl, store, _)) = + let (module S) = Store.Impl.generic_keyed impl in + run + (let* t = store in + let* k = S.Head.get t in + print "%a" S.Commit.pp_hash k; + Lwt.return_unit) + in + Term.(mk snapshot $ store ())); + } + +(* REVERT *) +let revert = + { + name = "revert"; + doc = "Revert the contents of the store to a previous state."; + man = []; + term = + (let snapshot = + let doc = + Arg.info ~docv:"SNAPSHOT" ~doc:"The snapshot to revert to." [] + in + Arg.(required & pos 0 (some string) None & doc) + in + let revert (S (impl, store, _)) snapshot = + let (module S) = Store.Impl.generic_keyed impl in + run + (let* t = store in + let hash = commit S.Hash.t snapshot in + let* s = S.Commit.of_hash (S.repo t) hash in + match s with + | Some s -> S.Head.set t s + | None -> failwith "invalid commit") + in + Term.(mk revert $ store () $ snapshot)); + } + +(* WATCH *) + +let run_command (type a b c) + (module S : Irmin.Generic_key.S + with type Schema.Path.t = a + and type Schema.Contents.t = b + and type Schema.Metadata.t = c) diff command proc = + let simple_output (k, v) = + let x = + match v with `Updated _ -> "*" | `Added _ -> "+" | `Removed _ -> "-" + in + print "%s %a" x (Irmin.Type.pp S.Path.t) k; + Lwt.return_unit + in + (* Check if there was a command passed, if not print a simple message to stdout, if there is + a command pass the whole diff *) + match command with + | h :: t -> + let ty = [%typ: (S.path * (S.contents * S.metadata) Irmin.Diff.t) list] in + let s = Fmt.str "%a" (Irmin.Type.pp_json ty) diff in + let make_proc () = + (* Start new process *) + let p = Lwt_process.open_process_out (h, Array.of_list (h :: t)) in + proc := Some p; + p + in + let proc = + (* Check if process is already running, if not run it *) + match !proc with + | None -> make_proc () + | Some p -> ( + (* Determine if the subprocess completed succesfully or exited with an error, + if it was successful then we can restart it, otherwise report the exit code + the user *) + let status = p#state in + match status with + | Lwt_process.Running -> p + | Exited (Unix.WEXITED 0) -> make_proc () + | Exited (Unix.WEXITED code) -> + Printf.printf "Subprocess exited with code %d\n" code; + exit code + | Exited (Unix.WSIGNALED code) | Exited (Unix.WSTOPPED code) -> + Printf.printf "Subprocess stopped with code %d\n" code; + exit code) + in + (* Write the diff to the subprocess *) + let* () = Lwt_io.write_line proc#stdin s in + Lwt_io.flush proc#stdin + | [] -> Lwt_list.iter_s simple_output diff + +let handle_diff (type a b) + (module S : Irmin.Generic_key.S + with type Schema.Path.t = a + and type commit = b) (path : a) command proc d = + let view (c, _) = + let* t = S.of_commit c in + S.find_tree t path >|= function None -> S.Tree.empty () | Some v -> v + in + let* x, y = + match d with + | `Updated (x, y) -> + let* x = view x in + let+ y = view y in + (x, y) + | `Added x -> + let+ x = view x in + (S.Tree.empty (), x) + | `Removed x -> + let+ x = view x in + (x, S.Tree.empty ()) + in + let* (diff : (S.path * (S.contents * S.metadata) Irmin.Diff.t) list) = + S.Tree.diff x y + in + run_command + (module S : Irmin.Generic_key.S + with type Schema.Path.t = S.path + and type Schema.Contents.t = S.contents + and type Schema.Metadata.t = S.metadata) + diff command proc + +let watch = + { + name = "watch"; + doc = "Get notifications when values change."; + man = []; + term = + (let watch (S (impl, store, _)) path command = + let (module S) = Store.Impl.generic_keyed impl in + let path = key S.Path.t path in + let proc = ref None in + let () = + at_exit (fun () -> + match !proc with None -> () | Some p -> p#terminate) + in + run + (let* t = store in + let* _ = + S.watch_key t path + (handle_diff + (module S : Irmin.Generic_key.S + with type Schema.Path.t = S.path + and type commit = S.commit) + path command proc) + in + let t, _ = Lwt.task () in + t) + in + let command = + let doc = Arg.info ~docv:"COMMAND" ~doc:"Command to execute" [] in + Arg.(value & pos_right 0 string [] & doc) + in + Term.(mk watch $ store () $ path $ command)); + } + +(* DOT *) +let dot = + { + name = "dot"; + doc = "Dump the contents of the store as a Graphviz file."; + man = []; + term = + (let basename = + let doc = + Arg.info ~docv:"BASENAME" + ~doc:"Basename for the .dot and .png files." [] + in + Arg.(required & pos 0 (some string) None & doc) + in + let no_dot_call = + let doc = + Arg.info + ~doc:"Do not call the `dot' utility on the generated `.dot` file." + [ "no-dot-call" ] + in + Arg.(value & flag & doc) + in + let full = + let doc = + Arg.info + ~doc: + "Show the full graph of objects, including the filesystem nodes \ + and the content blobs." + [ "full" ] + in + Arg.(value & flag & doc) + in + let dot (S (impl, store, _)) basename depth no_dot_call full = + let (module S) = Store.Impl.generic_keyed impl in + let module Dot = Irmin.Dot (S) in + let date d = + let tm = Unix.localtime (Int64.to_float d) in + Printf.sprintf "%2d:%2d:%2d" tm.Unix.tm_hour tm.Unix.tm_min + tm.Unix.tm_sec + in + run + (let* t = store in + let call_dot = not no_dot_call in + let buf = Buffer.create 1024 in + Dot.output_buffer ~html:false t ?depth ~full ~date buf >>= fun () -> + let oc = open_out_bin (basename ^ ".dot") in + let* () = + Lwt.finalize + (fun () -> + output_string oc (Buffer.contents buf); + Lwt.return_unit) + (fun () -> + close_out oc; + Lwt.return_unit) + in + if call_dot then ( + let i = Sys.command "/bin/sh -c 'command -v dot'" in + if i <> 0 then + [%logs.err + "Cannot find the `dot' utility. Please install it on your \ + system and be sure it is available in your $PATH."]; + let i = + Sys.command + (Printf.sprintf "dot -Tpng %s.dot -o%s.png" basename basename) + in + if i <> 0 then [%logs.err "The %s.dot is corrupted" basename]); + Lwt.return_unit) + in + Term.(mk dot $ store () $ basename $ depth $ no_dot_call $ full)); + } + +let config_man = + let version_string = Printf.sprintf "Irmin %s" Irmin.version in + ( ("irmin.yml", 5, "", version_string, "Irmin Manual"), + [ + `S Manpage.s_name; + `P "irmin.yml"; + `S Manpage.s_synopsis; + `P + "Configure certain command-line options to cut down on mistakes and \ + save on typing"; + `S Manpage.s_description; + `P + "An $(b,irmin.yml) file lets the user specify repetitve command-line \ + options in a YAML file. The $(b,irmin.yml) is read by default if it \ + is found in the current working directory or defined globally as \ + \\$HOME/.config/irmin/config.yml. The configuration file path can \ + also be set using the $(b,--config) command-line flag or by setting \ + \\$XDG_CONFIG_HOME. \n\ + \ The following keys are allowed: $(b,contents), $(b,store), \ + $(b,branch), $(b,root), $(b,bare) or $(b,head). These correspond to \ + the irmin options of the same names. Additionally, specific\n\ + \ backends may have other options available, these can be \ + lised using the $(b,options)\n\ + \ command and applied using the $(b,--opt) flag."; + `S Manpage.s_examples; + `P + "Here is an example $(b,irmin.yml) for accessing a local http irmin \ + store. This $(b,irmin.yml) prevents the user from having to specify \ + the $(b,store) and $(b,root) options for every command."; + `Pre " \\$ cat irmin.yml\n store: pack\n root: /path/to/my/store"; + ] + @ help_sections ) + +(* HELP *) +let help = + { + name = "help"; + doc = "Display help about Irmin and Irmin commands."; + man = + [ `P "Use `$(mname) help topics' to get the full list of help topics." ]; + term = + (let topic = + let doc = Arg.info [] ~docv:"TOPIC" ~doc:"The topic to get help on." in + Arg.(value & pos 0 (some string) None & doc) + in + let help man_format cmds topic = + match topic with + | None -> `Help (`Pager, None) + | Some topic -> ( + let topics = "irmin.yml" :: cmds in + let conv, _ = + Arg.enum (List.rev_map (fun s -> (s, s)) ("topics" :: topics)) + in + match conv topic with + | `Error e -> `Error (false, e) + | `Ok t when t = "topics" -> + List.iter print_endline topics; + `Ok () + | `Ok t when t = "irmin.yml" -> + `Ok + (Cmdliner.Manpage.print man_format Format.std_formatter + config_man) + | `Ok t -> `Help (man_format, Some t)) + in + Term.(ret (mk help $ deprecated_man_format $ Term.choice_names $ topic))); + } + +(* GRAPHQL *) +let graphql = + { + name = "graphql"; + doc = "Run a graphql server."; + man = []; + term = + (let port = + let doc = Arg.info ~doc:"Port for graphql server." [ "p"; "port" ] in + Arg.(value & opt int 8080 & doc) + in + let addr = + let doc = + Arg.info ~doc:"Address for graphql server." [ "a"; "address" ] + in + Arg.(value & opt string "localhost" & doc) + in + let graphql (S (impl, store, remote_fn)) port addr = + let (module S) = Store.Impl.generic_keyed impl in + run + (let module Server = + Graphql.Server.Make + (S) + (struct + let remote = remote_fn + end) + in + let* t = store in + let server = Server.v (S.repo t) in + let* ctx = Conduit_lwt_unix.init ~src:addr () in + let ctx = Cohttp_lwt_unix.Net.init ~ctx () in + let on_exn exn = + [%logs.debug "on_exn: %s" (Printexc.to_string exn)] + in + Cohttp_lwt_unix.Server.create ~on_exn ~ctx + ~mode:(`TCP (`Port port)) + server) + in + Term.(mk graphql $ store () $ port $ addr)); + } + +let options = + { + name = "options"; + doc = "Get information about backend specific configuration options."; + man = []; + term = + (let options (store, hash, contents) = + let module Conf = Irmin.Backend.Conf in + let store, _ = Resolver.load_config ?store ?hash ?contents () in + let spec = Store.spec store in + Seq.iter + (fun (Conf.K k) -> + let name = Conf.name k in + if name = "root" || name = "uri" then () + else + let ty = Conf.ty k in + let doc = Conf.doc k |> Option.value ~default:"" in + let ty = + Fmt.str "%a" Irmin.Type.pp_ty ty + |> Astring.String.filter (fun c -> c <> '\n') + in + Fmt.pr "%s: %s\n\t%s\n" name ty doc) + (Conf.Spec.keys spec) + in + Term.(mk options $ Store.term ())); + } + +let branches = + { + name = "branches"; + doc = "List branches"; + man = []; + term = + (let branches (S (impl, store, _)) = + let (module S) = Store.Impl.generic_keyed impl in + run + (let* t = store in + let+ branches = S.Branch.list (S.repo t) in + List.iter (Fmt.pr "%a\n" (Irmin.Type.pp S.branch_t)) branches) + in + Term.(mk branches $ store ())); + } + +let weekday Unix.{ tm_wday; _ } = + match tm_wday with + | 0 -> "Sun" + | 1 -> "Mon" + | 2 -> "Tue" + | 3 -> "Wed" + | 4 -> "Thu" + | 5 -> "Fri" + | 6 -> "Sat" + | _ -> assert false + +let month Unix.{ tm_mon; _ } = + match tm_mon with + | 0 -> "Jan" + | 1 -> "Feb" + | 2 -> "Mar" + | 3 -> "Apr" + | 4 -> "May" + | 5 -> "Jun" + | 6 -> "Jul" + | 7 -> "Aug" + | 8 -> "Sep" + | 9 -> "Oct" + | 10 -> "Nov" + | 11 -> "Dec" + | _ -> assert false + +let log = + { + name = "log"; + doc = "List commits"; + man = []; + term = + (let plain = + let doc = Arg.info ~doc:"Show plain text without pager" [ "plain" ] in + Arg.(value & flag & doc) + in + let pager = + let doc = Arg.info ~doc:"Specify pager program to use" [ "pager" ] in + Arg.(value & opt string "pager" & doc) + in + let num = + let doc = + Arg.info ~doc:"Number of entries to show" [ "n"; "max-count" ] + in + Arg.(value & opt (some int) None & doc) + in + let skip = + let doc = Arg.info ~doc:"Number of entries to skip" [ "skip" ] in + Arg.(value & opt (some int) None & doc) + in + let reverse = + let doc = Arg.info ~doc:"Print in reverse order" [ "reverse" ] in + Arg.(value & flag & doc) + in + let exception Return in + let commits (S (impl, store, _)) plain pager num skip reverse = + let (module S) = Store.Impl.generic_keyed impl in + run + (let* t = store in + let fmt f date = + Fmt.pf f "%s %s %02d %02d:%02d:%02d %04d" (weekday date) + (month date) date.tm_mday date.tm_hour date.tm_min date.tm_sec + (date.tm_year + 1900) + in + let repo = S.repo t in + let skip = ref (Option.value ~default:0 skip) in + let num = Option.value ~default:0 num in + let num_count = ref 0 in + let commit formatter key = + if num > 0 && !num_count >= num then raise Return + else if !skip > 0 then + let () = decr skip in + Lwt.return_unit + else + let+ commit = S.Commit.of_key repo key >|= Option.get in + let hash = S.Backend.Commit.Key.to_hash key in + let info = S.Commit.info commit in + let date = S.Info.date info in + let author = S.Info.author info in + let message = S.Info.message info in + let date = Unix.localtime (Int64.to_float date) in + let () = + Fmt.pf formatter "commit %a\nAuthor: %s\nDate: %a\n\n%s\n\n%!" + (Irmin.Type.pp S.hash_t) hash author fmt date message + in + incr num_count + in + let* max = S.Head.get t >|= fun x -> [ `Commit (S.Commit.key x) ] in + let iter ~commit ~max repo = + Lwt.catch + (fun () -> + if reverse then S.Repo.iter ~commit ~min:[] ~max repo + else S.Repo.breadth_first_traversal ~commit ~max repo) + (function Return -> Lwt.return_unit | exn -> raise exn) + in + if plain then + let commit = commit Format.std_formatter in + iter ~commit ~max repo + else + Lwt.catch + (fun () -> + let out = Unix.open_process_out pager in + let commit = commit (Format.formatter_of_out_channel out) in + let+ () = iter ~commit ~max repo in + let _ = Unix.close_process_out out in + ()) + (function + | Sys_error s when String.equal s "Broken pipe" -> + Lwt.return_unit + | exn -> raise exn)) + in + Term.(mk commits $ store () $ plain $ pager $ num $ skip $ reverse)); + } + +let default = + let doc = "Irmin, the database that never forgets." in + let man = + [ + `S "DESCRIPTION"; + `P + "Irmin is a distributed database used primarily for application data. \ + It is designed to work with a large variety of backends and has \ + built-in snapshotting, reverting and branching mechanisms."; + `P + "Use either $(mname) --help or $(mname) help for \ + more information on a specific command."; + ] + in + let usage () = + Fmt.pr + "usage: irmin [--version]\n\ + \ [--help]\n\ + \ []\n\n\ + The most commonly used subcommands are:\n\ + \ init %s\n\ + \ get %s\n\ + \ set %s\n\ + \ remove %s\n\ + \ list %s\n\ + \ tree %s\n\ + \ clone %s\n\ + \ fetch %s\n\ + \ merge %s\n\ + \ pull %s\n\ + \ push %s\n\ + \ snapshot %s\n\ + \ revert %s\n\ + \ watch %s\n\ + \ dot %s\n\ + \ graphql %s\n\ + \ http %s\n\ + \ options %s\n\ + \ branches %s\n\ + \ log %s\n\n\ + See `irmin help ` for more information on a specific command.\n\ + %!" + init.doc get.doc set.doc remove.doc list.doc tree.doc clone.doc fetch.doc + merge.doc pull.doc push.doc snapshot.doc revert.doc watch.doc dot.doc + graphql.doc http.doc options.doc branches.doc log.doc + in + ( Term.(mk usage $ const ()), + deprecated_info "irmin" ~version:Irmin.version ~sdocs:global_option_section + ~doc ~man ) + +let commands = + List.map create_command + [ + help; + init; + http; + get; + set; + remove; + list; + tree; + clone; + fetch; + merge; + pull; + push; + snapshot; + revert; + watch; + dot; + graphql; + options; + branches; + log; + ] + +let run ~default:x y = + match deprecated_eval_choice x y with `Error _ -> exit 1 | _ -> () diff --git a/vendors/irmin/src/irmin-cli/cli.mli b/vendors/irmin/src/irmin-cli/cli.mli new file mode 100644 index 000000000000..6141f56afa6b --- /dev/null +++ b/vendors/irmin/src/irmin-cli/cli.mli @@ -0,0 +1,42 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** CLI commands. *) + +type command = (unit Cmdliner.Term.t * Cmdliner.Term.info[@alert "-deprecated"]) +(** [Cmdliner] commands. *) + +val default : command +(** The default command: show a summary of the commands. *) + +val commands : command list +(** List of available sub-commands. *) + +val run : default:command -> command list -> unit +(** Create a command-line tool with the given subcommands. *) + +(** {2 Command-builder helper} *) + +type sub = { + name : string; + doc : string; + man : Cmdliner.Manpage.block list; + term : unit Cmdliner.Term.t; +} +(** Subcommand. *) + +val create_command : sub -> command +(** Build a subcommand. *) diff --git a/vendors/irmin/src/irmin-cli/dune b/vendors/irmin/src/irmin-cli/dune new file mode 100644 index 000000000000..fef4f2b5cf9c --- /dev/null +++ b/vendors/irmin/src/irmin-cli/dune @@ -0,0 +1,23 @@ +(library + (name irmin_cli) + (public_name irmin-cli) + (libraries + astring + dynlink + irmin + irmin-tezos + irmin-pack.unix + irmin-git.unix + irmin-fs.unix + irmin-graphql.unix + irmin-http.unix + irmin-watcher + cmdliner + git-unix + cohttp-lwt-unix + unix + yaml) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-cli/import.ml b/vendors/irmin/src/irmin-cli/import.ml new file mode 100644 index 000000000000..fff6d09bdbae --- /dev/null +++ b/vendors/irmin/src/irmin-cli/import.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin-cli/info.ml b/vendors/irmin/src/irmin-cli/info.ml new file mode 100644 index 000000000000..e8a35aa652dc --- /dev/null +++ b/vendors/irmin/src/irmin-cli/info.ml @@ -0,0 +1,34 @@ +(* + * Copyright (c) 2013-2021 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Irmin.Info.S) = struct + include I + + let v ?author fmt = + Fmt.kstr + (fun message () -> + let date = Int64.of_float (Unix.gettimeofday ()) in + let author = + match author with + | Some a -> a + | None -> + (* XXX: get "git config user.name" *) + Printf.sprintf "Irmin %s.[%d]" (Unix.gethostname ()) + (Unix.getpid ()) + in + v ~author ~message date) + fmt +end diff --git a/vendors/irmin/src/irmin-cli/info.mli b/vendors/irmin/src/irmin-cli/info.mli new file mode 100644 index 000000000000..515845dc7511 --- /dev/null +++ b/vendors/irmin/src/irmin-cli/info.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2021 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Irmin.Info.S) : sig + include Irmin.Info.S with type t = I.t + + val v : ?author:string -> ('b, Format.formatter, unit, f) format4 -> 'b +end diff --git a/vendors/irmin/src/irmin-cli/irmin_cli.ml b/vendors/irmin/src/irmin-cli/irmin_cli.ml new file mode 100644 index 000000000000..929dcffa71c5 --- /dev/null +++ b/vendors/irmin/src/irmin-cli/irmin_cli.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Cli +module Resolver = Resolver diff --git a/vendors/irmin/src/irmin-cli/irmin_cli.mli b/vendors/irmin/src/irmin-cli/irmin_cli.mli new file mode 100644 index 000000000000..d2ee8e93e26e --- /dev/null +++ b/vendors/irmin/src/irmin-cli/irmin_cli.mli @@ -0,0 +1,7 @@ +include module type of Cli +(** @inline *) + +module Resolver : sig + include module type of Resolver + (** @inline *) +end diff --git a/vendors/irmin/src/irmin-cli/resolver.ml b/vendors/irmin/src/irmin-cli/resolver.ml new file mode 100644 index 000000000000..e0c2a250a781 --- /dev/null +++ b/vendors/irmin/src/irmin-cli/resolver.ml @@ -0,0 +1,732 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Cmdliner +open Astring +module Xgit = Irmin_git_unix +module Http = Irmin_http_unix + +let global_option_section = "COMMON OPTIONS" + +module Conf = Irmin.Backend.Conf + +let try_parse ty v = + match Irmin.Type.of_string ty v with + | Error e -> ( + let x = Format.sprintf "{\"some\": %s}" v in + match Irmin.Type.of_string ty x with + | Error _ -> + let y = Format.sprintf "{\"some\": \"%s\"}" v in + Irmin.Type.of_string ty y |> Result.map_error (fun _ -> e) + | v -> v) + | v -> v + +let pconv t = + let pp = Irmin.Type.pp t in + let parse s = + match try_parse t s with Ok x -> `Ok x | Error (`Msg e) -> `Error e + in + (parse, pp) + +let config_path_term = + let name = "config" in + let doc = "Allows configuration file to be specified on the command-line." in + let docv = "PATH" in + let docs = "COMMON OPTIONS" in + let mk = pconv Irmin.Type.(option string) in + let i = Arg.info ~docv ~docs ~doc [ name ] in + Arg.(value & opt mk None i) + +let root_term = + let name = "root" in + let doc = "The location of the Irmin store on disk." in + let docv = "PATH" in + let docs = "COMMON OPTIONS" in + let mk = pconv Irmin.Type.(option string) in + let i = Arg.info ~docv ~docs ~doc [ name ] in + Arg.(value & opt mk None i) + +let ( / ) = Filename.concat +let global_config_path = "irmin" / "config.yml" + +(* Contents *) + +module Contents = struct + type t = (module Irmin.Contents.S) + + let all = + ref + [ + ("string", (module Irmin.Contents.String : Irmin.Contents.S)); + ("json", (module Irmin.Contents.Json)); + ("json-value", (module Irmin.Contents.Json_value)); + ] + + let default = "string" |> fun n -> ref (n, List.assoc n !all) + + let add name ?default:(x = false) m = + all := (name, m) :: !all; + if x then default := (name, m) + + let find name = + match List.assoc_opt (String.Ascii.lowercase name) !all with + | Some c -> c + | None -> + let valid = String.concat ~sep:", " (List.split !all |> fst) in + let msg = + Printf.sprintf "Invalid content type: %s. Expected one of: %s." name + valid + in + failwith msg + + let term () = + let content_types = !all |> List.map (fun (name, _) -> (name, name)) in + let kind = + let doc = + Fmt.str "The type of user-defined contents (%s). Default is `%s'." + (Arg.doc_alts_enum content_types) + (fst !default) + in + let arg_info = + Arg.info ~doc ~docs:global_option_section [ "contents"; "c" ] + in + Arg.(value & opt (some string) None & arg_info) + in + let create kind = kind in + Term.(const create $ kind) +end + +type contents = Contents.t + +module Hash = struct + type t = (module Irmin.Hash.S) + type hash_function = Fixed of t | Variable_size of (int option -> t) + + module type SIZEABLE = functor + (S : sig + val digest_size : int + end) + -> Irmin.Hash.S + + let variable_size (module Make : SIZEABLE) (module Default : Irmin.Hash.S) = + Variable_size + (function + | Some s -> + (module struct + include Make (struct + let digest_size = s + end) + end : Irmin.Hash.S) + | None -> (module Default)) + + let all = + ref + [ + ( "blake2b", + variable_size + (module Irmin.Hash.Make_BLAKE2B : SIZEABLE) + (module Irmin.Hash.BLAKE2B : Irmin.Hash.S) ); + ( "blake2s", + variable_size + (module Irmin.Hash.Make_BLAKE2S : SIZEABLE) + (module Irmin.Hash.BLAKE2S : Irmin.Hash.S) ); + ("rmd160", Fixed (module Irmin.Hash.RMD160 : Irmin.Hash.S)); + ("sha1", Fixed (module Irmin.Hash.SHA1 : Irmin.Hash.S)); + ("sha224", Fixed (module Irmin.Hash.SHA224 : Irmin.Hash.S)); + ("sha256", Fixed (module Irmin.Hash.SHA256 : Irmin.Hash.S)); + ("sha384", Fixed (module Irmin.Hash.SHA384 : Irmin.Hash.S)); + ("sha512", Fixed (module Irmin.Hash.SHA512 : Irmin.Hash.S)); + ("tezos", Fixed (module Irmin_tezos.Schema.Hash : Irmin.Hash.S)); + ] + + let default = ref ("blake2b", (module Irmin.Hash.BLAKE2B : Irmin.Hash.S)) + + let add name ?default:(x = false) m = + all := (name, Fixed m) :: !all; + if x then default := (name, m) + + let find_hashfn name = + match List.assoc_opt (String.Ascii.lowercase name) !all with + | Some c -> c + | None -> + let valid = String.concat ~sep:", " (List.split !all |> fst) in + let msg = + Printf.sprintf "Invalid hash function: %s. Expected one of: %s." name + valid + in + failwith msg + + let of_specifier hashname = + let ( >>= ) x f = match x with Ok x -> f x | Error _ as e -> e in + (match String.cut ~rev:true ~sep:"/" hashname with + | Some (hashname, size) -> ( + match int_of_string_opt size with + | Some size -> Ok (hashname, Some size) + | None -> Error (`Msg (Fmt.str "Non-numeric hash size %s passed" size))) + | None -> Ok (hashname, None)) + >>= fun (hashname, size_opt) -> + match (find_hashfn hashname, size_opt) with + | Variable_size hashfn, size_opt -> Ok (hashfn size_opt) + | Fixed hashfn, None -> Ok hashfn + | Fixed _, Some size -> + Error + (`Msg + (Fmt.str "Cannot specify a size for hash function `%s' (%d passed)." + hashname size)) + + let find h = + of_specifier h |> function Ok h -> h | Error (`Msg e) -> failwith e + + let hash_function_conv : t Cmdliner.Arg.conv = Arg.conv (of_specifier, Fmt.nop) + + let term () = + let kind = + let quote s = Fmt.str "`%s'" s in + let hash_types = !all |> List.map (fun (name, _) -> (name, name)) in + let variable_size_types = + !all + |> List.filter (function + | _, Variable_size _ -> true + | _, Fixed _ -> false) + |> List.map fst + in + let pp_prose_list = + Fmt.of_to_string (function + | [] -> "" + | [ h ] -> quote h + | hs -> + let rev_hs = List.rev hs in + Fmt.str "%s and %s" + (String.concat ~sep:", " (List.rev_map quote (List.tl rev_hs))) + (quote (List.hd rev_hs))) + in + let pp_plural = + Fmt.of_to_string (function _ :: _ :: _ -> "s" | _ -> "") + in + let pp_variable_size_doc ppf = function + | [] -> () + | _ :: _ as hs -> + Fmt.pf ppf + "\n\ + The bit-length of the hash function%a %a may optionally be set \ + with a trailing slash (e.g. `%s/16')." + pp_plural hs pp_prose_list hs (List.hd hs) + in + let doc = + Fmt.str "The hash function (%s). Default is `%s'.%a" + (Arg.doc_alts_enum hash_types) + (fst !default) pp_variable_size_doc variable_size_types + in + let arg_info = + Arg.info ~doc ~docs:global_option_section [ "hash"; "h" ] + in + Arg.(value & opt (some hash_function_conv) None & arg_info) + in + let create kind = kind in + Term.(const create $ kind) +end + +type hash = Hash.t + +(* Store *) + +module Store = struct + module Impl = struct + type 'a t = + | Hash_keyed : (module Irmin.S with type t = 'a) -> 'a t + | Generic_keyed : (module Irmin.Generic_key.S with type t = 'a) -> 'a t + + let generic_keyed (type a) (t : a t) : + (module Irmin.Generic_key.S with type t = a) = + match t with Hash_keyed (module S) -> (module S) | Generic_keyed x -> x + + let hash_keyed = function Hash_keyed x -> Some x | Generic_keyed _ -> None + end + + type remote_fn = + ?ctx:Mimic.ctx -> ?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t + + type t = + | T : { + impl : _ Impl.t; + spec : Irmin.Backend.Conf.Spec.t; + remote : remote_fn option; + } + -> t + + let spec (T { spec; _ }) = spec + + type store_functor = + | Fixed_hash of (contents -> t) + | Variable_hash of (hash -> contents -> t) + | Fixed of t + + module type G = sig + include Irmin.S + + val remote : remote_fn + end + + let v ?remote spec s = T { impl = Impl.Hash_keyed s; spec; remote } + let v_generic ?remote spec s = T { impl = Impl.Generic_keyed s; spec; remote } + let v_git (module S : G) = v Irmin_git.Conf.spec (module S) ~remote:S.remote + + let create : + Irmin.Backend.Conf.Spec.t -> (module Irmin.Maker) -> hash -> contents -> t + = + fun spec (module S) (module H) (module C) -> + let module Schema = struct + include Irmin.Schema.KV (C) + module Hash = H + end in + let module S = S.Make (Schema) in + v spec (module S) + + let mem = create Irmin_mem.Conf.spec (module Irmin_mem) + let irf = create Irmin_fs.Conf.spec (module Irmin_fs_unix) + + let http = function + | T { impl = Generic_keyed _; _ } -> + Fmt.failwith + "Unsupported backend: can't build an HTTP server over a store that \ + is not keyed by hashes" + | T { impl = Hash_keyed (module S); spec; remote } -> + T + { + impl = Hash_keyed (module Http.Client (S)); + spec = Irmin.Backend.Conf.Spec.join spec [ Irmin_http.Conf.spec ]; + remote; + } + + let git (module C : Irmin.Contents.S) = v_git (module Xgit.FS.KV (C)) + let git_mem (module C : Irmin.Contents.S) = v_git (module Xgit.Mem.KV (C)) + + module Irmin_pack_maker : Irmin.Generic_key.Maker = struct + include Irmin_pack_unix.Maker (Irmin_tezos.Conf) + + module Make (Schema : Irmin.Schema.S) = Make (struct + include Schema + module Node = Irmin.Node.Generic_key.Make (Hash) (Path) (Metadata) + module Commit_maker = Irmin.Commit.Generic_key.Maker (Info) + module Commit = Commit_maker.Make (Hash) + end) + end + + let pack : hash -> contents -> t = + fun (module H) (module C) -> + let module Schema = struct + include Irmin.Schema.KV (C) + module Hash = H + end in + v_generic Irmin_pack.Conf.spec (module Irmin_pack_maker.Make (Schema)) + + let tezos = v_generic Irmin_pack.Conf.spec (module Irmin_tezos.Store) + + let all = + ref + [ + ("git", Fixed_hash git); + ("git-mem", Fixed_hash git_mem); + ("irf", Variable_hash irf); + ("mem", Variable_hash mem); + ("mem-http", Variable_hash (fun h c -> http (mem h c))); + ("git-http", Fixed_hash (fun c -> http (git c))); + ("pack", Variable_hash pack); + ("tezos", Fixed tezos); + ] + + let default = "git" |> fun n -> ref (n, List.assoc n !all) + + let add name ?default:(x = false) m = + all := (name, m) :: !all; + if x then default := (name, m) + + let find name = + match List.assoc_opt (String.Ascii.lowercase name) !all with + | Some s -> s + | None -> + let valid = String.concat ~sep:", " (List.split !all |> fst) in + let msg = + Printf.sprintf "Invalid store type: %s. Expected one of: %s." name + valid + in + failwith msg + + let generic_keyed = function + | T { impl = Generic_keyed (module S); _ } -> + (module S : Irmin.Generic_key.S) + | T { impl = Hash_keyed (module S); _ } -> (module S : Irmin.Generic_key.S) + + let hash_keyed = function + | T { impl = Generic_keyed (module S); _ } -> None + | T { impl = Hash_keyed (module S); _ } -> Some (module S : Irmin.S) + + let remote (T { remote; _ }) = remote + + let term () = + let store = + let store_types = !all |> List.map (fun (name, _) -> (name, name)) in + let doc = + Fmt.str "The storage backend (%s). Default is `%s'." + (Arg.doc_alts_enum store_types) + (fst !default) + in + let arg_info = + Arg.info ~doc ~docs:global_option_section [ "s"; "store" ] + in + Arg.(value & opt (some string) None & arg_info) + in + let create store hash contents = (store, hash, contents) in + Term.(const create $ store $ Hash.term () $ Contents.term ()) +end + +(* Config *) + +let home = + try Sys.getenv "HOME" + with Not_found -> ( + try (Unix.getpwuid (Unix.getuid ())).Unix.pw_dir + with Unix.Unix_error _ | Not_found -> + if Sys.win32 then try Sys.getenv "AppData" with Not_found -> "" else "") + +let config_root () = + try Sys.getenv "XDG_CONFIG_HOME" + with Not_found -> + if Sys.win32 then home / "Local Settings" else home / ".config" + +let config_term = + let create root config_path (opts : (string * string) list list) = + (root, config_path, opts) + in + let doc = + "Backend-specific options. See the output of `irmin options` for a list of \ + options supported by the selected backend" + in + let opts = + Arg.info ~docv:"OPTIONS" ~docs:global_option_section ~doc + [ "opt"; "options" ] + in + Term.( + const create + $ root_term + $ config_path_term + $ Arg.(value @@ opt_all (list (pair ~sep:'=' string string)) [] opts)) + +type store = S : 'a Store.Impl.t * 'a Lwt.t * Store.remote_fn option -> store + +let rec read_config_file path = + let home = config_root () / global_config_path in + let path = + match path with + | Some path -> + if (not (Sys.file_exists path)) && not (String.equal path home) then + Fmt.failwith "config file does not exist: %s" path + else path + | None -> "irmin.yml" + in + let global = + if String.equal path home then `O [] else read_config_file (Some home) + in + if not (Sys.file_exists path) then global + else + let () = [%logs.debug "Loading config from file: %s" path] in + let oc = open_in path in + let len = in_channel_length oc in + let buf = really_input_string oc len in + close_in oc; + if Astring.String.(is_empty (trim buf)) then `O [] + else + match Yaml.of_string buf with + | Ok (`O _ as y) -> Yaml.Util.combine_exn y global + | Ok `Null -> global + | Ok _ -> Fmt.failwith "invalid YAML file: %s" path + | Error (`Msg msg) -> Fmt.failwith "unable to parse YAML: %s" msg + +let rec json_of_yaml : Yaml.value -> Yojson.Basic.t = function + | `O x -> `Assoc (List.map (fun (k, v) -> (k, json_of_yaml v)) x) + | `A x -> `List (List.map json_of_yaml x) + | (`Null | `Bool _ | `Float _ | `String _) as x -> x + +let parse_config ?root y spec = + let config = Conf.empty spec in + (* Initialise root for the examples in README to pass. *) + let config = Conf.add config (Conf.root spec) "." in + let config = + List.fold_left + (fun config k -> + match (Conf.Spec.find_key spec k, Yaml.Util.find_exn k y) with + | Some (Irmin.Backend.Conf.K k), Some v -> + let v = json_of_yaml v |> Yojson.Basic.to_string in + let v = + match Irmin.Type.of_json_string (Conf.ty k) v with + | Error _ -> + let v = Format.sprintf "{\"some\": %s}" v in + Irmin.Type.of_json_string (Conf.ty k) v |> Result.get_ok + | Ok v -> v + in + Conf.add config k v + | None, _ -> ( + match k with + | "contents" | "hash" | "store" | "plugin" -> config + | _ -> + Fmt.invalid_arg "unknown config key for %s: %s" + (Conf.Spec.name spec) k) + | _ -> config) + config (Yaml.Util.keys_exn y) + in + let config = + match (root, Conf.Spec.find_key spec "root") with + | Some root, Some (K r) -> + let v = Irmin.Type.of_string (Conf.ty r) root |> Result.get_ok in + Conf.add config r v + | _ -> config + in + config + +let load_plugin ?plugin config = + match plugin with + | Some p -> Dynlink.loadfile_private p + | None -> ( + match Yaml.Util.find "plugin" config with + | Ok (Some v) -> Dynlink.loadfile_private (Yaml.Util.to_string_exn v) + | _ -> ()) + +let get_store ?plugin config (store, hash, contents) = + let () = load_plugin ?plugin config in + let store = + match store with + | Some s -> Store.find s + | None -> ( + match Yaml.Util.find_exn "store" config with + | Some (`String s) -> ( + match store with Some s -> Store.find s | None -> Store.find s) + | _ -> snd !Store.default) + in + let contents = + match contents with + | Some s -> Contents.find s + | None -> ( + match Yaml.Util.find_exn "contents" config with + | Some (`String s) -> Contents.find s + | _ -> snd !Contents.default) + in + let hash = + match hash with + | Some s -> Some s + | None -> ( + match Yaml.Util.find_exn "hash" config with + | Some (`String s) -> Some (Hash.find s) + | _ -> None) + in + match store with + | Variable_hash s -> + let hash : Hash.t = Option.value ~default:(snd !Hash.default) hash in + s hash contents + | Fixed_hash s -> ( + (* error if a hash function has been passed *) + match hash with + | None -> s contents + | _ -> + Fmt.failwith "Cannot customize the hash function for the given store") + | Fixed s -> ( + match hash with + | None -> s + | _ -> + Fmt.failwith "Cannot customize the hash function for the given store") + +let load_config ?plugin ?root ?config_path ?store ?hash ?contents () = + let y = read_config_file config_path in + let store = get_store ?plugin y (store, hash, contents) in + let spec = Store.spec store in + let config = parse_config ?root y spec in + (store, config) + +let string_value = function `String s -> s | _ -> raise Not_found + +let find_key config name = + Yaml.Util.find_exn name config |> Option.map (fun x -> string_value x) + +let handle_decode_err err t x = + match Irmin.Type.of_string t x with Ok h -> h | _ -> invalid_arg err + +let get_branch (type a) + (module S : Irmin.Generic_key.S with type Schema.Branch.t = a) config branch + = + let of_string = Option.map (handle_decode_err "invalid branch" S.Branch.t) in + match branch with + | None -> of_string (find_key config "branch") + | Some t -> of_string (Some t) + +let get_commit (type a b) + (module S : Irmin.Generic_key.S + with type commit = a + and type Schema.Hash.t = b) config commit = + let of_string = Option.map (handle_decode_err "invalid commit" S.Hash.t) in + match commit with + | None -> of_string (find_key config "commit") + | Some t -> of_string (Some t) + +let build_irmin_config config root opts (store, hash, contents) branch commit + plugin : store = + let (T { impl; spec; remote }) = + get_store ?plugin config (store, hash, contents) + in + let (module S) = Store.Impl.generic_keyed impl in + let branch = get_branch (module S) config branch in + let commit = get_commit (module S) config commit in + let config = parse_config ?root config spec in + let config = + List.fold_left + (fun config (k, v) -> + let (Irmin.Backend.Conf.K key) = + if k = "root" then + invalid_arg + "use the --root flag to set the root directory instead of \ + passing it as a config" + else + match Conf.Spec.find_key spec k with + | Some x -> x + | None -> invalid_arg ("opt: " ^ k) + in + let ty = Conf.ty key in + let v = try_parse ty v |> Result.get_ok in + let config = Conf.add config key v in + config) + config (List.flatten opts) + in + let spec = + match (branch, commit) with + | _, Some hash -> ( + S.Repo.v config >>= fun repo -> + let* commit = S.Commit.of_hash repo hash in + match commit with + | None -> invalid_arg "unknown commit" + | Some c -> S.of_commit c) + | None, None -> S.Repo.v config >>= S.main + | Some b, None -> S.Repo.v config >>= fun repo -> S.of_branch repo b + in + S (impl, spec, remote) + +let branch = + let doc = + Arg.info ~doc:"The current branch name. Default is the store's main branch." + ~docs:global_option_section ~docv:"BRANCH" [ "b"; "branch" ] + in + Arg.(value & opt (some string) None & doc) + +let commit = + let doc = + Arg.info + ~doc:"The store's head commit. This will take precedence over --branch." + ~docs:global_option_section ~docv:"COMMIT" [ "commit" ] + in + Arg.(value & opt (some string) None & doc) + +let plugin = + let doc = "Register new contents, store or hash types" in + Arg.(value & opt (some string) None & info ~doc [ "plugin" ]) + +let store () = + let create plugin store (root, config_path, opts) branch commit = + let y = read_config_file config_path in + build_irmin_config y root opts store branch commit plugin + in + Term.(const create $ plugin $ Store.term () $ config_term $ branch $ commit) + +let header_conv = + let parse str = + match String.cut ~sep:":" str with + | Some (k, v) -> Ok (String.trim k, String.trim v) + | None -> Error (`Msg "invalid header") + in + let print ppf (k, v) = Fmt.pf ppf "%s: %s" k v in + Cmdliner.Arg.conv (parse, print) + +let headers = + let doc = + Arg.info ~docv:"HEADER" ~doc:"Extra HTTP headers to use when sync." [ "H" ] + in + Arg.(value & opt_all header_conv [] & doc) + +type Irmin.remote += R of Cohttp.Header.t option * string + +(* FIXME: this is a very crude heuristic to choose the remote + kind. Would be better to read the config file and look for remote + alias. *) +let infer_remote hash contents branch headers str = + let hash = match hash with None -> snd !Hash.default | Some c -> c in + let contents = + match contents with + | None -> snd !Contents.default + | Some c -> Contents.find c + in + if Sys.file_exists str then + let r = + if Sys.file_exists (str / ".git") then Store.git contents + else if Sys.file_exists (str / "store.dict") then Store.pack hash contents + else Store.irf hash contents + in + match r with + | Store.T { impl; spec; _ } -> + let (module R) = Store.Impl.generic_keyed impl in + let config = Conf.empty spec in + let config = + match Conf.Spec.find_key spec "root" with + | Some (K r) -> + let v = Irmin.Type.of_string (Conf.ty r) str |> Result.get_ok in + Conf.add config r v + | _ -> config + in + let* repo = R.Repo.v config in + let branch = + match branch with + | Some b -> Irmin.Type.of_string R.branch_t b |> Result.get_ok + | None -> R.Branch.main + in + let+ r = R.of_branch repo branch in + Irmin.remote_store (module R) r + else + let headers = + match headers with [] -> None | h -> Some (Cohttp.Header.of_list h) + in + Lwt.return (R (headers, str)) + +let remote () = + let repo = + let doc = + Arg.info ~docv:"REMOTE" + ~doc:"The URI of the remote repository to clone from." [] + in + Arg.(required & pos 0 (some string) None & doc) + in + let create (store, hash, contents) (root, config_path, opts) branch commit + headers str = + let y = read_config_file config_path in + let store = + build_irmin_config y root opts (store, hash, contents) branch commit None + in + let remote = infer_remote hash contents branch headers str in + (store, remote) + in + Term.( + const create + $ Store.term () + $ config_term + $ branch + $ commit + $ headers + $ repo) diff --git a/vendors/irmin/src/irmin-cli/resolver.mli b/vendors/irmin/src/irmin-cli/resolver.mli new file mode 100644 index 000000000000..783d995c259b --- /dev/null +++ b/vendors/irmin/src/irmin-cli/resolver.mli @@ -0,0 +1,135 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Irmin store resolver. *) + +val global_option_section : string +val branch : string option Cmdliner.Term.t + +(** {1 Hash} *) +module Hash : sig + type t = (module Irmin.Hash.S) + + val add : string -> ?default:bool -> (module Irmin.Hash.S) -> unit + val find : string -> t + val term : unit -> t option Cmdliner.Term.t +end + +type hash = Hash.t + +(** {1 Contents} *) +module Contents : sig + type t = (module Irmin.Contents.S) + + val add : string -> ?default:bool -> (module Irmin.Contents.S) -> unit + val find : string -> t + val term : unit -> string option Cmdliner.Term.t +end + +type contents = Contents.t + +(** {1 Global Configuration} *) + +module Store : sig + module Impl : sig + (** The type of {i implementations} of an Irmin store. + + Stores can be either keyed by hashes or by some other abstract type. In + the latter case, the store implementation cannot be used to build HTTP / + GraphQL servers using [irmin-unix]. This limitation may be lifted in a + future version of [irmin-unix]. *) + type 'a t = + | Hash_keyed : (module Irmin.S with type t = 'a) -> 'a t + | Generic_keyed : (module Irmin.Generic_key.S with type t = 'a) -> 'a t + + val generic_keyed : 'a t -> (module Irmin.Generic_key.S with type t = 'a) + val hash_keyed : 'a t -> (module Irmin.S with type t = 'a) option + end + + type remote_fn = + ?ctx:Mimic.ctx -> ?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t + + type t + (** The type for store configurations. A configuration value contains: the + store implementation a creator of store's state and endpoint. *) + + type store_functor = + | Fixed_hash of (contents -> t) + | Variable_hash of (hash -> contents -> t) + | Fixed of t + (** The type of constructors of a store configuration. Depending on the + backend, a store may require a hash function. *) + + val v : + ?remote:remote_fn -> + Irmin.Backend.Conf.Spec.t -> + (module Irmin.S with type t = _) -> + t + + val v_generic : + ?remote:remote_fn -> + Irmin.Backend.Conf.Spec.t -> + (module Irmin.Generic_key.S with type t = _) -> + t + + val mem : hash -> contents -> t + val irf : hash -> contents -> t + val http : t -> t + val git : contents -> t + val pack : hash -> contents -> t + val find : string -> store_functor + val add : string -> ?default:bool -> store_functor -> unit + val spec : t -> Irmin.Backend.Conf.Spec.t + val generic_keyed : t -> (module Irmin.Generic_key.S) + val hash_keyed : t -> (module Irmin.S) option + val remote : t -> remote_fn option + + val term : + unit -> (string option * hash option * string option) Cmdliner.Term.t +end + +(** {1 Stores} *) + +val load_config : + ?plugin:string -> + ?root:string -> + ?config_path:string -> + ?store:string -> + ?hash:hash -> + ?contents:string -> + unit -> + Store.t * Irmin.config +(** Load config file from disk + + [plugin] is the path to an OCaml plugin in cmxs format to be loaded at + runtime + + [config_path] can be used to specify the location of a configuration file. + + [root] is used to specify the path of the store. + + The values provided for [store], [hash] and [contents] will be used by + default if no other value is found in the config file *) + +type store = S : 'a Store.Impl.t * 'a Lwt.t * Store.remote_fn option -> store + +val store : unit -> store Cmdliner.Term.t +(** Parse the command-line arguments and then the config file. *) + +type Irmin.remote += R of Cohttp.Header.t option * string + +val remote : unit -> (store * Irmin.remote Lwt.t) Cmdliner.Term.t +(** Parse a remote store location. *) diff --git a/vendors/irmin/src/irmin-containers/blob_log.ml b/vendors/irmin/src/irmin-containers/blob_log.ml new file mode 100644 index 000000000000..722284ab16b8 --- /dev/null +++ b/vendors/irmin/src/irmin-containers/blob_log.ml @@ -0,0 +1,81 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Blob_log (T : Time.S) (V : Irmin.Type.S) : + Irmin.Contents.S with type t = (V.t * T.t) list = struct + type t = (V.t * T.t) list [@@deriving irmin] + + let compare_t = Irmin.Type.(unstage (compare T.t)) + let compare (_, t1) (_, t2) = compare_t t1 t2 + + let newer_than timestamp entries = + let rec util acc = function + | [] -> List.rev acc + | (_, x) :: _ when compare_t x timestamp <= 0 -> List.rev acc + | h :: t -> util (h :: acc) t + in + util [] entries + + let merge ~old v1 v2 = + let open Irmin.Merge.Infix in + let ok = Irmin.Merge.ok in + old () >>=* fun old -> + let old = match old with None -> [] | Some o -> o in + let l1, l2 = + match old with + | [] -> (v1, v2) + | (_, t) :: _ -> (newer_than t v1, newer_than t v2) + in + let l3 = List.sort compare (List.rev_append l1 l2) in + ok (List.rev_append l3 old) + + let merge = Irmin.Merge.(option (v t merge)) +end + +module type S = sig + module Store : Irmin.KV + + type value + + val append : path:Store.path -> Store.t -> value -> unit Lwt.t + val read_all : path:Store.path -> Store.t -> value list Lwt.t +end + +module Make (Backend : Irmin.KV_maker) (T : Time.S) (V : Irmin.Type.S) = struct + module Store = Backend.Make (Blob_log (T) (V)) + + let empty_info = Store.Info.none + + type value = V.t + + let create_entry v = (v, T.now ()) + + let append ~path t v = + Store.find t path >>= function + | None -> Store.set_exn ~info:empty_info t path [ create_entry v ] + | Some l -> Store.set_exn ~info:empty_info t path (create_entry v :: l) + + let read_all ~path t = + Store.find t path >|= function + | None -> [] + | Some l -> List.map (fun (v, _) -> v) l +end + +module FS (V : Irmin.Type.S) = Make (Irmin_fs_unix.KV) (Time.Machine) (V) +module Mem (V : Irmin.Type.S) = Make (Irmin_mem.KV) (Time.Machine) (V) diff --git a/vendors/irmin/src/irmin-containers/blob_log.mli b/vendors/irmin/src/irmin-containers/blob_log.mli new file mode 100644 index 000000000000..6ac444dc0b33 --- /dev/null +++ b/vendors/irmin/src/irmin-containers/blob_log.mli @@ -0,0 +1,54 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** The implementation of log in which it is maintained as a single unit, or + blob. Hence, two versions of the log cannot share their common predecessor. + The type of values to be stored as well as a method to obtain timestamps are + provided by the user. + + Merging does the following: the newer entries from each branch, with respect + to the least common ancestor, are taken, merged and then appended in front + of the LCA. *) + +(** Signature of [Blob_log] *) +module type S = sig + module Store : Irmin.KV + (** Store for the log. All store related operations like branching, cloning, + merging, etc are done through this module. *) + + type value + (** Type of log entry *) + + val append : path:Store.path -> Store.t -> value -> unit Lwt.t + (** Append an entry to the log *) + + val read_all : path:Store.path -> Store.t -> value list Lwt.t + (** Read the entire log *) +end + +(** [Make] returns a mergeable blob log using the backend and other parameters + as specified by the user. *) +module Make (Backend : Irmin.KV_maker) (T : Time.S) (V : Irmin.Type.S) : + S with type value = V.t + +(** Blob log instantiated using the {{!Irmin_fs_unix} FS backend} provided by + [Irmin_fs_unix] and the timestamp method {!Time.Unix} *) +module FS (V : Irmin.Type.S) : S with type value = V.t + +(** Blob log instantiated using the {{!Irmin_mem} in-memory backend} provided by + [Irmin_mem] and the timestamp method {!Time.Unix} *) +module Mem (V : Irmin.Type.S) : S with type value = V.t diff --git a/vendors/irmin/src/irmin-containers/counter.ml b/vendors/irmin/src/irmin-containers/counter.ml new file mode 100644 index 000000000000..148f797771de --- /dev/null +++ b/vendors/irmin/src/irmin-containers/counter.ml @@ -0,0 +1,59 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Counter : Irmin.Contents.S with type t = int64 = struct + type t = int64 + + let t = Irmin.Type.int64 + let merge = Irmin.Merge.(option counter) +end + +module type S = sig + module Store : Irmin.KV + + val inc : + ?by:int64 -> ?info:Store.Info.f -> path:Store.path -> Store.t -> unit Lwt.t + + val dec : + ?by:int64 -> ?info:Store.Info.f -> path:Store.path -> Store.t -> unit Lwt.t + + val read : path:Store.path -> Store.t -> int64 Lwt.t +end + +module Make (Backend : Irmin.KV_maker) = struct + module Store = Backend.Make (Counter) + + let empty_info = Store.Info.none + + let modify by info t path fn = + Store.find t path >>= function + | None -> Store.set_exn ~info t path (fn 0L by) + | Some v -> Store.set_exn ~info t path (fn v by) + + let inc ?(by = 1L) ?(info = empty_info) ~path t = + modify by info t path (fun x by -> Int64.add x by) + + let dec ?(by = 1L) ?(info = empty_info) ~path t = + modify by info t path (fun x by -> Int64.sub x by) + + let read ~path t = Store.find t path >|= function None -> 0L | Some v -> v +end + +module FS = Make (Irmin_fs_unix.KV) +module Mem = Make (Irmin_mem.KV) diff --git a/vendors/irmin/src/irmin-containers/counter.mli b/vendors/irmin/src/irmin-containers/counter.mli new file mode 100644 index 000000000000..4759a7f5c22b --- /dev/null +++ b/vendors/irmin/src/irmin-containers/counter.mli @@ -0,0 +1,54 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** The implementation of an [int64] counter. This module supports operations to + increment, decrement and read the value of the counter. + + Merge semantics is as follows: if [old] is the value of the LCA and [v1] and + [v2] are the current values, then the merged value is [v1 + v2 - old]. *) + +(** Counter signature *) +module type S = sig + module Store : Irmin.KV + (** Content store of counter. All store related operations like branching, + cloning, merging, etc are done through this module. *) + + val inc : + ?by:int64 -> ?info:Store.Info.f -> path:Store.path -> Store.t -> unit Lwt.t + (** Increment the counter by the amount specified using [by]. If no value is + specified, then [by] is assigned the value 1L. *) + + val dec : + ?by:int64 -> ?info:Store.Info.f -> path:Store.path -> Store.t -> unit Lwt.t + (** Decrement the counter by the amount specified using [by]. If no value is + specified, then [by] is assigned the value 1L. *) + + val read : path:Store.path -> Store.t -> int64 Lwt.t + (** Read the value of the counter *) +end + +(** [Make] returns a mergeable counter using the backend and other parameters as + specified by the user. *) +module Make (Backend : Irmin.KV_maker) : S + +module FS : S +(** Counter instantiated using the {{!Irmin_fs_unix} FS backend} provided by + [Irmin_fs_unix] *) + +module Mem : S +(** Counter instantiated using the {{!Irmin_mem} in-memory backend} provided by + [Irmin_mem] *) diff --git a/vendors/irmin/src/irmin-containers/dune b/vendors/irmin/src/irmin-containers/dune new file mode 100644 index 000000000000..c0271dfd7251 --- /dev/null +++ b/vendors/irmin/src/irmin-containers/dune @@ -0,0 +1,8 @@ +(library + (name irmin_containers) + (public_name irmin-containers) + (libraries irmin irmin.mem irmin-fs.unix mtime mtime.clock.os) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-containers/import.ml b/vendors/irmin/src/irmin-containers/import.ml new file mode 100644 index 000000000000..2a449bdd3b77 --- /dev/null +++ b/vendors/irmin/src/irmin-containers/import.ml @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends +module FS = Irmin_fs_unix diff --git a/vendors/irmin/src/irmin-containers/irmin_containers.ml b/vendors/irmin/src/irmin-containers/irmin_containers.ml new file mode 100644 index 000000000000..313bd7847fbc --- /dev/null +++ b/vendors/irmin/src/irmin-containers/irmin_containers.ml @@ -0,0 +1,47 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Irmin_containers] is a collection of simple, ready-to-use mergeable data + structures. Each data structure works with an arbitrary Irmin backend and is + customisable in a variety of ways. + + Additionally, [Irmin_containers] supplies instantiations of each of these + data structures with two backends: + + - the {{!Irmin_mem} in-memory backend} provided by {!Irmin_mem} + - the {{!Irmin_fs_unix} FS backend} provided by {!Irmin_fs_unix}. *) + +(** {1 Data structures} *) + +module Counter = Counter +module Lww_register = Lww_register +module Blob_log = Blob_log +module Linked_log = Linked_log + +(** {1 Auxiliary signatures and modules} *) + +(** [Store_maker] is the signature for the backend input to the data structures. + The Irmin stores of the data structures are constructed using modules of + this type *) + +module type Content_addressable = Stores.Content_addressable + +(** [Cas_maker] is the signature for the store which will be used to maintain + linked data structures. The elements are hashed into this store and the hash + value is used to construct the linkages. *) + +module Time = Time diff --git a/vendors/irmin/src/irmin-containers/linked_log.ml b/vendors/irmin/src/irmin-containers/linked_log.ml new file mode 100644 index 000000000000..8ba08b1b567d --- /dev/null +++ b/vendors/irmin/src/irmin-containers/linked_log.ml @@ -0,0 +1,168 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Log_item (T : Time.S) (H : Irmin.Hash.S) (V : Irmin.Type.S) = struct + type t = { time : T.t; msg : V.t; prev : H.t option } [@@deriving irmin] +end + +module Store_item (T : Time.S) (H : Irmin.Hash.S) (V : Irmin.Type.S) = struct + module L = Log_item (T) (H) (V) + + type t = Value of L.t | Merge of L.t list [@@deriving irmin] +end + +module Linked_log + (C : Stores.Content_addressable) + (T : Time.S) + (H : Irmin.Hash.S) + (V : Irmin.Type.S) = +struct + type t = H.t [@@deriving irmin] + + module L = Log_item (T) (H) (V) + module S = Store_item (T) (H) (V) + + module Store = struct + module CAS = C.Make (H) (Store_item (T) (H) (V)) + + let get_store = + let st = CAS.v @@ C.config in + fun () -> st + + let read st k = CAS.find st k + + let read_exn st k = + CAS.find st k >>= function + | None -> Lwt.fail_with "key not found in the store" + | Some v -> Lwt.return v + + let add st v = CAS.batch st (fun t -> CAS.add t v) + end + + let append prev msg = + let* store = Store.get_store () in + Store.add store (Value { time = T.now (); msg; prev }) + + let read_key k = + let* store = Store.get_store () in + Store.read_exn store k + + let compare_t = Irmin.Type.(unstage (compare T.t)) + let sort l = List.sort (fun i1 i2 -> compare_t i2.L.time i1.L.time) l + + let merge ~old:_ v1 v2 = + let open Irmin.Merge in + let* store = Store.get_store () in + let* v1 = Store.read store v1 in + let* v2 = Store.read store v2 in + let convert_to_list = function + | None -> [] + | Some (S.Value v) -> [ v ] + | Some (S.Merge lv) -> lv + in + let lv1 = convert_to_list v1 in + let lv2 = convert_to_list v2 in + Store.add store (S.Merge (sort @@ lv1 @ lv2)) >>= ok + + let merge = Irmin.Merge.(option (v t merge)) +end + +module type S = sig + include Blob_log.S + + type cursor + + val get_cursor : path:Store.path -> Store.t -> cursor Lwt.t + val read : num_items:int -> cursor -> (value list * cursor) Lwt.t +end + +module Make + (Backend : Irmin.KV_maker) + (C : Stores.Content_addressable) + (T : Time.S) + (H : Irmin.Hash.S) + (V : Irmin.Type.S) + () = +struct + module L = Linked_log (C) (T) (H) (V) + module Store = Backend.Make (L) + + module Set_elt = struct + type t = H.t + + let compare = Irmin.Type.(unstage (compare H.t)) + end + + module HashSet = Set.Make (Set_elt) + + type value = V.t + + type cursor = { + seen : HashSet.t; + cache : Log_item(T)(H)(V).t list; + store : Store.t; + } + + let empty_info = Store.Info.none + + let append ~path t e = + let* prev = Store.find t path in + let* v = L.append prev e in + Store.set_exn ~info:empty_info t path v + + let get_cursor ~path store = + let mk_cursor seen cache = { seen; cache; store } in + Store.find store path >>= function + | None -> Lwt.return (mk_cursor HashSet.empty []) + | Some k -> ( + L.read_key k >|= function + | Value v -> mk_cursor (HashSet.singleton k) [ v ] + | Merge l -> mk_cursor (HashSet.singleton k) l) + + let rec read_log cursor num_items acc = + if num_items <= 0 then Lwt.return (List.rev acc, cursor) + else + match cursor.cache with + | [] -> Lwt.return (List.rev acc, cursor) + | { msg; prev = None; _ } :: xs -> + read_log { cursor with cache = xs } (num_items - 1) (msg :: acc) + | { msg; prev = Some pk; _ } :: xs -> ( + if HashSet.mem pk cursor.seen then + read_log { cursor with cache = xs } (num_items - 1) (msg :: acc) + else + let seen = HashSet.add pk cursor.seen in + L.read_key pk >>= function + | Value v -> + read_log + { cursor with seen; cache = L.sort (v :: xs) } + (num_items - 1) (msg :: acc) + | Merge l -> + read_log + { cursor with seen; cache = L.sort (l @ xs) } + (num_items - 1) (msg :: acc)) + + let read ~num_items cursor = read_log cursor num_items [] + let read_all ~path t = get_cursor t ~path >>= read ~num_items:max_int >|= fst +end + +module FS (C : Stores.Content_addressable) (V : Irmin.Type.S) () = + Make (Irmin_fs_unix.KV) (C) (Time.Machine) (Irmin.Hash.SHA1) (V) () + +module Mem (C : Stores.Content_addressable) (V : Irmin.Type.S) () = + Make (Irmin_mem.KV) (C) (Time.Machine) (Irmin.Hash.SHA1) (V) () diff --git a/vendors/irmin/src/irmin-containers/linked_log.mli b/vendors/irmin/src/irmin-containers/linked_log.mli new file mode 100644 index 000000000000..4c6f05084a3a --- /dev/null +++ b/vendors/irmin/src/irmin-containers/linked_log.mli @@ -0,0 +1,61 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** The linked list implementation of log. Due to the linked property, two + versions of the log share their common predecessor. As it is a linked data + structure, a content addressable store is required. Along with that, a + method to obtain timestamps, a hash for the content addressable store and + the type of values stored must also be provided. *) + +(** Signature of [Linked_log] *) +module type S = sig + include Blob_log.S + (** @inline *) + + type cursor + (** Type of cursor. Cursor is like a marker from which a certain number of + entries can be read *) + + val get_cursor : path:Store.path -> Store.t -> cursor Lwt.t + (** Create a new cursor over the log entires at the given path *) + + val read : num_items:int -> cursor -> (value list * cursor) Lwt.t + (** Read at most [num_items] entries from the cursor. If the number specified + is greater than the number of log entries from the cursor, the log is read + till the end. If the input cursor has already reached the end, then an + empty list is returned *) +end + +(** [Make] returns a mergeable linked log using the backend and other parameters + as specified by the user. *) +module Make + (Backend : Irmin.KV_maker) + (C : Stores.Content_addressable) + (T : Time.S) + (H : Irmin.Hash.S) + (V : Irmin.Type.S) + () : S with type value = V.t + +(** Linked log instantiated using the {{!Irmin_fs_unix} FS backend} provided by + [Irmin_fs_unix], timestamp method {!Time.Unix} and hash {!Irmin.Hash.SHA1} *) +module FS (C : Stores.Content_addressable) (V : Irmin.Type.S) () : + S with type value = V.t + +(** Linked log instantiated using the {{!Irmin_mem} in-memory backend} provided + by [Irmin_mem], timestamp method {!Time.Unix} and hash {!Irmin.Hash.SHA1} *) +module Mem (C : Stores.Content_addressable) (V : Irmin.Type.S) () : + S with type value = V.t diff --git a/vendors/irmin/src/irmin-containers/lww_register.ml b/vendors/irmin/src/irmin-containers/lww_register.ml new file mode 100644 index 000000000000..8c5ed1b1a8fc --- /dev/null +++ b/vendors/irmin/src/irmin-containers/lww_register.ml @@ -0,0 +1,65 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module LWW (T : Time.S) (V : Irmin.Type.S) : + Irmin.Contents.S with type t = V.t * T.t = struct + type t = V.t * T.t [@@deriving irmin] + + let compare_t = Irmin.Type.(unstage (compare T.t)) + let compare_v = Irmin.Type.(unstage (compare V.t)) + + let compare (v1, t1) (v2, t2) = + let res = compare_t t1 t2 in + if res = 0 then compare_v v1 v2 else res + + let merge ~old:_ v1 v2 = + let open Irmin.Merge in + if compare v1 v2 > 0 then ok v1 else ok v2 + + let merge = Irmin.Merge.(option (v t merge)) +end + +module type S = sig + module Store : Irmin.KV + + type value + + val read : path:Store.path -> Store.t -> value option Lwt.t + + val write : + ?info:Store.Info.f -> path:Store.path -> Store.t -> value -> unit Lwt.t +end + +module Make (Backend : Irmin.KV_maker) (T : Time.S) (V : Irmin.Type.S) = struct + module Store = Backend.Make (LWW (T) (V)) + + let empty_info = Store.Info.none + + type value = V.t + + let read ~path t = + Store.find t path >|= function None -> None | Some (v, _) -> Some v + + let write ?(info = empty_info) ~path t v = + let timestamp = T.now () in + Store.set_exn ~info t path (v, timestamp) +end + +module FS (V : Irmin.Type.S) = Make (Irmin_fs_unix.KV) (Time.Machine) (V) +module Mem (V : Irmin.Type.S) = Make (Irmin_mem.KV) (Time.Machine) (V) diff --git a/vendors/irmin/src/irmin-containers/lww_register.mli b/vendors/irmin/src/irmin-containers/lww_register.mli new file mode 100644 index 000000000000..ac8851a35bbf --- /dev/null +++ b/vendors/irmin/src/irmin-containers/lww_register.mli @@ -0,0 +1,53 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** The implementation of last-write-wins register. The value to be stored in + the register and the timestamp method are provided by the user. + + Merge semantics: The value with the largest timestamp is chosen. If two + values have the same timestamp, then the larger value is selected based on + the compare specified by the user. *) + +(** Signature of [Lww_register] *) +module type S = sig + module Store : Irmin.KV + (** Content store of the register. All store related operations like + branching, cloning, merging, etc are done through this module. *) + + type value + (** Type of values stored in the register *) + + val read : path:Store.path -> Store.t -> value option Lwt.t + (** Reads the value from the register. Returns [None] if no value is written *) + + val write : + ?info:Store.Info.f -> path:Store.path -> Store.t -> value -> unit Lwt.t + (** Writes the provided value to the register *) +end + +(** [Make] returns a mergeable last-write-wins register using the backend and + other parameters as specified by the user. *) +module Make (Backend : Irmin.KV_maker) (T : Time.S) (V : Irmin.Type.S) : + S with type value = V.t + +(** LWW register instantiated using the {{!Irmin_fs_unix} FS backend} provided + by [Irmin_fs_unix] and the timestamp method {!Time.Unix} *) +module FS (V : Irmin.Type.S) : S with type value = V.t + +(** LWW register instantiated using the {{!Irmin_mem} in-memory backend} + provided by [Irmin_mem] and the timestamp method {!Time.Unix} *) +module Mem (V : Irmin.Type.S) : S with type value = V.t diff --git a/vendors/irmin/src/irmin-containers/stores.ml b/vendors/irmin/src/irmin-containers/stores.ml new file mode 100644 index 000000000000..8474e1724b16 --- /dev/null +++ b/vendors/irmin/src/irmin-containers/stores.ml @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type Content_addressable = sig + module Make : Irmin.Content_addressable.Maker + + val config : Irmin.config +end diff --git a/vendors/irmin/src/irmin-containers/time.ml b/vendors/irmin/src/irmin-containers/time.ml new file mode 100644 index 000000000000..9a308d85cb3e --- /dev/null +++ b/vendors/irmin/src/irmin-containers/time.ml @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + include Irmin.Type.S + + val now : unit -> t +end + +module Machine : S = struct + type t = Mtime.t + + let t = + let open Mtime in + Irmin.Type.map ~equal ~compare Irmin.Type.int64 Mtime.of_uint64_ns + Mtime.to_uint64_ns + + let now = Mtime_clock.now +end diff --git a/vendors/irmin/src/irmin-containers/time.mli b/vendors/irmin/src/irmin-containers/time.mli new file mode 100644 index 000000000000..7a7da4a707d3 --- /dev/null +++ b/vendors/irmin/src/irmin-containers/time.mli @@ -0,0 +1,32 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Time] specifies a source of timestamps. Timestamps must be monotonic for + the data structures to function properly. *) + +(** Signature for the timestamps *) +module type S = sig + include Irmin.Type.S + (** Type of the timestamp *) + + val now : unit -> t + (** Returns a timestamp *) +end + +module Machine : S +(** A timestamp method using system-specific monotonic clocks (as provided by + the [Mtime] package). *) diff --git a/vendors/irmin/src/irmin-fs/dune b/vendors/irmin/src/irmin-fs/dune new file mode 100644 index 000000000000..abe176afd411 --- /dev/null +++ b/vendors/irmin/src/irmin-fs/dune @@ -0,0 +1,8 @@ +(library + (name irmin_fs) + (public_name irmin-fs) + (libraries astring irmin logs lwt) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-fs/import.ml b/vendors/irmin/src/irmin-fs/import.ml new file mode 100644 index 000000000000..71053e21ba54 --- /dev/null +++ b/vendors/irmin/src/irmin-fs/import.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin-fs/irmin_fs.ml b/vendors/irmin/src/irmin-fs/irmin_fs.ml new file mode 100644 index 000000000000..b3d989ea17d1 --- /dev/null +++ b/vendors/irmin/src/irmin-fs/irmin_fs.ml @@ -0,0 +1,424 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Astring + +let src = Logs.Src.create "irmin.fs" ~doc:"Irmin disk persistence" + +module Log = (val Logs.src_log src : Logs.LOG) + +let ( / ) = Filename.concat + +module type Config = sig + val dir : string -> string + val file_of_key : string -> string + val key_of_file : string -> string +end + +module type IO = sig + type path = string + + val rec_files : path -> string list Lwt.t + val file_exists : path -> bool Lwt.t + val read_file : path -> string option Lwt.t + val mkdir : path -> unit Lwt.t + + type lock + + val lock_file : string -> lock + val write_file : ?temp_dir:path -> ?lock:lock -> path -> string -> unit Lwt.t + + val test_and_set_file : + ?temp_dir:path -> + lock:lock -> + string -> + test:string option -> + set:string option -> + bool Lwt.t + + val remove_file : ?lock:lock -> path -> unit Lwt.t +end + +(* ~path *) + +module Conf = struct + include Irmin.Backend.Conf + + let spec = Spec.v "ifs" + + module Key = struct + let root = root spec + end +end + +let config r = Conf.(verify (add (empty Conf.spec) Key.root r)) + +module Read_only_ext + (IO : IO) + (S : Config) + (K : Irmin.Type.S) + (V : Irmin.Type.S) = +struct + type key = K.t + type value = V.t + type 'a t = { path : string } + + let get_path config = Option.value Conf.(find_root config) ~default:"." + + let v config = + let path = get_path config in + IO.mkdir path >|= fun () -> { path } + + let close _ = Lwt.return_unit + let cast t = (t :> read_write t) + let batch t f = f (cast t) + + let file_of_key { path; _ } key = + path / S.file_of_key (Irmin.Type.to_string K.t key) + + let lock_of_key { path; _ } key = + IO.lock_file (path / "lock" / S.file_of_key (Irmin.Type.to_string K.t key)) + + let mem t key = + let file = file_of_key t key in + IO.file_exists file + + let of_bin_string = Irmin.Type.(unstage (of_bin_string V.t)) + + let value v = + match of_bin_string v with + | Ok v -> Some v + | Error (`Msg e) -> + [%log.err "Irmin_fs.value %s" e]; + None + + let pp_key = Irmin.Type.pp K.t + + let find t key = + [%log.debug "find %a" pp_key key]; + IO.read_file (file_of_key t key) >|= function + | None -> None + | Some x -> value x + + let list t = + [%log.debug "list"]; + let+ files = IO.rec_files (S.dir t.path) in + let files = + let p = String.length t.path in + List.fold_left + (fun acc file -> + let n = String.length file in + if n <= p + 1 then acc + else + let file = String.with_range file ~first:(p + 1) in + file :: acc) + [] files + in + List.fold_left + (fun acc file -> + match Irmin.Type.of_string K.t (S.key_of_file file) with + | Ok k -> k :: acc + | Error (`Msg e) -> + [%log.err "Irmin_fs.list: %s" e]; + acc) + [] files +end + +module Append_only_ext + (IO : IO) + (S : Config) + (K : Irmin.Type.S) + (V : Irmin.Type.S) = +struct + include Read_only_ext (IO) (S) (K) (V) + + let temp_dir t = t.path / "tmp" + let to_bin_string = Irmin.Type.(unstage (to_bin_string V.t)) + + let add t key value = + [%log.debug "add %a" pp_key key]; + let file = file_of_key t key in + let temp_dir = temp_dir t in + IO.file_exists file >>= function + | true -> Lwt.return_unit + | false -> + let str = to_bin_string value in + IO.write_file ~temp_dir file str +end + +module Atomic_write_ext + (IO : IO) + (S : Config) + (K : Irmin.Type.S) + (V : Irmin.Type.S) = +struct + module RO = Read_only_ext (IO) (S) (K) (V) + module W = Irmin.Backend.Watch.Make (K) (V) + + type t = { t : unit RO.t; w : W.t } + type key = RO.key + type value = RO.value + type watch = W.watch * (unit -> unit Lwt.t) + + let temp_dir t = t.t.RO.path / "tmp" + + module E = Ephemeron.K1.Make (struct + type t = string + + let equal x y = compare x y = 0 + let hash = Hashtbl.hash + end) + + let watches = E.create 10 + + let v config = + let+ t = RO.v config in + let w = + let path = RO.get_path config in + try E.find watches path + with Not_found -> + let w = W.v () in + E.add watches path w; + w + in + { t; w } + + let close t = W.clear t.w >>= fun () -> RO.close t.t + let find t = RO.find t.t + let mem t = RO.mem t.t + let list t = RO.list t.t + + let listen_dir t = + let dir = S.dir t.t.RO.path in + let key file = + match Irmin.Type.of_string K.t file with + | Ok t -> Some t + | Error (`Msg e) -> + [%log.err "listen_dir: %s" e]; + None + in + W.listen_dir t.w dir ~key ~value:(RO.find t.t) + + let watch_key t key ?init f = + let* stop = listen_dir t in + let+ w = W.watch_key t.w key ?init f in + (w, stop) + + let watch t ?init f = + let* stop = listen_dir t in + let+ w = W.watch t.w ?init f in + (w, stop) + + let unwatch t (id, stop) = stop () >>= fun () -> W.unwatch t.w id + let raw_value = Irmin.Type.(unstage (to_bin_string V.t)) + + let set t key value = + [%log.debug "update %a" RO.pp_key key]; + let temp_dir = temp_dir t in + let file = RO.file_of_key t.t key in + let lock = RO.lock_of_key t.t key in + IO.write_file ~temp_dir file ~lock (raw_value value) >>= fun () -> + W.notify t.w key (Some value) + + let remove t key = + [%log.debug "remove %a" RO.pp_key key]; + let file = RO.file_of_key t.t key in + let lock = RO.lock_of_key t.t key in + let* () = IO.remove_file ~lock file in + W.notify t.w key None + + let test_and_set t key ~test ~set = + [%log.debug "test_and_set %a" RO.pp_key key]; + let temp_dir = temp_dir t in + let file = RO.file_of_key t.t key in + let lock = RO.lock_of_key t.t key in + let raw_value = function None -> None | Some v -> Some (raw_value v) in + let* b = + IO.test_and_set_file file ~temp_dir ~lock ~test:(raw_value test) + ~set:(raw_value set) + in + let+ () = if b then W.notify t.w key set else Lwt.return_unit in + b + + let clear t = + [%log.debug "clear"]; + let remove_file key = + IO.remove_file ~lock:(RO.lock_of_key t.t key) (RO.file_of_key t.t key) + in + list t >>= Lwt_list.iter_p remove_file +end + +module Maker_ext (IO : IO) (Obj : Config) (Ref : Config) = struct + module AO = Append_only_ext (IO) (Obj) + module AW = Atomic_write_ext (IO) (Ref) + module CA = Irmin.Content_addressable.Make (AO) + include Irmin.Maker (CA) (AW) +end + +let string_chop_prefix ~prefix str = + let len = String.length prefix in + if String.length str <= len then "" else String.with_range str ~first:len + +module Ref = struct + let dir p = p / "refs" + + (* separator for branch names is '/', so need to rewrite the path on + Windows. *) + + let file_of_key key = + let file = + if Sys.os_type <> "Win32" then key + else String.concat ~sep:Filename.dir_sep (String.cuts ~sep:"/" key) + in + "refs" / file + + let key_of_file file = + let key = string_chop_prefix ~prefix:("refs" / "") file in + if Sys.os_type <> "Win32" then key + else String.concat ~sep:"/" (String.cuts ~sep:Filename.dir_sep key) +end + +module Obj = struct + let dir t = t / "objects" + + let file_of_key k = + let pre = String.with_range k ~len:2 in + let suf = String.with_range k ~first:2 in + "objects" / pre / suf + + let key_of_file path = + let path = string_chop_prefix ~prefix:("objects" / "") path in + let path = String.cuts ~sep:Filename.dir_sep path in + let path = String.concat ~sep:"" path in + path +end + +module Append_only (IO : IO) = Append_only_ext (IO) (Obj) +module Atomic_write (IO : IO) = Atomic_write_ext (IO) (Ref) +module Maker (IO : IO) = Maker_ext (IO) (Obj) (Ref) + +module KV (IO : IO) = struct + module AO = Append_only (IO) + module AW = Atomic_write (IO) + module CA = Irmin.Content_addressable.Make (AO) + include Irmin.KV_maker (CA) (AW) +end + +module IO_mem = struct + type t = { + watches : (string, string -> unit Lwt.t) Hashtbl.t; + files : (string, string) Hashtbl.t; + } + + let t = { watches = Hashtbl.create 3; files = Hashtbl.create 13 } + + type path = string + type lock = Lwt_mutex.t + + let locks = Hashtbl.create 10 + + let lock_file file = + try Hashtbl.find locks file + with Not_found -> + let l = Lwt_mutex.create () in + Hashtbl.add locks file l; + l + + let with_lock l f = + match l with None -> f () | Some l -> Lwt_mutex.with_lock l f + + let set_listen_hook () = + let h _ dir f = + Hashtbl.replace t.watches dir f; + Lwt.return (fun () -> + Hashtbl.remove t.watches dir; + Lwt.return_unit) + in + Irmin.Backend.Watch.set_listen_dir_hook h + + let notify file = + Hashtbl.fold + (fun dir f acc -> + if String.is_prefix ~affix:dir file then f file :: acc else acc) + t.watches [] + |> Lwt_list.iter_p (fun x -> x) + + let mkdir _ = Lwt.return_unit + + let remove_file ?lock file = + with_lock lock (fun () -> + Hashtbl.remove t.files file; + Lwt.return_unit) + + let rec_files dir = + Hashtbl.fold + (fun k _ acc -> if String.is_prefix ~affix:dir k then k :: acc else acc) + t.files [] + |> Lwt.return + + let file_exists file = Hashtbl.mem t.files file |> Lwt.return + + let read_file file = + try + let buf = Hashtbl.find t.files file in + Lwt.return_some buf + with Not_found -> Lwt.return_none + + let write_file ?temp_dir:_ ?lock file v = + let* () = + with_lock lock (fun () -> + Hashtbl.replace t.files file v; + Lwt.return_unit) + in + notify file + + let equal x y = + match (x, y) with + | None, None -> true + | Some x, Some y -> String.equal x y + | _ -> false + + let test_and_set_file ?temp_dir:_ ~lock file ~test ~set = + let f () = + let old = try Some (Hashtbl.find t.files file) with Not_found -> None in + let b = + if not (equal old test) then false + else + match set with + | None -> + Hashtbl.remove t.files file; + true + | Some v -> + Hashtbl.replace t.files file v; + true + in + let+ () = if b then notify file else Lwt.return_unit in + b + in + with_lock (Some lock) f + + let clear () = + Hashtbl.clear t.files; + Hashtbl.clear t.watches; + Lwt.return_unit +end + +(* Enforce that {!S} is a sub-type of {!Irmin.Maker}. *) +module Maker_is_a_maker : Irmin.Maker = Maker (IO_mem) + +(* Enforce that {!KV} is a sub-type of {!Irmin.KV_maker}. *) +module KV_is_a_KV : Irmin.KV_maker = KV (IO_mem) diff --git a/vendors/irmin/src/irmin-fs/irmin_fs.mli b/vendors/irmin/src/irmin-fs/irmin_fs.mli new file mode 100644 index 000000000000..cebbd10c1bf8 --- /dev/null +++ b/vendors/irmin/src/irmin-fs/irmin_fs.mli @@ -0,0 +1,109 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Disk persistence. *) + +module Conf : sig + open Irmin.Backend.Conf + + val spec : Spec.t + + module Key : sig + val root : string key + end +end + +val config : string -> Irmin.config +(** [config root] is the a configuration with the key {!Irmin.Config.root} set + to [root]. **) + +module type IO = sig + (** {1 File-system abstractions} *) + + type path = string + (** The type for paths. *) + + (** {2 Read operations} *) + + val rec_files : path -> string list Lwt.t + (** [rec_files dir] is the list of files recursively present in [dir] and all + of its sub-directories. Return filenames prefixed by [dir]. *) + + val file_exists : path -> bool Lwt.t + (** [file_exist f] is true if [f] exists. *) + + val read_file : path -> string option Lwt.t + (** Read the contents of a file using mmap. *) + + (** {2 Write Operations} *) + + val mkdir : path -> unit Lwt.t + (** Create a directory. *) + + type lock + (** The type for file locks. *) + + val lock_file : path -> lock + (** [lock_file f] is the lock associated to the file [f]. *) + + val write_file : ?temp_dir:path -> ?lock:lock -> path -> string -> unit Lwt.t + (** Atomic writes. *) + + val test_and_set_file : + ?temp_dir:string -> + lock:lock -> + path -> + test:string option -> + set:string option -> + bool Lwt.t + (** Test and set. *) + + val remove_file : ?lock:lock -> path -> unit Lwt.t + (** Remove a file or directory (even if non-empty). *) +end + +module Append_only (IO : IO) : Irmin.Append_only.Maker +module Atomic_write (IO : IO) : Irmin.Atomic_write.Maker +module Maker (IO : IO) : Irmin.Maker +module KV (IO : IO) : Irmin.KV_maker with type info = Irmin.Info.default + +(** {2 Advanced configuration} *) + +module type Config = sig + (** Same as [Config] but gives more control on the file hierarchy. *) + + val dir : string -> string + (** [dir root] is the sub-directory to look for the keys. *) + + val file_of_key : string -> string + (** Convert a key to a filename. *) + + val key_of_file : string -> string + (** Convert a filename to a key. *) +end + +module Append_only_ext (IO : IO) (C : Config) : Irmin.Append_only.Maker +module Atomic_write_ext (IO : IO) (C : Config) : Irmin.Atomic_write.Maker +module Maker_ext (IO : IO) (Obj : Config) (Ref : Config) : Irmin.Maker + +(** {1 In-memory IO mocks} *) + +module IO_mem : sig + include IO + + val clear : unit -> unit Lwt.t + val set_listen_hook : unit -> unit +end diff --git a/vendors/irmin/src/irmin-fs/unix/dune b/vendors/irmin/src/irmin-fs/unix/dune new file mode 100644 index 000000000000..e406d43ff9df --- /dev/null +++ b/vendors/irmin/src/irmin-fs/unix/dune @@ -0,0 +1,8 @@ +(library + (public_name irmin-fs.unix) + (name irmin_fs_unix) + (libraries irmin-fs irmin.unix lwt.unix) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.ml b/vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.ml new file mode 100644 index 000000000000..4b11a1cb77e4 --- /dev/null +++ b/vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.ml @@ -0,0 +1,311 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends + +let src = Logs.Src.create "fs.unix" ~doc:"logs fs unix events" + +module Log = (val Logs.src_log src : Logs.LOG) + +module IO = struct + let mkdir_pool = Lwt_pool.create 1 (fun () -> Lwt.return_unit) + let mmap_threshold = 4096 + + (* Files smaller than this are loaded using [read]. Use of mmap is + necessary to handle packfiles efficiently. Since these are stored + in a weak map, we won't run out of open files if we keep + accessing the same one. Using read is necessary to handle + references, since these are mutable and can't be cached. Using + mmap here leads to hitting the OS limit on the number of open + files. This threshold must be larger than the size of a + reference. *) + + (* Pool of opened files *) + let openfile_pool = Lwt_pool.create 200 (fun () -> Lwt.return_unit) + + let protect_unix_exn = function + | Unix.Unix_error _ as e -> Lwt.fail (Failure (Printexc.to_string e)) + | e -> Lwt.fail e + + let ignore_enoent = function + | Unix.Unix_error (Unix.ENOENT, _, _) -> Lwt.return_unit + | e -> Lwt.fail e + + let protect f x = Lwt.catch (fun () -> f x) protect_unix_exn + let safe f x = Lwt.catch (fun () -> f x) ignore_enoent + + let mkdir dirname = + let rec aux dir = + if Sys.file_exists dir && Sys.is_directory dir then Lwt.return_unit + else + let clear = + if Sys.file_exists dir then ( + [%log.debug "%s already exists but is a file, removing." dir]; + safe Lwt_unix.unlink dir) + else Lwt.return_unit + in + clear >>= fun () -> + aux (Filename.dirname dir) >>= fun () -> + [%log.debug "mkdir %s" dir]; + protect (Lwt_unix.mkdir dir) 0o755 + in + Lwt_pool.use mkdir_pool (fun () -> aux dirname) + + let file_exists f = + Lwt.catch + (fun () -> Lwt_unix.file_exists f) + (function + (* See https://github.com/ocsigen/lwt/issues/316 *) + | Unix.Unix_error (Unix.ENOTDIR, _, _) -> Lwt.return_false + | e -> Lwt.fail e) + + module Lock = struct + let is_stale max_age file = + Lwt.catch + (fun () -> + let+ s = Lwt_unix.stat file in + if s.Unix.st_mtime < 1.0 (* ??? *) then false + else Unix.gettimeofday () -. s.Unix.st_mtime > max_age) + (function + | Unix.Unix_error (Unix.ENOENT, _, _) -> Lwt.return_false + | e -> Lwt.fail e) + + let unlock file = Lwt_unix.unlink file + + let lock ?(max_age = 10. *. 60. (* 10 minutes *)) ?(sleep = 0.001) file = + let rec aux i = + [%log.debug "lock %s %d" file i]; + let* is_stale = is_stale max_age file in + if is_stale then ( + [%log.err "%s is stale, removing it." file]; + unlock file >>= fun () -> aux 1) + else + let create () = + let pid = Unix.getpid () in + mkdir (Filename.dirname file) >>= fun () -> + let* fd = + Lwt_unix.openfile file + [ Unix.O_CREAT; Unix.O_RDWR; Unix.O_EXCL ] + 0o600 + in + let oc = Lwt_io.of_fd ~mode:Lwt_io.Output fd in + Lwt_io.write_int oc pid >>= fun () -> Lwt_unix.close fd + in + Lwt.catch create (function + | Unix.Unix_error (Unix.EEXIST, _, _) -> + let backoff = + 1. + +. Random.float + (let i = float i in + i *. i) + in + Lwt_unix.sleep (sleep *. backoff) >>= fun () -> aux (i + 1) + | e -> Lwt.fail e) + in + aux 1 + + let with_lock file fn = + match file with + | None -> fn () + | Some f -> lock f >>= fun () -> Lwt.finalize fn (fun () -> unlock f) + end + + type path = string + + (* we use file locking *) + type lock = path + + let lock_file x = x + let file_exists = file_exists + + let list_files kind dir = + if Sys.file_exists dir && Sys.is_directory dir then + let d = Sys.readdir dir in + let d = Array.to_list d in + let d = List.map (Filename.concat dir) d in + let d = List.filter kind d in + let d = List.sort String.compare d in + Lwt.return d + else Lwt.return_nil + + let directories dir = + list_files (fun f -> try Sys.is_directory f with Sys_error _ -> false) dir + + let files dir = + list_files + (fun f -> try not (Sys.is_directory f) with Sys_error _ -> false) + dir + + let write_string fd b = + let rec rwrite fd buf ofs len = + let* n = Lwt_unix.write_string fd buf ofs len in + if len = 0 then Lwt.fail End_of_file + else if n < len then rwrite fd buf (ofs + n) (len - n) + else Lwt.return_unit + in + match String.length b with 0 -> Lwt.return_unit | len -> rwrite fd b 0 len + + let delays = Array.init 20 (fun i -> 0.1 *. (float i ** 2.)) + + let command fmt = + Printf.ksprintf + (fun str -> + [%log.debug "[exec] %s" str]; + let i = Sys.command str in + if i <> 0 then [%log.debug "[exec] error %d" i]; + Lwt.return_unit) + fmt + + let remove_dir dir = + if Sys.os_type = "Win32" then command "cmd /d /v:off /c rd /s /q %S" dir + else command "rm -rf %S" dir + + let remove_file ?lock file = + Lock.with_lock lock (fun () -> + Lwt.catch + (fun () -> Lwt_unix.unlink file) + (function + (* On Windows, [EACCES] can also occur in an attempt to + rename a file or directory or to remove an existing + directory. *) + | Unix.Unix_error (Unix.EACCES, _, _) + | Unix.Unix_error (Unix.EISDIR, _, _) -> + remove_dir file + | Unix.Unix_error (Unix.ENOENT, _, _) -> Lwt.return_unit + | e -> Lwt.fail e)) + + let rename = + if Sys.os_type <> "Win32" then Lwt_unix.rename + else fun tmp file -> + let rec aux i = + Lwt.catch + (fun () -> Lwt_unix.rename tmp file) + (function + (* On Windows, [EACCES] can also occur in an attempt to + rename a file or directory or to remove an existing + directory. *) + | Unix.Unix_error (Unix.EACCES, _, _) as e -> + if i >= Array.length delays then Lwt.fail e + else + let* exists = file_exists file in + if exists && Sys.is_directory file then + remove_dir file >>= fun () -> aux (i + 1) + else ( + [%log.debug "Got EACCES, retrying in %.1fs" delays.(i)]; + Lwt_unix.sleep delays.(i) >>= fun () -> aux (i + 1)) + | e -> Lwt.fail e) + in + aux 0 + + let with_write_file ?temp_dir file fn = + let* () = + match temp_dir with None -> Lwt.return_unit | Some d -> mkdir d + in + let dir = Filename.dirname file in + mkdir dir >>= fun () -> + let tmp = Filename.temp_file ?temp_dir (Filename.basename file) "write" in + Lwt_pool.use openfile_pool (fun () -> + [%log.debug "Writing %s (%s)" file tmp]; + let* fd = + let open Lwt_unix in + openfile tmp [ O_WRONLY; O_NONBLOCK; O_CREAT; O_TRUNC ] 0o644 + in + let* () = + Lwt.finalize (fun () -> protect fn fd) (fun () -> Lwt_unix.close fd) + in + rename tmp file) + + let read_file_with_read file size = + let chunk_size = max 4096 (min size 0x100000) in + let buf = Bytes.create size in + let flags = [ Unix.O_RDONLY ] in + let perm = 0o0 in + let* fd = Lwt_unix.openfile file flags perm in + let rec aux off = + let read_size = min chunk_size (size - off) in + let* read = Lwt_unix.read fd buf off read_size in + let off = off + read in + if off >= size then Lwt.return (Bytes.unsafe_to_string buf) else aux off + in + Lwt.finalize (fun () -> aux 0) (fun () -> Lwt_unix.close fd) + + let read_file_with_mmap file = + let fd = Unix.(openfile file [ O_RDONLY; O_NONBLOCK ] 0o644) in + let ba = Lwt_bytes.map_file ~fd ~shared:false () in + Unix.close fd; + + (* XXX(samoht): ideally we should not do a copy here. *) + Lwt.return (Lwt_bytes.to_string ba) + + let read_file file = + Lwt.catch + (fun () -> + Lwt_pool.use openfile_pool (fun () -> + [%log.debug "Reading %s" file]; + let* stats = Lwt_unix.stat file in + let size = stats.Lwt_unix.st_size in + let+ buf = + if size >= mmap_threshold then read_file_with_mmap file + else read_file_with_read file size + in + Some buf)) + (function + | Unix.Unix_error _ | Sys_error _ -> Lwt.return_none | e -> Lwt.fail e) + + let write_file ?temp_dir ?lock file b = + let write () = + with_write_file file ?temp_dir (fun fd -> write_string fd b) + in + Lock.with_lock lock (fun () -> + Lwt.catch write (function + | Unix.Unix_error (Unix.EISDIR, _, _) -> remove_dir file >>= write + | e -> Lwt.fail e)) + + let test_and_set_file ?temp_dir ~lock file ~test ~set = + Lock.with_lock (Some lock) (fun () -> + let* v = read_file file in + let equal = + match (test, v) with + | None, None -> true + | Some x, Some y -> String.equal x y + | _ -> false + in + if not equal then Lwt.return_false + else + let+ () = + match set with + | None -> remove_file file + | Some v -> write_file ?temp_dir file v + in + true) + + let rec_files dir = + let rec aux accu dir = + let* ds = directories dir in + let* fs = files dir in + Lwt_list.fold_left_s aux (fs @ accu) ds + in + aux [] dir +end + +module Append_only = Irmin_fs.Append_only (IO) +module Atomic_write = Irmin_fs.Atomic_write (IO) +include Irmin_fs.Maker (IO) +module KV = Irmin_fs.KV (IO) +module Append_only_ext = Irmin_fs.Append_only_ext (IO) +module Atomic_write_ext = Irmin_fs.Atomic_write_ext (IO) +module Maker_ext = Irmin_fs.Maker_ext (IO) +include Irmin_unix diff --git a/vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.mli b/vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.mli new file mode 100644 index 000000000000..bcfe07779031 --- /dev/null +++ b/vendors/irmin/src/irmin-fs/unix/irmin_fs_unix.mli @@ -0,0 +1,30 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Append_only : Irmin.Append_only.Maker +module Atomic_write : Irmin.Atomic_write.Maker +include Irmin.Maker +module KV : Irmin.KV_maker with type info = Irmin.Info.default + +(** {1 Extended Stores} *) + +module Append_only_ext (C : Irmin_fs.Config) : Irmin.Append_only.Maker +module Atomic_write_ext (C : Irmin_fs.Config) : Irmin.Atomic_write.Maker +module Maker_ext (Obj : Irmin_fs.Config) (Ref : Irmin_fs.Config) : Irmin.Maker + +(** {1 Common Unix utilities} *) + +include module type of Irmin_unix diff --git a/vendors/irmin/src/irmin-git/atomic_write.ml b/vendors/irmin/src/irmin-git/atomic_write.ml new file mode 100644 index 000000000000..58ea59963f89 --- /dev/null +++ b/vendors/irmin/src/irmin-git/atomic_write.ml @@ -0,0 +1,308 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Atomic_write_intf + +module Check_closed (S : Irmin.Atomic_write.S) = struct + type t = { closed : bool ref; t : S.t } + type key = S.key + type value = S.value + + let check_not_closed t = if !(t.closed) then raise Irmin.Closed + + let mem t k = + check_not_closed t; + S.mem t.t k + + let find t k = + check_not_closed t; + S.find t.t k + + let set t k v = + check_not_closed t; + S.set t.t k v + + let test_and_set t k ~test ~set = + check_not_closed t; + S.test_and_set t.t k ~test ~set + + let remove t k = + check_not_closed t; + S.remove t.t k + + let list t = + check_not_closed t; + S.list t.t + + type watch = S.watch + + let watch t ?init f = + check_not_closed t; + S.watch t.t ?init f + + let watch_key t k ?init f = + check_not_closed t; + S.watch_key t.t k ?init f + + let unwatch t w = + check_not_closed t; + S.unwatch t.t w + + let v t = { closed = ref false; t } + + let close t = + if !(t.closed) then Lwt.return_unit + else ( + t.closed := true; + S.close t.t) + + let clear t = + check_not_closed t; + S.clear t.t +end + +module Make (K : Key) (G : Git.S) = struct + module Key = K + module Val = Irmin.Hash.Make (G.Hash) + module W = Irmin.Backend.Watch.Make (Key) (Val) + + let handle_git_err = function + | Ok x -> Lwt.return x + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e + + type t = { + bare : bool; + dot_git : Fpath.t; + git_head : G.Hash.t Git.Reference.contents; + t : G.t; + w : W.t; + m : Lwt_mutex.t; + } + + let watches = Hashtbl.create 10 + + type key = Key.t + type value = Val.t + type watch = W.watch * (unit -> unit Lwt.t) + + let branch_of_git r = + let str = String.trim @@ Git.Reference.to_string r in + match K.of_ref str with Ok r -> Some r | Error (`Msg _) -> None + + let git_of_branch r = Git.Reference.v (Fmt.to_to_string K.pp_ref r) + let pp_key = Irmin.Type.pp Key.t + + let ref_read_opt t head = + (* Make a best-effort attempt to check that the reference actually + exists before [read]-ing it, since the [Error `Reference_not_found] + case causes a spurious warning to be logged inside [ocaml-git]. *) + G.Ref.mem t head >>= function + | false -> Lwt.return_none + | true -> ( + let* r = G.Ref.read t head in + match r with + | Ok r -> Lwt.return_some r + | Error (`Reference_not_found _ | `Not_found _) -> + (* We may still hit this case due to a race condition, but it's very unlikely. *) + Lwt.return_none + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e) + + let mem { t; _ } r = + [%log.debug "mem %a" pp_key r]; + G.Ref.mem t (git_of_branch r) + + let find { t; _ } r = + [%log.debug "find %a" pp_key r]; + let b = git_of_branch r in + let* exists = G.Ref.mem t b in + if not exists then Lwt.return_none + else + let* k = G.Ref.resolve t b in + match k with + | Error (`Reference_not_found _) -> Lwt.return_none + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e + | Ok k -> Lwt.return_some k + + let listen_dir t = + let ( / ) = Filename.concat in + if G.has_global_watches then + let dir = Fpath.(to_string @@ (t.dot_git / "refs" / "heads")) in + let key file = + match K.of_ref ("refs" / "heads" / file) with + | Ok x -> Some x + | Error (`Msg e) -> + [%log.err "listen: file %s: %s" file e]; + None + in + W.listen_dir t.w dir ~key ~value:(find t) + else Lwt.return (fun () -> Lwt.return_unit) + + let watch_key t key ?init f = + [%log.debug "watch_key %a" pp_key key]; + let* stop = listen_dir t in + let+ w = W.watch_key t.w key ?init f in + (w, stop) + + let watch t ?init f = + [%log.debug "watch"]; + let* stop = listen_dir t in + let+ w = W.watch t.w ?init f in + (w, stop) + + let unwatch t (w, stop) = + let* () = stop () in + W.unwatch t.w w + + let v ?lock ~head ~bare t = + let m = match lock with None -> Lwt_mutex.create () | Some l -> l in + let dot_git = G.dotgit t in + let write_head head = + let head = Git.Reference.Ref head in + let+ () = + let+ r = + if G.has_global_checkout then + Lwt_mutex.with_lock m (fun () -> + G.Ref.write t Git.Reference.head head) + else Lwt.return (Ok ()) + in + match r with + | Error e -> [%log.err "Cannot create HEAD: %a" G.pp_error e] + | Ok () -> () + in + head + in + let+ git_head = + match head with + | Some h -> write_head h + | None -> ( + ref_read_opt t Git.Reference.head >>= function + | None -> write_head (git_of_branch K.main) + | Some head -> Lwt.return head) + in + let w = + try Hashtbl.find watches (G.dotgit t) + with Not_found -> + let w = W.v () in + Hashtbl.add watches (G.dotgit t) w; + w + in + { git_head; bare; t; w; dot_git; m } + + let list { t; _ } = + [%log.debug "list"]; + let+ refs = G.Ref.list t in + List.fold_left + (fun acc (r, _) -> + match branch_of_git r with None -> acc | Some r -> r :: acc) + [] refs + + let write_index t gr gk = + [%log.debug "write_index"]; + if G.has_global_checkout then [%log.debug "write_index"]; + let git_head = Git.Reference.Ref gr in + [%log.debug "write_index/if bare=%b head=%a" t.bare Git.Reference.pp gr]; + if (not t.bare) && git_head = t.git_head then ( + [%log.debug "write cache (%a)" Git.Reference.pp gr]; + + (* FIXME G.write_index t.t gk *) + let _ = gk in + Lwt.return_unit) + else Lwt.return_unit + + let pp_branch = Irmin.Type.pp K.t + + let set t r k = + [%log.debug "set %a" pp_branch r]; + let gr = git_of_branch r in + Lwt_mutex.with_lock t.m @@ fun () -> + let* e = G.Ref.write t.t gr (Git.Reference.Uid k) in + let* () = handle_git_err e in + let* () = W.notify t.w r (Some k) in + write_index t gr k + + let remove t r = + [%log.debug "remove %a" pp_branch r]; + Lwt_mutex.with_lock t.m @@ fun () -> + let* e = G.Ref.remove t.t (git_of_branch r) in + let* () = handle_git_err e in + W.notify t.w r None + + let eq_head_contents_opt x y = + match (x, y) with + | None, None -> true + | Some x, Some y -> Git.Reference.equal_contents ~equal:G.Hash.equal x y + | _ -> false + + let test_and_set t r ~test ~set = + [%log.debug fun f -> + let pp = Fmt.option ~none:(Fmt.any "") (Irmin.Type.pp Val.t) in + f "test_and_set %a: %a => %a" pp_branch r pp test pp set] + ; + let gr = git_of_branch r in + let c = function None -> None | Some h -> Some (Git.Reference.Uid h) in + let ok r = + let+ () = handle_git_err r in + true + in + Lwt_mutex.with_lock t.m (fun () -> + let* x = ref_read_opt t.t gr in + let* b = + if not (eq_head_contents_opt x (c test)) then Lwt.return_false + else + match c set with + | None -> + let* r = G.Ref.remove t.t gr in + ok r + | Some h -> + let* r = G.Ref.write t.t gr h in + ok r + in + let* () = + if + (* We do not protect [write_index] because it can take a long + time and we don't want to hold the lock for too long. Would + be safer to grab a lock, although the expanded filesystem + is not critical for Irmin consistency (it's only a + convenience for the user). *) + b + then W.notify t.w r set + else Lwt.return_unit + in + let+ () = + if b then + match set with + | None -> Lwt.return_unit + | Some v -> write_index t gr v + else Lwt.return_unit + in + b) + + let close _ = Lwt.return_unit + + let clear t = + [%log.debug "clear"]; + Lwt_mutex.with_lock t.m (fun () -> + let* refs = G.Ref.list t.t in + Lwt_list.iter_p + (fun (r, _) -> + let* e = G.Ref.remove t.t r in + let* () = handle_git_err e in + match branch_of_git r with + | Some k -> W.notify t.w k None + | None -> Lwt.return_unit) + refs) +end diff --git a/vendors/irmin/src/irmin-git/atomic_write.mli b/vendors/irmin/src/irmin-git/atomic_write.mli new file mode 100644 index 000000000000..419e1da5af59 --- /dev/null +++ b/vendors/irmin/src/irmin-git/atomic_write.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Backend module: turn a Git store into an Irmin backend for Git references. *) + +include Atomic_write_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-git/atomic_write_intf.ml b/vendors/irmin/src/irmin-git/atomic_write_intf.ml new file mode 100644 index 000000000000..92f5b2731f56 --- /dev/null +++ b/vendors/irmin/src/irmin-git/atomic_write_intf.ml @@ -0,0 +1,43 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type Key = sig + include Irmin.Branch.S + + val pp_ref : t Fmt.t + val of_ref : string -> (t, [ `Msg of string ]) result +end + +module type Sigs = sig + module type Key = Key + + module Make (K : Key) (G : Git.S) : sig + include Irmin.Atomic_write.S with type key = K.t and type value = G.Hash.t + + val v : + ?lock:Lwt_mutex.t -> + head:G.Reference.t option -> + bare:bool -> + G.t -> + t Lwt.t + end + + module Check_closed (S : Irmin.Atomic_write.S) : sig + include Irmin.Atomic_write.S with type key = S.key and type value = S.value + + val v : S.t -> t + end +end diff --git a/vendors/irmin/src/irmin-git/backend.ml b/vendors/irmin/src/irmin-git/backend.ml new file mode 100644 index 000000000000..7acccf408a07 --- /dev/null +++ b/vendors/irmin/src/irmin-git/backend.ml @@ -0,0 +1,133 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type G = sig + include Git.S + + val v : ?dotgit:Fpath.t -> Fpath.t -> (t, error) result Lwt.t +end + +module Make + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) + (Schema : Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) = +struct + module Hash = Irmin.Hash.Make (G.Hash) + module Schema = Schema + module Key = Irmin.Key.Of_hash (Hash) + module Commit_key = Key + module Node_key = Key + + module Contents = struct + module S = Contents.Make (G) (Schema.Contents) + include Irmin.Contents.Store (S) (S.Hash) (S.Val) + end + + module Node = struct + module S = Node.Store (G) (Schema.Path) + + include + Irmin.Node.Store (Contents) (S) (S.Key) (S.Val) (Metadata) (Schema.Path) + end + + module Node_portable = Irmin.Node.Portable.Of_node (Node.Val) + + module Commit = struct + module S = Commit.Store (G) + include Irmin.Commit.Store (Schema.Info) (Node) (S) (S.Hash) (S.Val) + end + + module Commit_portable = Irmin.Commit.Portable.Of_commit (Commit.S.Val) + + module Branch = struct + module Key = Schema.Branch + module Val = Commit_key + module S = Atomic_write.Make (Schema.Branch) (G) + include Atomic_write.Check_closed (S) + + let v ?lock ~head ~bare t = S.v ?lock ~head ~bare t >|= v + end + + module Slice = Irmin.Backend.Slice.Make (Contents) (Node) (Commit) + + module Repo = struct + let handle_git_err = function + | Ok x -> Lwt.return x + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e + + type t = { config : Irmin.config; closed : bool ref; g : G.t; b : Branch.t } + + let branch_t t = t.b + let contents_t t : 'a Contents.t = (t.closed, t.g) + let node_t t : 'a Node.t = (contents_t t, (t.closed, t.g)) + let commit_t t : 'a Commit.t = (node_t t, (t.closed, t.g)) + let batch t f = f (contents_t t) (node_t t) (commit_t t) + + type config = { + root : string; + dot_git : string option; + level : int option; + buffers : int option; + head : G.Reference.t option; + bare : bool; + } + + let config c = + let module C = Irmin.Backend.Conf in + let root = C.find_root c |> Option.value ~default:"." in + let dot_git = C.get c Conf.Key.dot_git in + let level = C.get c Conf.Key.level in + let head = C.get c Conf.Key.head in + let bare = C.get c Conf.Key.bare in + let buffers = C.get c Conf.Key.buffers in + { root; dot_git; level; head; buffers; bare } + + let fopt f = function None -> None | Some x -> Some (f x) + + let v conf = + let { root; dot_git; head; bare; _ } = config conf in + let dotgit = fopt Fpath.v dot_git in + let root = Fpath.v root in + let* g = G.v ?dotgit root >>= handle_git_err in + let+ b = Branch.v ~head ~bare g in + { g; b; closed = ref false; config = (conf :> Irmin.config) } + + let config t = t.config + let close t = Branch.close t.b >|= fun () -> t.closed := true + end + + module Remote = struct + include Remote.Make (G) (S) (Schema.Branch) + + let v repo = Lwt.return repo.Repo.g + end + + let git_of_repo r = r.Repo.g + + let repo_of_git ?head ?(bare = true) ?lock g = + let+ b = Branch.v ?lock ~head ~bare g in + { + Repo.config = Irmin.Backend.Conf.empty Conf.spec; + closed = ref false; + g; + b; + } +end diff --git a/vendors/irmin/src/irmin-git/backend.mli b/vendors/irmin/src/irmin-git/backend.mli new file mode 100644 index 000000000000..fe261ae8a6dd --- /dev/null +++ b/vendors/irmin/src/irmin-git/backend.mli @@ -0,0 +1,51 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type G = sig + include Git.S + + val v : ?dotgit:Fpath.t -> Fpath.t -> (t, error) result Lwt.t +end + +module Make + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) + (Schema : Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) : sig + type t := bool ref * G.t + + include + Irmin.Backend.S + with module Schema = Schema + with type 'a Contents.t = t + and type 'a Node.t = t * t + and type 'a Commit.t = (t * t) * t + and type Contents.key = G.hash + and type Node.key = G.hash + and type Commit.key = G.hash + and type Remote.endpoint = Mimic.ctx * Smart_git.Endpoint.t + + val git_of_repo : Repo.t -> G.t + + val repo_of_git : + ?head:Git.Reference.t -> + ?bare:bool -> + ?lock:Lwt_mutex.t -> + G.t -> + Repo.t Lwt.t +end diff --git a/vendors/irmin/src/irmin-git/branch.ml b/vendors/irmin/src/irmin-git/branch.ml new file mode 100644 index 000000000000..830c7ac90f10 --- /dev/null +++ b/vendors/irmin/src/irmin-git/branch.ml @@ -0,0 +1,32 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Astring + +module type S = Atomic_write.Key + +module Make (B : Irmin.Branch.S) = struct + include B + + let pp = Irmin.Type.pp B.t + let pp_ref ppf b = Fmt.pf ppf "refs/heads/%a" pp b + + let of_ref str = + match String.cuts ~sep:"/" str with + | "refs" :: "heads" :: b -> + Irmin.Type.of_string B.t (String.concat ~sep:"/" b) + | _ -> Error (`Msg (Fmt.str "%s is not a valid branch" str)) +end diff --git a/vendors/irmin/src/irmin-git/branch.mli b/vendors/irmin/src/irmin-git/branch.mli new file mode 100644 index 000000000000..9c8ccfda5855 --- /dev/null +++ b/vendors/irmin/src/irmin-git/branch.mli @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** one-to-one mapping between Irmin and Git branches. *) + +module type S = sig + include Atomic_write.Key + (** inline *) +end + +module Make (B : Irmin.Branch.S) : S with type t = B.t diff --git a/vendors/irmin/src/irmin-git/commit.ml b/vendors/irmin/src/irmin-git/commit.ml new file mode 100644 index 000000000000..e35223e02ee5 --- /dev/null +++ b/vendors/irmin/src/irmin-git/commit.ml @@ -0,0 +1,126 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module Make (G : Git.S) = struct + module Info = Irmin.Info.Default + module Raw = Git.Value.Make (G.Hash) + module Hash = Irmin.Hash.Make (G.Hash) + module Key = Irmin.Key.Of_hash (Hash) + + type t = G.Value.Commit.t + type commit_key = Key.t [@@deriving irmin] + type node_key = Key.t [@@deriving irmin] + type hash = Hash.t [@@deriving irmin] + + let info_of_git author message = + let id = author.Git.User.name in + let date, _ = author.Git.User.date in + (* FIXME: tz offset is ignored *) + Info.v ~author:id ~message date + + let name_email name = + let name = String.trim name in + try + let i = String.rindex name ' ' in + let email = String.sub name (i + 1) (String.length name - i - 1) in + if + String.length email > 0 + && email.[0] = '<' + && email.[String.length email - 1] = '>' + then + let email = String.sub email 1 (String.length email - 2) in + let name = String.trim (String.sub name 0 i) in + (name, email) + else (name, "irmin@openmirage.org") + with Not_found -> (name, "irmin@openmirage.org") + + let of_git g = + let node = G.Value.Commit.tree g in + let parents = G.Value.Commit.parents g in + let author = G.Value.Commit.author g in + let message = G.Value.Commit.message g in + let message = Option.value ~default:"" message in + let info = info_of_git author message in + (info, node, parents) + + let to_git info node parents = + let tree = node in + let parents = List.fast_sort G.Hash.compare parents in + let author = + let date = Info.date info in + let name, email = name_email (Info.author info) in + Git.User.{ name; email; date = (date, None) } + in + let message = Info.message info in + G.Value.Commit.make (* FIXME: should be v *) + ~tree ~parents ~author ~committer:author + (if message = "" then None else Some message) + + let v ~info ~node ~parents = to_git info node parents + let xnode g = G.Value.Commit.tree g + let node t = xnode t + let parents g = G.Value.Commit.parents g + + let info g = + let author = G.Value.Commit.author g in + let message = Option.value ~default:"" (G.Value.Commit.message g) in + info_of_git author message + + module C = Irmin.Commit.Make (Hash) + + let of_c c = to_git (C.info c) (C.node c) (C.parents c) + + let to_c t = + let info, node, parents = of_git t in + C.v ~info ~node ~parents + + let to_bin t = Raw.to_raw (G.Value.commit t) + + let encode_bin (t : t) k = + [%log.debug "Commit.encode_bin"]; + k (to_bin t) + + let decode_bin buf pos_ref = + [%log.debug "Commit.decode_bin"]; + let off = !pos_ref in + match Raw.of_raw_with_header ~off buf with + | Ok (Git.Value.Commit t) -> + pos_ref := String.length buf; + t + | Ok _ -> failwith "wrong object kind" + | Error _ -> failwith "wrong object kind" + + let size_of = Irmin.Type.Size.custom_dynamic () + let t = Irmin.Type.map ~bin:(encode_bin, decode_bin, size_of) C.t of_c to_c +end + +module Store (G : Git.S) = struct + module Info = Irmin.Info.Default + module Hash = Irmin.Hash.Make (G.Hash) + module Val = Make (G) + + module V = struct + type t = G.Value.Commit.t + + let type_eq = function `Commit -> true | _ -> false + let of_git = function Git.Value.Commit c -> Some c | _ -> None + let to_git c = G.Value.commit c + end + + include Content_addressable.Check_closed (Content_addressable.Make (G) (V)) +end diff --git a/vendors/irmin/src/irmin-git/commit.mli b/vendors/irmin/src/irmin-git/commit.mli new file mode 100644 index 000000000000..506dc5e06187 --- /dev/null +++ b/vendors/irmin/src/irmin-git/commit.mli @@ -0,0 +1,40 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Backend module: turn a Git store into an Irmin backend for Git commits. *) + +module Make (G : Git.S) : + Irmin.Commit.S + with type t = G.Value.Commit.t + and type hash = G.hash + and module Info = Irmin.Info.Default + +module Store (G : Git.S) : sig + include + Irmin.Content_addressable.S + with type _ t = bool ref * G.t + and type key = G.Hash.t + and type value = G.Value.Commit.t + + module Info = Irmin.Info.Default + module Hash : Irmin.Hash.S with type t = key + + module Val : + Irmin.Commit.S + with type t = value + and type hash = key + and module Info = Info +end diff --git a/vendors/irmin/src/irmin-git/conf.ml b/vendors/irmin/src/irmin-git/conf.ml new file mode 100644 index 000000000000..ad95ba6f0197 --- /dev/null +++ b/vendors/irmin/src/irmin-git/conf.ml @@ -0,0 +1,70 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Backend.Conf + +let spec = Spec.v "git" + +module Key = struct + let reference : Git.Reference.t Irmin.Type.t = + let of_string str = Git.Reference.of_string str |> Result.get_ok in + let to_string r = Git.Reference.to_string r in + Irmin.Type.(map string) of_string to_string + + let head = + key ~spec ~doc:"The main branch of the Git repository." "head" + Irmin.Type.(option reference) + None + + let bare = + key ~spec ~doc:"Do not expand the filesystem on the disk." "bare" + Irmin.Type.bool false + + let level = + key ~spec ~doc:"The Zlib compression level." "level" + Irmin.Type.(option int) + None + + let buffers = + key ~spec ~doc:"The number of 4K pre-allocated buffers." "buffers" + Irmin.Type.(option int) + None + + let dot_git = + key ~spec + ~doc:"The location of the .git directory. By default set to [$root/.git]." + "dot-git" + Irmin.Type.(option string) + None +end + +let init ?head ?bare ?level ?dot_git ?buffers root = + let module C = Irmin.Backend.Conf in + let config = C.empty spec in + (* Initialise an fresh root_key, otherwise [C.add config root_key root] has no + effect on current config. *) + let root_key = C.root spec in + let config = C.add config root_key root in + let config = + match bare with + | None -> C.add config Key.bare (C.default Key.bare) + | Some b -> C.add config Key.bare b + in + let config = C.add config Key.head head in + let config = C.add config Key.level level in + let config = C.add config Key.dot_git dot_git in + let config = C.add config Key.buffers buffers in + C.verify config diff --git a/vendors/irmin/src/irmin-git/conf.mli b/vendors/irmin/src/irmin-git/conf.mli new file mode 100644 index 000000000000..00672756de40 --- /dev/null +++ b/vendors/irmin/src/irmin-git/conf.mli @@ -0,0 +1,36 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Backend.Conf + +val spec : Spec.t + +module Key : sig + val head : Git.Reference.t option key + val bare : bool key + val level : int option key + val buffers : int option key + val dot_git : string option key +end + +val init : + ?head:Git.Reference.t -> + ?bare:bool -> + ?level:int -> + ?dot_git:string -> + ?buffers:int -> + string -> + Irmin.config diff --git a/vendors/irmin/src/irmin-git/content_addressable.ml b/vendors/irmin/src/irmin-git/content_addressable.ml new file mode 100644 index 000000000000..c0fd2c5128ac --- /dev/null +++ b/vendors/irmin/src/irmin-git/content_addressable.ml @@ -0,0 +1,96 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Content_addressable_intf + +module Make (G : Git.S) (V : Value.S with type value := G.Value.t) = struct + module H = Irmin.Hash.Make (G.Hash) + + let handle_git_err = function + | Ok x -> Lwt.return x + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e + + type 'a t = G.t + type key = H.t [@@deriving irmin ~pp ~equal] + type value = V.t + + let mem t key = + [%log.debug "mem %a" pp_key key]; + G.mem t key >>= function + | false -> Lwt.return_false + | true -> ( + G.read t key >>= function + | Error (`Reference_not_found _ | `Not_found _) -> Lwt.return_false + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e + | Ok v -> Lwt.return (V.type_eq (G.Value.kind v))) + + let find t key = + [%log.debug "find %a" pp_key key]; + G.read t key >>= function + | Error (`Reference_not_found _ | `Not_found _) -> Lwt.return_none + | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e + | Ok v -> Lwt.return (V.of_git v) + + let add t v = + let v = V.to_git v in + let* k, _ = G.write t v >>= handle_git_err in + [%log.debug "add %a" pp_key k]; + Lwt.return k + + let unsafe_add t k v = + let+ k' = add t v in + if equal_key k k' then () + else + Fmt.failwith + "[Git.unsafe_append] %a is not a valid key. Expecting %a instead.\n" + pp_key k pp_key k' + + let batch t f = f t + let close _ = Lwt.return () +end + +module Check_closed (S : Irmin.Content_addressable.S) = struct + type 'a t = bool ref * 'a S.t + type key = S.key + type value = S.value + + let check_not_closed t = if !(fst t) then raise Irmin.Closed + + let mem t k = + check_not_closed t; + S.mem (snd t) k + + let find t k = + check_not_closed t; + S.find (snd t) k + + let add t v = + check_not_closed t; + S.add (snd t) v + + let unsafe_add t k v = + check_not_closed t; + S.unsafe_add (snd t) k v + + let batch t f = + check_not_closed t; + S.batch (snd t) (fun x -> f (fst t, x)) + + let close (c, _) = + c := true; + Lwt.return () +end diff --git a/vendors/irmin/src/irmin-git/content_addressable.mli b/vendors/irmin/src/irmin-git/content_addressable.mli new file mode 100644 index 000000000000..5eec2a5c3482 --- /dev/null +++ b/vendors/irmin/src/irmin-git/content_addressable.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Backend module: turn a Git store into an Irmin backend for Git values. *) + +include Content_addressable_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-git/content_addressable_intf.ml b/vendors/irmin/src/irmin-git/content_addressable_intf.ml new file mode 100644 index 000000000000..52324bcf4673 --- /dev/null +++ b/vendors/irmin/src/irmin-git/content_addressable_intf.ml @@ -0,0 +1,31 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type Sigs = sig + module Make (G : Git.S) (V : Value.S with type value := G.Value.t) : + Irmin.Content_addressable.S + with type _ t = G.t + and type key = G.Hash.t + and type value = V.t + + module Check_closed (S : Irmin.Content_addressable.S) : sig + include + Irmin.Content_addressable.S + with type 'a t = bool ref * 'a S.t + and type key = S.key + and type value = S.value + end +end diff --git a/vendors/irmin/src/irmin-git/contents.ml b/vendors/irmin/src/irmin-git/contents.ml new file mode 100644 index 000000000000..62c50b5c9f44 --- /dev/null +++ b/vendors/irmin/src/irmin-git/contents.ml @@ -0,0 +1,64 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module Make (G : Git.S) (C : Irmin.Contents.S) = struct + module Raw = Git.Value.Make (G.Hash) + module Hash = Irmin.Hash.Make (G.Hash) + + module V = struct + type t = C.t + + let type_eq = function `Blob -> true | _ -> false + + let of_git = function + | Git.Value.Blob b -> ( + let str = G.Value.Blob.to_string b in + match Irmin.Type.of_string C.t str with + | Ok x -> Some x + | Error (`Msg e) -> Fmt.invalid_arg "error %s" e) + | _ -> None + + let to_git b = + let str = Irmin.Type.to_string C.t b in + G.Value.blob (G.Value.Blob.of_string str) + end + + include Content_addressable.Check_closed (Content_addressable.Make (G) (V)) + + module Val = struct + include C + + let to_bin t = Raw.to_raw (V.to_git t) + let encode_bin (t : t) k = k (to_bin t) + + let decode_bin buf pos_ref = + [%log.debug "Content.decode_bin"]; + let off = !pos_ref in + match Raw.of_raw_with_header ~off buf with + | Ok g -> ( + match V.of_git g with + | Some g -> + pos_ref := String.length buf; + g + | None -> failwith "wrong object kind") + | Error (`Msg _) -> failwith "wrong object" + + let size_of = Irmin.Type.Size.custom_dynamic () + let t = Irmin.Type.like ~bin:(encode_bin, decode_bin, size_of) t + end +end diff --git a/vendors/irmin/src/irmin-git/contents.mli b/vendors/irmin/src/irmin-git/contents.mli new file mode 100644 index 000000000000..d4a06b35cc58 --- /dev/null +++ b/vendors/irmin/src/irmin-git/contents.mli @@ -0,0 +1,28 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Backend module: turn a Git store into an Irmin backend for Git blobs. *) + +module Make (G : Git.S) (C : Irmin.Contents.S) : sig + include + Irmin.Content_addressable.S + with type _ t = bool ref * G.t + and type key = G.Hash.t + and type value = C.t + + module Hash : Irmin.Hash.S with type t = key + module Val : Irmin.Contents.S with type t = value +end diff --git a/vendors/irmin/src/irmin-git/dune b/vendors/irmin/src/irmin-git/dune new file mode 100644 index 000000000000..4e03acfc5e2f --- /dev/null +++ b/vendors/irmin/src/irmin-git/dune @@ -0,0 +1,8 @@ +(library + (name irmin_git) + (public_name irmin-git) + (libraries astring cstruct fmt fpath git irmin logs lwt uri irmin.mem mimic) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-git/import.ml b/vendors/irmin/src/irmin-git/import.ml new file mode 100644 index 000000000000..464589ac6082 --- /dev/null +++ b/vendors/irmin/src/irmin-git/import.ml @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends + +let src = Logs.Src.create "irmin.git" ~doc:"Irmin Git-format store" + +module Log = (val Logs.src_log src : Logs.LOG) diff --git a/vendors/irmin/src/irmin-git/irmin_git.ml b/vendors/irmin/src/irmin-git/irmin_git.ml new file mode 100644 index 000000000000..d62b30b994b6 --- /dev/null +++ b/vendors/irmin/src/irmin-git/irmin_git.ml @@ -0,0 +1,348 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin_git_intf +open! Import +module Conf = Conf +module Metadata = Metadata +module Branch = Branch +module Reference = Reference +module Schema = Schema + +let config = Conf.init + +type reference = Reference.t [@@deriving irmin] + +module Maker_ext + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) = +struct + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Make + (Schema : Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) = + struct + module B = Backend.Make (G) (S) (Schema) + include Irmin.Of_backend (B) + + let git_of_repo = B.git_of_repo + let repo_of_git = B.repo_of_git + + let git_commit (repo : Repo.t) (h : commit) : G.Value.Commit.t option Lwt.t + = + let h = Commit.hash h in + G.read (git_of_repo repo) h >|= function + | Ok (Git.Value.Commit c) -> Some c + | _ -> None + + module Git = G + end +end + +module Mem = struct + include Git.Mem.Store + + let confs = Hashtbl.create 10 + let find_conf c = Hashtbl.find_opt confs c + + let add_conf c t = + Hashtbl.replace confs c t; + t + + let v' ?dotgit root = v ?dotgit root + + let v ?dotgit root = + let conf = (dotgit, root) in + match find_conf conf with + | Some x -> Lwt.return x + | None -> v' ?dotgit root >|= add_conf conf +end + +module Maker + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) = +struct + module Maker = Maker_ext (G) (S) + + type endpoint = Maker.endpoint + + module Make + (Sc : Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) = + Maker.Make (Sc) +end + +module No_sync = struct + type error = + [ `Not_found | `Msg of string | `Exn of exn | `Cycle | `Invalid_flow ] + + let pp_error _ _ = assert false + + let fetch ?push_stdout:_ ?push_stderr:_ ?threads:_ ~ctx:_ _ _ ?version:_ + ?capabilities:_ ?deepen:_ _ = + assert false + + let push ~ctx:_ _ _ ?version:_ ?capabilities:_ _ = assert false +end + +module Content_addressable (G : Git.S) = struct + module G = struct + include G + + let v ?dotgit:_ _root = assert false + end + + module type S = Irmin.Content_addressable.S with type key = G.Hash.t + + module Maker = Maker_ext (G) (No_sync) + + module Make (V : Irmin.Type.S) = struct + module V = struct + include V + + let merge = Irmin.Merge.default Irmin.Type.(option V.t) + end + + module Schema = Schema.Make (G) (V) (Reference) + module M = Maker.Make (Schema) + module X = M.Backend.Contents + + let state t = + let+ r = M.repo_of_git (snd t) in + M.Backend.Repo.contents_t r + + type 'a t = bool ref * G.t + type key = X.key + type value = X.value + + let with_state0 f t = + let* t = state t in + f t + + let with_state1 f t x = + let* t = state t in + f t x + + let add = with_state1 X.add + let pp_key = Irmin.Type.pp X.Key.t + let equal_key = Irmin.Type.(unstage (equal X.Key.t)) + + let unsafe_add t k v = + let+ k' = with_state1 X.add t v in + if equal_key k k' then () + else + Fmt.failwith + "[Git.unsafe_append] %a is not a valid key. Expecting %a instead.\n" + pp_key k pp_key k' + + let find = with_state1 X.find + let mem = with_state1 X.mem + let close = with_state0 X.close + let batch t f = f t + end +end + +module Atomic_write (G : Git.S) = struct + module type S = Irmin.Atomic_write.S with type value = G.Hash.t + + module Make (K : Irmin.Branch.S) = struct + module K = struct + include K + + let main = + match Irmin.Type.of_string K.t "main" with + | Ok x -> x + | Error (`Msg e) -> failwith e + end + + module AW = Atomic_write.Make (Branch.Make (K)) (G) + include Atomic_write.Check_closed (AW) + end +end + +module KV + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) = +struct + module Maker = Maker (G) (S) + module Branch = Branch.Make (Irmin.Branch.String) + include Irmin.Key.Store_spec.Hash_keyed + + type endpoint = Maker.endpoint + type metadata = Metadata.t + type branch = Branch.t + type hash = G.hash + type info = Irmin.Info.default + + module Make (C : Irmin.Contents.S) = Maker.Make (Schema.Make (G) (C) (Branch)) +end + +module Ref + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) = +struct + module Maker = Maker_ext (G) (S) + + type endpoint = Maker.endpoint + type branch = reference + + module Make (C : Irmin.Contents.S) = + Maker.Make (Schema.Make (G) (C) (Reference)) +end + +include Conf + +module Generic_KV + (CA : Irmin.Content_addressable.Maker) + (AW : Irmin.Atomic_write.Maker) = +struct + module G = Mem + + type endpoint = unit + type metadata = Metadata.t + type hash = G.hash + type info = Irmin.Info.default + + include Irmin.Key.Store_spec.Hash_keyed + + module Schema (C : Irmin.Contents.S) = struct + module Metadata = Metadata + module Contents = C + module Path = Irmin.Path.String_list + module Branch = Branch.Make (Irmin.Branch.String) + module Hash = Irmin.Hash.Make (Mem.Hash) + module Node = Node.Make (G) (Path) + module Commit = Commit.Make (G) + module Info = Irmin.Info.Default + end + + module Make (C : Irmin.Contents.S) = struct + module Sc = Schema (C) + + (* We use a dummy store to get the serialisation functions. This is + probably not necessary and we could use Git.Value.Raw instead. *) + module Dummy = struct + module G = Mem + module Maker = Maker (G) (No_sync) + module S = Maker.Make (Sc) + include S.Backend + end + + module CA = Irmin.Content_addressable.Check_closed (CA) + module AW = Irmin.Atomic_write.Check_closed (AW) + + module X = struct + module Schema = Sc + module Hash = Dummy.Hash + module Info = Irmin.Info.Default + module Key = Irmin.Key.Of_hash (Hash) + + module Contents = struct + module V = Dummy.Contents.Val + module CA = CA (Hash) (V) + include Irmin.Contents.Store (CA) (Hash) (V) + end + + module Node = struct + module V = Dummy.Node.Val + module CA = CA (Hash) (V) + + include + Irmin.Node.Store (Contents) (CA) (Hash) (V) (Dummy.Node.Metadata) + (Schema.Path) + end + + module Node_portable = Irmin.Node.Portable.Of_node (Node.Val) + + module Commit = struct + module V = struct + include Dummy.Commit.Val + module Info = Schema.Info + + type hash = Hash.t [@@deriving irmin] + end + + module CA = CA (Hash) (V) + include Irmin.Commit.Store (Info) (Node) (CA) (Hash) (V) + end + + module Commit_portable = Irmin.Commit.Portable.Of_commit (Commit.V) + + module Branch = struct + module Key = Dummy.Branch.Key + module Val = Dummy.Branch.Val + include AW (Key) (Val) + end + + module Slice = Dummy.Slice + module Remote = Irmin.Backend.Remote.None (Branch.Val) (Branch.Key) + + module Repo = struct + (* FIXME: remove duplication with irmin.mli *) + type t = { + config : Irmin.config; + contents : read Contents.t; + nodes : read Node.t; + commits : read Commit.t; + branch : Branch.t; + } + + let contents_t t = t.contents + let node_t t = t.nodes + let commit_t t = t.commits + let branch_t t = t.branch + let config t = t.config + + let batch t f = + Contents.CA.batch t.contents @@ fun c -> + Node.CA.batch (snd t.nodes) @@ fun n -> + Commit.CA.batch (snd t.commits) @@ fun ct -> + let contents_t = c in + let node_t = (contents_t, n) in + let commit_t = (node_t, ct) in + f contents_t node_t commit_t + + let v config = + let* contents = Contents.CA.v config in + let* nodes = Node.CA.v config in + let* commits = Commit.CA.v config in + let nodes = (contents, nodes) in + let commits = (nodes, commits) in + let+ branch = Branch.v config in + { contents; nodes; commits; branch; config } + + let close t = + Contents.CA.close t.contents >>= fun () -> + Node.CA.close (snd t.nodes) >>= fun () -> + Commit.CA.close (snd t.commits) >>= fun () -> Branch.close t.branch + end + end + + include Irmin.Of_backend (X) + end +end + +(* Enforce that {!KV} is a sub-type of {!Irmin.KV_maker}. *) +module KV_is_a_KV_maker : Irmin.KV_maker = KV (Mem) (No_sync) + +(* Enforce that {!Generic_KV} is a sub-type of {!Irmin.KV_maker}. *) +module Generic_KV_is_a_KV_maker : Irmin.KV_maker = + Generic_KV (Irmin_mem.Content_addressable) (Irmin_mem.Atomic_write) diff --git a/vendors/irmin/src/irmin-git/irmin_git.mli b/vendors/irmin/src/irmin-git/irmin_git.mli new file mode 100644 index 000000000000..a37f3b9cb17f --- /dev/null +++ b/vendors/irmin/src/irmin-git/irmin_git.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Git backend *) + +include Irmin_git_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-git/irmin_git_intf.ml b/vendors/irmin/src/irmin-git/irmin_git_intf.ml new file mode 100644 index 000000000000..f6e57f4841a5 --- /dev/null +++ b/vendors/irmin/src/irmin-git/irmin_git_intf.ml @@ -0,0 +1,156 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type G = sig + include Git.S + + val v : ?dotgit:Fpath.t -> Fpath.t -> (t, error) result Lwt.t +end + +module type S = sig + (** The Git backend specializes a few types: + + - the allowed metadata are {!type-Metadata.t}. + - the hash algorithm is SHA1. *) + + module Git : Git.S + (** Access to the underlying Git store. *) + + module Schema : + Irmin.Schema.S with type Metadata.t = Metadata.t and type Hash.t = Git.hash + + include Irmin.S with type hash = Schema.Hash.t and module Schema := Schema + + val git_commit : Repo.t -> commit -> Git.Value.Commit.t option Lwt.t + (** [git_commit repo h] is the commit corresponding to [h] in the repository + [repo]. *) + + val git_of_repo : Repo.t -> Git.t + (** [of_repo r] is the Git store associated to [r]. *) + + val repo_of_git : + ?head:Git.Reference.t -> + ?bare:bool -> + ?lock:Lwt_mutex.t -> + Git.t -> + Repo.t Lwt.t + (** [to_repo t] is the Irmin repository associated to [t]. *) +end + +(** Same as {!Irmin.Maker} but with a fixed hash (SHA1) and metadata (Git + metadata) implemtations. *) +module type Maker = sig + module G : G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Make + (Schema : Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) : + S + with module Git = G + and module Schema := Schema + and type Backend.Remote.endpoint = endpoint +end + +module type KV_maker = sig + module G : G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + type branch + + module Make (C : Irmin.Contents.S) : + S + with module Git = G + and type Schema.Contents.t = C.t + and type Schema.Metadata.t = Metadata.t + and type Schema.Info.t = Irmin.Info.default + and type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Hash.t = G.hash + and type Schema.Branch.t = branch + and type Backend.Remote.endpoint = endpoint +end + +module type Sigs = sig + module Metadata = Metadata + module Conf = Conf + module Branch = Branch + module Reference = Reference + module Schema = Schema + + (** {2 Module types} *) + + module type G = G + module type S = S + module type Maker = Maker + module type KV_maker = KV_maker + + val config : + ?head:Git.Reference.t -> + ?bare:bool -> + ?level:int -> + ?dot_git:string -> + ?buffers:int -> + string -> + Irmin.config + + type reference = Reference.t [@@deriving irmin] + + module Content_addressable (G : Git.S) : sig + (** Use Git as a content-addressable store. Values will be stored into + [.git/objects].*) + + module type S = Irmin.Content_addressable.S with type key = G.Hash.t + + module Make (V : Irmin.Type.S) : S with type value = V.t + end + + module Atomic_write (G : Git.S) : sig + (** Use Git as an atomic-write store. Values will be stored into + [.git/refs]. When using the Git filesystem backend, branch names .*) + + module type S = Irmin.Atomic_write.S with type value = G.Hash.t + + module Make (K : Irmin.Branch.S) : S with type key = K.t + end + + module Maker + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) : + Maker with module G := G + + module KV + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) : + KV_maker with module G := G and type branch = string + + module Ref + (G : G) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) : + KV_maker with module G := G and type branch = Reference.t + + module Generic_KV + (CA : Irmin.Content_addressable.Maker) + (AW : Irmin.Atomic_write.Maker) : + Irmin.KV_maker with type endpoint = unit and type info = Irmin.Info.default + + (** In-memory Git store. *) + module Mem : + G with type t = Digestif.SHA1.t Git.Mem.t and type hash = Digestif.SHA1.t +end diff --git a/vendors/irmin/src/irmin-git/metadata.ml b/vendors/irmin/src/irmin-git/metadata.ml new file mode 100644 index 000000000000..17c87cd01040 --- /dev/null +++ b/vendors/irmin/src/irmin-git/metadata.ml @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module X = struct + type t = [ `Normal | `Exec | `Link | `Everybody ] + + let t = + Irmin.Type.enum "metadata" + [ + ("normal", `Normal); + ("exec", `Exec); + ("link", `Link); + ("everybody", `Everybody); + ] +end + +include X + +let default = `Normal +let merge = Irmin.Merge.default X.t diff --git a/vendors/irmin/src/irmin-git/metadata.mli b/vendors/irmin/src/irmin-git/metadata.mli new file mode 100644 index 000000000000..f57547a3580c --- /dev/null +++ b/vendors/irmin/src/irmin-git/metadata.mli @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type t = [ `Normal | `Exec | `Link | `Everybody ] + +include Irmin.Metadata.S with type t := t diff --git a/vendors/irmin/src/irmin-git/node.ml b/vendors/irmin/src/irmin-git/node.ml new file mode 100644 index 000000000000..a0d24595fc22 --- /dev/null +++ b/vendors/irmin/src/irmin-git/node.ml @@ -0,0 +1,204 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module Make (G : Git.S) (P : Irmin.Path.S) = struct + module Hash = Irmin.Hash.Make (G.Hash) + module Key = Irmin.Key.Of_hash (Hash) + module Raw = Git.Value.Make (G.Hash) + module Path = P + module Metadata = Metadata + + type t = G.Value.Tree.t + type metadata = Metadata.t [@@deriving irmin] + type hash = Hash.t [@@deriving irmin] + type step = Path.step [@@deriving irmin] + type node_key = hash [@@deriving irmin] + type contents_key = hash [@@deriving irmin] + + type value = [ `Node of hash | `Contents of hash * metadata ] + [@@deriving irmin] + + let of_step = Irmin.Type.to_string P.step_t + + let to_step str = + match Irmin.Type.of_string P.step_t str with + | Ok x -> x + | Error (`Msg e) -> failwith e + + exception Exit of (step * value) list + + let list ?(offset = 0) ?length ?cache:_ t = + let t = G.Value.Tree.to_list t in + let length = match length with None -> List.length t | Some n -> n in + try + List.fold_left + (fun (i, acc) { Git.Tree.perm; name; node } -> + if i < offset then (i + 1, acc) + else if i >= offset + length then raise (Exit acc) + else + let name = to_step name in + match perm with + | `Dir -> (i + 1, (name, `Node node) :: acc) + | `Commit -> (i + 1, acc) (* FIXME *) + | #Metadata.t as p -> (i + 1, (name, `Contents (node, p)) :: acc)) + (0, []) t + |> fun (_, acc) -> List.rev acc + with Exit acc -> List.rev acc + + let find ?cache:_ t s = + let s = of_step s in + let rec aux = function + | [] -> None + | x :: xs when x.Git.Tree.name <> s -> aux xs + | { Git.Tree.perm; node; _ } :: _ -> ( + match perm with + | `Dir -> Some (`Node node) + | `Commit -> None (* FIXME *) + | #Metadata.t as p -> Some (`Contents (node, p))) + in + aux (Git.Tree.to_list t) + + let remove t step = G.Value.Tree.remove ~name:(of_step step) t + let is_empty = G.Value.Tree.is_empty + let length t = G.Value.Tree.length t |> Int64.to_int + + let add t name value = + let name = of_step name in + let entry = + match value with + | `Node node -> Git.Tree.entry ~name `Dir node + | `Contents (node, perm) -> + Git.Tree.entry ~name (perm :> Git.Tree.perm) node + in + (* FIXME(samoht): issue in G.Value.Tree.add *) + let entries = G.Value.Tree.to_list t in + match List.find (fun e -> e.Git.Tree.name = name) entries with + | exception Not_found -> Git.Tree.of_list (entry :: entries) + | e -> + let equal x y = + x.Git.Tree.perm = y.Git.Tree.perm + && x.name = y.name + && G.Hash.equal x.node y.node + in + if equal e entry then t + else + let entries = + List.filter (fun e -> e.Git.Tree.name <> name) entries + in + Git.Tree.of_list (entry :: entries) + + let empty : unit -> t = + (* [Git.Tree.t] is immutable, so sharing a singleton empty tree is safe *) + Fun.const (Git.Tree.of_list []) + + let to_git perm (name, node) = + G.Value.Tree.entry ~name:(of_step name) perm node + + let v alist = + let alist = + List.rev_map + (fun (l, x) -> + let v k = (l, k) in + match x with + | `Node n -> to_git `Dir (v n) + | `Contents (c, perm) -> to_git (perm :> Git.Tree.perm) (v c)) + alist + in + (* Tree.of_list will sort the list in the right order *) + G.Value.Tree.of_list alist + + let alist t = + let mk_n k = `Node k in + let mk_c k metadata = `Contents (k, metadata) in + List.fold_left + (fun acc -> function + | { Git.Tree.perm = `Dir; name; node } -> + (to_step name, mk_n node) :: acc + | { Git.Tree.perm = `Commit; name; _ } -> + (* Irmin does not support Git submodules; do not follow them, + just consider *) + [%log.warn "skipping Git submodule: %s" name]; + acc + | { Git.Tree.perm = #Metadata.t as perm; name; node; _ } -> + (to_step name, mk_c node perm) :: acc) + [] (G.Value.Tree.to_list t) + |> List.rev + + module N = Irmin.Node.Make (Hash) (P) (Metadata) + + let to_n t = N.of_list (alist t) + let of_n n = v (N.list n) + let to_bin t = Raw.to_raw (G.Value.tree t) + let of_list = v + let of_seq seq = List.of_seq seq |> v + + let seq ?offset ?length ?cache t = + list ?offset ?length ?cache t |> List.to_seq + + let clear _ = () + + let encode_bin (t : t) k = + [%log.debug "Tree.encode_bin"]; + k (to_bin t) + + let decode_bin buf pos_ref = + [%log.debug "Tree.decode_bin"]; + let off = !pos_ref in + match Raw.of_raw_with_header buf ~off with + | Ok (Git.Value.Tree t) -> + pos_ref := String.length buf; + t + | Ok _ -> failwith "wrong object kind" + | Error _ -> failwith "wrong object" + + let size_of = Irmin.Type.Size.custom_dynamic () + let t = Irmin.Type.map ~bin:(encode_bin, decode_bin, size_of) N.t of_n to_n + + let merge ~contents ~node = + let merge = N.merge ~contents ~node in + Irmin.Merge.like t merge to_n of_n + + exception Dangling_hash of { context : string; hash : hash } + + let with_handler _ n = n + let head t = `Node (list t) + + module Ht = + Irmin.Hash.Typed + (Hash) + (struct + type nonrec t = t [@@deriving irmin] + end) + + let hash_exn ?force:_ = Ht.hash +end + +module Store (G : Git.S) (P : Irmin.Path.S) = struct + module Key = Irmin.Hash.Make (G.Hash) + module Val = Make (G) (P) + + module V = struct + type t = G.Value.Tree.t + + let type_eq = function `Tree -> true | _ -> false + let to_git t = G.Value.tree t + let of_git = function Git.Value.Tree t -> Some t | _ -> None + end + + include Content_addressable.Check_closed (Content_addressable.Make (G) (V)) +end diff --git a/vendors/irmin/src/irmin-git/node.mli b/vendors/irmin/src/irmin-git/node.mli new file mode 100644 index 000000000000..4514c7e4b33a --- /dev/null +++ b/vendors/irmin/src/irmin-git/node.mli @@ -0,0 +1,41 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Backend module: turn a Git store into an Irmin backend for Git trees. *) + +module Make (G : Git.S) (P : Irmin.Path.S) : + Irmin.Node.S + with type t = G.Value.Tree.t + and type hash = G.hash + and type step = P.step + and type metadata = Metadata.t + +module Store (G : Git.S) (P : Irmin.Path.S) : sig + include + Irmin.Content_addressable.S + with type _ t = bool ref * G.t + and type key = G.Hash.t + and type value = G.Value.Tree.t + + module Key : Irmin.Hash.S with type t = key + + module Val : + Irmin.Node.S + with type t = value + and type hash = key + and type step = P.step + and type metadata = Metadata.t +end diff --git a/vendors/irmin/src/irmin-git/reference.ml b/vendors/irmin/src/irmin-git/reference.ml new file mode 100644 index 000000000000..cc3632781601 --- /dev/null +++ b/vendors/irmin/src/irmin-git/reference.ml @@ -0,0 +1,45 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Astring + +module type S = Atomic_write.Key + +type t = + [ `Branch of string | `Remote of string | `Tag of string | `Other of string ] +[@@deriving irmin] + +let pp_ref ppf = function + | `Branch b -> Fmt.pf ppf "refs/heads/%s" b + | `Remote r -> Fmt.pf ppf "refs/remotes/%s" r + | `Tag t -> Fmt.pf ppf "refs/tags/%s" t + | `Other o -> Fmt.pf ppf "refs/%s" o + +let path l = String.concat ~sep:"/" l + +let of_ref str = + match String.cuts ~sep:"/" str with + | "refs" :: "heads" :: b -> Ok (`Branch (path b)) + | "refs" :: "remotes" :: r -> Ok (`Remote (path r)) + | "refs" :: "tags" :: t -> Ok (`Tag (path t)) + | "refs" :: o -> Ok (`Other (path o)) + | _ -> Error (`Msg (Fmt.str "%s is not a valid reference" str)) + +let t = Irmin.Type.like t ~pp:pp_ref ~of_string:of_ref +let main = `Branch Irmin.Branch.String.main + +let is_valid = function + | `Branch s | `Tag s | `Remote s | `Other s -> Irmin.Branch.String.is_valid s diff --git a/vendors/irmin/src/irmin-git/reference.mli b/vendors/irmin/src/irmin-git/reference.mli new file mode 100644 index 000000000000..703f1241f632 --- /dev/null +++ b/vendors/irmin/src/irmin-git/reference.mli @@ -0,0 +1,30 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** one-to-one mapping between Irmin and Git references. *) + +module type S = sig + include Atomic_write.Key + (** @inline *) +end + +type t = + [ `Branch of string | `Remote of string | `Tag of string | `Other of string ] +[@@deriving irmin] +(** The type for Git references. Use the {!Branch} module to only deal with + [`Branch] values. *) + +include S with type t := t diff --git a/vendors/irmin/src/irmin-git/remote.ml b/vendors/irmin/src/irmin-git/remote.ml new file mode 100644 index 000000000000..d357af18e11e --- /dev/null +++ b/vendors/irmin/src/irmin-git/remote.ml @@ -0,0 +1,99 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +let ( >>? ) = Lwt_result.bind + +module Make + (G : Git.S) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) + (B : Irmin.Branch.S) = +struct + let src = Logs.Src.create "irmin.git-remote" ~doc:"Git remote" + + module Gitlog = (val Logs.src_log src : Logs.LOG) + module H = Irmin.Hash.Make (G.Hash) + + type t = G.t + type commit = H.t + type branch = B.t + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + let git_of_branch_str str = Git.Reference.v ("refs/heads/" ^ str) + let git_of_branch r = git_of_branch_str (Irmin.Type.to_string B.t r) + + (* let o_head_of_git = function None -> Ok None | Some k -> Ok (Some k) *) + + let msgf fmt = Fmt.kstr (fun err -> `Msg err) fmt + let reword_error f = function Ok _ as v -> v | Error err -> Error (f err) + + let fetch t ?depth (ctx, e) br = + [%log.debug "fetch %a" Smart_git.Endpoint.pp e]; + let push_stdout msg = Gitlog.info (fun f -> f "%s" msg) + and push_stderr msg = Gitlog.warn (fun f -> f "%s" msg) + and deepen = + match depth with Some depth -> Some (`Depth depth) | None -> None + and reference = git_of_branch br + and capabilities = + [ + `Side_band_64k; + `Multi_ack_detailed; + `Ofs_delta; + `Thin_pack; + `Report_status; + ] + in + S.fetch ~push_stdout ~push_stderr ~capabilities ~ctx e t ?deepen + (`Some [ (reference, reference) ]) + >>= function + | Error `Not_found -> Lwt.return (Error (`Msg "not found")) + | Error (`Msg err) -> Lwt.return (Error (`Msg err)) + | Error (`Exn err) -> Lwt.return (Error (`Msg (Printexc.to_string err))) + | Error err -> + Fmt.kstr (fun e -> Lwt.return (Error (`Msg e))) "%a" S.pp_error err + | Ok None -> Lwt.return (Ok None) + | Ok (Some (_, [ (reference, hash) ])) -> + let value = Git.Reference.uid hash in + let br = + Git.Reference.v ("refs/remotes/origin/" ^ Irmin.Type.to_string B.t br) + in + G.Ref.write t br value >|= reword_error (msgf "%a" G.pp_error) + >>? fun () -> + G.Ref.write t reference value >|= reword_error (msgf "%a" G.pp_error) + >>? fun () -> Lwt.return (Ok (Some hash)) + | _ -> assert false + + let push t ?depth:_ (ctx, e) br = + [%log.debug "push %a" Smart_git.Endpoint.pp e]; + let reference = git_of_branch br in + let capabilities = + [ + `Side_band_64k; + `Multi_ack_detailed; + `Ofs_delta; + `Thin_pack; + `Report_status; + ] + in + S.push ~capabilities ~ctx e t [ `Update (reference, reference) ] + >|= function + | Error (`Msg err) -> Error (`Msg err) + | Error (`Exn exn) -> Error (`Msg (Printexc.to_string exn)) + | Error `Not_found -> Error (`Msg "not found") + | Error err -> Error (`Msg (Fmt.str "%a" S.pp_error err)) + | Ok () -> Ok () +end diff --git a/vendors/irmin/src/irmin-git/remote.mli b/vendors/irmin/src/irmin-git/remote.mli new file mode 100644 index 000000000000..341b0b73f52a --- /dev/null +++ b/vendors/irmin/src/irmin-git/remote.mli @@ -0,0 +1,25 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make + (G : Git.S) + (S : Git.Sync.S with type hash := G.hash and type store := G.t) + (B : Irmin.Branch.S) : + Irmin.Backend.Remote.S + with type commit = G.hash + and type branch = B.t + and type t = G.t + and type endpoint = Mimic.ctx * Smart_git.Endpoint.t diff --git a/vendors/irmin/src/irmin-git/schema.ml b/vendors/irmin/src/irmin-git/schema.ml new file mode 100644 index 000000000000..66a6fec3913f --- /dev/null +++ b/vendors/irmin/src/irmin-git/schema.ml @@ -0,0 +1,52 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + module Branch : Branch.S + + include + Irmin.Schema.S + with module Metadata = Metadata + and module Branch := Branch + and type Info.t = Irmin.Info.default + and type Path.step = string + and type Path.t = string list + + module Node : + Irmin.Node.S + with type metadata = Metadata.t + and type step = Path.step + and type hash = Hash.t + + module Commit : Irmin.Commit.S with module Info := Info and type hash = Hash.t +end + +module Make (G : Git.S) (V : Irmin.Contents.S) (B : Branch.S) : + S + with type Hash.t = G.hash + and module Contents = V + and module Branch = B + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t = struct + module Metadata = Metadata + module Contents = V + module Path = Irmin.Path.String_list + module Branch = B + module Hash = Irmin.Hash.Make (G.Hash) + module Node = Node.Make (G) (Path) + module Commit = Commit.Make (G) + module Info = Irmin.Info.Default +end diff --git a/vendors/irmin/src/irmin-git/unix/dune b/vendors/irmin/src/irmin-git/unix/dune new file mode 100644 index 000000000000..3947e48d5d3f --- /dev/null +++ b/vendors/irmin/src/irmin-git/unix/dune @@ -0,0 +1,8 @@ +(library + (public_name irmin-git.unix) + (name irmin_git_unix) + (libraries cohttp-lwt-unix git-unix irmin-git irmin.unix lwt.unix) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-git/unix/irmin_git_unix.ml b/vendors/irmin/src/irmin-git/unix/irmin_git_unix.ml new file mode 100644 index 000000000000..6c9dbdabe15f --- /dev/null +++ b/vendors/irmin/src/irmin-git/unix/irmin_git_unix.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Xgit +include Irmin_unix diff --git a/vendors/irmin/src/irmin-git/unix/xgit.ml b/vendors/irmin/src/irmin-git/unix/xgit.ml new file mode 100644 index 000000000000..4b8489b8775a --- /dev/null +++ b/vendors/irmin/src/irmin-git/unix/xgit.ml @@ -0,0 +1,91 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Syntax +include Xgit_intf + +let src = Logs.Src.create "git.unix" ~doc:"logs git's unix events" + +module Log = (val Logs.src_log src : Logs.LOG) + +let remote ?ctx ?headers uri = + let+ ctx = + match ctx with + | Some x -> Lwt.return x + | None -> Git_unix.ctx (Happy_eyeballs_lwt.create ()) + in + let ( ! ) f a b = f b a in + let headers = Option.map Cohttp.Header.to_list headers in + match Smart_git.Endpoint.of_string uri with + | Ok edn -> + let edn = + Option.fold ~none:edn + ~some:(!Smart_git.Endpoint.with_headers_if_http edn) + headers + in + (ctx, edn) + | Error (`Msg err) -> Fmt.invalid_arg "remote: %s" err + +module Maker (G : Irmin_git.G) = struct + module G = G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Maker = struct + module S = Irmin_git.Maker (G) (Git_unix.Sync (G)) + module KV = Irmin_git.KV (G) (Git_unix.Sync (G)) + module Ref = Irmin_git.Ref (G) (Git_unix.Sync (G)) + end + + module Make + (S : Irmin_git.Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) = + struct + include Maker.S.Make (S) + + let remote ?ctx ?headers uri = + let+ e = remote ?ctx ?headers uri in + E e + end + + module KV (C : Irmin.Contents.S) = struct + include Maker.KV.Make (C) + + let remote ?ctx ?headers uri = + let+ e = remote ?ctx ?headers uri in + E e + end + + module Ref (C : Irmin.Contents.S) = struct + include Maker.Ref.Make (C) + + let remote ?ctx ?headers uri = + let+ e = remote ?ctx ?headers uri in + E e + end +end + +module FS = struct + include Maker (Git_unix.Store) + module G = Git_unix.Store +end + +module Mem = struct + include Maker (Irmin_git.Mem) + module G = Irmin_git.Mem +end diff --git a/vendors/irmin/src/irmin-git/unix/xgit.mli b/vendors/irmin/src/irmin-git/unix/xgit.mli new file mode 100644 index 000000000000..7b34325a4b7c --- /dev/null +++ b/vendors/irmin/src/irmin-git/unix/xgit.mli @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Xgit_intf.Sigs +(** @inline *) + +module Maker (G : G) : Backend with module G = G +module FS : Backend with module G = Git_unix.Store +module Mem : Backend with module G = Irmin_git.Mem diff --git a/vendors/irmin/src/irmin-git/unix/xgit_intf.ml b/vendors/irmin/src/irmin-git/unix/xgit_intf.ml new file mode 100644 index 000000000000..dcaa9b4f215b --- /dev/null +++ b/vendors/irmin/src/irmin-git/unix/xgit_intf.ml @@ -0,0 +1,78 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type G = sig + include Git.S + + val v : ?dotgit:Fpath.t -> Fpath.t -> (t, error) result Lwt.t +end + +module type S = sig + include + Irmin_git.S + with type Backend.Remote.endpoint = Mimic.ctx * Smart_git.Endpoint.t + + val remote : + ?ctx:Mimic.ctx -> ?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t +end + +module type Backend = sig + (* FIXME: remove signature duplication *) + + module G : Irmin_git.G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Make + (Schema : Irmin_git.Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) : + S + with module Git = G + and type Backend.Remote.endpoint = endpoint + and module Schema := Schema + + module KV (C : Irmin.Contents.S) : + S + with module Git = G + and type Schema.Contents.t = C.t + and type Schema.Metadata.t = Irmin_git.Metadata.t + and type Schema.Info.t = Irmin.Info.default + and type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Hash.t = G.hash + and type Schema.Branch.t = string + and type Backend.Remote.endpoint = endpoint + + module Ref (C : Irmin.Contents.S) : + S + with module Git = G + and type Schema.Contents.t = C.t + and type Schema.Metadata.t = Irmin_git.Metadata.t + and type Schema.Info.t = Irmin.Info.default + and type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Hash.t = G.hash + and type Schema.Branch.t = Irmin_git.reference + and type Backend.Remote.endpoint = endpoint +end + +module type Sigs = sig + module type G = G + module type S = S + module type Backend = Backend +end diff --git a/vendors/irmin/src/irmin-git/value.ml b/vendors/irmin/src/irmin-git/value.ml new file mode 100644 index 000000000000..0d3e97d312c9 --- /dev/null +++ b/vendors/irmin/src/irmin-git/value.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Value_intf diff --git a/vendors/irmin/src/irmin-git/value.mli b/vendors/irmin/src/irmin-git/value.mli new file mode 100644 index 000000000000..fcce43ffaeb0 --- /dev/null +++ b/vendors/irmin/src/irmin-git/value.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Value_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-git/value_intf.ml b/vendors/irmin/src/irmin-git/value_intf.ml new file mode 100644 index 000000000000..0c32e6442e1e --- /dev/null +++ b/vendors/irmin/src/irmin-git/value_intf.ml @@ -0,0 +1,28 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + type t + type value + + val type_eq : [ `Commit | `Blob | `Tree | `Tag ] -> bool + val to_git : t -> value + val of_git : value -> t option +end + +module type Sigs = sig + module type S = S +end diff --git a/vendors/irmin/src/irmin-graphql/dune b/vendors/irmin/src/irmin-graphql/dune new file mode 100644 index 000000000000..e5221faa3cf0 --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/dune @@ -0,0 +1,15 @@ +(library + (name irmin_graphql) + (public_name irmin-graphql) + (libraries + fmt + cohttp + cohttp-lwt + graphql-cohttp + graphql + graphql-lwt + graphql_parser + irmin + lwt) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-graphql/import.ml b/vendors/irmin/src/irmin-graphql/import.ml new file mode 100644 index 000000000000..71053e21ba54 --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/import.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin-graphql/server.ml b/vendors/irmin/src/irmin-graphql/server.ml new file mode 100644 index 000000000000..2cd1c1a0ab32 --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/server.ml @@ -0,0 +1,969 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Schema = Graphql_lwt.Schema + +module type S = sig + module IO : Cohttp_lwt.S.IO + + type repo + type server + + type response_action = + [ `Expert of Cohttp.Response.t * (IO.ic -> IO.oc -> unit Lwt.t) + | `Response of Cohttp.Response.t * Cohttp_lwt.Body.t ] + + val schema : repo -> unit Schema.schema + + val execute_request : + unit Schema.schema -> + Cohttp_lwt.Request.t -> + Cohttp_lwt.Body.t -> + response_action Lwt.t + + val v : repo -> server +end + +let of_irmin_result = function + | Ok _ as ok -> ok + | Error (`Msg msg) -> Error msg + +module Option = struct + let map f t = match t with None -> None | Some x -> Some (f x) +end + +module Result = struct + let ok x = Ok x +end + +module type CONFIG = sig + type info + + val remote : (?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t) option + + val info : + ?author:string -> ('a, Format.formatter, unit, unit -> info) format4 -> 'a +end + +module type CUSTOM_TYPE = sig + type t + + val schema_typ : (unit, t option) Schema.typ + val arg_typ : t option Schema.Arg.arg_typ +end + +module type CUSTOM_TYPES = sig + type path + type metadata + type contents + type hash + type branch + type commit_key + type node_key + type contents_key + + module Path : CUSTOM_TYPE with type t := path + module Metadata : CUSTOM_TYPE with type t := metadata + module Contents : CUSTOM_TYPE with type t := contents + module Hash : CUSTOM_TYPE with type t := hash + module Branch : CUSTOM_TYPE with type t := branch + module Commit_key : CUSTOM_TYPE with type t := commit_key + module Contents_key : CUSTOM_TYPE with type t := contents_key + module Node_key : CUSTOM_TYPE with type t := node_key +end + +module Default_type (T : sig + include Irmin.Type.S + + val name : string +end) = +struct + let schema_typ = + let coerce t = `String (Irmin.Type.to_string T.t t) in + Schema.scalar T.name ~coerce + + let arg_typ = + let coerce = function + | `String s -> of_irmin_result (Irmin.Type.of_string T.t s) + | _ -> Error "Invalid input value" + in + Schema.Arg.scalar T.name ~coerce +end + +module Default_types (S : Irmin.Generic_key.S) = struct + module Path = Default_type (struct + include S.Path + + let name = "Path" + end) + + module Metadata = Default_type (struct + include S.Metadata + + let name = "Metadata" + end) + + module Contents = Default_type (struct + include S.Contents + + let name = "Value" + end) + + module Hash = Default_type (struct + include S.Hash + + let name = "Hash" + end) + + module Branch = Default_type (struct + include S.Branch + + let name = "BranchName" + end) + + module Commit_key = Default_type (struct + type t = S.commit_key + + let t = S.commit_key_t + let name = "CommitKey" + end) + + module Node_key = Default_type (struct + type t = S.node_key + + let t = S.node_key_t + let name = "NodeKey" + end) + + module Contents_key = Default_type (struct + type t = S.contents_key + + let t = S.contents_key_t + let name = "ContentsKey" + end) +end + +module Make_ext + (Server : Cohttp_lwt.S.Server) + (Config : CONFIG) + (Store : Irmin.Generic_key.S with type Schema.Info.t = Config.info) + (Types : CUSTOM_TYPES + with type path := Store.path + and type metadata := Store.metadata + and type contents := Store.contents + and type hash := Store.hash + and type branch := Store.branch + and type commit_key := Store.commit_key + and type node_key := Store.node_key + and type contents_key := Store.contents_key) = +struct + module IO = Server.IO + module Sync = Irmin.Sync.Make (Store) + module Graphql_server = Graphql_cohttp.Make (Schema) (IO) (Cohttp_lwt.Body) + module Info = Store.Info + + type repo = Store.repo + type server = Server.t + type info = Store.info + + type txn_args = { + author : string option; + message : string option; + retries : int option; + allow_empty : bool option; + parents : Store.commit_key list option; + } + + let txn_args repo input = + match input with + | Some input -> + let message = match input.message with None -> "" | Some m -> m in + let author = input.author in + let parents = + match input.parents with + | Some l -> + Lwt_list.filter_map_s (Store.Commit.of_key repo) l + >>= Lwt.return_some + | None -> Lwt.return_none + in + let+ parents = parents in + ( Config.info ?author "%s" message, + input.retries, + input.allow_empty, + parents ) + | None -> Lwt.return (Config.info "", None, None, None) + + type response_action = + [ `Expert of Cohttp.Response.t * (IO.ic -> IO.oc -> unit Lwt.t) + | `Response of Cohttp.Response.t * Cohttp_lwt.Body.t ] + + type tree_item = { + path : Store.path; + value : Store.contents option; + metadata : Store.metadata option; + } + + let mk_branch repo = function + | Some b -> Store.of_branch repo b + | None -> Store.main repo + + let rec concat_path a b = + match Store.Path.decons a with + | None -> b + | Some (step, a_tl) -> Store.Path.cons step (concat_path a_tl b) + + module Input = struct + let coerce_remote = function + | `String s -> ( + match Config.remote with + | Some remote -> Ok (remote s) + | None -> Error "sync is not available") + | _ -> Error "Invalid input value" + + let remote = Schema.Arg.(scalar "Remote" ~coerce:coerce_remote) + let path = Types.Path.arg_typ + let hash = Types.Hash.arg_typ + let commit_key = Types.Commit_key.arg_typ + let branch = Types.Branch.arg_typ + let value = Types.Contents.arg_typ + let metadata = Types.Metadata.arg_typ + let contents_key = Types.Contents_key.arg_typ + + let info = + Schema.Arg.( + obj "InfoInput" + ~fields: + [ + arg "author" ~typ:string; + arg "message" ~typ:string; + arg "retries" ~typ:int; + arg "allow_empty" ~typ:bool; + arg "parents" ~typ:(list (non_null commit_key)); + ] + ~coerce:(fun author message retries allow_empty parents -> + { author; message; retries; allow_empty; parents })) + + let item = + Schema.Arg.( + obj "TreeItem" + ~fields: + [ + arg "path" ~typ:(non_null path); + arg "value" ~typ:value; + arg "metadata" ~typ:metadata; + ] + ~coerce:(fun path value metadata -> { path; value; metadata })) + + let tree = Schema.Arg.(list (non_null item)) + end + + type 'ctx store_schema = { + commit : ('ctx, Store.commit option) Schema.typ; + info : ('ctx, info option) Schema.typ; + tree : ('ctx, (Store.tree * Store.path) option) Schema.typ; + branch : ('ctx, (Store.t * Store.Branch.t) option) Schema.typ; + contents : + ('ctx, (Store.contents * Store.metadata * Store.path) option) Schema.typ; + contents_key_value : + ('ctx, (Store.contents_key * Store.metadata) option) Schema.typ; + node_key_value : ('ctx, Store.node_key option) Schema.typ; + } + + let rec store_schema = + lazy + ( Schema.fix @@ fun recursive -> + let commit = + Schema.( + recursive.obj "Commit" ~fields:(fun t -> + [ + field "tree" ~typ:(non_null t.tree) ~args:[] + ~resolve:(fun _ c -> + (Store.Commit.tree c, Store.Path.empty)); + field "parents" + ~typ: + (non_null (list (non_null Types.Commit_key.schema_typ))) + ~args:[] + ~resolve:(fun _ c -> Store.Commit.parents c); + field "info" ~typ:(non_null t.info) ~args:[] + ~resolve:(fun _ c -> Store.Commit.info c); + field "hash" ~typ:(non_null Types.Hash.schema_typ) ~args:[] + ~resolve:(fun _ c -> Store.Commit.hash c); + field "key" ~typ:(non_null Types.Commit_key.schema_typ) + ~args:[] ~resolve:(fun _ c -> Store.Commit.key c); + ])) + in + let info = + Schema.( + obj "Info" + ~fields: + [ + field "date" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ i -> Info.date i |> Int64.to_string); + field "author" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ i -> Info.author i); + field "message" ~typ:(non_null string) ~args:[] + ~resolve:(fun _ i -> Info.message i); + ]) + in + let tree = + Schema.( + recursive.obj "Tree" ~fields:(fun t -> + [ + field "path" ~typ:(non_null Types.Path.schema_typ) ~args:[] + ~resolve:(fun _ (_, path) -> path); + io_field "get" + ~args:Arg.[ arg "path" ~typ:(non_null Input.path) ] + ~typ:Types.Contents.schema_typ + ~resolve:(fun _ (tree, _) path -> + Store.Tree.find tree path >|= Result.ok); + io_field "get_contents" + ~args:Arg.[ arg "path" ~typ:(non_null Input.path) ] + ~typ:t.contents + ~resolve:(fun _ (tree, tree_path) path -> + Store.Tree.find_all tree path + >|= Option.map (fun (c, m) -> + let path' = concat_path tree_path path in + (c, m, path')) + >|= Result.ok); + io_field "get_tree" + ~args:Arg.[ arg "path" ~typ:(non_null Input.path) ] + ~typ:t.tree + ~resolve:(fun _ (tree, tree_path) path -> + Store.Tree.find_tree tree path + >|= Option.map (fun tree -> + let tree_path' = concat_path tree_path path in + (tree, tree_path')) + >|= Result.ok); + io_field "list_contents_recursively" ~args:[] + ~typ:(non_null (list (non_null t.contents))) + ~resolve:(fun _ (tree, path) -> + let rec tree_list ?(acc = []) tree path = + match Store.Tree.destruct tree with + | `Contents (c, m) -> + Store.Tree.Contents.force_exn c >|= fun c -> + (c, m, path) :: acc + | `Node _ -> + let* l = Store.Tree.list tree Store.Path.empty in + Lwt_list.fold_left_s + (fun acc (step, t) -> + let path' = Store.Path.rcons path step in + tree_list t path' ~acc) + acc l + >|= List.rev + in + tree_list tree path >>= Lwt.return_ok); + field "hash" ~typ:(non_null Types.Hash.schema_typ) ~args:[] + ~resolve:(fun _ (tree, _) -> Store.Tree.hash tree); + field "key" ~typ:kinded_key ~args:[] + ~resolve:(fun _ (tree, _) -> + match Store.Tree.key tree with + | Some (`Contents (k, m)) -> + let f = Lazy.force contents_key_as_kinded_key in + Some (f (k, m)) + | Some (`Node k) -> + let f = Lazy.force node_key_as_kinded_key in + Some (f k) + | None -> None); + io_field "list" + ~typ:(non_null (list (non_null node))) + ~args:[] + ~resolve:(fun _ (tree, tree_path) -> + Store.Tree.list tree Store.Path.empty + >>= Lwt_list.map_s (fun (step, tree) -> + let absolute_path = + Store.Path.rcons tree_path step + in + match Store.Tree.destruct tree with + | `Contents (c, m) -> + let+ c = Store.Tree.Contents.force_exn c in + let f = Lazy.force contents_as_node in + f (c, m, absolute_path) + | _ -> + let f = Lazy.force tree_as_node in + Lwt.return (f (tree, absolute_path))) + >|= Result.ok); + ])) + in + let branch = + Schema.( + recursive.obj "Branch" ~fields:(fun t -> + [ + field "name" ~typ:(non_null Types.Branch.schema_typ) ~args:[] + ~resolve:(fun _ (_, b) -> b); + io_field "head" ~args:[] ~typ:t.commit + ~resolve:(fun _ (t, _) -> Store.Head.find t >|= Result.ok); + io_field "tree" ~args:[] ~typ:(non_null t.tree) + ~resolve:(fun _ (t, _) -> + let+ tree = Store.tree t in + Ok (tree, Store.Path.empty)); + io_field "last_modified" + ~typ:(non_null (list (non_null t.commit))) + ~args: + Arg. + [ + arg "path" ~typ:(non_null Input.path); + arg "depth" ~typ:int; + arg "n" ~typ:int; + ] + ~resolve:(fun _ (t, _) path depth n -> + Store.last_modified ?depth ?n t path >|= Result.ok); + io_field "lcas" + ~typ:(non_null (list (non_null t.commit))) + ~args:Arg.[ arg "commit" ~typ:(non_null Input.hash) ] + ~resolve:(fun _ (t, _) commit -> + Store.Commit.of_hash (Store.repo t) commit >>= function + | Some commit -> ( + Store.lcas_with_commit t commit >>= function + | Ok lcas -> Lwt.return (Ok lcas) + | Error e -> + let msg = + Irmin.Type.to_string Store.lca_error_t e + in + Lwt.return (Error msg)) + | None -> Lwt.return (Error "Commit not found")); + ])) + in + let contents = + Schema.( + obj "Contents" + ~fields: + [ + field "path" ~typ:(non_null Types.Path.schema_typ) ~args:[] + ~resolve:(fun _ (_, _, path) -> path); + field "metadata" ~typ:(non_null Types.Metadata.schema_typ) + ~args:[] ~resolve:(fun _ (_, metadata, _) -> metadata); + field "value" ~typ:(non_null Types.Contents.schema_typ) + ~args:[] ~resolve:(fun _ (contents, _, _) -> contents); + field "hash" ~typ:(non_null Types.Hash.schema_typ) ~args:[] + ~resolve:(fun _ (contents, _, _) -> + Store.Contents.hash contents); + ]) + in + + let contents_key_value = + Schema.( + obj "ContentsKeyValue" + ~fields: + [ + field "metadata" ~typ:(non_null Types.Metadata.schema_typ) + ~args:[] ~resolve:(fun _ (_, metadata) -> metadata); + field "contents" ~typ:(non_null Types.Contents_key.schema_typ) + ~args:[] ~resolve:(fun _ (key, _) -> key); + ]) + in + let node_key_value = + Schema.( + obj "NodeKeyValue" + ~fields: + [ + field "node" ~typ:(non_null Types.Node_key.schema_typ) + ~args:[] ~resolve:(fun _ x -> x); + ]) + in + { + commit; + info; + tree; + branch; + contents; + contents_key_value; + node_key_value; + } ) + + and kinded_key = Schema.union "KindedKey" + and node = Schema.union "Node" + and tree_as_node = lazy (Schema.add_type node (Lazy.force store_schema).tree) + + and contents_as_node = + lazy (Schema.add_type node (Lazy.force store_schema).contents) + + and node_key_as_kinded_key = + lazy (Schema.add_type kinded_key (Lazy.force store_schema).node_key_value) + + and contents_key_as_kinded_key = + lazy + (Schema.add_type kinded_key (Lazy.force store_schema).contents_key_value) + + [@@@ocaml.warning "-5"] + + let _ = Lazy.force tree_as_node + let _ = Lazy.force contents_as_node + let _ = Lazy.force node_key_as_kinded_key + let _ = Lazy.force contents_key_as_kinded_key + let store_schema = Lazy.force store_schema + + let err_write e = + Lwt.return (Error (Irmin.Type.to_string Store.write_error_t e)) + + let remote s = + match Config.remote with + | Some _ -> + Schema. + [ + io_field "clone" ~typ:store_schema.commit + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "remote" ~typ:(non_null Input.remote); + ] + ~resolve:(fun _ _src branch remote -> + let* t = mk_branch s branch in + let* remote = remote in + Sync.fetch t remote >>= function + | Ok (`Head d) -> Store.Head.set t d >|= fun () -> Ok (Some d) + | Ok `Empty -> Lwt.return (Ok None) + | Error (`Msg e) -> Lwt.return (Error e)); + io_field "push" ~typ:store_schema.commit + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "remote" ~typ:(non_null Input.remote); + arg "depth" ~typ:int; + ] + ~resolve:(fun _ _src branch remote depth -> + let* t = mk_branch s branch in + let* remote = remote in + Sync.push t ?depth remote >>= function + | Ok (`Head commit) -> Lwt.return (Ok (Some commit)) + | Ok `Empty -> Lwt.return (Ok None) + | Error e -> + let s = Fmt.to_to_string Sync.pp_push_error e in + Lwt.return (Error s)); + io_field "pull" ~typ:store_schema.commit + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "remote" ~typ:(non_null Input.remote); + arg "info" ~typ:Input.info; + arg "depth" ~typ:int; + ] + ~resolve:(fun _ _src branch remote info depth -> + let* t = mk_branch s branch in + let strategy = + match info with + | Some info -> + let+ info, _, _, _ = txn_args s (Some info) in + `Merge info + | None -> Lwt.return `Set + in + let* remote = remote in + strategy >>= Sync.pull ?depth t remote >>= function + | Ok (`Head h) -> Lwt.return (Ok (Some h)) + | Ok `Empty -> Lwt.return (Ok None) + | Error (`Msg msg) -> Lwt.return (Error msg) + | Error (`Conflict msg) -> + Lwt.return (Error ("conflict: " ^ msg))); + ] + | None -> [] + + let to_tree tree l = + Lwt_list.fold_left_s + (fun tree -> function + | { path; value = Some v; metadata } -> + Store.Tree.add tree ?metadata path v + | { path; value = None; _ } -> Store.Tree.remove tree path) + tree l + + let mutations s = + Schema. + [ + io_field "set" ~typ:store_schema.commit + ~doc:"Associate contents with the given path" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "value" ~typ:(non_null Input.value); + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch k v i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + Store.set t ?retries ?allow_empty ?parents k v ~info >>= function + | Ok () -> Store.Head.find t >|= Result.ok + | Error e -> err_write e); + io_field "set_tree" ~typ:store_schema.commit + ~doc:"Set the tree at \"path\"" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "tree" ~typ:(non_null Input.tree); + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch k items i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + Lwt.catch + (fun () -> + let tree = Store.Tree.empty () in + let* tree = to_tree tree items in + Store.set_tree t ?retries ?allow_empty ?parents ~info k tree + >>= function + | Ok _ -> Store.Head.find t >|= Result.ok + | Error e -> err_write e) + (function Failure e -> Lwt.return (Error e) | e -> raise e)); + io_field "update_tree" ~typ:store_schema.commit + ~doc:"Add/remove items from the tree specified by \"path\"" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "tree" ~typ:(non_null Input.tree); + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch k items i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + Lwt.catch + (fun () -> + Store.with_tree t ?retries ?allow_empty ?parents k ~info + (fun tree -> + let tree = + match tree with + | Some t -> t + | None -> Store.Tree.empty () + in + to_tree tree items >>= Lwt.return_some) + >>= function + | Ok _ -> Store.Head.find t >|= Result.ok + | Error e -> err_write e) + (function Failure e -> Lwt.return (Error e) | e -> raise e)); + io_field "set_all" ~typ:store_schema.commit + ~doc:"Set contents and metadata" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "value" ~typ:(non_null Input.value); + arg "metadata" ~typ:Input.metadata; + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch k v m i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + let* tree = + Store.find_tree t k >>= function + | Some tree -> Lwt.return tree + | None -> Lwt.return (Store.Tree.empty ()) + in + let* tree = Store.Tree.add tree k ?metadata:m v in + Store.set_tree t ?retries ?allow_empty ?parents k tree ~info + >>= function + | Ok () -> Store.Head.find t >|= Result.ok + | Error e -> err_write e); + io_field "test_and_set" ~typ:store_schema.commit + ~doc: + "Update a value with \"set\" argument if \"test\" matches the \ + current value" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "test" ~typ:Input.value; + arg "set" ~typ:Input.value; + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch k test set i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + Store.test_and_set ?retries ?allow_empty ?parents ~info t k ~test + ~set + >>= function + | Ok _ -> Store.Head.find t >|= Result.ok + | Error e -> err_write e); + io_field "test_set_and_get" ~typ:store_schema.commit + ~doc: + "Update a value with \"set\" argument if \"test\" matches the \ + current value. The commit returned is gauranteed to be that of a \ + successful update to the store." + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "test" ~typ:Input.value; + arg "set" ~typ:Input.value; + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch k test set i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + Store.test_set_and_get ?retries ?allow_empty ?parents ~info t k + ~test ~set + >>= function + | Ok _ as v -> Lwt.return v + | Error e -> err_write e); + io_field "test_and_set_branch" ~typ:(non_null bool) + ~doc: + "Update a branch with \"set\" argument if \"test\" matches the \ + current value" + ~args: + Arg. + [ + arg "branch" ~typ:(non_null Input.branch); + arg "test" ~typ:Input.commit_key; + arg "set" ~typ:Input.commit_key; + ] + ~resolve:(fun _ _src branch test set -> + let branches = Store.Backend.Repo.branch_t s in + Store.Backend.Branch.test_and_set branches branch ~test ~set + >|= Result.ok); + io_field "remove" ~typ:store_schema.commit + ~doc:"Remove a path from the store" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch key i -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s i in + Store.remove t ?retries ?allow_empty ?parents key ~info >>= function + | Ok () -> Store.Head.find t >|= Result.ok + | Error e -> err_write e); + io_field "merge" ~typ:Types.Hash.schema_typ + ~doc:"Merge the current value at the given path with another value" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "value" ~typ:Input.value; + arg "old" ~typ:Input.value; + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch key value old info -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s info in + Store.merge t key ~info ?retries ?allow_empty ?parents ~old value + >>= function + | Ok _ -> Store.hash t key >|= Result.ok + | Error e -> err_write e); + io_field "merge_tree" ~typ:store_schema.commit + ~doc:"Merge a branch with a tree" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "path" ~typ:(non_null Input.path); + arg "value" ~typ:Input.tree; + arg "old" ~typ:Input.tree; + arg "info" ~typ:Input.info; + ] + ~resolve:(fun _ _src branch key value old info -> + let* t = mk_branch s branch in + let* info, retries, allow_empty, parents = txn_args s info in + let* old = + match old with + | Some old -> + let tree = Store.Tree.empty () in + to_tree tree old >>= Lwt.return_some + | None -> Lwt.return_none + in + let* value = + match value with + | Some value -> + let tree = Store.Tree.empty () in + to_tree tree value >>= Lwt.return_some + | None -> Lwt.return_none + in + Store.merge_tree t key ~info ?retries ?allow_empty ?parents ~old + value + >>= function + | Ok _ -> Store.Head.find t >|= Result.ok + | Error e -> err_write e); + io_field "merge_with_branch" ~typ:store_schema.commit + ~doc:"Merge a branch with another branch" + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "from" ~typ:(non_null Input.branch); + arg "info" ~typ:Input.info; + arg "max_depth" ~typ:int; + arg "n" ~typ:int; + ] + ~resolve:(fun _ _src into from i max_depth n -> + let* t = mk_branch s into in + let* info, _, _, _ = txn_args s i in + let* _ = Store.merge_with_branch t from ~info ?max_depth ?n in + Store.Head.find t >|= Result.ok); + io_field "merge_with_commit" + ~doc:"Merge a branch with a specific commit" ~typ:store_schema.commit + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "from" ~typ:(non_null Input.hash); + arg "info" ~typ:Input.info; + arg "max_depth" ~typ:int; + arg "n" ~typ:int; + ] + ~resolve:(fun _ _src into from i max_depth n -> + let* t = mk_branch s into in + let* info, _, _, _ = txn_args s i in + Store.Commit.of_hash (Store.repo t) from >>= function + | Some from -> ( + Store.merge_with_commit t from ~info ?max_depth ?n >>= function + | Ok _ -> Store.Head.find t >|= Result.ok + | Error e -> + Lwt.return + (Error (Irmin.Type.to_string Irmin.Merge.conflict_t e))) + | None -> Lwt.return (Error "invalid hash")); + io_field "revert" ~doc:"Revert to a previous commit" + ~typ:store_schema.commit + ~args: + Arg. + [ + arg "branch" ~typ:Input.branch; + arg "commit" ~typ:(non_null Input.hash); + ] + ~resolve:(fun _ _src branch commit -> + Store.Commit.of_hash s commit >>= function + | Some commit -> + let* t = mk_branch s branch in + Store.Head.set t commit >|= fun () -> Ok (Some commit) + | None -> Lwt.return (Ok None)); + ] + + let diff = + Schema.( + obj "Diff" + ~fields: + [ + field "commit" ~typ:(non_null store_schema.commit) ~args:[] + ~resolve:(fun _ctx -> function + | `Added c | `Removed c | `Updated (_, c) -> c); + ]) + + let map_diff diff ~added ~removed ~updated = + match diff with + | `Added x -> `Added (added x) + | `Removed x -> `Removed (removed x) + | `Updated (x, y) -> `Updated (updated x y) + + let subscriptions s = + Schema. + [ + subscription_field "watch" ~typ:(non_null diff) + ~doc:"Watch for changes to a branch" + ~args: + Arg.[ arg "branch" ~typ:Input.branch; arg "path" ~typ:Input.path ] + ~resolve:(fun _ctx branch path -> + let* t = mk_branch s branch in + let stream, push = Lwt_stream.create () in + let destroy_stream watch () = + push None; + Lwt.ignore_result (Store.unwatch watch) + in + match path with + | None -> + let+ watch = + Store.watch t (fun diff -> + push (Some diff); + Lwt.return_unit) + in + Ok (stream, destroy_stream watch) + | Some path -> + let+ watch = + Store.watch_key t path (function diff -> + push + (Some + (map_diff diff + ~added:(fun (c, _) -> c) + ~removed:(fun (c, _) -> c) + ~updated:(fun (before, _) (after, _) -> + (before, after)))); + Lwt.return_unit) + in + Ok (stream, destroy_stream watch)); + ] + + let schema s = + let mutations = mutations s @ remote s in + let subscriptions = subscriptions s in + Schema.( + schema ~mutations ~subscriptions + [ + io_field "commit" ~doc:"Find commit by hash" ~typ:store_schema.commit + ~args:Arg.[ arg "hash" ~typ:(non_null Input.hash) ] + ~resolve:(fun _ _src hash -> + Store.Commit.of_hash s hash >|= Result.ok); + io_field "contents" ~doc:"Find contents by hash" + ~typ:Types.Contents.schema_typ + ~args:Arg.[ arg "hash" ~typ:(non_null Input.hash) ] + ~resolve:(fun _ _src k -> Store.Contents.of_hash s k >|= Result.ok); + io_field "contents_hash" ~doc:"Get the hash of some contents" + ~typ:(non_null Types.Hash.schema_typ) + ~args:Arg.[ arg "value" ~typ:(non_null Input.value) ] + ~resolve:(fun _ _src c -> + Lwt.return (Store.Contents.hash c) >|= Result.ok); + io_field "commit_of_key" ~doc:"Find commit by key" + ~typ:store_schema.commit + ~args:Arg.[ arg "key" ~typ:(non_null Input.commit_key) ] + ~resolve:(fun _ _src k -> Store.Commit.of_key s k >|= Result.ok); + io_field "contents_of_key" ~doc:"Find contents by key" + ~typ:Types.Contents.schema_typ + ~args:Arg.[ arg "key" ~typ:(non_null Input.contents_key) ] + ~resolve:(fun _ _src k -> Store.Contents.of_key s k >|= Result.ok); + io_field "branches" ~doc:"Get a list of all branches" + ~typ:(non_null (list (non_null store_schema.branch))) + ~args:[] + ~resolve:(fun _ _ -> + Store.Branch.list s + >>= Lwt_list.map_p (fun branch -> + let+ store = Store.of_branch s branch in + (store, branch)) + >|= Result.ok); + io_field "main" ~doc:"Get main branch" ~typ:store_schema.branch + ~args:[] ~resolve:(fun _ _ -> + let+ t = Store.main s in + Ok (Some (t, Store.Branch.main))); + io_field "branch" ~doc:"Get branch by name" ~typ:store_schema.branch + ~args:Arg.[ arg "name" ~typ:(non_null Input.branch) ] + ~resolve:(fun _ _ branch -> + let+ t = Store.of_branch s branch in + Ok (Some (t, branch))); + ]) + + let execute_request ctx req = Graphql_server.execute_request ctx () req + + let v store = + let schema = schema store in + let callback = Graphql_server.make_callback (fun _ctx -> ()) schema in + Server.make_response_action ~callback () +end + +module Make + (Server : Cohttp_lwt.S.Server) + (Config : CONFIG) + (Store : Irmin.Generic_key.S with type Schema.Info.t = Config.info) = +struct + module Types = Default_types (Store) + include Make_ext (Server) (Config) (Store) (Types) +end diff --git a/vendors/irmin/src/irmin-graphql/server.mli b/vendors/irmin/src/irmin-graphql/server.mli new file mode 100644 index 000000000000..84a778fa6556 --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/server.mli @@ -0,0 +1,119 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Schema = Graphql_lwt.Schema + +(** GraphQL server *) +module type S = sig + module IO : Cohttp_lwt.S.IO + + type repo + type server + + type response_action = + [ `Expert of Cohttp.Response.t * (IO.ic -> IO.oc -> unit Lwt.t) + | `Response of Cohttp.Response.t * Cohttp_lwt.Body.t ] + + val schema : repo -> unit Schema.schema + + val execute_request : + unit Schema.schema -> + Cohttp_lwt.Request.t -> + Cohttp_lwt.Body.t -> + response_action Lwt.t + + val v : repo -> server +end + +(** GraphQL server config *) +module type CONFIG = sig + type info + + val remote : (?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t) option + + val info : + ?author:string -> ('a, Format.formatter, unit, unit -> info) format4 -> 'a +end + +(** Custom GraphQL schema type and argument type for [type t]. *) +module type CUSTOM_TYPE = sig + type t + + val schema_typ : (unit, t option) Schema.typ + val arg_typ : t option Schema.Arg.arg_typ +end + +(** GraphQL types for Irmin concepts (key, metadata, contents, hash and branch). *) +module type CUSTOM_TYPES = sig + type path + type metadata + type contents + type hash + type branch + type commit_key + type contents_key + type node_key + + module Path : CUSTOM_TYPE with type t := path + module Metadata : CUSTOM_TYPE with type t := metadata + module Contents : CUSTOM_TYPE with type t := contents + module Hash : CUSTOM_TYPE with type t := hash + module Branch : CUSTOM_TYPE with type t := branch + module Commit_key : CUSTOM_TYPE with type t := commit_key + module Contents_key : CUSTOM_TYPE with type t := contents_key + module Node_key : CUSTOM_TYPE with type t := node_key +end + +(** Default GraphQL types for the Irmin store [S]. *) +module Default_types (S : Irmin.Generic_key.S) : + CUSTOM_TYPES + with type path := S.path + and type metadata := S.metadata + and type contents := S.contents + and type hash := S.hash + and type branch := S.branch + and type commit_key := S.commit_key + and type contents_key := S.contents_key + and type node_key := S.node_key + +(** Create a GraphQL server with default GraphQL types for [S]. *) +module Make + (Server : Cohttp_lwt.S.Server) + (Config : CONFIG) + (Store : Irmin.Generic_key.S with type Schema.Info.t = Config.info) : + S + with type repo = Store.repo + and type server = Server.t + and module IO = Server.IO + +(** Create a GraphQL server with custom GraphQL types. *) +module Make_ext + (Server : Cohttp_lwt.S.Server) + (Config : CONFIG) + (Store : Irmin.Generic_key.S with type Schema.Info.t = Config.info) + (Types : CUSTOM_TYPES + with type path := Store.path + and type metadata := Store.metadata + and type contents := Store.contents + and type hash := Store.hash + and type branch := Store.branch + and type commit_key := Store.commit_key + and type contents_key := Store.contents_key + and type node_key := Store.node_key) : + S + with type repo = Store.repo + and type server = Server.t + and module IO = Server.IO diff --git a/vendors/irmin/src/irmin-graphql/unix/dune b/vendors/irmin/src/irmin-graphql/unix/dune new file mode 100644 index 000000000000..694d4afc3565 --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/unix/dune @@ -0,0 +1,8 @@ +(library + (public_name irmin-graphql.unix) + (name irmin_graphql_unix) + (libraries cohttp-lwt-unix irmin-graphql irmin.unix git-unix lwt.unix) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.ml b/vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.ml new file mode 100644 index 000000000000..b7e4d46c23f6 --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.ml @@ -0,0 +1,76 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type remote_fn = + ?ctx:Mimic.ctx -> ?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t + +module Server = struct + module Remote = struct + module None = struct + let remote = None + end + end + + module Make_ext + (S : Irmin.Generic_key.S) (Remote : sig + val remote : remote_fn option + end) + (T : Irmin_graphql.Server.CUSTOM_TYPES + with type path := S.path + and type metadata := S.metadata + and type contents := S.contents + and type hash := S.hash + and type branch := S.branch + and type commit_key := S.commit_key + and type contents_key := S.contents_key + and type node_key := S.node_key) = + Irmin_graphql.Server.Make_ext + (Cohttp_lwt_unix.Server) + (struct + module Info = Irmin_unix.Info (S.Info) + + type info = S.info + + let info = Info.v + + let remote = + match Remote.remote with + | Some fn -> Some (fun ?headers v -> fn ?headers v) + | None -> None + end) + (S) + (T) + + module Make + (S : Irmin.Generic_key.S) (Remote : sig + val remote : remote_fn option + end) = + Irmin_graphql.Server.Make + (Cohttp_lwt_unix.Server) + (struct + module Info = Irmin_unix.Info (S.Info) + + type info = S.info + + let info = Info.v + + let remote = + match Remote.remote with + | Some fn -> Some (fun ?headers v -> fn ?headers v) + | None -> None + end) + (S) +end diff --git a/vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.mli b/vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.mli new file mode 100644 index 000000000000..2bd6fdc2185d --- /dev/null +++ b/vendors/irmin/src/irmin-graphql/unix/irmin_graphql_unix.mli @@ -0,0 +1,53 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type remote_fn = + ?ctx:Mimic.ctx -> ?headers:Cohttp.Header.t -> string -> Irmin.remote Lwt.t + +module Server : sig + module Remote : sig + module None : sig + val remote : remote_fn option + end + end + + module Make + (S : Irmin.Generic_key.S) (Remote : sig + val remote : remote_fn option + end) : + Irmin_graphql.Server.S + with type repo = S.repo + and type server = Cohttp_lwt_unix.Server.t + and module IO = Cohttp_lwt_unix.IO + + module Make_ext + (S : Irmin.Generic_key.S) (Remote : sig + val remote : remote_fn option + end) + (T : Irmin_graphql.Server.CUSTOM_TYPES + with type path := S.path + and type metadata := S.metadata + and type contents := S.contents + and type hash := S.hash + and type branch := S.branch + and type commit_key := S.commit_key + and type contents_key := S.contents_key + and type node_key := S.node_key) : + Irmin_graphql.Server.S + with type repo = S.repo + and type server = Cohttp_lwt_unix.Server.t + and module IO = Cohttp_lwt_unix.IO +end diff --git a/vendors/irmin/src/irmin-http/closeable.ml b/vendors/irmin/src/irmin-http/closeable.ml new file mode 100644 index 000000000000..9e38a7ffbb0f --- /dev/null +++ b/vendors/irmin/src/irmin-http/closeable.ml @@ -0,0 +1,118 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open S + +module Content_addressable (S : Content_addressable.S) = struct + type 'a t = { closed : bool ref; t : 'a S.t } + type key = S.key + type value = S.value + type ctx = S.ctx + + let check_not_closed t = if !(t.closed) then raise Irmin.Closed + + let mem t k = + check_not_closed t; + S.mem t.t k + + let find t k = + check_not_closed t; + S.find t.t k + + let add t v = + check_not_closed t; + S.add t.t v + + let unsafe_add t k v = + check_not_closed t; + S.unsafe_add t.t k v + + let v ?ctx uri item items = + let+ t = S.v ?ctx uri item items in + { closed = ref false; t } + + let close t = + if !(t.closed) then Lwt.return_unit + else ( + t.closed := true; + S.close t.t) + + let batch t f = + check_not_closed t; + S.batch t.t (fun w -> f { t = w; closed = t.closed }) +end + +module Atomic_write (S : Atomic_write.S) = struct + type t = { closed : bool ref; t : S.t } + type key = S.key + type value = S.value + type ctx = S.ctx + + let check_not_closed t = if !(t.closed) then raise Irmin.Closed + + let mem t k = + check_not_closed t; + S.mem t.t k + + let find t k = + check_not_closed t; + S.find t.t k + + let set t k v = + check_not_closed t; + S.set t.t k v + + let test_and_set t k ~test ~set = + check_not_closed t; + S.test_and_set t.t k ~test ~set + + let remove t k = + check_not_closed t; + S.remove t.t k + + let list t = + check_not_closed t; + S.list t.t + + type watch = S.watch + + let watch t ?init f = + check_not_closed t; + S.watch t.t ?init f + + let watch_key t k ?init f = + check_not_closed t; + S.watch_key t.t k ?init f + + let unwatch t w = + check_not_closed t; + S.unwatch t.t w + + let v ?ctx uri item items = + let+ t = S.v ?ctx uri item items in + { closed = ref false; t } + + let close t = + if !(t.closed) then Lwt.return_unit + else ( + t.closed := true; + S.close t.t) + + let clear t = + check_not_closed t; + S.clear t.t +end diff --git a/vendors/irmin/src/irmin-http/closeable.mli b/vendors/irmin/src/irmin-http/closeable.mli new file mode 100644 index 000000000000..965927b9db26 --- /dev/null +++ b/vendors/irmin/src/irmin-http/closeable.mli @@ -0,0 +1,32 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Augments primitive store modules with close semantics *) + +open S + +module Content_addressable (M : Content_addressable.S) : + Content_addressable.S + with type key = M.key + and type value = M.value + and type ctx = M.ctx + +module Atomic_write (M : Atomic_write.S) : + Atomic_write.S + with type key = M.key + and type value = M.value + and type watch = M.watch + and type ctx = M.ctx diff --git a/vendors/irmin/src/irmin-http/common.ml b/vendors/irmin/src/irmin-http/common.ml new file mode 100644 index 000000000000..6ce4b62db1e7 --- /dev/null +++ b/vendors/irmin/src/irmin-http/common.ml @@ -0,0 +1,29 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let irmin_version = "X-IrminVersion" + +type status = { status : string } [@@deriving irmin] + +type 'a set = { test : 'a option; set : 'a option; v : 'a option } +[@@deriving irmin] + +type ('a, 'b) event = { branch : 'a; diff : 'b Irmin.Diff.t } [@@deriving irmin] +type ('a, 'b) init = { branch : 'a; commit : 'b } [@@deriving irmin] +type 'a merge = { old : 'a; left : 'a; right : 'a } [@@deriving irmin] + +type 'a merge_result = ('a option, Irmin.Merge.conflict) result +[@@deriving irmin] diff --git a/vendors/irmin/src/irmin-http/dune b/vendors/irmin/src/irmin-http/dune new file mode 100644 index 000000000000..a3dc1b3ad467 --- /dev/null +++ b/vendors/irmin/src/irmin-http/dune @@ -0,0 +1,19 @@ +(library + (name irmin_http) + (public_name irmin-http) + (libraries + astring + cohttp + cohttp-lwt + fmt + irmin + jsonm + logs + lwt + uri + unix + webmachine) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-http/import.ml b/vendors/irmin/src/irmin-http/import.ml new file mode 100644 index 000000000000..71053e21ba54 --- /dev/null +++ b/vendors/irmin/src/irmin-http/import.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin-http/irmin_http.ml b/vendors/irmin/src/irmin-http/irmin_http.ml new file mode 100644 index 000000000000..0191c7c60751 --- /dev/null +++ b/vendors/irmin/src/irmin-http/irmin_http.ml @@ -0,0 +1,566 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Common +open Astring +open! Import + +let src = Logs.Src.create "irmin.http" ~doc:"Irmin HTTP REST interface" + +module Log = (val Logs.src_log src : Logs.LOG) +module T = Irmin.Type + +module Conf = struct + include Irmin.Backend.Conf + + let spec = Spec.v "http" + + module Key = struct + (* ~uri *) + let uri = + key ~spec ~docv:"URI" ~docs:"COMMON OPTIONS" + ~doc:"Location of the remote store." "uri" + Irmin.Type.(option uri) + None + end +end + +let config x config = + let a = Conf.empty Conf.spec in + Conf.(verify (union (add a Key.uri (Some x)) config)) + +let uri_append t path = + match Uri.path t :: path with + | [] -> t + | path -> + let buf = Buffer.create 10 in + List.iter + (function + | "" -> () + | s -> + if s.[0] <> '/' then Buffer.add_char buf '/'; + Buffer.add_string buf s) + path; + let path = Buffer.contents buf in + Uri.with_path t path + +let err_no_uri () = invalid_arg "Irmin_http.create: No URI specified" + +let get_uri config = + match Conf.(get config Key.uri) with None -> err_no_uri () | Some u -> u + +let invalid_arg fmt = Fmt.kstr Lwt.fail_invalid_arg fmt + +exception Escape of ((int * int) * (int * int)) * Jsonm.error + +let () = + Printexc.register_printer (function + | Escape ((start, end_), err) -> + Fmt.kstr + (fun s -> Some s) + "Escape ({ start = %a; end = %a; error = %a })" + Fmt.(Dump.pair int int) + start + Fmt.(Dump.pair int int) + end_ Jsonm.pp_error err + | _ -> None) + +let json_stream (stream : string Lwt_stream.t) : Jsonm.lexeme list Lwt_stream.t + = + let d = Jsonm.decoder `Manual in + let rec lexeme () = + match Jsonm.decode d with + | `Lexeme l -> Lwt.return l + | `Error e -> Lwt.fail (Escape (Jsonm.decoded_range d, e)) + | `End -> assert false + | `Await -> ( + Lwt_stream.get stream >>= function + | None -> Lwt.fail (Escape (Jsonm.decoded_range d, `Expected `Value)) + | Some str -> + Jsonm.Manual.src d (Bytes.of_string str) 0 (String.length str); + lexeme ()) + in + let lexemes e = + let lexemes = ref [] in + let objs = ref 0 in + let arrs = ref 0 in + let rec aux () = + let* l = lexeme e in + lexemes := l :: !lexemes; + let () = + match l with + | `Os -> incr objs + | `As -> incr arrs + | `Oe -> decr objs + | `Ae -> decr arrs + | `Name _ | `Null | `Bool _ | `String _ | `Float _ -> () + in + if !objs > 0 || !arrs > 0 then aux () else Lwt.return_unit + in + let+ () = aux () in + List.rev !lexemes + in + let open_stream () = + lexeme () >>= function + | `As -> Lwt.return_unit + | _ -> Lwt.fail (Escape (Jsonm.decoded_range d, `Expected (`Aval true))) + in + let opened = ref false in + let open_and_get () = + if not !opened then ( + open_stream () >>= fun () -> + opened := true; + lexemes () >|= Option.some) + else lexemes () >|= Option.some + in + Lwt_stream.from open_and_get + +let of_json = Irmin.Type.of_json_string +let to_json = Irmin.Type.to_json_string + +module Helper (Client : Cohttp_lwt.S.Client) : + S.Helper with type ctx = Client.ctx = struct + type ctx = Client.ctx + + let err_bad_version v = + invalid_arg "bad server version: expecting %s, but got %s" Irmin.version + (match v with None -> "" | Some v -> v) + + let check_version r = + match Cohttp.Header.get (Cohttp.Response.headers r) irmin_version with + | None -> err_bad_version None + | Some v -> + if v <> Irmin.version then err_bad_version (Some v) else Lwt.return_unit + + let is_success r = + match Cohttp.Response.status r with `OK -> true | _ -> false + + let map_string_response parse (r, b) = + check_version r >>= fun () -> + let* b = Cohttp_lwt.Body.to_string b in + if is_success r then + match parse b with + | Ok x -> Lwt.return x + | Error (`Msg e) -> + Lwt.fail_with (Fmt.str "Error while parsing %S: %s" b e) + else Lwt.fail_with ("Server error: " ^ b) + + let map_stream_response t (r, b) = + check_version r >>= fun () -> + if not (is_success r) then + let* b = Cohttp_lwt.Body.to_string b in + Lwt.fail_with ("Server error: " ^ b) + else + let stream = Cohttp_lwt.Body.to_stream b in + let stream = json_stream stream in + let stream = + let aux j = + match T.decode_json_lexemes t j with + | Error (`Msg e) -> Lwt.fail_with e + | Ok c -> Lwt.return c + in + Lwt_stream.map_s aux stream + in + Lwt.return stream + + let headers ~keep_alive () = + let keep_alive = + if keep_alive then [ ("Connection", "Keep-Alive") ] else [] + in + Cohttp.Header.of_list + ([ (irmin_version, Irmin.version); ("Content-type", "application/json") ] + @ keep_alive) + + let map_call meth t ctx ~keep_alive ?body path fn = + let uri = uri_append t path in + let body = match body with None -> None | Some b -> Some (`String b) in + let headers = headers ~keep_alive () in + [%log.debug "%s %s" (Cohttp.Code.string_of_method meth) (Uri.path uri)]; + Lwt.catch + (fun () -> Client.call ?ctx meth ~headers ?body uri >>= fn) + (fun e -> + [%log.debug "request to %a failed: %a" Uri.pp_hum uri Fmt.exn e]; + Lwt.fail e) + + let call meth t ctx ?body path parse = + map_call meth t ctx ~keep_alive:false ?body path (map_string_response parse) + + let call_stream meth t ctx ?body path parse = + map_call meth t ctx ~keep_alive:true ?body path (map_stream_response parse) +end + +module RO (Client : Cohttp_lwt.S.Client) (K : Irmin.Type.S) (V : Irmin.Type.S) : + S.Read_only.S + with type ctx = Client.ctx + and type key = K.t + and type value = V.t = struct + type ctx = Client.ctx + + module HTTP = Helper (Client) + + type 'a t = { + uri : Uri.t; + item : string; + items : string; + ctx : Client.ctx option; + } + + let uri t = t.uri + let item t = t.item + let items t = t.items + let close _ = Lwt.return () + + type key = K.t + type value = V.t + + let key_str = Irmin.Type.to_string K.t + let val_of_str = Irmin.Type.of_string V.t + + let find t key = + HTTP.map_call `GET t.uri t.ctx ~keep_alive:false + [ t.item; key_str key ] + (fun ((r, _) as x) -> + if Cohttp.Response.status r = `Not_found then Lwt.return_none + else HTTP.map_string_response val_of_str x >|= Option.some) + + let mem t key = + HTTP.map_call `GET t.uri t.ctx ~keep_alive:false + [ t.item; key_str key ] + (fun (r, _) -> + if Cohttp.Response.status r = `Not_found then Lwt.return_false + else Lwt.return_true) + + let v ?ctx uri item items = Lwt.return { uri; item; items; ctx } +end + +module CA (Client : Cohttp_lwt.S.Client) (H : Irmin.Hash.S) (V : Irmin.Type.S) = +struct + include RO (Client) (H) (V) + + let add t value = + let body = Irmin.Type.to_string V.t value in + HTTP.call `POST t.uri t.ctx [ t.items ] ~body (Irmin.Type.of_string H.t) + + let unsafe_add t key value = + let body = Irmin.Type.to_string V.t value in + HTTP.call `POST t.uri t.ctx + [ "unsafe"; t.items; key_str key ] + ~body + Irmin.Type.(of_string unit) + + let cast t = (t :> read_write t) + + let batch t f = + (* TODO:cache the writes locally and send everything in one batch *) + f (cast t) + + let close _ = Lwt.return_unit +end + +module RW : S.Atomic_write.Maker = +functor + (Client : Cohttp_lwt.S.Client) + (K : Irmin.Type.S) + (V : Irmin.Type.S) + -> + struct + module RO = RO (Client) (K) (V) + module HTTP = RO.HTTP + module W = Irmin.Backend.Watch.Make (K) (V) + + type key = RO.key + type value = RO.value + type watch = W.watch + type ctx = Client.ctx + + (* cache the stream connections to the server: we open only one + connection per stream kind. *) + type cache = { mutable stop : unit -> unit } + + let empty_cache () = { stop = (fun () -> ()) } + + type t = { t : read RO.t; w : W.t; keys : cache; glob : cache } + + let get t = HTTP.call `GET (RO.uri t.t) t.t.ctx + let put t = HTTP.call `PUT (RO.uri t.t) t.t.ctx + let get_stream t = HTTP.call_stream `GET (RO.uri t.t) t.t.ctx + let post_stream t = HTTP.call_stream `POST (RO.uri t.t) t.t.ctx + + let v ?ctx uri item items = + let* t = RO.v ?ctx uri item items in + let w = W.v () in + let keys = empty_cache () in + let glob = empty_cache () in + Lwt.return { t; w; keys; glob } + + let find t = RO.find t.t + let mem t = RO.mem t.t + let key_str = Irmin.Type.to_string K.t + let list t = get t [ RO.items t.t ] (of_json T.(list K.t)) + + let set t key value = + let value = { v = Some value; set = None; test = None } in + let body = to_json (set_t V.t) value in + put t [ RO.item t.t; key_str key ] ~body (of_json status_t) >>= function + | { status = "ok" } -> Lwt.return_unit + | e -> Lwt.fail_with e.status + + let test_and_set t key ~test ~set = + let value = { v = None; set; test } in + let body = to_json (set_t V.t) value in + put t [ RO.item t.t; key_str key ] ~body (of_json status_t) >>= function + | { status = "true" } -> Lwt.return_true + | { status = "false" } -> Lwt.return_false + | e -> Lwt.fail_with e.status + + let pp_key = Irmin.Type.pp K.t + + let remove t key = + HTTP.map_call `DELETE (RO.uri t.t) t.t.ctx ~keep_alive:false + [ RO.item t.t; key_str key ] + (fun (r, b) -> + match Cohttp.Response.status r with + | `Not_found | `OK -> Lwt.return_unit + | _ -> + let* b = Cohttp_lwt.Body.to_string b in + Fmt.kstr Lwt.fail_with "cannot remove %a: %s" pp_key key b) + + let nb_keys t = fst (W.stats t.w) + let nb_glob t = snd (W.stats t.w) + + (* run [t] and returns an handler to stop the task. *) + let stoppable t = + let s, u = Lwt.task () in + Lwt.async (fun () -> Lwt.pick [ s; t () ]); + function () -> Lwt.wakeup u () + + let watch_key t key ?init f = + let key_str = Irmin.Type.to_string K.t key in + let init_stream () = + if nb_keys t <> 0 then Lwt.return_unit + else + let* s = + match init with + | None -> get_stream t [ "watch"; key_str ] (event_t K.t V.t) + | Some init -> + let body = to_json V.t init in + post_stream t [ "watch"; key_str ] ~body (event_t K.t V.t) + in + let stop () = + Lwt_stream.iter_s + (fun { diff; _ } -> + let diff = + match diff with + | `Removed _ -> None + | `Added v | `Updated (_, v) -> Some v + in + W.notify t.w key diff) + s + in + t.keys.stop <- stoppable stop; + Lwt.return_unit + in + let* () = init_stream () in + W.watch_key t.w key ?init f + + let watch t ?init f = + let init_stream () = + if nb_glob t <> 0 then Lwt.return_unit + else + let* s = + match init with + | None -> get_stream t [ "watches" ] (event_t K.t V.t) + | Some init -> + let init = + List.map (fun (branch, commit) -> { branch; commit }) init + in + let body = to_json T.(list (init_t K.t V.t)) init in + post_stream t [ "watches" ] ~body (event_t K.t V.t) + in + let stop () = + Lwt_stream.iter_s + (fun ev -> + let diff = + match ev.diff with + | `Removed _ -> None + | `Added v | `Updated (_, v) -> Some v + in + let k = ev.branch in + [%log.debug fun l -> + let pp_opt = + Fmt.option ~none:(Fmt.any "") (Irmin.Type.pp V.t) + in + l "notify %a: %a" pp_key k pp_opt diff] + ; + W.notify t.w k diff) + s + in + t.glob.stop <- stoppable stop; + Lwt.return_unit + in + let* () = init_stream () in + W.watch t.w ?init f + + let stop x = + let () = try x.stop () with _e -> () in + x.stop <- (fun () -> ()) + + let unwatch t id = + W.unwatch t.w id >>= fun () -> + if nb_keys t = 0 then stop t.keys; + if nb_glob t = 0 then stop t.glob; + Lwt.return_unit + + let close _ = Lwt.return_unit + + let clear t = + HTTP.call `POST t.t.uri t.t.ctx [ "clear"; t.t.items ] + Irmin.Type.(of_string unit) + end + +module type HTTP_CLIENT = sig + include Cohttp_lwt.S.Client + + val ctx : unit -> ctx option +end + +module Client (Client : HTTP_CLIENT) (S : Irmin.S) = struct + module X = struct + module Hash = S.Hash + module Schema = S.Schema + module Key = Irmin.Key.Of_hash (Hash) + + module Contents = struct + module X = struct + module Key = S.Hash + module Val = S.Contents + module CA = CA (Client) (Key) (Val) + include Closeable.Content_addressable (CA) + end + + include Irmin.Contents.Store (X) (X.Key) (X.Val) + + let v ?ctx config = X.v ?ctx config "blob" "blobs" + end + + module Node = struct + module Val = S.Backend.Node.Val + module Hash = Irmin.Hash.Typed (S.Hash) (Val) + module CA = CA (Client) (S.Hash) (Val) + include Irmin.Indexable.Of_content_addressable (S.Hash) (CA) + module Contents = Contents + module Metadata = S.Metadata + module Path = S.Path + + let merge (t : _ t) = + let f ~(old : Key.t option Irmin.Merge.promise) left right = + let* old = + old () >|= function + | Ok (Some old) -> old + | Ok None -> None + | Error _ -> None + in + let body = + Irmin.Type.(to_string (merge_t (option Key.t))) { old; left; right } + in + let result = merge_result_t Key.t in + CA.HTTP.call `POST t.uri t.ctx [ t.items; "merge" ] ~body + (Irmin.Type.of_string result) + in + Irmin.Merge.(v Irmin.Type.(option Key.t)) f + + let v ?ctx config = CA.v ?ctx config "tree" "trees" + end + + module Node_portable = Irmin.Node.Portable.Of_node (Node.Val) + + module Commit = struct + module X = struct + module Key = S.Hash + + module Val = struct + include S.Backend.Commit.Val + module Info = S.Info + + type hash = S.Hash.t [@@deriving irmin] + end + + module CA = CA (Client) (Key) (Val) + include Closeable.Content_addressable (CA) + end + + include Irmin.Commit.Store (S.Info) (Node) (X) (X.Key) (X.Val) + + let v ?ctx config = X.v ?ctx config "commit" "commits" + end + + module Commit_portable = Irmin.Commit.Portable.Of_commit (Commit.X.Val) + module Slice = Irmin.Backend.Slice.Make (Contents) (Node) (Commit) + module Remote = Irmin.Backend.Remote.None (Hash) (S.Branch) + + module Branch = struct + module Key = S.Branch + module Val = Commit.Key + include Closeable.Atomic_write (RW (Client) (Key) (S.Hash)) + + let v ?ctx config = v ?ctx config "branch" "branches" + end + + module Repo = struct + type t = { + config : Irmin.config; + contents : read Contents.t; + node : read Node.t; + commit : read Commit.t; + branch : Branch.t; + } + + let branch_t t = t.branch + let commit_t t = t.commit + let node_t t = t.node + let contents_t t = t.contents + let config t = t.config + + let batch t f = + Contents.X.batch t.contents @@ fun contents_t -> + Node.batch t.node @@ fun node_t -> + Commit.X.batch (snd t.commit) @@ fun commit_t -> + let commit_t = (node_t, commit_t) in + f contents_t node_t commit_t + + let v config = + let uri = get_uri config in + let ctx = Client.ctx () in + let* contents = Contents.v ?ctx uri in + let* node = Node.v ?ctx uri in + let* commit = Commit.v ?ctx uri in + let+ branch = Branch.v ?ctx uri in + let commit = (node, commit) in + { contents; node; commit; branch; config } + + let close t = + let* () = Contents.X.close t.contents in + let* () = Branch.close t.branch in + Commit.X.close (snd t.commit) + end + end + + include Irmin.Of_backend (X) +end + +module type SERVER = Irmin_http_server.S + +module Server = Irmin_http_server.Make diff --git a/vendors/irmin/src/irmin-http/irmin_http.mli b/vendors/irmin/src/irmin-http/irmin_http.mli new file mode 100644 index 000000000000..aa64b506faab --- /dev/null +++ b/vendors/irmin/src/irmin-http/irmin_http.mli @@ -0,0 +1,60 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** JSON REST/CRUD interface. *) + +val config : Uri.t -> Irmin.config -> Irmin.config + +module Conf : sig + open Irmin.Backend.Conf + + val spec : Spec.t + + module Key : sig + val uri : Uri.t option key + end +end + +module type HTTP_CLIENT = sig + include Cohttp_lwt.S.Client + + val ctx : unit -> ctx option +end + +module Client (C : HTTP_CLIENT) (S : Irmin.S) : + Irmin.S + with type hash = S.hash + and module Schema = S.Schema + and type Backend.Remote.endpoint = unit + +(** HTTP server *) + +module type SERVER = sig + type repo + (** The type for Irmin repository. *) + + type t + (** The type for HTTP configuration. *) + + val v : ?strict:bool -> repo -> t + (** [v repo] returns the configuration for a server serving the contents of + [repo]. If [strict] is set, incoming connections will fail if they do not + have the right {i X-IrminVersion} headers. *) +end + +(** Create an HTTP server, serving the contents of an Irmin database. *) +module Server (HTTP : Cohttp_lwt.S.Server) (S : Irmin.S) : + SERVER with type repo = S.Repo.t and type t = HTTP.t diff --git a/vendors/irmin/src/irmin-http/irmin_http_server.ml b/vendors/irmin/src/irmin-http/irmin_http_server.ml new file mode 100644 index 000000000000..0e8e409227fb --- /dev/null +++ b/vendors/irmin/src/irmin-http/irmin_http_server.ml @@ -0,0 +1,406 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common +module T = Irmin.Type + +let to_json = Irmin.Type.to_json_string +let of_json = Irmin.Type.of_json_string +let src = Logs.Src.create "irmin.http-srv" ~doc:"Irmin REST API server" + +module Log = (val Logs.src_log src : Logs.LOG) + +module type S = sig + type repo + type t + + val v : ?strict:bool -> repo -> t +end + +let ok = { status = "ok" } +let bool b = { status = string_of_bool b } + +module Make (HTTP : Cohttp_lwt.S.Server) (S : Irmin.S) = struct + module Wm = struct + module Rd = Webmachine.Rd + + module Clock = struct + let now () = int_of_float (Unix.gettimeofday ()) + end + + include Webmachine.Make (HTTP.IO) (Clock) + end + + module B = S.Backend + + class virtual resource = + object + inherit [Cohttp_lwt.Body.t] Wm.resource + + method! finish_request rd = + Wm.Rd.with_resp_headers + (fun h -> Cohttp.Header.add h irmin_version Irmin.version) + rd + |> Wm.continue () + end + + let parse_error rd str (`Msg e) = + let err = Fmt.str "Parse error %S: %s" str e in + Wm.respond ~body:(`String err) 400 rd + + module Content_addressable (S : sig + include Irmin.Content_addressable.S + + val batch : B.Repo.t -> (read_write t -> 'a Lwt.t) -> 'a Lwt.t + end) + (K : Irmin.Type.S with type t = S.key) + (V : Irmin.Type.S with type t = S.value) = + struct + let with_key rd f = + match Irmin.Type.of_string K.t (Wm.Rd.lookup_path_info_exn "id" rd) with + | Ok key -> f key + | Error _ -> Wm.respond 404 rd + + let add rd repo = + let* body = Cohttp_lwt.Body.to_string rd.Wm.Rd.req_body in + match Irmin.Type.of_string V.t body with + | Error e -> parse_error rd body e + | Ok body -> + S.batch repo @@ fun db -> + let* new_id = S.add db body in + let resp_body = `String (Irmin.Type.to_string K.t new_id) in + Wm.continue true { rd with Wm.Rd.resp_body } + + let unsafe_add rd repo key = + let* body = Cohttp_lwt.Body.to_string rd.Wm.Rd.req_body in + match Irmin.Type.of_string V.t body with + | Error e -> parse_error rd body e + | Ok body -> + S.batch repo @@ fun db -> + S.unsafe_add db key body >>= fun () -> + let resp_body = `String "" in + Wm.continue true { rd with Wm.Rd.resp_body } + + class items repo = + object + inherit resource + method! allowed_methods rd = Wm.continue [ `POST ] rd + + method content_types_provided rd = + Wm.continue [ ("application/json", fun _ -> assert false) ] rd + + method content_types_accepted rd = Wm.continue [] rd + method! process_post rd = add rd repo + end + + class unsafe_items repo = + object + inherit resource + method! allowed_methods rd = Wm.continue [ `POST ] rd + + method content_types_provided rd = + Wm.continue [ ("application/json", fun _ -> assert false) ] rd + + method content_types_accepted rd = Wm.continue [] rd + method! process_post rd = with_key rd (unsafe_add rd repo) + end + + class merge merge repo = + object + inherit resource + method! allowed_methods rd = Wm.continue [ `POST ] rd + + method content_types_provided rd = + Wm.continue [ ("application/json", fun _ -> assert false) ] rd + + method content_types_accepted rd = Wm.continue [] rd + + method! process_post rd = + let* body = Cohttp_lwt.Body.to_string rd.Wm.Rd.req_body in + match Irmin.Type.(of_string (merge_t (option K.t))) body with + | Error e -> parse_error rd body e + | Ok { old; left; right } -> + S.batch repo @@ fun db -> + let old = Irmin.Merge.promise old in + let* m = Irmin.Merge.f (merge db) ~old left right in + let result = merge_result_t K.t in + let resp_body = `String Irmin.(Type.to_string result m) in + Wm.continue true { rd with Wm.Rd.resp_body } + end + + class item db = + object (self) + inherit resource + + method private to_json rd = + with_key rd (fun key -> + let str = Irmin.Type.to_string V.t in + S.find db key >>= function + | Some value -> Wm.continue (`String (str value)) rd + | None -> Wm.respond 404 rd) + + method! allowed_methods rd = Wm.continue [ `GET; `HEAD ] rd + method content_types_accepted rd = Wm.continue [] rd + + method! resource_exists rd = + with_key rd (fun key -> + let* mem = S.mem db key in + Wm.continue mem rd) + + method content_types_provided rd = + Wm.continue [ ("application/json", self#to_json) ] rd + end + end + + module Atomic_write + (S : Irmin.Atomic_write.S) + (K : Irmin.Type.S with type t = S.key) + (V : Irmin.Type.S with type t = S.value) = + struct + class items db = + object (self) + inherit resource + method! allowed_methods rd = Wm.continue [ `GET; `HEAD ] rd + method content_types_accepted rd = Wm.continue [] rd + + method private to_json rd = + let* keys = S.list db in + let json = to_json T.(list K.t) keys in + Wm.continue (`String json) rd + + method content_types_provided rd = + Wm.continue [ ("application/json", self#to_json) ] rd + end + + let with_key rd f = + match Irmin.Type.of_string K.t rd.Wm.Rd.dispatch_path with + | Ok x -> f x + | Error _ -> Wm.respond 404 rd + + class item db = + object (self) + inherit resource + + method private of_json rd = + let* body = Cohttp_lwt.Body.to_string rd.Wm.Rd.req_body in + match of_json (set_t V.t) body with + | Error e -> parse_error rd body e + | Ok v -> + with_key rd (fun key -> + match v.v with + | Some v -> + S.set db key v >>= fun () -> + let resp_body = `String (to_json status_t ok) in + let rd = { rd with Wm.Rd.resp_body } in + Wm.continue true rd + | None -> + let* b = S.test_and_set db key ~test:v.test ~set:v.set in + let resp_body = `String (to_json status_t (bool b)) in + let rd = { rd with Wm.Rd.resp_body } in + Wm.continue b rd) + + method private to_json rd = + with_key rd (fun key -> + let str = Irmin.Type.to_string V.t in + S.find db key >>= function + | Some value -> Wm.continue (`String (str value)) rd + | None -> Wm.respond 404 rd) + + method! resource_exists rd = + with_key rd (fun key -> + let* mem = S.mem db key in + Wm.continue mem rd) + + method! allowed_methods rd = + Wm.continue [ `GET; `HEAD; `PUT; `DELETE ] rd + + method content_types_provided rd = + Wm.continue [ ("application/json", self#to_json) ] rd + + method content_types_accepted rd = + Wm.continue [ ("application/json", self#of_json) ] rd + + method! delete_resource rd = + with_key rd (fun key -> + S.remove db key >>= fun () -> + let resp_body = `String (to_json status_t ok) in + Wm.continue true { rd with Wm.Rd.resp_body }) + end + + class watches db = + object (self) + inherit resource + method! allowed_methods rd = Wm.continue [ `GET; `HEAD; `POST ] rd + method content_types_accepted rd = Wm.continue [] rd + + method private stream ?init () = + let stream, push = Lwt_stream.create () in + let init = + Option.map (List.map (fun i -> (i.branch, i.commit))) init + in + let+ w = + S.watch ?init db (fun branch diff -> + let v = to_json (event_t K.t V.t) { branch; diff } in + push (Some v); + push (Some ","); + Lwt.return_unit) + in + Lwt.async (fun () -> + Lwt_stream.closed stream >>= fun () -> S.unwatch db w); + push (Some "["); + `Stream stream + + method! process_post rd = + let* body = Cohttp_lwt.Body.to_string rd.Wm.Rd.req_body in + match of_json T.(list (init_t K.t V.t)) body with + | Error e -> parse_error rd body e + | Ok init -> + let* resp_body = self#stream ~init () in + Wm.continue true { rd with Wm.Rd.resp_body } + + method private of_json rd = + let* body = self#stream () in + Wm.continue body rd + + method content_types_provided rd = + Wm.continue [ ("application/json", self#of_json) ] rd + end + + class watch db = + object (self) + inherit resource + method! allowed_methods rd = Wm.continue [ `GET; `HEAD; `POST ] rd + method content_types_accepted rd = Wm.continue [] rd + + method private stream ?init key = + let stream, push = Lwt_stream.create () in + let+ w = + S.watch_key ?init db key (fun diff -> + let v = to_json (event_t K.t V.t) { branch = key; diff } in + push (Some v); + push (Some ","); + Lwt.return_unit) + in + Lwt.async (fun () -> + Lwt_stream.closed stream >>= fun () -> S.unwatch db w); + push (Some "["); + `Stream stream + + method! process_post rd = + let* body = Cohttp_lwt.Body.to_string rd.Wm.Rd.req_body in + match of_json V.t body with + | Error e -> parse_error rd body e + | Ok init -> + with_key rd (fun key -> + let* resp_body = self#stream ~init key in + Wm.continue true { rd with Wm.Rd.resp_body }) + + method private of_json rd = + with_key rd (fun key -> + let* body = self#stream key in + Wm.continue body rd) + + method content_types_provided rd = + Wm.continue [ ("application/json", self#of_json) ] rd + end + end + + module Blob = + Content_addressable + (struct + include B.Contents + + let unsafe_add t k v = unsafe_add t k v >|= fun _ -> () + let batch t f = B.Repo.batch t @@ fun x _ _ -> f x + end) + (B.Contents.Key) + (B.Contents.Val) + + module Tree = + Content_addressable + (struct + include B.Node + + let unsafe_add t k v = unsafe_add t k v >|= fun _ -> () + let batch t f = B.Repo.batch t @@ fun _ x _ -> f x + end) + (B.Node.Key) + (B.Node.Val) + + module Commit = + Content_addressable + (struct + include B.Commit + + let unsafe_add t k v = unsafe_add t k v >|= fun _ -> () + let batch t f = B.Repo.batch t @@ fun _ _ x -> f x + end) + (B.Commit.Key) + (B.Commit.Val) + + module Branch = Atomic_write (B.Branch) (B.Branch.Key) (B.Branch.Val) + + type repo = S.Repo.t + type t = HTTP.t + + let v ?strict:_ db = + let blob = B.Repo.contents_t db in + let tree = B.Repo.node_t db in + let commit = B.Repo.commit_t db in + let branch = B.Repo.branch_t db in + let routes = + [ + ("/blobs", fun () -> new Blob.items db); + ("/blob/:id", fun () -> new Blob.item blob); + ("/trees", fun () -> new Tree.items db); + ("/trees/merge", fun () -> new Tree.merge S.Backend.Node.merge db); + ("/tree/:id", fun () -> new Tree.item tree); + ("/commits", fun () -> new Commit.items db); + ("/commit/:id", fun () -> new Commit.item commit); + ("/unsafe/blobs/:id", fun () -> new Blob.unsafe_items db); + ("/unsafe/trees/:id", fun () -> new Tree.unsafe_items db); + ("/unsafe/commits/:id", fun () -> new Commit.unsafe_items db); + ("/branches", fun () -> new Branch.items branch); + ("/branch/*", fun () -> new Branch.item branch); + ("/watches", fun () -> new Branch.watches branch); + ("/watch/*", fun () -> new Branch.watch branch); + ] + in + let pp_con = Fmt.of_to_string Cohttp.Connection.to_string in + let callback (_ch, conn) request body = + let open Cohttp in + [%log.debug "new connection %a" pp_con conn]; + let* status, headers, body, _path = + Wm.dispatch' routes ~body ~request >|= function + | None -> (`Not_found, Header.init (), `String "Not found", []) + | Some result -> result + in + [%log.info + "[%a] %d - %s %s" pp_con conn + (Code.code_of_status status) + (Code.string_of_method (Request.meth request)) + (Uri.path (Request.uri request))]; + + (* Finally, send the response to the client *) + HTTP.respond ~headers ~body ~status () + in + (* create the server and handle requests with the function defined above *) + let conn_closed (_, conn) = + [%log.debug "connection %a closed" pp_con conn] + in + HTTP.make ~callback ~conn_closed () +end diff --git a/vendors/irmin/src/irmin-http/irmin_http_server.mli b/vendors/irmin/src/irmin-http/irmin_http_server.mli new file mode 100644 index 000000000000..9e78f77f0a3d --- /dev/null +++ b/vendors/irmin/src/irmin-http/irmin_http_server.mli @@ -0,0 +1,34 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** HTTP server *) + +module type S = sig + type repo + (** The type for Irmin repository. *) + + type t + (** The type for HTTP configuration. *) + + val v : ?strict:bool -> repo -> t + (** [v repo] returns the configuration for a server serving the contents of + [repo]. If [strict] is set, incoming connections will fail if they do not + have the right {i X-IrminVersion} headers. *) +end + +(** Create an HTTP server, serving the contents of an Irmin database. *) +module Make (HTTP : Cohttp_lwt.S.Server) (S : Irmin.S) : + S with type repo = S.Repo.t and type t = HTTP.t diff --git a/vendors/irmin/src/irmin-http/s.ml b/vendors/irmin/src/irmin-http/s.ml new file mode 100644 index 000000000000..31c6aa6c029e --- /dev/null +++ b/vendors/irmin/src/irmin-http/s.ml @@ -0,0 +1,124 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module T = Irmin.Type + +module type Helper = sig + type ctx + + val err_bad_version : string option -> 'a Lwt.t + val check_version : Cohttp.Response.t -> unit Lwt.t + val is_success : Cohttp.Response.t -> bool + + val map_string_response : + (string -> ('a, [< `Msg of string ]) result) -> + Cohttp.Response.t * Cohttp_lwt.Body.t -> + 'a Lwt.t + + val map_stream_response : + 'a T.t -> Cohttp.Response.t * Cohttp_lwt.Body.t -> 'a Lwt_stream.t Lwt.t + + val headers : keep_alive:bool -> unit -> Cohttp.Header.t + + val map_call : + Cohttp.Code.meth -> + Uri.t -> + ctx option -> + keep_alive:bool -> + ?body:string -> + string list -> + (Cohttp.Response.t * Cohttp_lwt.Body.t -> 'a Lwt.t) -> + 'a Lwt.t + + val call : + Cohttp.Code.meth -> + Uri.t -> + ctx option -> + ?body:string -> + string list -> + (string -> ('a, [< `Msg of string ]) result) -> + 'a Lwt.t + + val call_stream : + Cohttp.Code.meth -> + Uri.t -> + ctx option -> + ?body:string -> + string list -> + 'a T.t -> + 'a Lwt_stream.t Lwt.t +end + +module Read_only = struct + module type S = sig + type ctx + + type -'a t = { + uri : Uri.t; + item : string; + items : string; + ctx : ctx option; + } + + include Irmin.Read_only.S with type 'a t := 'a t + module HTTP : Helper with type ctx = ctx + + val uri : 'a t -> Uri.t + val item : 'a t -> string + val items : 'a t -> string + val key_str : key -> string + val val_of_str : value T.of_string + val v : ?ctx:ctx -> Uri.t -> string -> string -> 'a t Lwt.t + end +end + +module Content_addressable = struct + module type S = sig + include Irmin.Content_addressable.S + + type ctx + + val v : ?ctx:ctx -> Uri.t -> string -> string -> 'a t Lwt.t + end + + module type Maker = functor + (Client : Cohttp_lwt.S.Client) + (H : Irmin.Hash.S) + (V : Irmin.Type.S) + -> S with type key = H.t and type value = V.t and type ctx = Client.ctx +end + +module Atomic_write = struct + module type S = sig + include Irmin.Atomic_write.S + + type ctx + + val v : ?ctx:ctx -> Uri.t -> string -> string -> t Lwt.t + end + + module type Maker = functor + (Client : Cohttp_lwt.S.Client) + (B : Irmin.Branch.S) + (H : Irmin.Hash.S) + -> sig + module W : Irmin.Backend.Watch.S with type key = B.t and type value = H.t + module RO : Read_only.S + module HTTP = RO.HTTP + include S with type key = B.t and type value = H.t and type ctx = Client.ctx + end +end diff --git a/vendors/irmin/src/irmin-http/unix/dune b/vendors/irmin/src/irmin-http/unix/dune new file mode 100644 index 000000000000..1b0a23456c2b --- /dev/null +++ b/vendors/irmin/src/irmin-http/unix/dune @@ -0,0 +1,8 @@ +(library + (public_name irmin-http.unix) + (name irmin_http_unix) + (libraries cohttp-lwt-unix irmin-http lwt.unix) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-http/unix/irmin_http_unix.ml b/vendors/irmin/src/irmin-http/unix/irmin_http_unix.ml new file mode 100644 index 000000000000..159cf80e80a3 --- /dev/null +++ b/vendors/irmin/src/irmin-http/unix/irmin_http_unix.ml @@ -0,0 +1,44 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type Sock = sig + val sock : string +end + +module DefaultSock = struct + let sock = "/var/run/irmin.sock" +end + +module type Http_client = sig + include module type of Cohttp_lwt_unix.Client + + val ctx : unit -> ctx option +end + +module Http_client (P : Sock) = struct + include Cohttp_lwt_unix.Client + + let ctx () = + let resolver = + let h = Hashtbl.create 1 in + Hashtbl.add h "irmin" (`Unix_domain_socket P.sock); + Resolver_lwt_unix.static h + in + Some (Cohttp_lwt_unix.Client.custom_ctx ~resolver ()) +end + +module Client = Irmin_http.Client (Http_client (DefaultSock)) +module Server = Irmin_http.Server (Cohttp_lwt_unix.Server) diff --git a/vendors/irmin/src/irmin-http/unix/irmin_http_unix.mli b/vendors/irmin/src/irmin-http/unix/irmin_http_unix.mli new file mode 100644 index 000000000000..2213e35c6ff4 --- /dev/null +++ b/vendors/irmin/src/irmin-http/unix/irmin_http_unix.mli @@ -0,0 +1,38 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type Sock = sig + val sock : string +end + +module type Http_client = sig + include module type of Cohttp_lwt_unix.Client + + val ctx : unit -> ctx option +end + +module Http_client (P : Sock) : Http_client + +module Client (S : Irmin.S) : + Irmin.S + with type hash = S.Hash.t + and module Schema = S.Schema + and type Backend.Remote.endpoint = unit + +module Server (S : Irmin.S) : + Irmin_http.SERVER + with type repo = S.Repo.t + and type t = Cohttp_lwt_unix.Server.t diff --git a/vendors/irmin/src/irmin-mirage/dune b/vendors/irmin/src/irmin-mirage/dune new file mode 100644 index 000000000000..a369cdfe7dc2 --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/dune @@ -0,0 +1,6 @@ +(library + (name irmin_mirage) + (public_name irmin-mirage) + (libraries fmt irmin irmin.mem mirage-clock ptime) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-mirage/git/dune b/vendors/irmin/src/irmin-mirage/git/dune new file mode 100644 index 000000000000..9d31cb910ee5 --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/git/dune @@ -0,0 +1,15 @@ +(library + (name irmin_mirage_git) + (public_name irmin-mirage-git) + (libraries + fmt + git + irmin + irmin-mirage + irmin-git + lwt + mirage-clock + mirage-kv + uri) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.ml b/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.ml new file mode 100644 index 000000000000..141b0d90d66d --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.ml @@ -0,0 +1,355 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Infix +include Irmin_mirage_git_intf + +let remote ?(ctx = Mimic.empty) ?headers uri = + let ( ! ) f a b = f b a in + match Smart_git.Endpoint.of_string uri with + | Ok edn -> + let edn = + Option.fold ~none:edn + ~some:(!Smart_git.Endpoint.with_headers_if_http edn) + headers + in + (ctx, edn) + | Error (`Msg err) -> Fmt.invalid_arg "remote: %s" err + +module Maker (G : Irmin_git.G) = struct + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Maker = Irmin_git.Maker (G) (Git.Mem.Sync (G)) + + module Make + (S : Irmin_git.Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) = + struct + include Maker.Make (S) + + let remote ?ctx ?headers uri = E (remote ?ctx ?headers uri) + end +end + +module Ref (G : Irmin_git.G) = struct + module Maker = Irmin_git.Ref (G) (Git.Mem.Sync (G)) + module G = G + + type branch = Maker.branch + type endpoint = Maker.endpoint + + module Make (C : Irmin.Contents.S) = struct + include Maker.Make (C) + + let remote ?ctx ?headers uri = E (remote ?ctx ?headers uri) + end +end + +module KV (G : Irmin_git.G) = struct + module Maker = Irmin_git.KV (G) (Git.Mem.Sync (G)) + module G = G + + type endpoint = Maker.endpoint + type branch = Maker.branch + + module Make (C : Irmin.Contents.S) = struct + include Maker.Make (C) + + let remote ?ctx ?headers uri = E (remote ?ctx ?headers uri) + end +end + +module KV_RO (G : Git.S) = struct + module Key = Mirage_kv.Key + + type key = Key.t + + module G = struct + include G + + let v ?dotgit:_ _root = assert false + end + + module Maker = KV (G) + module S = Maker.Make (Irmin.Contents.String) + module Sync = Irmin.Sync.Make (S) + + let disconnect _ = Lwt.return_unit + + type error = [ Mirage_kv.error | S.write_error ] + + let pp_error ppf = function + | #Mirage_kv.error as e -> Mirage_kv.pp_error ppf e + | #S.write_error as e -> Irmin.Type.pp S.write_error_t ppf e + + let err e : ('a, error) result = Error e + let err_not_found k = err (`Not_found k) + + let path x = + (* XXX(samoht): we should probably just push the Key module in + Irmin and remove the path abstraction completely ... *) + Key.segments x + + module Tree = struct + type t = { repo : S.repo; tree : S.tree } + + let digest t key = + S.Tree.find_tree t.tree (path key) >|= function + | None -> err_not_found key + | Some tree -> + let h = S.Tree.hash tree in + Ok (Irmin.Type.to_string S.Hash.t h) + + let list t key = + S.Tree.list t.tree (path key) >|= fun l -> + let l = + List.map + (fun (s, k) -> + ( s, + match S.Tree.destruct k with + | `Contents _ -> `Value + | `Node _ -> `Dictionary )) + l + in + Ok l + + let exists t key = + S.Tree.kind t.tree (path key) >|= function + | Some `Contents -> Ok (Some `Value) + | Some `Node -> Ok (Some `Dictionary) + | None -> Ok None + + let get t key = + S.Tree.find t.tree (path key) >|= function + | None -> err_not_found key + | Some v -> Ok v + end + + type t = { root : S.path; t : S.t } + + let head_message t = + S.Head.find t.t >|= function + | None -> "empty HEAD" + | Some h -> + let info = S.Commit.info h in + Fmt.str "commit: %a\nAuthor: %s\nDate: %Ld\n\n%s\n" S.Commit.pp_hash h + (S.Info.author info) (S.Info.date info) (S.Info.message info) + + let last_modified t key = + let key' = path key in + S.last_modified t.t key' >|= function + | [] -> Error (`Not_found key) + | h :: _ -> Ok (0, S.Info.date (S.Commit.info h)) + + let connect ?depth ?(branch = "main") ?(root = Mirage_kv.Key.empty) ?ctx + ?headers t uri = + let remote = S.remote ?ctx ?headers uri in + let head = Git.Reference.v ("refs/heads/" ^ branch) in + S.repo_of_git ~bare:true ~head t >>= fun repo -> + S.of_branch repo branch >>= fun t -> + Sync.pull_exn t ?depth remote `Set >|= fun _ -> + let root = path root in + { t; root } + + let tree t = + let repo = S.repo t.t in + (S.find_tree t.t t.root >|= function + | None -> S.Tree.empty () + | Some tree -> tree) + >|= fun tree -> { Tree.repo; tree } + + let exists t k = tree t >>= fun t -> Tree.exists t k + let get t k = tree t >>= fun t -> Tree.get t k + let list t k = tree t >>= fun t -> Tree.list t k + let digest t k = tree t >>= fun t -> Tree.digest t k + + let get t k = + match Key.segments k with + | [ "HEAD" ] -> head_message t >|= fun v -> Ok v + | _ -> get t k +end + +module KV_RW (G : Irmin_git.G) (C : Mirage_clock.PCLOCK) = struct + (* XXX(samoht): batches are stored in memory. This could be bad if + large objects are stored for too long... Might be worth having + a clever LRU, which pushes larges objects to the underlying + layer when needed. *) + + module RO = KV_RO (G) + module S = RO.S + module Tree = RO.Tree + module Info = Irmin_mirage.Info (S.Info) (C) + + type batch = { repo : S.repo; mutable tree : S.tree; origin : S.commit } + + type store = Batch of batch | Store of RO.t + + and t = { + store : store; + author : unit -> string; + msg : [ `Set of RO.key | `Remove of RO.key | `Batch ] -> string; + remote : Irmin.remote; + } + + type key = RO.key + type error = RO.error + + let pp_error = RO.pp_error + let default_author () = "irmin " + + let default_msg = function + | `Set k -> Fmt.str "Updating %a" Mirage_kv.Key.pp k + | `Remove k -> Fmt.str "Removing %a" Mirage_kv.Key.pp k + | `Batch -> "Commmiting batch operation" + + let connect ?depth ?branch ?root ?ctx ?headers ?(author = default_author) + ?(msg = default_msg) git uri = + RO.connect ?depth ?branch ?root ?ctx ?headers git uri >|= fun t -> + let remote = S.remote ?ctx ?headers uri in + { store = Store t; author; msg; remote } + + let disconnect t = + match t.store with Store t -> RO.disconnect t | Batch _ -> Lwt.return_unit + + (* XXX(samoht): always return the 'last modified' on the + underlying storage layer, not for the current batch. *) + let last_modified t key = + match t.store with + | Store t -> RO.last_modified t key + | Batch b -> + RO.S.of_commit b.origin >>= fun t -> + RO.last_modified { root = S.Path.empty; t } key + + let repo t = match t.store with Store t -> S.repo t.t | Batch b -> b.repo + + let tree t = + match t.store with + | Store t -> RO.tree t + | Batch b -> Lwt.return { Tree.tree = b.tree; repo = repo t } + + let digest t k = tree t >>= fun t -> Tree.digest t k + let exists t k = tree t >>= fun t -> Tree.exists t k + let get t k = tree t >>= fun t -> Tree.get t k + let list t k = tree t >>= fun t -> Tree.list t k + + type write_error = [ RO.error | Mirage_kv.write_error | RO.Sync.push_error ] + + let write_error = function + | Ok _ -> Ok () + | Error e -> Error (e :> write_error) + + let pp_write_error ppf = function + | #RO.error as e -> RO.pp_error ppf e + | #RO.Sync.push_error as e -> RO.Sync.pp_push_error ppf e + | #Mirage_kv.write_error as e -> Mirage_kv.pp_write_error ppf e + + let info t op = Info.f ~author:(t.author ()) "%s" (t.msg op) + let path = RO.path + + let set t k v = + let info = info t (`Set k) in + match t.store with + | Store s -> ( + S.set ~info s.t (path k) v >>= function + | Ok _ -> RO.Sync.push s.t t.remote >|= write_error + | Error e -> Lwt.return (Error (e :> write_error))) + | Batch b -> + S.Tree.add b.tree (path k) v >|= fun tree -> + b.tree <- tree; + Ok () + + let remove t k = + let info = info t (`Remove k) in + match t.store with + | Store s -> ( + S.remove ~info s.t (path k) >>= function + | Ok _ -> RO.Sync.push s.t t.remote >|= write_error + | Error e -> Lwt.return (Error (e :> write_error))) + | Batch b -> + S.Tree.remove b.tree (path k) >|= fun tree -> + b.tree <- tree; + Ok () + + let get_store_tree (t : RO.t) = + S.Head.find t.t >>= function + | None -> Lwt.return_none + | Some origin -> ( + let tree = S.Commit.tree origin in + S.Tree.find_tree tree t.root >|= function + | Some t -> Some (origin, t) + | None -> Some (origin, S.Tree.empty ())) + + let batch t ?(retries = 42) f = + let info = info t `Batch in + let one t = + match t.store with + | Batch _ -> Fmt.failwith "No recursive batches" + | Store s -> ( + let repo = S.repo s.t in + (* get the tree origin *) + get_store_tree s >>= function + | None -> f t >|= fun x -> Ok x (* no transaction is needed *) + | Some (origin, old_tree) -> ( + let batch = { repo; tree = old_tree; origin } in + let b = Batch batch in + f { t with store = b } >>= fun result -> + get_store_tree s >>= function + | None -> + (* Someting weird happened, retring *) + Lwt.return (Error `Retry) + | Some (_, main_tree) -> ( + Irmin.Merge.f S.Tree.merge + ~old:(Irmin.Merge.promise old_tree) + main_tree batch.tree + >>= function + | Error (`Conflict _) -> Lwt.return (Error `Retry) + | Ok new_tree -> ( + S.set_tree s.t ~info s.root new_tree >|= function + | Ok () -> Ok result + | Error _ -> Error `Retry)))) + in + let rec loop = function + | 0 -> Lwt.fail_with "Too many retries" + | n -> ( + one t >>= function + | Error `Retry -> loop (n - 1) + | Ok r -> Lwt.return r) + in + loop retries >>= fun r -> + match t.store with + | Batch _ -> Fmt.failwith "No recursive batches" + | Store s -> ( + RO.Sync.push s.t t.remote >>= function + | Ok _ -> Lwt.return r + | Error e -> Lwt.fail_with (Fmt.to_to_string RO.Sync.pp_push_error e)) +end + +module Mem = struct + module G = Irmin_git.Mem + include Maker (G) + + module Maker = struct + module Ref = Ref (G) + module KV = KV (G) + end + + module Ref = Maker.Ref + module KV = Maker.KV + module KV_RO = KV_RO (G) + module KV_RW = KV_RW (G) +end diff --git a/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.mli b/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.mli new file mode 100644 index 000000000000..856bab30055c --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin_mirage_git_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git_intf.ml b/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git_intf.ml new file mode 100644 index 000000000000..983aa5913fc0 --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/git/irmin_mirage_git_intf.ml @@ -0,0 +1,150 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + include + Irmin_git.S + with type Backend.Remote.endpoint = Mimic.ctx * Smart_git.Endpoint.t + + val remote : + ?ctx:Mimic.ctx -> ?headers:(string * string) list -> string -> Irmin.remote +end + +module type Maker = sig + module G : Irmin_git.G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Make + (Schema : Irmin_git.Schema.S + with type Hash.t = G.hash + with type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) : + S + with module Git = G + and type Backend.Remote.endpoint = endpoint + and module Schema := Schema +end + +module type KV_maker = sig + module G : Irmin_git.G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + type branch + + module Make (C : Irmin.Contents.S) : + S + with module Git = G + and type Schema.Contents.t = C.t + and module Schema.Metadata = Irmin_git.Metadata + and type Schema.Info.t = Irmin.Info.default + and type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Hash.t = G.hash + and type Schema.Branch.t = branch + and type Backend.Remote.endpoint = endpoint +end + +module type KV_RO = sig + type git + + include Mirage_kv.RO + + val connect : + ?depth:int -> + ?branch:string -> + ?root:key -> + ?ctx:Mimic.ctx -> + ?headers:(string * string) list -> + git -> + string -> + t Lwt.t + (** [connect ?depth ?branch ?path g uri] clones the given [uri] into [g] + repository, using the given [branch], [depth] and ['/']-separated + sub-[path]. By default, [branch] is main, [depth] is [1] and [path] is + empty, ie. reads will be relative to the root of the repository. *) +end + +module type KV_RW = sig + type git + + include Mirage_kv.RW + + val connect : + ?depth:int -> + ?branch:string -> + ?root:key -> + ?ctx:Mimic.ctx -> + ?headers:(string * string) list -> + ?author:(unit -> string) -> + ?msg:([ `Set of key | `Remove of key | `Batch ] -> string) -> + git -> + string -> + t Lwt.t + (** [connect ?depth ?branch ?path ?author ?msg g c uri] clones the given [uri] + into [g] repository, using the given [branch], [depth] and ['/']-separated + sub-[path]. By default, [branch] is main, [depth] is [1] and [path] is + empty, ie. reads will be relative to the root of the repository. [author], + [msg] and [c] are used to create new commit info values on every update. + By defaut [author] is [fun () -> "irmin" ] and [msg] + returns basic information about the kind of operations performed. *) +end + +module type Sigs = sig + module type S = S + module type Maker = Maker + module type KV_maker = KV_maker + module type KV_RO = KV_RO + module type KV_RW = KV_RW + + module Maker (G : Irmin_git.G) : Maker with module G := G + + module KV (G : Irmin_git.G) : + KV_maker with type branch = string and module G := G + + module Ref (G : Irmin_git.G) : + KV_maker with type branch = Irmin_git.reference and module G := G + + (** Functor to create a MirageOS' KV_RO store from a Git repository. The key + ["/HEAD"] always shows the current HEAD. *) + module KV_RO (G : Irmin_git.G) : KV_RO with type git := G.t + + (** Functor to create a MirageOS' KV_RW store from a Git repository. *) + module KV_RW (G : Irmin_git.G) (C : Mirage_clock.PCLOCK) : + KV_RW with type git := G.t + + (** Embed an Irmin store into an in-memory Git repository. *) + module Mem : sig + module G : Irmin_git.G + + type endpoint = Mimic.ctx * Smart_git.Endpoint.t + + module Make + (Schema : Irmin_git.Schema.S + with type Hash.t = G.hash + and type Node.t = G.Value.Tree.t + and type Commit.t = G.Value.Commit.t) : + S + with module Git = G + and type Backend.Remote.endpoint = endpoint + and module Schema := Schema + + module Ref : KV_maker with type branch = Irmin_git.reference + module KV : KV_maker with type branch = string + module KV_RO : KV_RO with type git := G.t + module KV_RW (C : Mirage_clock.PCLOCK) : KV_RW with type git := G.t + end +end diff --git a/vendors/irmin/src/irmin-mirage/graphql/dune b/vendors/irmin/src/irmin-mirage/graphql/dune new file mode 100644 index 000000000000..e159ea75a81b --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/graphql/dune @@ -0,0 +1,14 @@ +(library + (name irmin_mirage_graphql) + (public_name irmin-mirage-graphql) + (libraries + git.nss.git + cohttp-lwt + irmin + irmin-mirage + irmin-graphql + lwt + mirage-clock + uri) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.ml b/vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.ml new file mode 100644 index 000000000000..d582b40676c1 --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.ml @@ -0,0 +1,73 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Server = struct + module type S = sig + module Pclock : Mirage_clock.PCLOCK + module Http : Cohttp_lwt.S.Server + + module Store : + Irmin.S with type Backend.Remote.endpoint = Smart_git.Endpoint.t + + val start : http:(Http.t -> unit Lwt.t) -> Store.repo -> unit Lwt.t + end + + module Make + (Http : Cohttp_lwt.S.Server) + (Store : Irmin.S with type Backend.Remote.endpoint = Smart_git.Endpoint.t) + (Pclock : Mirage_clock.PCLOCK) = + struct + module Store = Store + module Pclock = Pclock + module Http = Http + + let init () = + let module Config = struct + type info = Store.info + + let info ?(author = "irmin-graphql") fmt = + let module I = Irmin_mirage.Info (Store.Info) (Pclock) in + I.f ~author fmt + + let remote = + Some + (fun ?headers uri -> + let ( ! ) f a b = f b a in + let headers = Option.map Cohttp.Header.to_list headers in + match Smart_git.Endpoint.of_string uri with + | Ok + ({ Smart_git.Endpoint.scheme = `HTTP _ | `HTTPS _; _ } as edn) + -> + let edn = + Option.fold ~none:edn + ~some:(!Smart_git.Endpoint.with_headers_if_http edn) + headers + in + Lwt.return (Store.E edn) + | Ok _ -> Fmt.invalid_arg "invalid remote: %s" uri + | Error (`Msg err) -> Fmt.invalid_arg "invalid remote: %s" err) + end in + (module Irmin_graphql.Server.Make (Http) (Config) (Store) + : Irmin_graphql.Server.S + with type server = Http.t + and type repo = Store.repo) + + let start ~http store = + let (module G) = init () in + let server = G.v store in + http server + end +end diff --git a/vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.mli b/vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.mli new file mode 100644 index 000000000000..ff824b07abc0 --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/graphql/irmin_mirage_graphql.mli @@ -0,0 +1,36 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Server : sig + module type S = sig + module Pclock : Mirage_clock.PCLOCK + module Http : Cohttp_lwt.S.Server + + module Store : + Irmin.S with type Backend.Remote.endpoint = Smart_git.Endpoint.t + + val start : http:(Http.t -> unit Lwt.t) -> Store.repo -> unit Lwt.t + end + + module Make + (Http : Cohttp_lwt.S.Server) + (Store : Irmin.S with type Backend.Remote.endpoint = Smart_git.Endpoint.t) + (Pclock : Mirage_clock.PCLOCK) : + S + with module Pclock = Pclock + and module Store = Store + and module Http = Http +end diff --git a/vendors/irmin/src/irmin-mirage/irmin_mirage.ml b/vendors/irmin/src/irmin-mirage/irmin_mirage.ml new file mode 100644 index 000000000000..4a65f51c1fb2 --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/irmin_mirage.ml @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Info (Info : Irmin.Info.S) (C : Mirage_clock.PCLOCK) = struct + let f ~author fmt = + Fmt.kstr + (fun message () -> + C.now_d_ps () |> Ptime.v |> Ptime.to_float_s |> Int64.of_float + |> fun date -> Info.v ~author ~message date) + fmt +end diff --git a/vendors/irmin/src/irmin-mirage/irmin_mirage.mli b/vendors/irmin/src/irmin-mirage/irmin_mirage.mli new file mode 100644 index 000000000000..4ecd99a9d57d --- /dev/null +++ b/vendors/irmin/src/irmin-mirage/irmin_mirage.mli @@ -0,0 +1,27 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** MirageOS backend, with bi-directional compatibility with Git *) + +(** The context to use for synchronisation. *) + +module Info (Info : Irmin.Info.S) (C : Mirage_clock.PCLOCK) : sig + (** {1 Commit info creators} *) + + val f : author:string -> ('a, Format.formatter, unit, Info.f) format4 -> 'a + (** [f ~author msg] is a new commit info with [author] as commit author, + [C.now_d_ps ()] as commit date and [msg] as commit message.*) +end diff --git a/vendors/irmin/src/irmin-pack-tools/README.md b/vendors/irmin/src/irmin-pack-tools/README.md new file mode 100644 index 000000000000..30e038b14898 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/README.md @@ -0,0 +1,99 @@ +# Irmin-pack-tools +This folder contains several tools meant to provide usefull ways to debug and dump informations about stores. + +Currently, there are the following tools: +- [`ppcf`](#ppcf), a json printer for control files +- [`ppidx`](#ppidx), a json printer for index folders +- [`tezos-explorer`](#tezos-explorer), a gui for a fast exploration of tezos stores + +## ppcf +This tool prints a control file in a human readable manner (json), allowing to fetch important informations easily. +It is fairly straightforward: +```shell +$ dune exec -- irmin-ppcf Upper|Volume +``` +The first argument, either `Upper` or `Volume` tells the tool if you are trying to read the control file of a normal store, or from a volume store. +The second one is the path to the control file (e.g. `output/root/store.control`) + +It will typically give the following json output: +``` +{"Valid":{"V5":{"dict_end_poff":1548250,"appendable_chunk_poff":9056699,"checksum":2724660738,"chunk_start_idx":1,"chunk_num":5,"volume_num":0,"status":{"Gced":{"suffix_start_offset":35654891,"generation":5,"latest_gc_target_offset":35654787,"suffix_dead_bytes":20655801}}}}} +``` +Which can be further improved using the tool `jq`: +```shell +$ dune exec -- irmin-ppcf Upper|Volume | jq +``` +Will give: +```json +{ + "Valid": { + "V5": { + "dict_end_poff": 1548250, + "appendable_chunk_poff": 9056699, + "checksum": 2724660738, + "chunk_start_idx": 1, + "chunk_num": 5, + "volume_num": 0, + "status": { + "Gced": { + "suffix_start_offset": 35654891, + "generation": 5, + "latest_gc_target_offset": 35654787, + "suffix_dead_bytes": 20655801 + } + } + } + } +} +``` + +## ppidx +This tool prints the informations stored in the index of a store in a human readable manner (json), allowing to fetch important informations easily. +It is fairly straightforward: +```shell +$ dune exec -- irmin-ppidx +``` +The second one is the path to the root of the store, not the index folder (e.g. `output/root/` where `output/root/index/` exists) + +It will typically give the following json output, with one line per entry registered: +``` +{"hash":"cGrDVlQkzEjlw2DA4bL5fAnDSOh4TRKtLZrAiavclsI=","off":13431448,"len":101,"kind":"Commit_v2"} +{"hash":"i2LiUbc7fPMu5ON1MLN97thf7cU0OUTcDBwNlvzAUVo=","off":95461096,"len":103,"kind":"Commit_v2"} +{"hash":"cXMN2n8Re6RAvVbHbzaptzfIdFp+X/ey36S5RiWTsUw=","off":28541134,"len":104,"kind":"Commit_v2"} +... +``` +Which can be further improved using the tool `jq`: +```shell +$ dune exec -- irmin-ppidx > index +$ jq -s '.' -- index +``` +Will give: +```json +{ + "hash": "cGrDVlQkzEjlw2DA4bL5fAnDSOh4TRKtLZrAiavclsI=", + "off": 13431448, + "len": 101, + "kind": "Commit_v2" +} +{ + "hash": "i2LiUbc7fPMu5ON1MLN97thf7cU0OUTcDBwNlvzAUVo=", + "off": 95461096, + "len": 103, + "kind": "Commit_v2" +} +{ + "hash": "cXMN2n8Re6RAvVbHbzaptzfIdFp+X/ey36S5RiWTsUw=", + "off": 28541134, + "len": 104, + "kind": "Commit_v2" +} +... +``` + +However, it might be useful to sort the json output using the offset. You can do so by specifying a sort function: +```shell +$ jq -s 'sort_by(.off)' -- index +``` + +## tezos-explorer +TODO diff --git a/vendors/irmin/src/irmin-pack-tools/ppcf/dune b/vendors/irmin/src/irmin-pack-tools/ppcf/dune new file mode 100644 index 000000000000..2700e07eb6fc --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/ppcf/dune @@ -0,0 +1,8 @@ +(executable + (public_name irmin-ppcf) + (package irmin-pack-tools) + (name ppcf) + (modules ppcf) + (libraries irmin-pack irmin-pack.unix cmdliner) + (preprocess + (pps ppx_repr))) diff --git a/vendors/irmin/src/irmin-pack-tools/ppcf/ppcf.ml b/vendors/irmin/src/irmin-pack-tools/ppcf/ppcf.ml new file mode 100644 index 000000000000..e59ec852ed46 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/ppcf/ppcf.ml @@ -0,0 +1,44 @@ +module Io = Irmin_pack_unix.Io.Unix +module Io_errors = Irmin_pack_unix.Io_errors.Make (Io) +module Upper_control = Irmin_pack_unix.Control_file.Upper (Io) +module Volume_control = Irmin_pack_unix.Control_file.Volume (Io) + +type store_type = Upper | Volume + +let print_cf read print control_file = + let r = read ~path:control_file in + match r with + | Error err -> Io_errors.raise_error err + | Ok payload -> Fmt.pr "%a\n" (Irmin.Type.pp_json print) payload + +let main = function + | Upper -> + print_cf Upper_control.read_raw_payload + Irmin_pack_unix.Control_file.Payload.Upper.raw_payload_t + | Volume -> + print_cf Volume_control.read_raw_payload + Irmin_pack_unix.Control_file.Payload.Volume.raw_payload_t + +(** Cmdliner **) + +open Cmdliner + +let store_type = + Arg.( + required + & pos 0 (some (enum [ ("Upper", Upper); ("Volume", Volume) ])) None + & info [] ~docv:"store type" + ~doc:"the type of control file, either Upper or Volume") + +let control_file = + Arg.( + required + & pos 1 (some string) None + & info [] ~docv:"control file" ~doc:"the path to the control file") + +let main_cmd = + let doc = "a json printer for irmin pack control files" in + let info = Cmd.info "irmin-ppcf" ~doc in + Cmd.v info Term.(const main $ store_type $ control_file) + +let () = exit (Cmd.eval ~catch:false main_cmd) diff --git a/vendors/irmin/src/irmin-pack-tools/ppidx/dune b/vendors/irmin/src/irmin-pack-tools/ppidx/dune new file mode 100644 index 000000000000..478c8b663b1d --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/ppidx/dune @@ -0,0 +1,8 @@ +(executable + (public_name irmin-ppidx) + (package irmin-pack-tools) + (name ppidx) + (modules ppidx) + (libraries irmin-pack irmin-pack.unix cmdliner) + (preprocess + (pps ppx_irmin.internal))) diff --git a/vendors/irmin/src/irmin-pack-tools/ppidx/ppidx.ml b/vendors/irmin/src/irmin-pack-tools/ppidx/ppidx.ml new file mode 100644 index 000000000000..41784d21e766 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/ppidx/ppidx.ml @@ -0,0 +1,33 @@ +module Hash = Irmin.Hash.SHA256 +module Index = Irmin_pack_unix.Index.Make (Hash) + +type t = { hash : string; off : Optint.Int63.t; len : int; kind : string } +[@@deriving irmin] + +let dump_json k v = + let hash = Base64.encode_exn (Index.Key.encode k) in + let off, len, kind = v in + let kind = Fmt.str "%a" Irmin_pack.Pack_value.Kind.pp kind in + let a = { hash; off; len; kind } in + Fmt.pr "%a@." (Irmin.Type.pp_json t) a + +let main root_folder = + let v = Index.v_exn ~readonly:true ~log_size:500_000 root_folder in + Index.iter dump_json v + +(** Cmdliner **) + +open Cmdliner + +let root_folder = + Arg.( + required + & pos 0 (some string) None + & info [] ~docv:"root folder" ~doc:"the path to the store") + +let main_cmd = + let doc = "a json printer for the informations stored in the index folder" in + let info = Cmd.info "irmin-ppidx" ~doc in + Cmd.v info Term.(const main $ root_folder) + +let () = exit (Cmd.eval ~catch:false main_cmd) diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/dune b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/dune new file mode 100644 index 000000000000..ad79cf77ae37 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/dune @@ -0,0 +1,17 @@ +(executable + (public_name irmin-tezos-explorer) + (package irmin-pack-tools) + (name main) + (modules main parse show files ring import) + (libraries + irmin-pack + irmin-pack.unix + irmin-tezos + notty + notty.unix + index.unix + hex + ptime + cmdliner) + (preprocess + (pps ppx_repr))) diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/files.ml b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/files.ml new file mode 100644 index 000000000000..6811dbc5cbb7 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/files.ml @@ -0,0 +1,151 @@ +open Import +module Kind = Irmin_pack.Pack_value.Kind + +module Varint = struct + type t = int [@@deriving repr ~decode_bin ~encode_bin] + + (** LEB128 stores 7 bits per byte. An OCaml [int] has at most 63 bits. + [63 / 7] equals [9]. *) + let max_encoded_size = 9 +end + +module Make (Conf : Irmin_pack.Conf.S) (Schema : Irmin.Schema.Extended) = struct + module Maker = Irmin_pack_unix.Maker (Conf) + module Store = Maker.Make (Schema) + module Hash = Store.Hash + module Key = Irmin_pack_unix.Pack_key.Make (Hash) + module Io = Irmin_pack_unix.Io.Unix + module Errs = Irmin_pack_unix.Io_errors.Make (Io) + module Pack_index = Irmin_pack_unix.Index.Make (Hash) + + module File_manager = + Irmin_pack_unix.File_manager.Make (Io) (Pack_index) (Errs) + + module Dispatcher = Irmin_pack_unix.Dispatcher.Make (File_manager) + + module Inode = struct + module Value = Schema.Node (Key) (Key) + include Irmin_pack.Inode.Make_internal (Conf) (Hash) (Key) (Value) + + type compress = Compress.t [@@deriving repr ~decode_bin] + end + + module Commit = struct + module Value = struct + include Schema.Commit (Key) (Key) + module Info = Schema.Info + end + + include Irmin_pack.Pack_value.Of_commit (Hash) (Key) (Value) + + type compress = Commit_direct.t [@@deriving repr ~decode_bin] + end + + type hash = Store.hash [@@deriving repr ~pp] + type key = Key.t [@@deriving repr ~pp] + type entry = [ `Contents | `Inode | `Commit ] + + let max_bytes_needed_to_discover_length = + Hash.hash_size + 1 + Varint.max_encoded_size + + let min_bytes_needed_to_discover_length = Hash.hash_size + 1 + + let decode_entry_header buffer = + let buffer = Bytes.unsafe_to_string buffer in + let i0 = 0 in + + let imagic = i0 + Hash.hash_size in + let kind = Kind.of_magic_exn buffer.[imagic] in + + let ilength = i0 + Hash.hash_size + 1 in + let pos_ref = ref ilength in + let suffix_length = Varint.decode_bin buffer pos_ref in + let length_length = !pos_ref - ilength in + + (kind, Hash.hash_size + 1 + length_length + suffix_length) + + let decode_entry_kind buffer = + let buffer = Bytes.unsafe_to_string buffer in + let i0 = 0 in + let imagic = i0 + Hash.hash_size in + Kind.of_magic_exn buffer.[imagic] + + let decode_entry_len buffer = + let buffer = Bytes.unsafe_to_string buffer in + let i0 = 0 in + let ilength = i0 + Hash.hash_size + 1 in + let pos_ref = ref ilength in + let suffix_length = Varint.decode_bin buffer pos_ref in + let length_length = !pos_ref - ilength in + Hash.hash_size + 1 + length_length + suffix_length + + let decode_entry dispatcher buffer off = + let _ = + Dispatcher.read_range_exn dispatcher ~off + ~min_len:min_bytes_needed_to_discover_length + ~max_len:max_bytes_needed_to_discover_length buffer + in + let kind, len = decode_entry_header buffer in + let _ = Dispatcher.read_exn dispatcher ~off ~len:Hash.hash_size buffer in + let hash = Bytes.sub_string buffer 0 Hash.hash_size in + let _ = Dispatcher.read_exn dispatcher ~off ~len buffer in + let content = Bytes.sub_string buffer 0 len in + (hash, kind, len, content) + + let guess_entry_len dispatcher ~off = + let min_bytes_needed_to_discover_length = Hash.hash_size + 1 in + let max_bytes_needed_to_discover_length = + min_bytes_needed_to_discover_length + Varint.max_encoded_size + in + let buffer = Bytes.create max_bytes_needed_to_discover_length in + let _ = + Dispatcher.read_range_exn dispatcher ~off + ~min_len:min_bytes_needed_to_discover_length + ~max_len:max_bytes_needed_to_discover_length buffer + in + decode_entry_len buffer + + let iter_store fm ~on_entry = + let dispatcher = Dispatcher.v fm |> Errs.raise_if_error in + let buffer = Bytes.create (4096 * 4096) in + let on_entry ~off ~len = + let _ = Dispatcher.read_exn dispatcher ~off ~len buffer in + let kind = decode_entry_kind buffer in + let entry = + match kind with + | Inode_v1_unstable | Inode_v1_stable | Commit_v1 -> assert false + | Dangling_parent_commit | Commit_v2 -> `Commit + | Contents -> `Contents + | Inode_v2_root | Inode_v2_nonroot -> `Inode + in + on_entry off entry + in + let rec traverse off = + match Dispatcher.next_valid_offset dispatcher ~off with + | None -> () + | Some off -> + let len = guess_entry_len dispatcher ~off in + on_entry ~off ~len; + let next_off = Int63.add off (Int63.of_int len) in + traverse next_off + in + traverse Int63.zero + + let rec traverse_dict dict size buffer off acc = + if off < size then ( + File_manager.Dict.read_exn dict buffer ~off ~len:4; + let len = Int32.to_int @@ Bytes.get_int32_be buffer 0 in + let off = Int63.(add off (of_int 4)) in + File_manager.Dict.read_exn dict buffer ~off ~len; + let str = Bytes.sub_string buffer 0 len in + let acc = str :: acc in + let off = Int63.(add off (of_int len)) in + traverse_dict dict size buffer off acc) + else acc + + let load_dict (dict : File_manager.Dict.t) buffer = + let max_offset = File_manager.Dict.end_poff dict in + let off = Int63.zero in + let dict = traverse_dict dict max_offset buffer off [] in + List.rev dict +end diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/import.ml b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/import.ml new file mode 100644 index 000000000000..a746dd26a336 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/import.ml @@ -0,0 +1,5 @@ +module Int63 = struct + include Optint.Int63 + + let t = Irmin.Type.int63 +end diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/main.ml b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/main.ml new file mode 100644 index 000000000000..433c14e50ab2 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/main.ml @@ -0,0 +1,69 @@ +open Cmdliner + +(* Common arguments *) +let store_path = + Arg.( + value + & opt string "." + & info [ "store_path" ] + ~doc:"the path to the irmin store files, default to `.`") + +let info_last_path = + Arg.( + value + & opt string "store.info.last" + & info [ "store_info_last" ] + ~doc: + "the path to the info file generated for last entries data, default \ + to `store.info.last`") + +let info_next_path = + Arg.( + value + & opt string "store.info.next" + & info [ "store_info_next" ] + ~doc: + "the path to the info file generated for next entries data, default \ + to `store.info.next`") + +let index_path = + Arg.( + value + & opt string "store.idx" + & info [ "store_idx" ] + ~doc:"the path to the index file generated, default to `store.index`") + +(* Command parse *) +let parse_cmd = + let doc = + "parses a pack file and generates the associated .info & .idx files" + in + let info = Cmd.info "parse" ~doc in + Cmd.v info + Term.( + const Parse.main + $ store_path + $ info_last_path + $ info_next_path + $ index_path) + +(* Command show *) +let show_cmd = + let doc = "graphical user interface for pack files inspection" in + let info = Cmd.info "show" ~doc in + Cmd.v info + Term.( + const Show.main + $ store_path + $ info_last_path + $ info_next_path + $ index_path) + +(* Main command *) +let main_cmd = + let doc = "a visual tool for irmin pack files inspection" in + let info = Cmd.info "irmin-pack-inspect" ~version:"%%VERSION%%" ~doc in + let default = Term.(ret (const (`Help (`Pager, None)))) in + Cmd.group info ~default [ parse_cmd; show_cmd ] + +let () = exit (Cmd.eval ~catch:false main_cmd) diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/parse.ml b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/parse.ml new file mode 100644 index 000000000000..f3e2d6b66f3b --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/parse.ml @@ -0,0 +1,141 @@ +open Import +open Files +module Files = Make (Irmin_tezos.Conf) (Irmin_tezos.Schema) + +type ctx = { off : Int63.t; info : info } +and info = { commits : int list; contents : int list; inodes : int list } + +let empty_info () = { commits = []; contents = []; inodes = [] } + +type info_ring = { + commit : int Ring.t; + contents : int Ring.t; + inode : int Ring.t; +} + +let info_ring () = + { commit = Ring.make 1000; contents = Ring.make 1000; inode = Ring.make 1000 } + +let ctx_buffer = Bytes.create (4096 * 4096) + +let dump_ctx fd ctx = + let idx = ref 0 in + let f s = + String.iteri (fun i c -> Bytes.set ctx_buffer (!idx + i) c) s; + idx := !idx + String.length s + in + let flag = + List.length ctx.info.commits + + Int.shift_left (List.length ctx.info.contents) 2 + + Int.shift_left (List.length ctx.info.inodes) 4 + in + Varint.encode_bin flag f; + List.iter (fun v -> Varint.encode_bin v f) ctx.info.commits; + List.iter (fun v -> Varint.encode_bin v f) ctx.info.contents; + List.iter (fun v -> Varint.encode_bin v f) ctx.info.inodes; + let _ = Unix.write fd ctx_buffer 0 !idx in + (!idx, ctx.off) + +let dump_idx fd i i2 off = + let idx = ref 0 in + let f s = + String.iteri (fun i c -> Bytes.set ctx_buffer (!idx + i) c) s; + idx := !idx + String.length s + in + Varint.encode_bin i f; + Varint.encode_bin i2 f; + Varint.encode_bin off f; + let _ = Unix.write fd ctx_buffer 0 !idx in + () + +let dump_idxs fd n is is2 = + let idx = ref 0 in + let f s = + String.iteri (fun i c -> Bytes.set ctx_buffer (!idx + i) c) s; + idx := !idx + String.length s + in + Varint.encode_bin (n + 1) f; + let _ = Unix.write fd ctx_buffer 0 !idx in + let off = List.fold_left (fun acc (i, _) -> i + acc) 0 is2 in + let _ = + List.fold_left2 + (fun (i, i2) (i', off) (i2', _) -> + dump_idx fd i (i2 - i2') (Int63.to_int off); + (i + i', i2 - i2')) + (0, off) is is2 + in + () + +let get_values r = List.filter_map (Ring.get r) [ 1; 10; 1000 ] + +let main store_path info_last_path info_next_path idx_path = + let conf = Irmin_pack.Conf.init store_path in + match Files.File_manager.open_ro conf with + | Error exn -> Fmt.pr "%a\n%!" (Irmin.Type.pp Files.Errs.t) exn + | Ok fm -> + let info_fd = + Unix.openfile info_last_path Unix.[ O_RDWR; O_CREAT; O_TRUNC ] 0o644 + in + let idxs = ref [] in + let offsets = ref [] in + let i = ref (-1) in + let last_info = ref (empty_info ()) in + let r = info_ring () in + let on_entry off entry = + incr i; + let ctx = { off; info = !last_info } in + (match entry with + | `Commit -> + Ring.add r.commit !i; + let commits = get_values r.commit in + last_info := { !last_info with commits } + | `Contents -> + Ring.add r.contents !i; + let contents = get_values r.contents in + last_info := { !last_info with contents } + | `Inode -> + Ring.add r.inode !i; + let inodes = get_values r.inode in + last_info := { !last_info with inodes }); + let idx = dump_ctx info_fd ctx in + idxs := idx :: !idxs; + offsets := (entry, off) :: !offsets + in + Files.iter_store fm ~on_entry; + let entries = !i in + Unix.close info_fd; + let info_fd = + Unix.openfile info_next_path Unix.[ O_WRONLY; O_CREAT; O_TRUNC ] 0o644 + in + let idxs2 = ref [] in + let i = ref (-1) in + let last_info = ref (empty_info ()) in + let r = info_ring () in + let get_next (entry, off) = + incr i; + let ctx = { off; info = !last_info } in + (match entry with + | `Commit -> + Ring.add r.commit (entries - !i); + let commits = get_values r.commit in + last_info := { !last_info with commits } + | `Contents -> + Ring.add r.contents (entries - !i); + let contents = get_values r.contents in + last_info := { !last_info with contents } + | `Inode -> + Ring.add r.inode (entries - !i); + let inodes = get_values r.inode in + last_info := { !last_info with inodes }); + let idx = dump_ctx info_fd ctx in + idxs2 := idx :: !idxs2 + in + List.iter get_next !offsets; + let idx_fd = + Unix.openfile idx_path Unix.[ O_WRONLY; O_CREAT; O_TRUNC ] 0o644 + in + dump_idxs idx_fd entries (List.rev !idxs) !idxs2; + Unix.close idx_fd + +let main store_path info_last_path info_next_path index_path = + main store_path info_last_path info_next_path index_path diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/ring.ml b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/ring.ml new file mode 100644 index 000000000000..8b381c5e06c1 --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/ring.ml @@ -0,0 +1,11 @@ +type 'a t = { n : int; mutable i : int; a : 'a option array } + +let make n = { n; i = 0; a = Array.make n None } + +let add r x = + Array.set r.a r.i (Some x); + r.i <- (r.i + 1) mod r.n + +let unsafe_get r i = r.a.((r.i - i + r.n) mod r.n) +let get r i = if i <= r.n then unsafe_get r i else None +let to_list r = List.init r.n (fun i -> get r (i + 1)) diff --git a/vendors/irmin/src/irmin-pack-tools/tezos_explorer/show.ml b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/show.ml new file mode 100644 index 000000000000..235c1abbe7eb --- /dev/null +++ b/vendors/irmin/src/irmin-pack-tools/tezos_explorer/show.ml @@ -0,0 +1,900 @@ +open Notty +open Notty_unix +open Import +open Files +module Files = Make (Irmin_tezos.Conf) (Irmin_tezos.Schema) + +type entry_content = { + hash : string; + kind : Kind.t; + off : Int63.t; + length : int; + contents : string; +} + +type entry_ctx = { last : info; next : info } +and info = { commit : int list; contents : int list; inode : int list } + +type idxs = { entry : int; off_info : off_info; off_pack : Int63.t } +and off_info = { off_last : Int63.t; off_next : Int63.t } + +type history = { entry : int; off : Int63.t; kind : Kind.t } + +type context = { + info_last_fd : Unix.file_descr; + info_next_fd : Unix.file_descr; + idxs : idxs list; + fm : Files.File_manager.t; + dispatcher : Files.Dispatcher.t; + dict : string list; + max_entry : int; + max_offset : Int63.t; + history : history Ring.t; + mutable entry : int; + mutable entry_ctx : entry_ctx; + mutable entry_content : entry_content; + mutable x : int; + mutable y : int; +} + +let buffer = Bytes.create (4096 * 4096) + +let get_entry c off = + let hash, kind, length, contents = + Files.decode_entry c.dispatcher buffer off + in + let hash = Result.get_ok @@ Base64.encode hash in + { hash; kind; off; length; contents } + +let read ~fd ~buffer ~fd_offset ~buffer_offset ~length = + let rec aux fd_offset buffer_offset length read_count = + let r = + Index_unix.Syscalls.pread ~fd ~fd_offset ~buffer ~buffer_offset ~length + in + let read_count = read_count + r in + if r = 0 then read_count (* end of file *) + else if r = length then read_count + else + (aux [@tailcall]) + (Int63.add fd_offset (Int63.of_int r)) + (buffer_offset + r) (length - r) read_count + in + aux fd_offset buffer_offset length 0 + +let load_idxs fd = + let idx = ref 0 in + let _ = + read ~fd ~buffer ~fd_offset:Int63.zero ~buffer_offset:0 + ~length:Varint.max_encoded_size + in + let buf = Bytes.unsafe_to_string buffer in + let max_entry = Varint.decode_bin buf idx in + let idxs = + List.init max_entry (fun i -> + let _ = + read ~fd ~buffer ~fd_offset:(Int63.of_int !idx) ~buffer_offset:0 + ~length:(Varint.max_encoded_size * 3) + in + let buffer = Bytes.unsafe_to_string buffer in + let i' = ref 0 in + let off_last_info = Int63.of_int @@ Varint.decode_bin buffer i' in + let off_next_info = Int63.of_int @@ Varint.decode_bin buffer i' in + let off_pack = Int63.of_int @@ Varint.decode_bin buffer i' in + idx := !i' + !idx; + let off_info = { off_last = off_last_info; off_next = off_next_info } in + { entry = i; off_info; off_pack }) + in + (max_entry, idxs) + +let load_entry fd_last fd_next off_info = + let _ = + read ~fd:fd_last ~buffer ~fd_offset:off_info.off_last ~buffer_offset:0 + ~length:(Varint.max_encoded_size * 7) + in + let buf = Bytes.unsafe_to_string buffer in + let idx = ref 0 in + let flag = Varint.decode_bin buf idx in + let n = Int.logand flag 0b11 in + let commit = List.init n (fun _ -> Varint.decode_bin buf idx) in + let n = Int.shift_right_logical (Int.logand flag 0b1100) 2 in + let contents = List.init n (fun _ -> Varint.decode_bin buf idx) in + let n = Int.shift_right_logical (Int.logand flag 0b110000) 4 in + let inode = List.init n (fun _ -> Varint.decode_bin buf idx) in + let last = { commit; contents; inode } in + let _ = + read ~fd:fd_next ~buffer ~fd_offset:off_info.off_next ~buffer_offset:0 + ~length:(Varint.max_encoded_size * 7) + in + let buf = Bytes.unsafe_to_string buffer in + let idx = ref 0 in + let flag = Varint.decode_bin buf idx in + let n = Int.logand flag 0b11 in + let commit = List.init n (fun _ -> Varint.decode_bin buf idx) in + let n = Int.shift_right_logical (Int.logand flag 0b1100) 2 in + let contents = List.init n (fun _ -> Varint.decode_bin buf idx) in + let n = Int.shift_right_logical (Int.logand flag 0b110000) 4 in + let inode = List.init n (fun _ -> Varint.decode_bin buf idx) in + let next = { commit; contents; inode } in + { last; next } + +let reload_context c i = + let idxs = List.nth c.idxs i in + if i <> c.entry then + Ring.add c.history + { + entry = c.entry; + off = c.entry_content.off; + kind = c.entry_content.kind; + }; + c.entry <- i; + c.entry_ctx <- load_entry c.info_last_fd c.info_next_fd idxs.off_info; + c.entry_content <- get_entry c idxs.off_pack + +let reload_context_with_off c off = + let idxs = + Option.get + @@ List.find_opt (fun idxs -> Int63.equal off idxs.off_pack) c.idxs + in + if idxs.entry <> c.entry then + Ring.add c.history + { + entry = c.entry; + off = c.entry_content.off; + kind = c.entry_content.kind; + }; + c.entry <- idxs.entry; + c.entry_ctx <- load_entry c.info_last_fd c.info_next_fd idxs.off_info; + c.entry_content <- get_entry c off + +module Menu = struct + let button_attr b b' = + match (b, b') with + | true, true -> A.(bg lightwhite ++ fg black) + | true, false -> A.(fg lightwhite) + | false, true -> A.(fg @@ gray 16) + | false, false -> A.(fg @@ gray 8) + + let button s a h = + let attr = button_attr a h in + I.string attr s + + let back_str = + [| + ("◂──", "Go back by 1000 "); + ("◂─", "Go back by 10 "); + ("◂", "Go back by 1 "); + |] + + let forth_str = + [| + ("▸", "Go forth by 1 "); + ("─▸", "Go forth by 10 "); + ("──▸", "Go forth by 1000 "); + |] + + let gen_entry_buttons r c str = + let l = [ 1; 10; 1000 ] in + let f i c = reload_context c i in + Array.mapi + (fun i (button_txt, tooltip) -> + let i = if r then 2 - i else i in + let tooltip = tooltip ^ if i <> 0 then "entries" else "entry" in + let i = List.nth l i in + if r && c.entry - i >= 0 then + let e = c.entry - i in + (button button_txt true, f e, tooltip, Some e) + else if (not r) && c.entry + i < c.max_entry then + let e = c.entry + i in + (button button_txt true, f e, tooltip, Some e) + else (button button_txt false, (fun _ -> ()), tooltip, None)) + str + + let gen_buttons r s l str = + let f i c = if i <> -1 then reload_context c i in + Array.mapi + (fun i (button_txt, tooltip) -> + let i = if r then 2 - i else i in + let tooltip = tooltip ^ s ^ if i <> 0 then "s" else "" in + if i < List.length l then + let e = List.nth l i in + (button button_txt true, f e, tooltip, Some e) + else (button button_txt false, (fun _ -> ()), tooltip, None)) + str + + let text_button s = (button s true, (fun _ -> ()), s, None) + + let b c = + [| + Array.concat + [ + gen_entry_buttons true c back_str; + [| text_button "Entry " |]; + gen_entry_buttons false c forth_str; + ]; + Array.concat + [ + gen_buttons true "commit" c.entry_ctx.last.commit back_str; + [| text_button "Commit " |]; + gen_buttons false "commit" c.entry_ctx.next.commit forth_str; + ]; + Array.concat + [ + gen_buttons true "content" c.entry_ctx.last.contents back_str; + [| text_button "Content" |]; + gen_buttons false "content" c.entry_ctx.next.contents forth_str; + ]; + Array.concat + [ + gen_buttons true "inode" c.entry_ctx.last.inode back_str; + [| text_button "Inode " |]; + gen_buttons false "inode" c.entry_ctx.next.inode forth_str; + ]; + |] + + let buttons b ~x_off ~y_off x y = + let _, b = + Array.fold_left + (fun (y', acc) a -> + let l = + List.rev + @@ snd + @@ Array.fold_left + (fun (x', acc) (f, _, _, _) -> + (x' + 1, (f (x' = x && y' = y) |> I.pad ~l:1 ~t:0) :: acc)) + (0, []) a + in + (y' + 1, I.hcat l :: acc)) + (0, []) b + in + I.(pad ~l:x_off ~t:y_off @@ vcat (List.rev b)) + + let bound m x = (x + m) mod m + + let move b c = function + | `Left -> c.x <- bound (Array.length b.(c.y)) (c.x - 1) + | `Right -> c.x <- bound (Array.length b.(c.y)) (c.x + 1) + | `Up -> + c.y <- bound (Array.length b) (c.y - 1); + c.x <- bound (Array.length b.(c.y)) c.x + | `Down -> + c.y <- bound (Array.length b) (c.y + 1); + c.x <- bound (Array.length b.(c.y)) c.x +end + +module Button = struct + type 'a t = { x : int; y : int; w : int; h : int; f : 'a } + + let on_press (x, y) b = + if x >= b.x && x < b.x + b.w && y >= b.y && y < b.y + b.h then Some b.f + else None + + let pad b x y = { b with x = b.x + x; y = b.y + y } +end + +let box h w = + let open I in + let bar = String.concat "" @@ List.init (w + 2) (fun _ -> "━") in + let t_bar = "┏" ^ bar ^ "┓" in + let m_bar = "┃" ^ String.make (w + 2) ' ' ^ "┃" in + let b_bar = "┗" ^ bar ^ "┛" in + let middle = + I.vcat (List.init h (fun _ -> string A.(fg white ++ st bold) m_bar)) + in + string A.(fg white ++ st bold) t_bar + <-> middle + <-> string A.(fg white ++ st bold) b_bar + +let double_box h1 h2 w = + let open I in + let bar = String.concat "" @@ List.init (w + 2) (fun _ -> "━") in + let t_bar = "┏" ^ bar ^ "┓" in + let m_bar = "┃" ^ String.make (w + 2) ' ' ^ "┃" in + let mf_bar = "┣" ^ bar ^ "┫" in + let b_bar = "┗" ^ bar ^ "┛" in + let middle1 = + I.vcat (List.init h1 (fun _ -> string A.(fg white ++ st bold) m_bar)) + in + let middle2 = + I.vcat (List.init h2 (fun _ -> string A.(fg white ++ st bold) m_bar)) + in + string A.(fg white ++ st bold) t_bar + <-> middle1 + <-> string A.(fg white ++ st bold) mf_bar + <-> middle2 + <-> string A.(fg white ++ st bold) b_bar + +let position_text c i = + match i with + | None -> I.empty + | Some i -> + let d = i - c.entry in + let entry_txt = if d = -1 || d = 1 then "entry" else "entries" in + let { off_pack; _ } = List.nth c.idxs i in + let content = get_entry c off_pack in + let open I in + let color, text = + match content.kind with + | Commit_v1 | Commit_v2 -> (A.red, "Commit") + | Dangling_parent_commit -> (A.magenta, "Dangling commit") + | Contents -> (A.lightblue, "Contents") + | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root | Inode_v2_nonroot + -> + (A.green, "Inode") + in + let arrow = + if d < 0 then + string A.(fg color ++ st bold) text + <|> string A.(fg lightwhite ++ st bold) " ◀━━━▪" + else + string A.(fg lightwhite ++ st bold) "▪━━━▶ " + <|> string A.(fg color ++ st bold) text + in + arrow + <-> void 0 1 + <-> strf ~attr:A.(fg lightwhite ++ st bold) "by %#d %s" (abs d) entry_txt + <-> void 0 1 + <-> strf + ~attr:A.(fg lightwhite ++ st bold) + "to offset %#d" (Int63.to_int off_pack) + |> pad ~l:30 ~t:1 + +let get_parent_commit c i = + let { off_info; _ } = List.nth c.idxs i in + let ctx = load_entry c.info_last_fd c.info_next_fd off_info in + List.nth ctx.next.commit 0 + +let show_commit c (commit : Files.Commit.Commit_direct.t) = + let open I in + let node_txt = string A.(fg lightred ++ st bold) "Node:" in + let addr_show ?(parent = true) (addr : Files.Commit.Commit_direct.address) = + let parent_commit ~parent c i = + if parent then + let parent_commit = get_parent_commit c i in + let img = + if c.entry == parent_commit then + strf ~attr:A.(fg lightgreen ++ st bold) "(Added by current commit)" + else + strf + ~attr:A.(fg lightmagenta ++ st bold) + "(Added by commit at entry %#d)" parent_commit + in + ( img, + [ + Button. + { + x = 0; + y = 1; + w = I.width img; + h = 1; + f = (fun c -> reload_context c parent_commit); + }; + ] ) + else (empty, []) + in + match addr with + | Offset addr -> ( + let hit_or_miss = + List.find_opt + (fun { off_pack; _ } -> Int63.equal addr off_pack) + c.idxs + in + match hit_or_miss with + | None -> + ( I.strf + ~attr:A.(fg lightwhite ++ st bold) + "Dangling entry (off %#d)" (Int63.to_int addr), + [] ) + | Some { entry; off_pack; _ } -> + let img, parent_img, parent_buttons = + let content = get_entry c off_pack in + let open I in + let color, text = + match content.kind with + | Commit_v1 | Commit_v2 -> (A.red, "Commit") + | Dangling_parent_commit -> (A.magenta, "Dangling commit") + | Contents -> (A.lightblue, "Contents") + | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root + | Inode_v2_nonroot -> + (A.green, "Inode") + in + let parent_img, parent_buttons = parent_commit ~parent c entry in + ( strf ~attr:A.(fg lightwhite ++ st bold) "Entry %#d (" entry + <|> string A.(fg color ++ st bold) text + <|> strf + ~attr:A.(fg lightwhite ++ st bold) + ", off %#d)" (Int63.to_int addr), + parent_img, + parent_buttons ) + in + ( img <-> parent_img, + Button. + { + x = 0; + y = 0; + w = I.width img; + h = 1; + f = (fun c -> reload_context_with_off c addr); + } + :: parent_buttons )) + | Hash _hash -> + (I.string A.(fg lightwhite ++ st bold) "Hash ", []) + in + let node, node_button = addr_show commit.node_offset in + let parents_txt = I.string A.(fg lightred ++ st bold) "Parents:" in + let parents, parents_buttons = + match commit.parent_offsets with + | [] -> (I.string A.(fg lightwhite ++ st bold) "none", []) + | parents -> + let l_img, l_buttons = + List.split + (List.mapi + (fun i addr -> + let node, node_button = addr_show ~parent:false addr in + (node, List.map (fun b -> Button.pad b 0 i) node_button)) + parents) + in + (I.hcat l_img, l_buttons) + in + let info_txt = I.string A.(fg lightred ++ st bold) "Info:" in + let info = commit.info in + let date = + Option.get + @@ Ptime.of_span + @@ Ptime.Span.of_int_s (Int64.to_int @@ Files.Store.Info.date info) + in + let info = + let open I in + string A.(fg lightwhite ++ st bold) "Author:" + <-> string A.(fg lightwhite ++ st bold) "Message:" + <-> string A.(fg lightwhite ++ st bold) "Date:" + <|> void 1 0 + <|> (string A.(fg lightwhite ++ st bold) (Files.Store.Info.author info) + <-> string A.(fg lightwhite ++ st bold) (Files.Store.Info.message info) + <-> strf + ~attr:A.(fg lightwhite ++ st bold) + "%a" (Ptime.pp_human ()) date) + in + let open I in + let img = node_txt <-> (void 2 0 <|> node) <-> void 0 1 <-> parents_txt in + ( img + <-> (void 2 0 <|> parents) + <-> void 0 1 + <-> info_txt + <-> (void 2 0 <|> info), + List.append + (List.map (fun b -> Button.pad b 2 1) node_button) + (List.map + (fun b -> Button.pad b 2 (I.height img)) + (List.flatten parents_buttons)) ) + +let show_inode c (inode : Files.Inode.compress) = + let open I in + let addr_show (addr : Files.Inode.Compress.address) = + let parent_commit c i = + let current_parent_commit = List.nth c.entry_ctx.next.commit 0 in + let parent_commit = get_parent_commit c i in + let img = + if current_parent_commit == parent_commit then + strf ~attr:A.(fg lightgreen ++ st bold) "(Added by parent commit)" + else + strf + ~attr:A.(fg lightmagenta ++ st bold) + "(Added by commit at entry %#d)" parent_commit + in + ( img, + [ + Button. + { + x = 0; + y = 1; + w = I.width img; + h = 1; + f = (fun c -> reload_context c parent_commit); + }; + ] ) + in + match addr with + | Offset addr -> + let hit_or_miss = + List.find_opt + (fun { off_pack; _ } -> Int63.equal addr off_pack) + c.idxs + in + let img, parent_img, parent_buttons = + match hit_or_miss with + | None -> + ( I.strf + ~attr:A.(fg lightwhite ++ st bold) + "Dangling entry (off %#d)" (Int63.to_int addr), + I.empty, + [] ) + | Some { entry; off_pack; _ } -> + let content = get_entry c off_pack in + let open I in + let color, text = + match content.kind with + | Commit_v1 | Commit_v2 -> (A.red, "Commit") + | Dangling_parent_commit -> (A.magenta, "Dangling commit") + | Contents -> (A.lightblue, "Contents") + | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root + | Inode_v2_nonroot -> + (A.green, "Inode") + in + let parent_img, parent_buttons = parent_commit c entry in + ( I.strf ~attr:A.(fg lightwhite ++ st bold) "Entry %#d (" entry + <|> I.string A.(fg color ++ st bold) text + <|> I.strf + ~attr:A.(fg lightwhite ++ st bold) + ", off %#d)" (Int63.to_int addr), + parent_img, + parent_buttons ) + in + + ( img <-> parent_img, + Button. + { + x = 0; + y = 0; + w = I.width img; + h = 1; + f = (fun c -> reload_context_with_off c addr); + } + :: parent_buttons ) + | Hash _hash -> + (I.string A.(fg lightwhite ++ st bold) "Hash ", []) + in + let name (n : Files.Inode.Compress.name) = + match n with + | Indirect dict_key -> + let key = List.nth_opt c.dict dict_key in + strf + ~attr:A.(fg lightwhite ++ st bold) + "Indirect key: \'%a\' (%#d)" (Fmt.option Fmt.string) key dict_key + | Direct step -> + strf ~attr:A.(fg lightwhite ++ st bold) "Direct key: %s" step + in + let value i (v : Files.Inode.Compress.value) = + let v, v_buttons = + match v with + | Contents (n, addr, ()) -> + let content, content_button = addr_show addr in + let img1 = string A.(fg lightred ++ st bold) "Contents:" in + let img2 = name n in + ( img1 <-> (void 2 0 <|> (img2 <-> content)), + List.map + (fun b -> Button.pad b 2 (I.height img1 + I.height img2)) + content_button ) + | Node (n, addr) -> + let node, node_button = addr_show addr in + let img1 = string A.(fg lightred ++ st bold) "Node:" in + let img2 = name n in + ( img1 <-> (void 2 0 <|> (img2 <-> node)), + List.map + (fun b -> Button.pad b 2 (I.height img1 + I.height img2)) + node_button ) + in + let img = strf ~attr:A.(fg lightred ++ st bold) "Value %#d:" i in + ( img <-> (void 2 0 <|> v), + List.map (fun b -> Button.pad b 2 (I.height img)) v_buttons ) + in + let ptr i (p : Files.Inode.Compress.ptr) = + let ptr, ptr_button = addr_show p.hash in + let img = strf ~attr:A.(fg lightred ++ st bold) "Ptr %#d:" i <|> void 2 0 in + (img <|> ptr, List.map (fun b -> Button.pad b (I.width img) i) ptr_button) + in + let tree (t : Files.Inode.Compress.tree) = + let t_img, t_buttons = List.split (List.mapi ptr t.entries) in + let img = + string A.(fg lightred ++ st bold) "Tree:" + <-> (void 2 0 + <|> strf ~attr:A.(fg lightwhite ++ st bold) "Depth: %#d" t.depth) + in + ( img <-> vcat t_img, + List.map (fun b -> Button.pad b 0 (I.height img)) (List.flatten t_buttons) + ) + in + let v (tv : Files.Inode.Compress.v) s = + let tv, tv_buttons = + match tv with + | Values l -> + let v, v_buttons = List.split (List.mapi value l) in + let _, v_buttons = + List.fold_left2 + (fun (i, acc) img b -> + (i + I.height img, List.map (fun b -> Button.pad b 0 i) b :: acc)) + (0, []) v v_buttons + in + (vcat v, List.flatten v_buttons) + | Tree t -> tree t + in + let img = + string A.(fg lightred ++ st bold) "Tagged:" + <-> (void 2 0 <|> string A.(fg lightwhite ++ st bold) s) + <-> void 0 1 + in + (img <-> tv, List.map (fun b -> Button.pad b 0 (I.height img)) tv_buttons) + in + match inode.tv with + | V0_stable tv -> v tv "Stable" + | V0_unstable tv -> v tv "Unstable" + | V1_root tv -> v tv.v "Root" + | V1_nonroot tv -> v tv.v "Non root" + +let kind_color (kind : Kind.t) = + match kind with + | Commit_v1 | Commit_v2 -> A.red + | Dangling_parent_commit -> A.magenta + | Contents -> A.lightblue + | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root | Inode_v2_nonroot -> + A.green + +let show_entry_content ~x_off ~y_off c = + let open I in + let hash = + I.string A.(fg lightred ++ st bold) "Hash:" + <-> (void 2 0 <|> I.string A.(fg lightwhite ++ st bold) c.entry_content.hash) + in + let kind = + I.string A.(fg lightred ++ st bold) "Kind:" + <-> (void 2 0 + <|> I.strf + ~attr:A.(fg (kind_color c.entry_content.kind) ++ st bold) + "%a" Kind.pp c.entry_content.kind) + in + match c.entry_content.kind with + | Inode_v2_root | Inode_v2_nonroot -> + let decoded = I.string A.(fg lightred ++ st bold) "Decoded:" in + let inode, inode_buttons = + show_inode c + @@ Files.Inode.decode_bin_compress c.entry_content.contents (ref 0) + in + let hex = I.string A.(fg lightred ++ st bold) "Hexdump:" in + let entry_header = Files.Hash.hash_size + 1 in + let contents_len = + String.length c.entry_content.contents - entry_header + in + let contents = + String.sub c.entry_content.contents entry_header contents_len + in + let contents = Hex.hexdump_s @@ Hex.of_string contents in + let contents = String.split_on_char '\n' contents in + let entry_hexdump = + I.vcat + @@ List.map + (fun s -> + let s = Printf.sprintf "%S" s in + I.string A.(fg lightwhite ++ st bold) s) + contents + in + let img = hash <-> void 0 1 <-> kind <-> void 0 1 <-> decoded in + ( img + <-> (void 2 0 <|> inode) + <-> void 0 1 + <-> hex + <-> (void 2 0 <|> entry_hexdump) + |> I.pad ~l:x_off ~t:y_off, + List.map + (fun b -> Button.pad b (x_off + 2) (y_off + I.height img)) + inode_buttons ) + | Commit_v2 | Dangling_parent_commit -> + let open I in + let entry_header = Files.Hash.hash_size + 2 in + let contents_len = + String.length c.entry_content.contents - entry_header + in + let contents = + String.sub c.entry_content.contents entry_header contents_len + in + let commit, commit_button = + show_commit c @@ Files.Commit.decode_bin_compress contents (ref 0) + in + let decoded = I.string A.(fg lightred ++ st bold) "Decoded:" in + let hex = I.string A.(fg lightred ++ st bold) "Hexdump:" in + let contents = Hex.hexdump_s @@ Hex.of_string contents in + let contents = String.split_on_char '\n' contents in + let entry_hexdump = + I.vcat + @@ List.map + (fun s -> + let s = Printf.sprintf "%S" s in + I.string A.(fg lightwhite ++ st bold) s) + contents + in + let img = hash <-> void 0 1 <-> kind <-> void 0 1 <-> decoded in + ( img + <-> (void 2 0 <|> commit) + <-> void 0 1 + <-> hex + <-> (void 2 0 <|> entry_hexdump) + |> I.pad ~l:x_off ~t:y_off, + List.map + (fun b -> Button.pad b (x_off + 2) (y_off + I.height img)) + commit_button ) + | _ -> + let entry_header = Files.Hash.hash_size + 1 in + let contents_len = + String.length c.entry_content.contents - entry_header + in + let contents = + String.sub c.entry_content.contents entry_header contents_len + in + let decoded = I.string A.(fg lightred ++ st bold) "Decoded:" in + let entry_decoded = I.string A.(fg lightwhite ++ st bold) "n/a" in + let hex = I.string A.(fg lightred ++ st bold) "Hexdump:" in + let contents = Hex.hexdump_s @@ Hex.of_string contents in + let contents = String.split_on_char '\n' contents in + let entry_hexdump = + I.vcat + @@ List.map + (fun s -> + let s = Printf.sprintf "%S" s in + I.string A.(fg lightwhite ++ st bold) s) + contents + in + ( hash + <-> void 0 1 + <-> kind + <-> void 0 1 + <-> decoded + <-> (void 2 0 <|> entry_decoded) + <-> void 0 1 + <-> hex + <-> (void 2 0 <|> entry_hexdump) + |> I.pad ~l:x_off ~t:y_off, + [] ) + +let show_history c = + let open I in + let f = function + | None -> (string A.(fg black) " ", []) + | Some { entry; off; kind } -> + let color, text = + match kind with + | Commit_v1 | Commit_v2 -> (A.red, "Commit") + | Dangling_parent_commit -> (A.magenta, "Dangling commit") + | Contents -> (A.lightblue, "Contents") + | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root + | Inode_v2_nonroot -> + (A.green, "Inode") + in + let img = + string A.(fg color ++ st bold) text + <|> I.strf + ~attr:A.(fg lightwhite ++ st bold) + " (entry %#d, offset %#d)" entry (Int63.to_int off) + in + ( img, + [ + Button. + { + x = 0; + y = 0; + w = I.width img; + h = 1; + f = (fun c -> reload_context c entry); + }; + ] ) + in + let history, history_buttons = + List.map f (Ring.to_list c.history) |> List.split + in + let history_text = vcat history in + let history_box = double_box 1 (height history_text) (width history_text) in + ( void 2 1 + <|> (void 1 1 + <-> string A.(fg lightwhite ++ st bold) "History" + <-> void 1 1 + <-> history_text) + history_box, + List.mapi (fun i b -> Button.pad b 2 (i + 3)) (List.flatten history_buttons) + ) + +let entry_pos c l t = + let open I in + string A.(fg lightyellow ++ st bold) "Entry:" + <|> void 1 0 + <|> strf ~attr:A.(fg lightwhite ++ st bold) "%#d/%#d" c.entry (c.max_entry - 1) + void 30 0 + <|> string A.(fg lightyellow ++ st bold) "Offset:" + <|> void 1 0 + <|> strf + ~attr:A.(fg lightwhite ++ st bold) + "%#d/%#d" + (Int63.to_int c.entry_content.off) + (Int63.to_int (Int63.pred c.max_offset)) + |> pad ~l ~t + +let rec loop t c = + let buttons = Menu.b c in + let _, _, tooltip, move = buttons.(c.y).(c.x) in + let menu_text = Menu.buttons buttons ~x_off:1 ~y_off:1 c.x c.y in + let menu_box = + double_box (I.height menu_text - 1) 1 (I.width menu_text - 2) + in + let tooltip = + I.string A.(fg lightwhite ++ st bold) tooltip |> I.pad ~l:2 ~t:6 + in + let history, history_buttons = show_history c in + let history_pad = fst (Term.size t) - I.width history in + let history = history |> I.pad ~l:history_pad in + let history_buttons = + List.map (fun b -> Button.pad b history_pad 0) history_buttons + in + let position_text = position_text c move in + let position_box = box (I.height menu_text + 1) (I.width position_text - 2) in + let entries, entries_buttons = show_entry_content ~x_off:2 ~y_off:10 c in + let l = + [ + menu_text; + tooltip; + menu_box; + history; + position_text; + position_box; + entries; + entry_pos c 2 8; + ] + in + let b = I.zcat l in + Term.image t b; + match Term.event t with + | `End | `Key (`Escape, []) | `Key (`ASCII 'C', [ `Ctrl ]) -> () + | `Key (`Arrow d, _) -> + Menu.move buttons c d; + loop t c + | `Key (`Enter, _) -> + let _, f, _, _ = buttons.(c.y).(c.x) in + f c; + loop t c + | `Mouse (`Press _, pos, _) -> + let l = + List.filter_map (Button.on_press pos) (entries_buttons @ history_buttons) + in + List.iter (fun f -> f c) l; + loop t c + | _ -> loop t c + +let main store_path info_last_path info_next_path index_path = + let conf = Irmin_pack.Conf.init store_path in + let fm = Files.File_manager.open_ro conf |> Files.Errs.raise_if_error in + let dispatcher = Files.Dispatcher.v fm |> Files.Errs.raise_if_error in + let max_offset = Files.Dispatcher.end_offset dispatcher in + let dict = Files.File_manager.dict fm in + let dict = Files.load_dict dict buffer in + let info_last_fd = + Unix.openfile info_last_path Unix.[ O_RDONLY; O_CLOEXEC ] 0o644 + in + let info_next_fd = + Unix.openfile info_next_path Unix.[ O_RDONLY; O_CLOEXEC ] 0o644 + in + let idx_fd = Unix.openfile index_path Unix.[ O_RDONLY; O_CLOEXEC ] 0o644 in + let max_entry, idxs = load_idxs idx_fd in + Unix.close idx_fd; + let history = Ring.make 50 in + let { entry; off_info; off_pack } = List.hd idxs in + let entry_ctx = load_entry info_last_fd info_next_fd off_info in + let entry_content = + Obj.magic "TODO: cyclical deps between entry_content and context" + in + let context = + { + info_last_fd; + info_next_fd; + idxs; + fm; + dispatcher; + dict; + max_entry; + max_offset; + x = 3; + y = 0; + history; + entry; + entry_ctx; + entry_content; + } + in + context.entry_content <- get_entry context off_pack; + loop (Term.create ()) context; + Unix.close info_last_fd; + Unix.close info_next_fd diff --git a/vendors/irmin/src/irmin-pack/atomic_write.ml b/vendors/irmin/src/irmin-pack/atomic_write.ml new file mode 100644 index 000000000000..0caddbaf880b --- /dev/null +++ b/vendors/irmin/src/irmin-pack/atomic_write.ml @@ -0,0 +1,37 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Atomic_write_intf + +module Value = struct + module type S = Value + + module Of_hash (X : Irmin.Hash.S) = struct + type t = X.t [@@deriving irmin ~of_bin_string] + + let null = + match of_bin_string (String.make X.hash_size '\000') with + | Ok x -> x + | Error _ -> assert false + end +end + +module Closeable (AW : S) = struct + include Irmin.Atomic_write.Check_closed_store (AW) + + let flush t = get_if_open_exn t |> AW.flush +end diff --git a/vendors/irmin/src/irmin-pack/atomic_write.mli b/vendors/irmin/src/irmin-pack/atomic_write.mli new file mode 100644 index 000000000000..e71e0673a37b --- /dev/null +++ b/vendors/irmin/src/irmin-pack/atomic_write.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Atomic_write_intf.Sigs diff --git a/vendors/irmin/src/irmin-pack/atomic_write_intf.ml b/vendors/irmin/src/irmin-pack/atomic_write_intf.ml new file mode 100644 index 000000000000..96b35e0542ff --- /dev/null +++ b/vendors/irmin/src/irmin-pack/atomic_write_intf.ml @@ -0,0 +1,56 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + include Irmin.Atomic_write.S + + val flush : t -> unit +end + +module type Persistent = sig + include S + + val v : ?fresh:bool -> ?readonly:bool -> string -> t Lwt.t +end + +module type Value = sig + include Irmin.Type.S + + val null : t + (** A special value that is reserved for use by the implementation of + {!Make_persistent} (and must never be passed by the user). *) +end + +module type Sigs = sig + module type S = S + module type Persistent = Persistent + + module Value : sig + module type S = Value + + module Of_hash (X : Irmin.Hash.S) : S with type t = X.t + end + + module Closeable (AW : S) : sig + include + S + with type key = AW.key + and type value = AW.value + and type watch = AW.watch + + val make_closeable : AW.t -> t + end +end diff --git a/vendors/irmin/src/irmin-pack/conf.ml b/vendors/irmin/src/irmin-pack/conf.ml new file mode 100644 index 000000000000..206d438878f6 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/conf.ml @@ -0,0 +1,159 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type length_header = [ `Varint ] option + +type inode_child_order = + [ `Seeded_hash | `Hash_bits | `Custom of depth:int -> bytes -> int ] + +module type S = sig + val entries : int + val stable_hash : int + val contents_length_header : length_header + val inode_child_order : inode_child_order + val forbid_empty_dir_persistence : bool +end + +module Default = struct + let fresh = false + let lru_size = 100_000 + let index_log_size = 2_500_000 + let readonly = false + let merge_throttle = `Block_writes + let indexing_strategy = Indexing_strategy.default + let use_fsync = false + let dict_auto_flush_threshold = 1_000_000 + let suffix_auto_flush_threshold = 1_000_000 + let no_migrate = false + let lower_root = None +end + +open Irmin.Backend.Conf + +let spec = Spec.v "pack" + +type merge_throttle = [ `Block_writes | `Overcommit_memory ] [@@deriving irmin] + +module Key = struct + let fresh = + key ~spec ~doc:"Start with a fresh disk." "fresh" Irmin.Type.bool + Default.fresh + + let lru_size = + key ~spec ~doc:"Size of the LRU cache for pack entries." "lru-size" + Irmin.Type.int Default.lru_size + + let index_log_size = + key ~spec ~doc:"Size of index logs." "index-log-size" Irmin.Type.int + Default.index_log_size + + let readonly = + key ~spec ~doc:"Start with a read-only disk." "readonly" Irmin.Type.bool + Default.readonly + + let merge_throttle = + key ~spec + ~doc:"Strategy to use for large writes when index caches are full." + "merge-throttle" merge_throttle_t Default.merge_throttle + + let root = root spec + + let lower_root = + key ~spec ~doc:"Optional path for lower layer directory." "lower-root" + Irmin.Type.(option string) + Default.lower_root + + let indexing_strategy = + let serialisable_t = [%typ: [ `Always | `Minimal ]] in + key ~spec ~doc:"Strategy to use for adding objects to the index" + "indexing-strategy" + (Irmin.Type.map serialisable_t + (function + | `Always -> Indexing_strategy.always + | `Minimal -> Indexing_strategy.minimal) + (fun _ -> Fmt.failwith "Can't serialise indexing strategy")) + Default.indexing_strategy + + let use_fsync = + key ~spec + ~doc:"Whether fsync should be used to ensure persistence order of files" + "use-fsync" Irmin.Type.bool Default.use_fsync + + let dict_auto_flush_threshold = + key ~spec ~doc:"Buffer size of the dict at which automatic flushes occur" + "dict-auto-flush-threshold" Irmin.Type.int + Default.dict_auto_flush_threshold + + let suffix_auto_flush_threshold = + key ~spec ~doc:"Buffer size of the suffix at which automatic flushes occur" + "suffix-auto-flush-threshold" Irmin.Type.int + Default.suffix_auto_flush_threshold + + let no_migrate = + key ~spec ~doc:"Prevent migration of V1 and V2 stores" "no-migrate" + Irmin.Type.bool Default.no_migrate +end + +let fresh config = get config Key.fresh +let lru_size config = get config Key.lru_size +let readonly config = get config Key.readonly +let index_log_size config = get config Key.index_log_size +let merge_throttle config = get config Key.merge_throttle + +let root config = + match find_root config with + | None -> + failwith + "unintialised root, call [Irmin_pack.Conf.init root] before opening \ + the store" + | Some root -> root + +let lower_root config = get config Key.lower_root +let indexing_strategy config = get config Key.indexing_strategy +let use_fsync config = get config Key.use_fsync +let dict_auto_flush_threshold config = get config Key.dict_auto_flush_threshold + +let suffix_auto_flush_threshold config = + get config Key.suffix_auto_flush_threshold + +let no_migrate config = get config Key.no_migrate + +let init ?(fresh = Default.fresh) ?(readonly = Default.readonly) + ?(lru_size = Default.lru_size) ?(index_log_size = Default.index_log_size) + ?(merge_throttle = Default.merge_throttle) + ?(indexing_strategy = Default.indexing_strategy) + ?(use_fsync = Default.use_fsync) + ?(dict_auto_flush_threshold = Default.dict_auto_flush_threshold) + ?(suffix_auto_flush_threshold = Default.suffix_auto_flush_threshold) + ?(no_migrate = Default.no_migrate) ?(lower_root = Default.lower_root) root = + let config = empty spec in + let config = add config Key.root root in + let config = add config Key.lower_root lower_root in + let config = add config Key.fresh fresh in + let config = add config Key.lru_size lru_size in + let config = add config Key.index_log_size index_log_size in + let config = add config Key.readonly readonly in + let config = add config Key.merge_throttle merge_throttle in + let config = add config Key.indexing_strategy indexing_strategy in + let config = add config Key.use_fsync use_fsync in + let config = + add config Key.dict_auto_flush_threshold dict_auto_flush_threshold + in + let config = + add config Key.suffix_auto_flush_threshold suffix_auto_flush_threshold + in + let config = add config Key.no_migrate no_migrate in + verify config diff --git a/vendors/irmin/src/irmin-pack/conf.mli b/vendors/irmin/src/irmin-pack/conf.mli new file mode 100644 index 000000000000..dffd80160e4d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/conf.mli @@ -0,0 +1,150 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type length_header = [ `Varint ] option + +type inode_child_order = + [ `Seeded_hash (** use a non-crypto seeded-hash of the step *) + | `Hash_bits (** crypto hash the step and extract the relevant bits. *) + | `Custom of depth:int -> bytes -> int (** use a custom index *) ] + +module type S = sig + val entries : int + (** The branching factor of the inode tree. 32 is a good choice for general + applications. *) + + val stable_hash : int + (** This offers a way to conditional base hashing on node entries instead of + inodes. It is available for some backwards compatibility applications, but + for most applications, this should be set to 0. *) + + val contents_length_header : length_header + (** Describes the length header of the user's contents values when + binary-encoded. Supported modes are: + + - [Some `Varint]: the length header is a LEB128-encoded integer at the + very beginning of the encoded value. + + - [None]: there is no length header, and values have unknown size. NOTE: + when using [irmin-pack] in this mode, the selected indexing strategy + {i must} index all contents values (as recovering contents values from + the store will require referring to the index for their length + information). *) + + val inode_child_order : inode_child_order + (** The strategy used for sorting entries. [`Hash_bits] is the recommended + choice. [`Seeded_hash] is vunerable to attacks if storing user-generated + keys. *) + + val forbid_empty_dir_persistence : bool + (** If [true], irmin-pack raises [Failure] if it is asked to save the empty + inode. This default is [false]. It should be set to [true] if the [Schema] + of the store allows a hash collision between the empty inode and this + string of length 1: ["\000"]. + + See https://github.com/mirage/irmin/issues/1304 *) +end + +val spec : Irmin.Backend.Conf.Spec.t + +type merge_throttle = [ `Block_writes | `Overcommit_memory ] [@@deriving irmin] +(** Strategy for when attempting to write when the index log is full and waiting + for an in-progress merge to complete. + + - [`Block_writes] will block writes + - [`Overcommit_memory] will allow writes by growing the in-memory cache + indefinitely *) + +module Key : sig + val fresh : bool Irmin.Backend.Conf.key + val lru_size : int Irmin.Backend.Conf.key + val index_log_size : int Irmin.Backend.Conf.key + val readonly : bool Irmin.Backend.Conf.key + val root : string Irmin.Backend.Conf.key + val lower_root : string option Irmin.Backend.Conf.key + val merge_throttle : merge_throttle Irmin.Backend.Conf.key + val indexing_strategy : Indexing_strategy.t Irmin.Backend.Conf.key + val use_fsync : bool Irmin.Backend.Conf.key + val dict_auto_flush_threshold : int Irmin.Backend.Conf.key + val suffix_auto_flush_threshold : int Irmin.Backend.Conf.key + val no_migrate : bool Irmin.Backend.Conf.key +end + +val fresh : Irmin.Backend.Conf.t -> bool +(** Flag to indicate that the store will start with fresh data on disk. Warning: + setting this to [true] will delete existing data. Default is [false]. *) + +val lru_size : Irmin.Backend.Conf.t -> int +(** Size, in number of entries, of LRU cache. Default [100_000]. *) + +val index_log_size : Irmin.Backend.Conf.t -> int +(** Size, in number of entries, of index log. Default [2_500_000]. *) + +val readonly : Irmin.Backend.Conf.t -> bool +(** Flag for opening data in read-only mode. Default [false]. *) + +val merge_throttle : Irmin.Backend.Conf.t -> merge_throttle +(** Strategy for how to handle writes when index log is full and a merge is + in-progress. Default [`Block_writes]. *) + +val root : Irmin.Backend.Conf.t -> string +(** Location of directory for saving data on disk. + + Note: The path before the root directory must exist. Only the final + directory in the path will be created if it is missing. *) + +val lower_root : Irmin.Backend.Conf.t -> string option +(** Optional path for lower layer directory. Default [None]. + + The presence or not of a lower layer has implications on the behaviour of + the GC: if a lower layer is present, the GC will archive data instead of + deleting it.*) + +val indexing_strategy : Irmin.Backend.Conf.t -> Indexing_strategy.t +(** Strategy for choosing which objects to index. See {!Indexing_strategy.t} for + more discussion. Default {!Indexing_strategy.default} *) + +val use_fsync : Irmin.Backend.Conf.t -> bool +(** Flag to indicate that fsync should be used to enforce durability when + flushing data to disk. Default [false]. *) + +val dict_auto_flush_threshold : Irmin.Backend.Conf.t -> int +(** Size, in bytes, when automatic flushing of dict file to disk. Default + [1_000_000]. *) + +val suffix_auto_flush_threshold : Irmin.Backend.Conf.t -> int +(** Size, in bytes, when automatic flushing of suffix file to disk. Default + [1_000_000]. *) + +val no_migrate : Irmin.Backend.Conf.t -> bool +(** Flag to prevent migration of data. Default [false]. *) + +val init : + ?fresh:bool -> + ?readonly:bool -> + ?lru_size:int -> + ?index_log_size:int -> + ?merge_throttle:merge_throttle -> + ?indexing_strategy:Indexing_strategy.t -> + ?use_fsync:bool -> + ?dict_auto_flush_threshold:int -> + ?suffix_auto_flush_threshold:int -> + ?no_migrate:bool -> + ?lower_root:string option -> + string -> + Irmin.config +(** [init root] creates a backend configuration for storing data with default + configuration parameters and stored at [root]. Flags are documented above. *) diff --git a/vendors/irmin/src/irmin-pack/dune b/vendors/irmin/src/irmin-pack/dune new file mode 100644 index 000000000000..e62d63c72461 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/dune @@ -0,0 +1,8 @@ +(library + (public_name irmin-pack) + (name irmin_pack) + (libraries fmt irmin irmin.data logs lwt optint) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-pack/import.ml b/vendors/irmin/src/irmin-pack/import.ml new file mode 100644 index 000000000000..f6601d6c7b51 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/import.ml @@ -0,0 +1,29 @@ +(* + * Copyright (c)2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends + +let src = Logs.Src.create "irmin.pack" ~doc:"irmin-pack backend" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Int63 = struct + include Optint.Int63 + + let t = Irmin.Type.int63 +end + +type int63 = Int63.t [@@deriving irmin] diff --git a/vendors/irmin/src/irmin-pack/indexable.ml b/vendors/irmin/src/irmin-pack/indexable.ml new file mode 100644 index 000000000000..d66ccc561f0e --- /dev/null +++ b/vendors/irmin/src/irmin-pack/indexable.ml @@ -0,0 +1,38 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Indexable_intf +open! Import + +module Closeable (CA : S) = struct + include Irmin.Indexable.Check_closed_store (CA) + + (** override of {!Irmin.Indexable.S.add} to allow read-only *) + let add t v = (get_if_open_exn t |> CA.add) v + + (** override of {!Irmin.Indexable.S.unsafe_add} to allow read-only *) + let unsafe_add t k v = (get_if_open_exn t |> CA.unsafe_add) k v + + let index_direct t h = (get_if_open_exn t |> CA.index_direct) h + + let unsafe_append ~ensure_unique ~overcommit t k v = + (get_if_open_exn t |> CA.unsafe_append ~ensure_unique ~overcommit) k v + + let unsafe_mem t k = (get_if_open_exn t |> CA.unsafe_mem) k + + let unsafe_find ~check_integrity t k = + (get_if_open_exn t |> CA.unsafe_find ~check_integrity) k +end diff --git a/vendors/irmin/src/irmin-pack/indexable.mli b/vendors/irmin/src/irmin-pack/indexable.mli new file mode 100644 index 000000000000..a933b97da2d2 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/indexable.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Indexable_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/indexable_intf.ml b/vendors/irmin/src/irmin-pack/indexable_intf.ml new file mode 100644 index 000000000000..6a3211debf17 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/indexable_intf.ml @@ -0,0 +1,56 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + include Irmin.Indexable.S + + val add : 'a t -> value -> key Lwt.t + (** Overwrite [add] to work with a read-only database handler. *) + + val unsafe_add : 'a t -> hash -> value -> key Lwt.t + (** Overwrite [unsafe_add] to work with a read-only database handler. *) + + val index_direct : _ t -> hash -> key option + + val unsafe_append : + ensure_unique:bool -> overcommit:bool -> 'a t -> hash -> value -> key + + val unsafe_mem : 'a t -> key -> bool + val unsafe_find : check_integrity:bool -> 'a t -> key -> value option +end + +module type Maker = sig + type key + + (** Save multiple kind of values in the same pack file. Values will be + distinguished using [V.kind], so they have to all be different. *) + module Make (V : Pack_value.S with type hash := key) : + S with type key = key and type value = V.t +end + +module type Sigs = sig + module type S = S + + module Closeable (CA : S) : sig + include + S with type key = CA.key and type hash = CA.hash and type value = CA.value + + val make_closeable : 'a CA.t -> 'a t + val get_if_open_exn : 'a t -> 'a CA.t + end +end diff --git a/vendors/irmin/src/irmin-pack/indexing_strategy.ml b/vendors/irmin/src/irmin-pack/indexing_strategy.ml new file mode 100644 index 000000000000..8833fce69c6f --- /dev/null +++ b/vendors/irmin/src/irmin-pack/indexing_strategy.ml @@ -0,0 +1,53 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type t = value_length:int -> Pack_value.Kind.t -> bool + +let always ~value_length:_ _ = true + +let minimal : t = + fun ~value_length:_ -> function + | Commit_v2 -> + (* Commits must be indexed as the branch store contains only their + hashes. All {i internal} references to V1 commits are via offset + (from other V1 commit objects). *) + true + | Inode_v2_root -> + (* It's safe not to index V1 root inodes because they are never + referenced by V0 commit objects (only V1 commit objects, which + contain direct pointers rather than hashes).*) + false + | Inode_v2_nonroot -> false + | Contents -> false + | Commit_v1 | Inode_v1_unstable | Inode_v1_stable -> + (* We never append new V0 values, so this choice is irrelevant to the + store implementation, but we do assume that existing V0 objects are + indexed (as they may be referenced via hash by other V0 objects), and + this must be accounted for when reconstructing the index. *) + true + | Dangling_parent_commit -> assert false + +let minimal_with_contents : t = + fun ~value_length:_ -> function + | Commit_v2 -> true + | Inode_v2_root -> false + | Inode_v2_nonroot -> false + | Contents -> true + | Commit_v1 | Inode_v1_unstable | Inode_v1_stable -> true + | Dangling_parent_commit -> assert false + +let default = always +let is_minimal x = x == minimal diff --git a/vendors/irmin/src/irmin-pack/indexing_strategy.mli b/vendors/irmin/src/irmin-pack/indexing_strategy.mli new file mode 100644 index 000000000000..3be95e9577b8 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/indexing_strategy.mli @@ -0,0 +1,47 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type t = value_length:int -> Pack_value.Kind.t -> bool +(** The type of configurations for [irmin-pack]'s indexing strategy, which + dictates whether or not newly-appended pack entries should also be added to + the index. Strategies are parameterised over: + + - the length of the binary encoding of the {i object} inside the pack entry + (i.e. not accounting for the encoded hash and kind character); + - the kind of the pack object having been added. + + Indexing more than the {!minimal} strategy only impacts performance and not + correctness: more indexing results in a larger index and a smaller pack + file. *) + +val always : t +(** The strategy that indexes all objects. *) + +val minimal : t +(** The strategy that indexes as few objects as possible while still maintaing + store integrity. *) + +val minimal_with_contents : t +(** The strategy that is similar to the minimal strategy but it also indexes + contents objects. *) + +val default : t +(** [default] is the indexing strategy used by [irmin-pack] instances that do + not explicitly set an indexing strategy in {!Irmin_pack.config}. Currently + set to {!always}. *) + +val is_minimal : t -> bool +(** [is_minimal t] is true if [t] is {!minimal}. *) diff --git a/vendors/irmin/src/irmin-pack/inode.ml b/vendors/irmin/src/irmin-pack/inode.ml new file mode 100644 index 000000000000..0e521d98e21a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/inode.ml @@ -0,0 +1,2406 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Inode_intf + +exception Max_depth of int + +module Make_internal + (Conf : Conf.S) + (H : Irmin.Hash.S) (Key : sig + include Irmin.Key.S with type hash = H.t + + val unfindable_of_hash : hash -> t + end) + (Node : Irmin.Node.Generic_key.S + with type hash = H.t + and type contents_key = Key.t + and type node_key = Key.t) = +struct + (** If [should_be_stable ~length ~root] is true for an inode [i], then [i] + hashes the same way as a [Node.t] containing the same entries. *) + let should_be_stable ~length ~root = + if length = 0 then true + else if not root then false + else if length <= Conf.stable_hash then true + else false + + module Node = struct + include Node + module H = Irmin.Hash.Typed (H) (Node) + + let hash = H.hash + end + + (* Keep at most 50 bits of information. *) + let max_depth = int_of_float (log (2. ** 50.) /. log (float Conf.entries)) + + module T = struct + type hash = H.t [@@deriving irmin ~pp ~to_bin_string ~equal] + type key = Key.t [@@deriving irmin ~pp ~equal] + type node_key = Node.node_key [@@deriving irmin] + type contents_key = Node.contents_key [@@deriving irmin] + + type step = Node.step + [@@deriving irmin ~compare ~to_bin_string ~of_bin_string ~short_hash] + + type metadata = Node.metadata [@@deriving irmin ~equal] + type value = Node.value [@@deriving irmin ~equal] + + module Metadata = Node.Metadata + + exception Dangling_hash = Node.Dangling_hash + + let raise_dangling_hash c hash = + let context = "Irmin_pack.Inode." ^ c in + raise (Dangling_hash { context; hash }) + + let unsafe_keyvalue_of_hashvalue = function + | `Contents (h, m) -> `Contents (Key.unfindable_of_hash h, m) + | `Node h -> `Node (Key.unfindable_of_hash h) + + let hashvalue_of_keyvalue = function + | `Contents (k, m) -> `Contents (Key.to_hash k, m) + | `Node k -> `Node (Key.to_hash k) + end + + module Step = + Irmin.Hash.Typed + (H) + (struct + type t = T.step + + let t = T.step_t + end) + + module Child_ordering : Child_ordering with type step := T.step = struct + open T + + type key = bytes + + let log_entry = int_of_float (log (float Conf.entries) /. log 2.) + + let () = + assert (log_entry >= 1); + (* NOTE: the [`Hash_bits] mode is restricted to inodes with at most 1024 + entries in order to simplify the implementation (see below). *) + assert ((not (Conf.inode_child_order = `Hash_bits)) || log_entry <= 10); + assert (Conf.entries = int_of_float (2. ** float log_entry)) + + let key = + match Conf.inode_child_order with + | `Hash_bits -> + (* Bytes.unsafe_of_string usage: possibly safe TODO justify safety, or switch to + use the safe Bytes.of_string *) + fun s -> Bytes.unsafe_of_string (hash_to_bin_string (Step.hash s)) + | `Seeded_hash | `Custom _ -> + (* Bytes.unsafe_of_string usage: possibly safe TODO justify safety, or switch to + use the safe Bytes.of_string *) + fun s -> Bytes.unsafe_of_string (step_to_bin_string s) + + (* Assume [k = cryto_hash(step)] (see {!key}) and [Conf.entry] can + can represented with [n] bits. Then, [hash_bits ~depth k] is + the [n]-bits integer [i] with the following binary representation: + + [k(n*depth) ... k(n*depth+n-1)] + + When [n] is not a power of 2, [hash_bits] needs to handle + unaligned reads properly. *) + let hash_bits ~depth k = + assert (Bytes.length k = Step.hash_size); + (* We require above that the child indices have at most 10 bits to ensure + that they span no more than 2 bytes of the step hash. The 3 byte case + (with [1 + 8 + 1]) does not happen for 10-bit indices because 10 is + even, but [2 + 8 + 1] would occur with 11-byte indices (e.g. when + [depth=2]). *) + let byte = 8 in + let initial_bit_pos = log_entry * depth in + let n = initial_bit_pos / byte in + let r = initial_bit_pos mod byte in + if n >= Step.hash_size then raise (Max_depth depth); + if r + log_entry <= byte then + (* The index is contained in a single character of the hash *) + let i = Bytes.get_uint8 k n in + let e0 = i lsr (byte - log_entry - r) in + let r0 = e0 land (Conf.entries - 1) in + r0 + else + (* The index spans two characters of the hash *) + let i0 = Bytes.get_uint8 k n in + let to_read = byte - r in + let rest = log_entry - to_read in + let mask = (1 lsl to_read) - 1 in + let r0 = (i0 land mask) lsl rest in + if n + 1 >= Step.hash_size then raise (Max_depth depth); + let i1 = Bytes.get_uint8 k (n + 1) in + let r1 = i1 lsr (byte - rest) in + r0 + r1 + + let short_hash = Irmin.Type.(unstage (short_hash bytes)) + let seeded_hash ~depth k = abs (short_hash ~seed:depth k) mod Conf.entries + + let index = + match Conf.inode_child_order with + | `Seeded_hash -> seeded_hash + | `Hash_bits -> hash_bits + | `Custom f -> f + end + + module StepMap = struct + include Map.Make (struct + type t = T.step + + let compare = T.compare_step + end) + + let of_list l = List.fold_left (fun acc (k, v) -> add k v acc) empty l + end + + module Val_ref : sig + open T + + type t [@@deriving irmin] + type v = private Key of Key.t | Hash of hash Lazy.t + + val inspect : t -> v + val of_key : key -> t + val of_hash : hash Lazy.t -> t + val promote_exn : t -> key -> unit + val to_hash : t -> hash + val to_lazy_hash : t -> hash Lazy.t + val to_key_exn : t -> key + val is_key : t -> bool + end = struct + open T + + (** Nodes that have been persisted to an underlying store are referenced via + keys. Otherwise, when building in-memory inodes (e.g. via [Portable] or + [of_concrete_exn]) lazily-computed hashes are used instead. If such + values are persisted, the hash reference can be promoted to a key + reference (but [Key] values are never demoted to hashes). + + NOTE: in future, we could reflect the case of this type in a type + parameter and refactor the [layout] types below to get static guarantees + that [Portable] nodes (with hashes for internal pointers) are not saved + without first saving their children. *) + type v = Key of Key.t | Hash of hash Lazy.t [@@deriving irmin ~pp_dump] + + type t = v ref + + let inspect t = !t + let of_key k = ref (Key k) + let of_hash h = ref (Hash h) + + let promote_exn t k = + let existing_hash = + match !t with + | Key k' -> + (* NOTE: it's valid for [k'] to not be strictly equal to [k], because + of duplicate objects in the store. In this case, we preferentially + take the newer key. *) + Key.to_hash k' + | Hash h -> Lazy.force h + in + if not (equal_hash existing_hash (Key.to_hash k)) then + Fmt.failwith + "Attempted to promote existing reference %a to an inconsistent key %a" + pp_dump_v !t pp_key k; + t := Key k + + let to_hash t = + match !t with Hash h -> Lazy.force h | Key k -> Key.to_hash k + + let to_lazy_hash t = + match !t with Hash h -> h | Key k -> lazy (Key.to_hash k) + + let is_key t = match !t with Key _ -> true | _ -> false + + let to_key_exn t = + match !t with + | Key k -> k + | Hash h -> + Fmt.failwith "Encountered unkeyed hash but expected key: %a" pp_hash + (Lazy.force h) + + let t = + let pre_hash_hash = Irmin.Type.(unstage (pre_hash hash_t)) in + let pre_hash x f = + match !x with + | Key k -> pre_hash_hash (Key.to_hash k) f + | Hash h -> pre_hash_hash (Lazy.force h) f + in + Irmin.Type.map ~pre_hash v_t (fun x -> ref x) (fun x -> !x) + end + + (* Binary representation. Used in two modes: + + - with [key]s as pointers to child values, when encoding values to add + to the underlying store (or decoding values read from the store) – + interoperable with the [Compress]-ed binary representation. + + - with either [key]s or [hash]es as pointers to child values, when + pre-computing the hash of a node with children that haven't yet been + written to the store. *) + module Bin = struct + open T + + (** Distinguishes between the two possible modes of binary value. *) + type _ mode = Ptr_key : key mode | Ptr_any : Val_ref.t mode + + type 'vref with_index = { index : int; vref : 'vref } [@@deriving irmin] + + type 'vref tree = { + depth : int; + length : int; + entries : 'vref with_index list; + } + [@@deriving irmin] + + type 'vref v = Values of (step * value) list | Tree of 'vref tree + [@@deriving irmin ~pre_hash] + + module V = + Irmin.Hash.Typed + (H) + (struct + type t = Val_ref.t v [@@deriving irmin] + end) + + type 'vref t = { hash : H.t Lazy.t; root : bool; v : 'vref v } + + let t : type vref. vref Irmin.Type.t -> vref t Irmin.Type.t = + fun vref_t -> + let open Irmin.Type in + let v_t = v_t vref_t in + let pre_hash_v = pre_hash_v vref_t in + let pre_hash x = pre_hash_v x.v in + record "Bin.t" (fun hash root v -> { hash = Lazy.from_val hash; root; v }) + |+ field "hash" H.t (fun t -> Lazy.force t.hash) + |+ field "root" bool (fun t -> t.root) + |+ field "v" v_t (fun t -> t.v) + |> sealr + |> like ~pre_hash + + let v ~hash ~root v = { hash; root; v } + let hash t = Lazy.force t.hash + + let depth t = + match t.v with + | Values _ -> if t.root then Some 0 else None + | Tree t -> Some t.depth + end + + (* Compressed binary representation *) + module Compress = struct + open T + + type dict_key = int [@@deriving irmin] + type pack_offset = int63 [@@deriving irmin] + type name = Indirect of dict_key | Direct of step + type address = Offset of pack_offset | Hash of H.t [@@deriving irmin] + type ptr = { index : int; hash : address } [@@deriving irmin] + + type tree = { depth : int; length : int; entries : ptr list } + [@@deriving irmin] + + type value = + | Contents of name * address * metadata + | Node of name * address + + let is_default = T.(equal_metadata Metadata.default) + + (* We distribute products over sums in the type representation of [value] + in order to pack many possible cases into a single tag character in the + encoded representation. + + - whether the referenced value is a [Node] or a [Contents] value; + + - in the [Contents] case, whether the associated metadata is [default] + (in which case the serialised representation elides it), or if it is + included; + + - whether the [name] of the entry is provided inline [Direct], or is + stored in the dict and refernced via a dict key [Indirect]; + + - whether the [address] of the entry is a pack offset or a hash to be + indexed *) + let[@ocamlformat "disable"] value_t : value Irmin.Type.t = + let module Payload = struct + (* Different payload types that can appear after packed tags: *) + let io = [%typ: dict_key * pack_offset] + let ih = [%typ: dict_key * H.t] + let do_ = [%typ: step * pack_offset] + let dh = [%typ: step * H.t] + (* As above but for contents values with non-default metadata: *) + let x_io = [%typ: dict_key * pack_offset * metadata] + let x_ih = [%typ: dict_key * H.t * metadata] + let x_do = [%typ: step * pack_offset * metadata] + let x_dh = [%typ: step * H.t * metadata] + end in + let open Irmin.Type in + variant "Compress.value" + (fun + (* The ordering of these arguments determines which tags are assigned + to the cases, so should not be changed: *) + contents_io contents_x_io node_io contents_ih contents_x_ih node_ih + contents_do contents_x_do node_do contents_dh contents_x_dh node_dh + -> function + | Node (Indirect n, Offset o) -> node_io (n, o) + | Node (Indirect n, Hash h) -> node_ih (n, h) + | Node (Direct n, Offset o) -> node_do (n, o) + | Node (Direct n, Hash h) -> node_dh (n, h) + | Contents (Indirect n, Offset o, m) -> if is_default m then contents_io (n, o) else contents_x_io (n, o, m) + | Contents (Indirect n, Hash h, m) -> if is_default m then contents_ih (n, h) else contents_x_ih (n, h, m) + | Contents (Direct n, Offset o, m) -> if is_default m then contents_do (n, o) else contents_x_do (n, o, m) + | Contents (Direct n, Hash h, m) -> if is_default m then contents_dh (n, h) else contents_x_dh (n, h, m)) + |~ case1 "contents-io" Payload.io (fun (n, o) -> Contents (Indirect n, Offset o, Metadata.default)) + |~ case1 "contents-x-io" Payload.x_io (fun (n, i, m) -> Contents (Indirect n, Offset i, m)) + |~ case1 "node-io" Payload.io (fun (n, i) -> Node (Indirect n, Offset i)) + |~ case1 "contents-ih" Payload.ih (fun (n, h) -> Contents (Indirect n, Hash h, Metadata.default)) + |~ case1 "contents-x-ih" Payload.x_ih (fun (n, h, m) -> Contents (Indirect n, Hash h, m)) + |~ case1 "node-ih" Payload.ih (fun (n, h) -> Node (Indirect n, Hash h)) + |~ case1 "contents-do" Payload.do_ (fun (n, i) -> Contents (Direct n, Offset i, Metadata.default)) + |~ case1 "contents-x-do" Payload.x_do (fun (n, i, m) -> Contents (Direct n, Offset i, m)) + |~ case1 "node-do" Payload.do_ (fun (n, i) -> Node (Direct n, Offset i)) + |~ case1 "contents-dh" Payload.dh (fun (n, i) -> Contents (Direct n, Hash i, Metadata.default)) + |~ case1 "contents-x-dh" Payload.x_dh (fun (n, i, m) -> Contents (Direct n, Hash i, m)) + |~ case1 "node-dd" Payload.dh (fun (n, i) -> Node (Direct n, Hash i)) + |> sealv + + type v = Values of value list | Tree of tree + [@@deriving irmin ~encode_bin ~decode_bin ~size_of] + + let dynamic_size_of_v_encoding = + match Irmin.Type.Size.of_encoding v_t with + | Irmin.Type.Size.Dynamic f -> f + | _ -> assert false + + type kind = Pack_value.Kind.t + [@@deriving irmin ~encode_bin ~decode_bin ~size_of] + + type nonrec int = int [@@deriving irmin ~encode_bin ~decode_bin] + + let no_length = 0 + let is_real_length length = not (length = 0) + + type v1 = { mutable length : int; v : v } [@@deriving irmin] + (** [length] is the length of the binary encoding of [v]. It is not known + right away. [length] is [no_length] when it isn't known. Calling + [encode_bin] or [size_of] will make [length] known. *) + + (** [tagged_v] sits between [v] and [t]. It is a variant with the header + binary encoded as the magic. *) + type tagged_v = + | V0_stable of v + | V0_unstable of v + | V1_root of v1 + | V1_nonroot of v1 + [@@deriving irmin] + + let encode_bin_tv_staggered ({ v; _ } as tv) kind f = + match size_of_v v with + | Some length -> + tv.length <- length; + encode_bin_kind kind f; + encode_bin_int length f; + encode_bin_v v f + | None -> + let buf = Buffer.create 1024 in + encode_bin_v v (Buffer.add_string buf); + let length = Buffer.length buf in + tv.length <- length; + encode_bin_kind kind f; + encode_bin_int length f; + f (Buffer.contents buf) + + let encode_bin_tv tv f = + match tv with + | V0_stable _ -> assert false + | V0_unstable _ -> assert false + | V1_root { length; v } when is_real_length length -> + encode_bin_kind Pack_value.Kind.Inode_v2_root f; + encode_bin_int length f; + encode_bin_v v f + | V1_nonroot { length; v } when is_real_length length -> + encode_bin_kind Pack_value.Kind.Inode_v2_nonroot f; + encode_bin_int length f; + encode_bin_v v f + | V1_root tv -> encode_bin_tv_staggered tv Pack_value.Kind.Inode_v2_root f + | V1_nonroot tv -> + encode_bin_tv_staggered tv Pack_value.Kind.Inode_v2_nonroot f + + let decode_bin_tv s off = + let kind = decode_bin_kind s off in + match kind with + | Pack_value.Kind.Inode_v1_unstable -> + let v = decode_bin_v s off in + V0_unstable v + | Inode_v1_stable -> + let v = decode_bin_v s off in + V0_stable v + | Inode_v2_root -> + let length = decode_bin_int s off in + assert (is_real_length length); + let v = decode_bin_v s off in + V1_root { length; v } + | Inode_v2_nonroot -> + let length = decode_bin_int s off in + assert (is_real_length length); + let v = decode_bin_v s off in + V1_nonroot { length; v } + | Commit_v1 | Commit_v2 -> assert false + | Contents -> assert false + | Dangling_parent_commit -> assert false + + let size_of_tv = + let of_encoding s off = + let offref = ref off in + let kind = decode_bin_kind s offref in + let magic_len = 1 in + match kind with + | Pack_value.Kind.Inode_v1_unstable | Inode_v1_stable -> + let vlen = dynamic_size_of_v_encoding s !offref in + magic_len + vlen + | Inode_v2_root | Inode_v2_nonroot -> + let before = !offref in + let vlen = decode_bin_int s offref in + let after = !offref in + let lenlen = after - before in + magic_len + lenlen + vlen + | Commit_v1 | Commit_v2 | Contents -> assert false + | Dangling_parent_commit -> assert false + in + Irmin.Type.Size.custom_dynamic ~of_encoding () + + let tagged_v_t = + Irmin.Type.like ~bin:(encode_bin_tv, decode_bin_tv, size_of_tv) tagged_v_t + + type t = { hash : H.t; tv : tagged_v } [@@deriving irmin] + + let v ~root ~hash v = + let length = no_length in + let tv = + if root then V1_root { v; length } else V1_nonroot { v; length } + in + { hash; tv } + + (** The rule to determine the [is_root] property of a v0 [Value] is a bit + convoluted, it relies on the fact that back then the following property + was enforced: [Conf.stable_hash > Conf.entries]. + + When [t] is of tag [Values], then [t] is root iff [t] is stable. + + When [t] is stable, then [t] is a root, because: + + - Only 2 functions produce stable inodes: [stabilize] and [empty]. + - Only the roots are output of [stabilize]. + - An empty map can only be located at the root. + + When [t] is a root of tag [Value], then [t] is stable, because: + + - All the roots are output of [stabilize]. + - When an unstable inode enters [stabilize], it becomes stable if it has + at most [Conf.stable_hash] leaves. + - A [Value] has at most [Conf.stable_hash] leaves because + [Conf.entries <= Conf.stable_hash] is enforced. *) + let is_root = function + | { tv = V0_stable (Values _); _ } -> true + | { tv = V0_unstable (Values _); _ } -> false + | { tv = V0_stable (Tree { depth; _ }); _ } + | { tv = V0_unstable (Tree { depth; _ }); _ } -> + depth = 0 + | { tv = V1_root _; _ } -> true + | { tv = V1_nonroot _; _ } -> false + end + + (** [Val_impl] defines the recursive structure of inodes. + + {3 Inode Layout} + + {4 Layout Types} + + The layout ['a layout] associated to an inode ['a t] defines certain + properties of the inode: + + - When [Total], the inode is self contained and immutable. + - When [Partial], chunks of the inode might be missing but they can be + fetched from the backend when needed using the available [find] function + stored in the layout. Mutable pointers act as cache. + - When [Truncated], chunks of the inode might be missing. Those chunks are + unreachable because the pointer to the backend is missing. The inode is + immutable. + + {4 Layout Instantiation} + + The layout of an inode is determined from the module [Val], it depends on + the way the inode was constructed: + + - When [Total], it originates from [Val.v] or [Val.empty]. + - When [Partial], it originates from [Val.of_bin], which is only used by + [Inode.find]. + - When [Truncated], it either originates from an [Irmin.Type] + deserialisation or from a proof. + + Almost all other functions in [Val_impl] are polymorphic regarding the + layout of the manipulated inode. + + {4 Details on the [Truncated] Layout} + + The [Truncated] layout is identical to [Partial] except for the missing + [find] function. + + On the one hand, when creating the root of a [Truncated] inode, the + pointers to children inodes - if any - are set to the [Broken] tag, + meaning that we know the hash to such children but we will have no way to + load them in the future. On the other hand, when adding child to a + [Truncated] inode, there is no such problem, the pointer is then set to + the [Intact] tag. + + A tree of inode only made of [Intact] tags is similar to a [Total] layout. + + As of Irmin 2.4 (February 2022), inode deserialisation using Repr happens + in [irmin/slice.ml] and [irmin/sync_ext.ml], and maybe some other places. + + At some point we might want to forbid such deserialisations and instead + use something in the flavour of [Val.of_bin] to create [Partial] inodes. + + {3 Topmost Inode Ancestor} + + [Val_impl.t] is a recursive type, it is labelled with a [depth] integer + that indicates the recursion depth. An inode with [depth = 0] corresponds + to the root of a directory, its hash is the hash of the directory. + + A [Val.t] points to the topmost [Val_impl.t] of an inode tree. In most + scenarios, that topmost inode has [depth = 0], but it is also legal for + the topmost inode to be an intermediate inode, i.e. with [depth > 0]. + + The only way for an inode tree to have an intermediate inode as root is to + fetch it from the backend by calling [Make_ext.find], using the hash of + that inode. + + Write-only operations are not permitted when the root is an intermediate + inode. *) + module Val_impl = struct + open T + + type _ layout = + | Total : total_ptr layout + | Partial : find -> partial_ptr layout + | Truncated : truncated_ptr layout + + and find = expected_depth:int -> key -> partial_ptr t option + + and partial_ptr_target = + | Dirty of partial_ptr t + | Lazy of key + | Lazy_loaded of partial_ptr t + (** A partial pointer differentiates the [Dirty] and [Lazy_loaded] + cases in order to remember that only the latter should be + collected when [clear] is called. + + The child in [Lazy_loaded] can only emanate from the disk. It can + be savely collected on [clear]. + + The child in [Dirty] can only emanate from a user modification, + e.g. through the [add] or [to_concrete] functions. It shouldn't be + collected on [clear] because it will be needed for [save]. *) + + and partial_ptr = { mutable target : partial_ptr_target } + and total_ptr = Total_ptr of total_ptr t [@@unboxed] + + and truncated_ptr = + | Broken of Val_ref.t + (** Initially [Hash.t], then set to [Key.t] when we try to save the + parent and successfully index the hash. *) + | Intact of truncated_ptr t + + and 'ptr tree = { depth : int; length : int; entries : 'ptr option array } + and 'ptr v = Values of value StepMap.t | Tree of 'ptr tree + + and 'ptr t = { + root : bool; + v : 'ptr v; + v_ref : Val_ref.t; + (** Represents what is known about [v]'s presence in a corresponding + store. Will be a [hash] if [v] is purely in-memory, and a [key] if + [v] has been written to / loaded from a store. *) + } + + module Ptr = struct + let val_ref : type ptr. ptr layout -> ptr -> Val_ref.t = function + | Total -> fun (Total_ptr ptr) -> ptr.v_ref + | Partial _ -> ( + fun { target } -> + match target with + | Lazy key -> Val_ref.of_key key + | Lazy_loaded { v_ref; _ } | Dirty { v_ref; _ } -> v_ref) + | Truncated -> ( function Broken v -> v | Intact ptr -> ptr.v_ref) + + let key_exn : type ptr. ptr layout -> ptr -> key = function + | Total -> fun (Total_ptr ptr) -> Val_ref.to_key_exn ptr.v_ref + | Partial _ -> ( + fun { target } -> + match target with + | Lazy key -> key + | Lazy_loaded { v_ref; _ } | Dirty { v_ref; _ } -> + Val_ref.to_key_exn v_ref) + | Truncated -> ( + function + | Broken h -> Val_ref.to_key_exn h + | Intact ptr -> Val_ref.to_key_exn ptr.v_ref) + + (** [force = false] will cause [target] to raise an exception when + encountering a tag [Lazy] inside a [Partial] inode. This feature is + used by [to_concrete] to make shallow the non-loaded inode branches. *) + let target : + type ptr. + expected_depth:int -> + cache:bool -> + force:bool -> + string -> + ptr layout -> + ptr -> + ptr t = + fun ~expected_depth ~cache ~force context layout -> + match layout with + | Total -> fun (Total_ptr t) -> t + | Partial find -> ( + function + | { target = Dirty entry } | { target = Lazy_loaded entry } -> + (* [target] is already cached. [cache] is only concerned with + new cache entries, not the older ones for which the irmin + users can discard using [clear]. *) + entry + | { target = Lazy key } as t -> ( + if not force then raise_dangling_hash context (Key.to_hash key); + match find ~expected_depth key with + | None -> + Fmt.failwith "%a: unknown inode key (%s)" pp_key key context + | Some x -> + if cache then t.target <- Lazy_loaded x; + x)) + | Truncated -> ( + function + | Intact entry -> entry + | Broken vref -> + let h = Val_ref.to_hash vref in + raise_dangling_hash context h) + + let of_target : type ptr. ptr layout -> ptr t -> ptr = function + | Total -> fun target -> Total_ptr target + | Partial _ -> fun target -> { target = Dirty target } + | Truncated -> fun target -> Intact target + + let of_key : type ptr. ptr layout -> key -> ptr = function + | Total -> assert false + | Partial _ -> fun key -> { target = Lazy key } + | Truncated -> fun key -> Broken (Val_ref.of_key key) + + type ('input, 'output) cps = { f : 'r. 'input -> ('output -> 'r) -> 'r } + [@@ocaml.unboxed] + + let save : + type ptr. + broken:(hash, key) cps -> + save_dirty:(ptr t, key) cps -> + clear:bool -> + ptr layout -> + ptr -> + unit = + fun ~broken ~save_dirty ~clear -> function + (* Invariant: after returning, we can recover the key from the saved + pointer (i.e. [key_exn] does not raise an exception). This is necessary + in order to be able to serialise a parent inode (for export) after + having saved its children. *) + | Total -> + fun (Total_ptr entry) -> + save_dirty.f entry (fun key -> + Val_ref.promote_exn entry.v_ref key) + | Partial _ -> ( + function + | { target = Dirty entry } as box -> + save_dirty.f entry (fun key -> + if clear then box.target <- Lazy key + else ( + box.target <- Lazy_loaded entry; + Val_ref.promote_exn entry.v_ref key)) + | { target = Lazy_loaded entry } as box -> + (* In this case, [entry.v_ref] is a [Hash h] such that [mem t + (index t h) = true]. We "save" the entry in order to trigger + the [index] lookup and recover the key, in order to meet the + return invariant above. + + TODO: refactor this case to be more precise. *) + save_dirty.f entry (fun key -> + if clear then box.target <- Lazy key) + | { target = Lazy _ } -> ()) + | Truncated -> ( + function + (* TODO: this branch is currently untested: we never attempt to + save a truncated node as part of the unit tests. *) + | Intact entry -> + save_dirty.f entry (fun key -> + Val_ref.promote_exn entry.v_ref key) + | Broken vref -> + if not (Val_ref.is_key vref) then + broken.f (Val_ref.to_hash vref) (fun key -> + Val_ref.promote_exn vref key)) + + let clear : + type ptr. + iter_dirty:(ptr layout -> ptr t -> unit) -> ptr layout -> ptr -> unit + = + fun ~iter_dirty layout ptr -> + match layout with + | Partial _ -> ( + match ptr with + | { target = Lazy _ } -> () + | { target = Dirty ptr } -> iter_dirty layout ptr + | { target = Lazy_loaded ptr } as box -> + (* Since a [Lazy_loaded] used to be a [Lazy], the key is always + available. *) + let key = Val_ref.to_key_exn ptr.v_ref in + box.target <- Lazy key) + | Total | Truncated -> () + end + + let pred layout t = + match t.v with + | Tree i -> + let key_of_ptr = Ptr.key_exn layout in + Array.fold_left + (fun acc -> function + | None -> acc + | Some ptr -> (None, `Inode (key_of_ptr ptr)) :: acc) + [] i.entries + | Values l -> + StepMap.fold + (fun s v acc -> + let v = + match v with + | `Node _ as k -> (Some s, k) + | `Contents (k, _) -> (Some s, `Contents k) + in + v :: acc) + l [] + + let length_of_v = function + | Values vs -> StepMap.cardinal vs + | Tree vs -> vs.length + + let length t = length_of_v t.v + + let rec clear layout t = + match t.v with + | Tree i -> + Array.iter + (Option.iter (Ptr.clear ~iter_dirty:clear layout)) + i.entries + | Values _ -> () + + let nb_children t = + match t.v with + | Tree i -> + Array.fold_left + (fun i -> function None -> i | Some _ -> i + 1) + 0 i.entries + | Values vs -> StepMap.cardinal vs + + type cont = off:int -> len:int -> (step * value) Seq.node + + let rec seq_tree layout bucket_seq ~depth ~cache : cont -> cont = + fun k ~off ~len -> + assert (off >= 0); + assert (len > 0); + match bucket_seq () with + | Seq.Nil -> k ~off ~len + | Seq.Cons (None, rest) -> seq_tree layout rest ~depth ~cache k ~off ~len + | Seq.Cons (Some i, rest) -> + let trg = + let expected_depth = depth + 1 in + Ptr.target ~expected_depth ~cache ~force:true "seq_tree" layout i + in + let trg_len = length trg in + if off - trg_len >= 0 then + (* Skip a branch of the inode tree in case the user asked for a + specific starting offset. + + Without this branch the algorithm would keep the same semantic + because [seq_value] would handles the pagination value by value + instead. *) + let off = off - trg_len in + seq_tree layout rest ~depth ~cache k ~off ~len + else + seq_v layout trg.v ~cache + (seq_tree layout rest ~depth ~cache k) + ~off ~len + + and seq_values layout value_seq : cont -> cont = + fun k ~off ~len -> + assert (off >= 0); + assert (len > 0); + match value_seq () with + | Seq.Nil -> k ~off ~len + | Cons (x, rest) -> + if off = 0 then + let len = len - 1 in + if len = 0 then + (* Yield the current value and skip the rest of the inode tree in + case the user asked for a specific length. *) + Seq.Cons (x, Seq.empty) + else Seq.Cons (x, fun () -> seq_values layout rest k ~off ~len) + else + (* Skip one value in case the user asked for a specific starting + offset. *) + let off = off - 1 in + seq_values layout rest k ~off ~len + + and seq_v layout v ~cache : cont -> cont = + fun k ~off ~len -> + assert (off >= 0); + assert (len > 0); + match v with + | Tree t -> + let depth = t.depth in + seq_tree layout (Array.to_seq t.entries) ~depth ~cache k ~off ~len + | Values vs -> seq_values layout (StepMap.to_seq vs) k ~off ~len + + let list_v layout v ~cache k ~off ~len = + match v with + | Tree _ -> + let s () = seq_v layout v ~cache k ~off ~len in + List.of_seq s + | Values vs -> + if off = 0 && len = Int.max_int then StepMap.bindings vs + else + let seq () = seq_values layout (StepMap.to_seq vs) k ~off ~len in + List.of_seq seq + + let empty_continuation : cont = fun ~off:_ ~len:_ -> Seq.Nil + + let seq layout ?offset:(off = 0) ?length:(len = Int.max_int) ?(cache = true) + t : (step * value) Seq.t = + if off < 0 then invalid_arg "Invalid pagination offset"; + if len < 0 then invalid_arg "Invalid pagination length"; + if len = 0 then Seq.empty + else fun () -> seq_v layout t.v ~cache empty_continuation ~off ~len + + let list layout ?offset:(off = 0) ?length:(len = Int.max_int) + ?(cache = true) t : (step * value) list = + if off < 0 then invalid_arg "Invalid pagination offset"; + if len < 0 then invalid_arg "Invalid pagination length"; + if len = 0 then [] + else list_v layout t.v ~cache empty_continuation ~off ~len + + let seq_tree layout ?(cache = true) i : (step * value) Seq.t = + let off = 0 in + let len = Int.max_int in + fun () -> seq_v layout (Tree i) ~cache empty_continuation ~off ~len + + let seq_v layout ?(cache = true) v : (step * value) Seq.t = + let off = 0 in + let len = Int.max_int in + fun () -> seq_v layout v ~cache empty_continuation ~off ~len + + let to_bin_v : + type ptr vref. ptr layout -> vref Bin.mode -> ptr v -> vref Bin.v = + fun layout mode node -> + Stats.incr_inode_to_binv (); + match node with + | Values vs -> + let vs = StepMap.bindings vs in + Bin.Values vs + | Tree t -> + let vref_of_ptr : ptr -> vref = + match mode with + | Bin.Ptr_any -> Ptr.val_ref layout + | Bin.Ptr_key -> Ptr.key_exn layout + in + let _, entries = + Array.fold_left + (fun (i, acc) -> function + | None -> (i + 1, acc) + | Some ptr -> + let vref = vref_of_ptr ptr in + (i + 1, { Bin.index = i; vref } :: acc)) + (0, []) t.entries + in + let entries = List.rev entries in + Bin.Tree { depth = t.depth; length = t.length; entries } + + let is_root t = t.root + let is_stable t = should_be_stable ~length:(length t) ~root:(is_root t) + + let to_bin layout mode t = + let v = to_bin_v layout mode t.v in + Bin.v ~root:(is_root t) ~hash:(Val_ref.to_lazy_hash t.v_ref) v + + type len = [ `Eq of int | `Ge of int ] [@@deriving irmin] + + module Concrete = struct + type kinded_key = + | Contents of contents_key + | Contents_x of metadata * contents_key + | Node of node_key + [@@deriving irmin] + + type entry = { name : step; key : kinded_key } [@@deriving irmin] + + type 'a pointer = { index : int; pointer : hash; tree : 'a } + [@@deriving irmin] + + type 'a tree = { depth : int; length : int; pointers : 'a pointer list } + [@@deriving irmin] + + type t = Tree of t tree | Values of entry list | Blinded + [@@deriving irmin] + + let to_entry (name, v) = + match v with + | `Contents (contents_key, m) -> + if T.equal_metadata m Metadata.default then + { name; key = Contents contents_key } + else { name; key = Contents_x (m, contents_key) } + | `Node node_key -> { name; key = Node node_key } + + let of_entry e = + ( e.name, + match e.key with + | Contents key -> `Contents (key, Metadata.default) + | Contents_x (m, key) -> `Contents (key, m) + | Node key -> `Node key ) + + type error = + [ `Invalid_hash of hash * hash * t + | `Invalid_depth of int * int * t + | `Invalid_length of len * int * t + | `Duplicated_entries of t + | `Duplicated_pointers of t + | `Unsorted_entries of t + | `Unsorted_pointers of t + | `Blinded_root + | `Too_large_values of t + | `Empty ] + [@@deriving irmin] + + let rec length = function + | Values l -> `Eq (List.length l) + | Tree t -> + List.fold_left + (fun acc p -> + match (acc, length p.tree) with + | `Eq x, `Eq y -> `Eq (x + y) + | (`Eq x | `Ge x), (`Eq y | `Ge y) -> `Ge (x + y)) + (`Eq 0) t.pointers + | Blinded -> `Ge 0 + + let pp = Irmin.Type.pp_json t + + let pp_len ppf = function + | `Eq e -> Fmt.pf ppf "%d" e + | `Ge e -> Fmt.pf ppf "'at least %d'" e + + let pp_error ppf = function + | `Invalid_hash (got, expected, t) -> + Fmt.pf ppf "invalid hash for %a@,got: %a@,expecting: %a" pp t + pp_hash got pp_hash expected + | `Invalid_depth (got, expected, t) -> + Fmt.pf ppf "invalid depth for %a@,got: %d@,expecting: %d" pp t got + expected + | `Invalid_length (got, expected, t) -> + Fmt.pf ppf "invalid length for %a@,got: %a@,expecting: %d" pp t + pp_len got expected + | `Duplicated_entries t -> Fmt.pf ppf "duplicated entries: %a" pp t + | `Duplicated_pointers t -> Fmt.pf ppf "duplicated pointers: %a" pp t + | `Unsorted_entries t -> Fmt.pf ppf "entries should be sorted: %a" pp t + | `Unsorted_pointers t -> + Fmt.pf ppf "pointers should be sorted: %a" pp t + | `Blinded_root -> Fmt.pf ppf "blinded root" + | `Too_large_values t -> + Fmt.pf ppf "A Values should have at most Conf.entries elements: %a" + pp t + | `Empty -> Fmt.pf ppf "concrete subtrees cannot be empty" + end + + let to_concrete ~force (la : 'ptr layout) (t : 'ptr t) = + let rec aux t = + let h = Val_ref.to_hash t.v_ref in + match t.v with + | Tree tr -> + ( h, + Concrete.Tree + { + depth = tr.depth; + length = tr.length; + pointers = + Array.fold_left + (fun (i, acc) e -> + match e with + | None -> (i + 1, acc) + | Some t -> + let expected_depth = tr.depth + 1 in + let pointer, tree = + try + aux + (Ptr.target ~expected_depth ~cache:true ~force + "to_concrete" la t) + with Dangling_hash { hash; _ } -> + (hash, Concrete.Blinded) + in + (i + 1, { Concrete.index = i; tree; pointer } :: acc)) + (0, []) tr.entries + |> snd + |> List.rev; + } ) + | Values l -> + ( h, + Concrete.Values (List.map Concrete.to_entry (StepMap.bindings l)) + ) + in + snd (aux t) + + exception Invalid_hash of hash * hash * Concrete.t + exception Invalid_depth of int * int * Concrete.t + exception Invalid_length of len * int * Concrete.t + exception Empty + exception Duplicated_entries of Concrete.t + exception Duplicated_pointers of Concrete.t + exception Unsorted_entries of Concrete.t + exception Unsorted_pointers of Concrete.t + exception Blinded_root + exception Too_large_values of Concrete.t + + let hash_equal = Irmin.Type.(unstage (equal hash_t)) + + let of_concrete_exn : type a. depth:int -> a layout -> _ -> a t = + fun ~depth la t -> + let sort_entries = + List.sort_uniq (fun x y -> compare x.Concrete.name y.Concrete.name) + in + let sort_pointers = + List.sort_uniq (fun x y -> compare x.Concrete.index y.Concrete.index) + in + let check_entries t es = + if es = [] then raise Empty; + let s = sort_entries es in + if List.compare_length_with es Conf.entries > 0 then + raise (Too_large_values t); + if List.compare_lengths s es <> 0 then raise (Duplicated_entries t); + if s <> es then raise (Unsorted_entries t) + in + let check_pointers t ps = + if ps = [] then raise Empty; + let s = sort_pointers ps in + if List.length s <> List.length ps then raise (Duplicated_pointers t); + if s <> ps then raise (Unsorted_pointers t) + in + let hash v = Bin.V.hash (to_bin_v la Bin.Ptr_any v) in + let rec aux depth t = + match t with + | Concrete.Blinded -> None + | Concrete.Values l -> + check_entries t l; + Some (Values (StepMap.of_list (List.map Concrete.of_entry l))) + | Concrete.Tree tr -> + let entries = Array.make Conf.entries None in + check_pointers t tr.pointers; + List.iter + (fun { Concrete.index; pointer; tree } -> + match aux (depth + 1) tree with + | None -> + (* Child is blinded *) + let ptr = + match la with + | Total -> assert false + | Partial _ -> + (* [of_concrete_exn (Partial _)] is only used in the + context of portable inodes, [unfindable_of_hash] is + fine. *) + let k = Key.unfindable_of_hash pointer in + Ptr.of_key la k + | Truncated -> + let v_ref = Val_ref.of_hash (Lazy.from_val pointer) in + (Broken v_ref : a) + in + entries.(index) <- Some ptr + | Some v -> + let hash = hash v in + if not (hash_equal hash pointer) then + raise (Invalid_hash (hash, pointer, t)); + let v_ref = Val_ref.of_hash (Lazy.from_val pointer) in + let t = { v_ref; root = false; v } in + entries.(index) <- Some (Ptr.of_target la t)) + tr.pointers; + if depth <> tr.depth then raise (Invalid_depth (depth, tr.depth, t)); + let () = + match Concrete.length t with + | `Eq length -> + if length <> tr.length then + raise (Invalid_length (`Eq length, tr.length, t)) + | `Ge length -> + if length > tr.length then + raise (Invalid_length (`Ge length, tr.length, t)) + in + + Some (Tree { depth = tr.depth; length = tr.length; entries }) + in + let v = + match aux depth t with None -> raise Blinded_root | Some v -> v + in + let length = length_of_v v in + let hash = + (* Compute the hash right away (not lazily) so that + [hash_exn ~force:false] is possible on the result of + [of_proof]. *) + if should_be_stable ~length ~root:(depth = 0) then + (* [seq_v] may call [find], even if some branches are blinded *) + let node = Node.of_seq (seq_v la v) in + Node.hash node + else hash v + in + { v_ref = Val_ref.of_hash (Lazy.from_val hash); root = depth = 0; v } + + let of_concrete ~depth la t = + try Ok (of_concrete_exn ~depth la t) with + | Invalid_hash (x, y, z) -> Error (`Invalid_hash (x, y, z)) + | Invalid_depth (x, y, z) -> Error (`Invalid_depth (x, y, z)) + | Invalid_length (x, y, z) -> Error (`Invalid_length (x, y, z)) + | Empty -> Error `Empty + | Duplicated_entries t -> Error (`Duplicated_entries t) + | Duplicated_pointers t -> Error (`Duplicated_pointers t) + | Unsorted_entries t -> Error (`Unsorted_entries t) + | Unsorted_pointers t -> Error (`Unsorted_pointers t) + | Too_large_values t -> Error (`Too_large_values t) + | Blinded_root -> Error `Blinded_root + + let hash t = Val_ref.to_hash t.v_ref + + let hash_exn ?(force = true) t = + match Val_ref.inspect t.v_ref with + | Key k -> Key.to_hash k + | Hash h -> + if Lazy.is_val h || force then Lazy.force h else raise Not_found + + let check_write_op_supported t = + if not @@ is_root t then + failwith "Cannot perform operation on non-root inode value." + + let stabilize_root layout t = + let n = length t in + (* If [t] is the empty inode (i.e. [n = 0]) then is is already stable *) + if n > Conf.stable_hash then { t with root = true } + else + let v_ref = + Val_ref.of_hash + (lazy + (let vs = seq layout ~cache:false t in + Node.hash (Node.of_seq vs))) + in + { v_ref; v = t.v; root = true } + + let index ~depth k = + if depth >= max_depth then raise (Max_depth depth); + Child_ordering.index ~depth k + + (** This function shouldn't be called with the [Total] layout. In the + future, we could add a polymorphic variant to the GADT parameter to + enfoce that. *) + let of_bin layout (t : key Bin.t) = + let v = + match t.Bin.v with + | Bin.Values vs -> + let vs = StepMap.of_list vs in + Values vs + | Tree t -> + let entries = Array.make Conf.entries None in + let ptr_of_key = Ptr.of_key layout in + List.iter + (fun { Bin.index; vref } -> + entries.(index) <- Some (ptr_of_key vref)) + t.entries; + Tree { depth = t.Bin.depth; length = t.length; entries } + in + { v_ref = Val_ref.of_hash t.Bin.hash; root = t.Bin.root; v } + + let recompute_hash layout t = + if is_stable t then + let vs = seq layout ~cache:false t in + Node.hash (Node.of_seq vs) + else + let v = to_bin_v layout Bin.Ptr_any t.v in + let hash = Bin.V.hash v in + hash + + let empty : 'a. 'a layout -> 'a t = + fun _ -> + let v_ref = Val_ref.of_hash (lazy (Node.hash (Node.empty ()))) in + { root = false; v_ref; v = Values StepMap.empty } + + let values layout vs = + let length = StepMap.cardinal vs in + if length = 0 then empty layout + else + let v = Values vs in + let v_ref = + Val_ref.of_hash (lazy (Bin.V.hash (to_bin_v layout Bin.Ptr_any v))) + in + { v_ref; root = false; v } + + let tree layout is = + let v = Tree is in + let v_ref = + Val_ref.of_hash (lazy (Bin.V.hash (to_bin_v layout Bin.Ptr_any v))) + in + { v_ref; root = false; v } + + let is_empty t = + match t.v with Values vs -> StepMap.is_empty vs | Tree _ -> false + + let find_value ~cache layout t s = + let key = Child_ordering.key s in + let rec aux = function + | Values vs -> ( try Some (StepMap.find s vs) with Not_found -> None) + | Tree t -> ( + let i = index ~depth:t.depth key in + let x = t.entries.(i) in + match x with + | None -> None + | Some i -> + let expected_depth = t.depth + 1 in + aux + (Ptr.target ~expected_depth ~cache ~force:true "find_value" + layout i) + .v) + in + aux t.v + + let find ?(cache = true) layout t s = find_value ~cache layout t s + + let rec add layout ~depth ~copy ~replace parent s key v k = + Stats.incr_inode_rec_add (); + match parent.v with + | Values vs -> + let length = + if replace then StepMap.cardinal vs else StepMap.cardinal vs + 1 + in + let parent = + if length <= Conf.entries then values layout (StepMap.add s v vs) + else + let vs = StepMap.bindings (StepMap.add s v vs) in + let empty = + tree layout + { length = 0; depth; entries = Array.make Conf.entries None } + in + let aux t (s', v) = + let key' = Child_ordering.key s' in + (add [@tailcall]) layout ~depth ~copy:false ~replace t s' key' v + (fun x -> x) + in + List.fold_left aux empty vs + in + k parent + | Tree tr -> ( + assert (depth = tr.depth); + let length = if replace then tr.length else tr.length + 1 in + let entries = if copy then Array.copy tr.entries else tr.entries in + let i = index ~depth key in + match entries.(i) with + | None -> + let child = values layout (StepMap.singleton s v) in + entries.(i) <- Some (Ptr.of_target layout child); + let parent = tree layout { tr with length; entries } in + k parent + | Some ptr -> + let child = + let expected_depth = depth + 1 in + (* [cache] is unimportant here as we've already called + [find_value] for that path.*) + Ptr.target ~expected_depth ~cache:true ~force:true "add" layout + ptr + in + (add [@tailcall]) layout ~depth:(depth + 1) ~copy ~replace child s + key v (fun child -> + entries.(i) <- Some (Ptr.of_target layout child); + let parent = tree layout { tr with length; entries } in + k parent)) + + let add layout ~copy t s v = + let k = Child_ordering.key s in + match find_value ~cache:true layout t s with + | Some v' when equal_value v v' -> t + | Some _ -> + add ~depth:0 layout ~copy ~replace:true t s k v Fun.id + |> stabilize_root layout + | None -> + add ~depth:0 layout ~copy ~replace:false t s k v Fun.id + |> stabilize_root layout + + let rec remove layout parent s key k = + Stats.incr_inode_rec_remove (); + match parent.v with + | Values vs -> + let parent = values layout (StepMap.remove s vs) in + k parent + | Tree tr -> ( + let depth = tr.depth in + let len = tr.length - 1 in + if len <= Conf.entries then + let vs = seq_tree layout tr in + let vs = StepMap.of_seq vs in + let vs = StepMap.remove s vs in + let parent = values layout vs in + k parent + else + let entries = Array.copy tr.entries in + let i = index ~depth key in + match entries.(i) with + | None -> assert false + | Some ptr -> + let child = + let expected_depth = depth + 1 in + (* [cache] is unimportant here as we've already called + [find_value] for that path.*) + Ptr.target ~expected_depth ~cache:true ~force:true "remove" + layout ptr + in + if length child = 1 then ( + entries.(i) <- None; + let parent = tree layout { depth; length = len; entries } in + k parent) + else + (remove [@tailcall]) layout child s key (fun child -> + entries.(i) <- Some (Ptr.of_target layout child); + let parent = + tree layout { tr with length = len; entries } + in + k parent)) + + let remove layout t s = + let k = Child_ordering.key s in + match find_value ~cache:true layout t s with + | None -> t + | Some _ -> remove layout t s k Fun.id |> stabilize_root layout + + let of_seq la l = + let t = + let rec aux_big seq inode = + match seq () with + | Seq.Nil -> inode + | Seq.Cons ((s, v), rest) -> + aux_big rest (add la ~copy:false inode s v) + in + let len = + (* [StepMap.cardinal] is (a bit) expensive to compute, let's track the + size of the map in a [ref] while doing [StepMap.update]. *) + ref 0 + in + let rec aux_small seq map = + match seq () with + | Seq.Nil -> + assert (!len <= Conf.entries); + values la map + | Seq.Cons ((s, v), rest) -> + let map = + StepMap.update s + (function + | None -> + incr len; + Some v + | Some _ -> Some v) + map + in + if !len = Conf.entries then aux_big rest (values la map) + else aux_small rest map + in + aux_small l StepMap.empty + in + stabilize_root la t + + let save layout ~add ~index ~mem t = + let clear = + (* When set to [true], collect the loaded inodes as soon as they're + saved. + + This parameter is not exposed yet. Ideally it would be exposed and + be forwarded from [Tree.export ?clear] through [P.Node.add]. + + It is currently set to false in order to preserve behaviour *) + false + in + let iter_entries = + let broken h k = + (* This function is called when we encounter a Broken pointer with + Truncated layouts. *) + match index h with + | None -> + Fmt.failwith + "You are trying to save to the backend an inode deserialized \ + using [Irmin.Type] that used to contain pointer(s) to inodes \ + which are unknown to the backend. Hash: %a" + pp_hash h + | Some key -> + (* The backend already knows this target inode, there is no need to + traverse further down. This happens during the unit tests. *) + k key + in + fun ~save_dirty arr -> + let iter_ptr = + Ptr.save ~broken:{ f = broken } ~save_dirty ~clear layout + in + Array.iter (Option.iter iter_ptr) arr + in + let rec aux ~depth t = + match t.v with + | Values _ -> ( + [%log.debug "Inode.save values depth:%d" depth]; + let unguarded_add hash = + let value = + (* NOTE: the choice of [Bin.mode] is irrelevant (and this + conversion is always safe), since nodes of kind [Values _] + contain no internal pointers. *) + to_bin layout Bin.Ptr_key t + in + let key = add hash value in + Val_ref.promote_exn t.v_ref key; + key + in + match Val_ref.inspect t.v_ref with + | Key key -> + if mem key then key else unguarded_add (Key.to_hash key) + | Hash hash -> unguarded_add (Lazy.force hash)) + | Tree n -> + [%log.debug "Inode.save tree depth:%d" depth]; + let save_dirty t k = + let key = + match Val_ref.inspect t.v_ref with + | Key key -> if mem key then key else aux ~depth:(depth + 1) t + | Hash hash -> ( + match index (Lazy.force hash) with + | Some key -> + if mem key then key + else + (* In this case, [index] has returned a key that is + not present in the underlying store. This is + permitted by the contract on index functions (and + required by [irmin-pack.mem]), but never happens + with the persistent {!Pack_store} backend (provided + the store is not corrupted). *) + aux ~depth:(depth + 1) t + | None -> aux ~depth:(depth + 1) t) + in + Val_ref.promote_exn t.v_ref key; + k key + in + iter_entries ~save_dirty:{ f = save_dirty } n.entries; + let bin = + (* Serialising with [Bin.Ptr_key] is safe here because just called + [Ptr.save] on any dirty children (and we never try to save + [Portable] nodes). *) + to_bin layout Bin.Ptr_key t + in + let key = add (Val_ref.to_hash t.v_ref) bin in + Val_ref.promote_exn t.v_ref key; + key + in + aux ~depth:0 t + + let check_stable layout t = + let rec check t any_stable_ancestor = + let stable = is_stable t || any_stable_ancestor in + match t.v with + | Values _ -> true + | Tree tree -> + Array.for_all + (function + | None -> true + | Some t -> + let t = + let expected_depth = tree.depth + 1 in + Ptr.target ~expected_depth ~cache:true ~force:true + "check_stable" layout t + in + (if stable then not (is_stable t) else true) + && check t stable) + tree.entries + in + check t (is_stable t) + + let contains_empty_map layout t = + let rec check_lower t = + match t.v with + | Values l when StepMap.is_empty l -> true + | Values _ -> false + | Tree inodes -> + Array.exists + (function + | None -> false + | Some t -> + let expected_depth = inodes.depth + 1 in + Ptr.target ~expected_depth ~cache:true ~force:true + "contains_empty_map" layout t + |> check_lower) + inodes.entries + in + check_lower t + + let is_tree t = match t.v with Tree _ -> true | Values _ -> false + + module Proof = struct + type value = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin] + + type t = + [ `Blinded of hash + | `Values of (step * value) list + | `Inode of int * (int * t) list ] + [@@deriving irmin] + + let weaken_step_value (step, v) = (step, hashvalue_of_keyvalue v) + + let strengthen_step_value (step, v) = + (* Since proofs are used only in the context of portable, using this + unsafe function is safe. *) + (step, unsafe_keyvalue_of_hashvalue v) + + let rec proof_of_concrete : + type a. hash Lazy.t -> Concrete.t -> (t -> a) -> a = + fun h concrete k -> + match concrete with + | Blinded -> k (`Blinded (Lazy.force h)) + | Values vs -> + let l = + List.map Concrete.of_entry vs |> List.map weaken_step_value + in + k (`Values l) + | Tree tr -> + let proofs = + List.fold_left + (fun acc (e : _ Concrete.pointer) -> + let hash = Lazy.from_val e.pointer in + proof_of_concrete hash e.tree (fun proof -> + (e.index, proof) :: acc)) + [] (List.rev tr.pointers) + in + k (`Inode (tr.length, proofs)) + + let hash_values ~depth l = + let inode = values Truncated (StepMap.of_list l) in + let t = + match depth with 0 -> { inode with root = true } | _ -> inode + in + hash t + + let hash_inode ~depth ~length es = + let entries = Array.make Conf.entries None in + List.iter (fun (index, ptr) -> entries.(index) <- Some ptr) es; + let v : truncated_ptr v = Tree { depth; length; entries } in + Bin.V.hash (to_bin_v Truncated Bin.Ptr_any v) + + let rec concrete_of_proof : + type a. depth:int -> t -> (hash -> Concrete.t -> a) -> a = + fun ~depth proof k -> + match proof with + | `Blinded h -> k h Concrete.Blinded + | `Values vs -> + let vs = List.map strengthen_step_value vs in + assert (List.compare_length_with vs Conf.entries <= 0); + let hash = hash_values ~depth vs in + let c = Concrete.Values (List.map Concrete.to_entry vs) in + k hash c + | `Inode (length, proofs) -> concrete_of_inode ~length ~depth proofs k + + and concrete_of_inode : + type a. + length:int -> + depth:int -> + (int * t) list -> + (hash -> Concrete.t -> a) -> + a = + fun ~length ~depth proofs k -> + let rec aux ps es = function + | [] -> + let c = Concrete.Tree { depth; length; pointers = ps } in + let hash = hash_inode ~depth ~length es in + k hash c + | (index, proof) :: proofs -> + concrete_of_proof ~depth:(depth + 1) proof (fun pointer tree -> + let ps = { Concrete.tree; pointer; index } :: ps in + let h = Val_ref.of_hash (Lazy.from_val pointer) in + let es = (index, Broken h) :: es in + aux ps es proofs) + in + aux [] [] (List.rev proofs) + + let proof_of_concrete h p = proof_of_concrete h p Fun.id + let concrete_of_proof ~depth p = concrete_of_proof ~depth p (fun _ t -> t) + + let to_proof la t : t = + let p = + if is_stable t then + (* To preserve the stable hash, the proof needs to contain + all the underlying values. *) + let bindings = + seq la t + |> Seq.map Concrete.to_entry + |> List.of_seq + |> List.fast_sort (fun x y -> + compare_step x.Concrete.name y.Concrete.name) + in + Concrete.Values bindings + else to_concrete ~force:false la t + in + proof_of_concrete (Val_ref.to_lazy_hash t.v_ref) p + + let of_proof (Partial _ as la) ~depth (proof : t) = + match proof with + | `Values vs when List.compare_length_with vs Conf.entries > 0 -> ( + if depth <> 0 then None + else + (* [proof] is a big stable inode that was unshallowed and encoded + in a [Values], it needs to be converted back to a [Tree] + shallowed. *) + let t = + of_seq Total (List.map strengthen_step_value vs |> List.to_seq) + in + let hash = + (* Compute the hash right away (not lazily) so that + [hash_exn ~force:false] is possible on the result of + [of_proof]. *) + hash t + in + let v_ref = Val_ref.of_hash (Lazy.from_val hash) in + match t.v with + | Values _ -> assert false + | Tree { depth; length; entries } -> + let ptr_of_key = Ptr.of_key la in + let entries = + Array.map + (function + | None -> None + | Some ptr -> + let hash = + Ptr.val_ref Total ptr |> Val_ref.to_hash + in + (* Since [of_proof] is only called in the context of + Portable inodes, [unfindable_of_hash] is safe. *) + let key = Key.unfindable_of_hash hash in + Some (ptr_of_key key)) + entries + in + let v = Tree { depth; length; entries } in + let t = { v_ref; v; root = true } in + Some t) + | _ -> ( + let c = concrete_of_proof ~depth proof in + match of_concrete la ~depth c with + | Ok v -> Some v + | Error _ -> None) + + let of_concrete t = proof_of_concrete (lazy (failwith "blinded root")) t + let to_concrete = concrete_of_proof ~depth:0 + end + + module Snapshot = struct + include T + + type kinded_hash = Contents of hash * metadata | Node of hash + [@@deriving irmin] + + type entry = { step : string; hash : kinded_hash } [@@deriving irmin] + + type inode_tree = { + depth : int; + length : int; + pointers : (int * hash) list; + } + [@@deriving irmin] + + type v = Inode_tree of inode_tree | Inode_value of entry list + [@@deriving irmin] + + type inode = { v : v; root : bool } [@@deriving irmin] + end + + let of_entry ~index e : step * Node.value = + let step = + match T.step_of_bin_string e.Snapshot.step with + | Ok s -> s + | Error (`Msg m) -> Fmt.failwith "step of bin error: %s" m + in + ( step, + match e.hash with + | Snapshot.Contents (hash, m) -> + let key = index hash in + `Contents (key, m) + | Node hash -> + let key = index hash in + `Node key ) + + let of_inode_tree ~index layout tr = + let entries = Array.make Conf.entries None in + let ptr_of_key hash = + let key = index hash in + Ptr.of_key layout key + in + List.iter + (fun (index, pointer) -> entries.(index) <- Some (ptr_of_key pointer)) + tr.Snapshot.pointers; + { depth = tr.depth; length = tr.length; entries } + + let of_snapshot ~index layout (v : Snapshot.inode) = + let t = + match v.v with + | Inode_value vs -> + values layout (StepMap.of_list (List.map (of_entry ~index) vs)) + | Inode_tree tr -> tree layout (of_inode_tree ~index layout tr) + in + if v.root then stabilize_root layout t else t + end + + module Raw = struct + type hash = H.t [@@deriving irmin] + type key = Key.t + type t = T.key Bin.t [@@deriving irmin] + type metadata = T.metadata [@@deriving irmin] + + let depth = Bin.depth + + exception Invalid_depth of { expected : int; got : int; v : t } + + let kind (t : t) = + (* This is the kind of newly appended values, let's use v2 then *) + if t.root then Pack_value.Kind.Inode_v2_root + else Pack_value.Kind.Inode_v2_nonroot + + let weight _ = 1 + let hash t = Bin.hash t + let step_to_bin = T.step_to_bin_string + let step_of_bin = T.step_of_bin_string + let encode_compress = Irmin.Type.(unstage (encode_bin Compress.t)) + let decode_compress = Irmin.Type.(unstage (decode_bin Compress.t)) + + let length_header = function + | Pack_value.Kind.Contents -> + (* NOTE: the Node instantiation of the pack store must have access to + the header format used by contents values in order to eagerly + construct contents keys with length information during + [key_of_offset]. *) + Conf.contents_length_header + | k -> Pack_value.Kind.length_header_exn k + + let decode_compress_length = + match Irmin.Type.Size.of_encoding Compress.t with + | Unknown | Static _ -> assert false + | Dynamic f -> f + + let encode_bin : + dict:(string -> int option) -> + offset_of_key:(Key.t -> int63 option) -> + hash -> + t Irmin.Type.encode_bin = + fun ~dict ~offset_of_key hash t -> + Stats.incr_inode_encode_bin (); + let step s : Compress.name = + let str = step_to_bin s in + if String.length str <= 3 then Direct s + else match dict str with Some i -> Indirect i | None -> Direct s + in + let address_of_key key : Compress.address = + match offset_of_key key with + | Some off -> Compress.Offset off + | None -> + (* The key references an inode/contents that is not in the pack + file. This is highly unusual but not forbidden. *) + Compress.Hash (Key.to_hash key) + in + let ptr : T.key Bin.with_index -> Compress.ptr = + fun n -> + let hash = address_of_key n.vref in + { index = n.index; hash } + in + let value : T.step * T.value -> Compress.value = function + | s, `Contents (c, m) -> + let s = step s in + let v = address_of_key c in + Compress.Contents (s, v, m) + | s, `Node n -> + let s = step s in + let v = address_of_key n in + Compress.Node (s, v) + in + (* List.map is fine here as the number of entries is small *) + let v : T.key Bin.v -> Compress.v = function + | Values vs -> Values (List.map value vs) + | Tree { depth; length; entries } -> + let entries = List.map ptr entries in + Tree { Compress.depth; length; entries } + in + let t = Compress.v ~root:t.root ~hash (v t.v) in + encode_compress t + + exception Exit of [ `Msg of string ] + + let decode_bin : + dict:(int -> string option) -> + key_of_offset:(int63 -> key) -> + key_of_hash:(hash -> key) -> + t Irmin.Type.decode_bin = + fun ~dict ~key_of_offset ~key_of_hash t pos_ref -> + Stats.incr_inode_decode_bin (); + let i = decode_compress t pos_ref in + let step : Compress.name -> T.step = function + | Direct n -> n + | Indirect s -> ( + match dict s with + | None -> raise_notrace (Exit (`Msg "dict")) + | Some s -> ( + match step_of_bin s with + | Error e -> raise_notrace (Exit e) + | Ok v -> v)) + in + let key : Compress.address -> T.key = function + | Offset off -> key_of_offset off + | Hash n -> key_of_hash n + in + let ptr : Compress.ptr -> T.key Bin.with_index = + fun n -> + let vref = key n.hash in + { index = n.index; vref } + in + let value : Compress.value -> T.step * T.value = function + | Contents (n, h, metadata) -> + let name = step n in + let hash = key h in + (name, `Contents (hash, metadata)) + | Node (n, h) -> + let name = step n in + let hash = key h in + (name, `Node hash) + in + let t : Compress.tagged_v -> T.key Bin.v = + fun tv -> + let v = + match tv with + | V0_stable v -> v + | V0_unstable v -> v + | V1_root { v; _ } -> v + | V1_nonroot { v; _ } -> v + in + match v with + | Values vs -> Values (List.rev_map value (List.rev vs)) + | Tree { depth; length; entries } -> + let entries = List.map ptr entries in + Tree { depth; length; entries } + in + let root = Compress.is_root i in + let v = t i.tv in + Bin.v ~root ~hash:(Lazy.from_val i.hash) v + + let decode_bin_length = decode_compress_length + + let decode_children_offsets ~entry_of_offset ~entry_of_hash t pos_ref = + let i = decode_compress t pos_ref in + let { Compress.tv; _ } = i in + let v = + match tv with + | V0_stable v | V0_unstable v -> v + | V1_root { v; _ } | V1_nonroot { v; _ } -> v + in + let entry_of_address = function + | Compress.Offset offset -> entry_of_offset offset + | Hash h -> entry_of_hash h + in + match v with + | Values ls -> + List.map + (function + | Compress.Contents (_, address, _) | Node (_, address) -> + entry_of_address address) + ls + | Tree { entries; _ } -> + List.map + (function ({ hash; _ } : Compress.ptr) -> entry_of_address hash) + entries + + module Snapshot = Val_impl.Snapshot + + let to_entry : T.step * Node.value -> Snapshot.entry = + fun (name, v) -> + let step = step_to_bin name in + match v with + | `Contents (contents_key, m) -> + let h = Key.to_hash contents_key in + { Snapshot.step; hash = Contents (h, m) } + | `Node node_key -> + let h = Key.to_hash node_key in + { step; hash = Node h } + + (* The implementation of [of_snapshot] is in the module [Val]. This is + because we cannot compute the hash of a root from [Bin]. *) + let to_snapshot : t -> Snapshot.inode = + fun t -> + match t.v with + | Bin.Tree tree -> + let inode_tree = + { + Snapshot.depth = tree.depth; + length = tree.length; + pointers = + List.map + (fun { Bin.index; vref } -> + let hash = Key.to_hash vref in + (index, hash)) + tree.entries; + } + in + { v = Inode_tree inode_tree; root = t.root } + | Values vs -> + let vs = List.map to_entry vs in + let v = Snapshot.Inode_value vs in + { v; root = t.root } + end + + module Snapshot = Val_impl.Snapshot + + let to_snapshot = Raw.to_snapshot + + type hash = T.hash + type key = Key.t + + let pp_hash = T.pp_hash + + module Val_portable = struct + include T + module I = Val_impl + + type t = + | Total of I.total_ptr I.t + | Partial of I.partial_ptr I.layout * I.partial_ptr I.t + | Truncated of I.truncated_ptr I.t + + type 'b apply_fn = { f : 'a. 'a I.layout -> 'a I.t -> 'b } [@@unboxed] + + let apply : t -> 'b apply_fn -> 'b = + fun t f -> + match t with + | Total v -> f.f I.Total v + | Partial (layout, v) -> f.f layout v + | Truncated v -> f.f I.Truncated v + + type map_fn = { f : 'a. 'a I.layout -> 'a I.t -> 'a I.t } [@@unboxed] + + let map : t -> map_fn -> t = + fun t f -> + match t with + | Total v -> + let v' = f.f I.Total v in + if v == v' then t else Total v' + | Partial (layout, v) -> + let v' = f.f layout v in + if v == v' then t else Partial (layout, v') + | Truncated v -> + let v' = f.f I.Truncated v in + if v == v' then t else Truncated v' + + let pred t = apply t { f = (fun layout v -> I.pred layout v) } + + let of_seq l = + Stats.incr_inode_of_seq (); + Total (I.of_seq Total l) + + let of_list l = of_seq (List.to_seq l) + + let seq ?offset ?length ?cache t = + apply t { f = (fun layout v -> I.seq layout ?offset ?length ?cache v) } + + let list ?offset ?length ?cache t = + apply t { f = (fun layout v -> I.list layout ?offset ?length ?cache v) } + + let empty () = of_list [] + let is_empty t = apply t { f = (fun _ v -> I.is_empty v) } + + let find ?cache t s = + apply t { f = (fun layout v -> I.find ?cache layout v s) } + + let add t s value = + Stats.incr_inode_add (); + let f layout v = + I.check_write_op_supported v; + I.add ~copy:true layout v s value + in + map t { f } + + let remove t s = + Stats.incr_inode_remove (); + let f layout v = + I.check_write_op_supported v; + I.remove layout v s + in + map t { f } + + let t : t Irmin.Type.t = + let pre_hash_binv = Irmin.Type.(unstage (pre_hash (Bin.v_t Val_ref.t))) in + let pre_hash_node = Irmin.Type.(unstage (pre_hash Node.t)) in + let pre_hash x = + let stable = apply x { f = (fun _ v -> I.is_stable v) } in + if not stable then + let bin = + apply x { f = (fun layout v -> I.to_bin layout Bin.Ptr_any v) } + in + pre_hash_binv bin.v + else + let vs = + (* If [x] is shallow, this [seq] call will perform IOs. *) + seq x + in + pre_hash_node (Node.of_seq vs) + in + let module Ptr_any = struct + let t = + Irmin.Type.map (Bin.t Val_ref.t) + (fun _ -> assert false) + (fun x -> + apply x { f = (fun layout v -> I.to_bin layout Bin.Ptr_any v) }) + + type nonrec t = t [@@deriving irmin ~equal ~compare ~pp] + + (* TODO(repr): add these to [ppx_repr] meta-deriving *) + (* TODO(repr): why is there no easy way to get a decoder value to pass to [map ~json]? *) + let encode_json = Irmin.Type.encode_json t + let decode_json _ = failwith "TODO" + end in + Irmin.Type.map ~pre_hash ~pp:Ptr_any.pp + ~json:(Ptr_any.encode_json, Ptr_any.decode_json) + ~equal:Ptr_any.equal ~compare:Ptr_any.compare (Bin.t T.key_t) + (fun bin -> Truncated (I.of_bin I.Truncated bin)) + (fun x -> + apply x { f = (fun layout v -> I.to_bin layout Bin.Ptr_key v) }) + + let hash_exn ?force t = apply t { f = (fun _ v -> I.hash_exn ?force v) } + + let save ?(allow_non_root = false) ~add ~index ~mem t = + if Conf.forbid_empty_dir_persistence && is_empty t then + failwith + "Persisting an empty node is forbidden by the configuration of the \ + irmin-pack store"; + let f layout v = + if not allow_non_root then I.check_write_op_supported v; + I.save layout ~add ~index ~mem v + in + apply t { f } + + let of_raw (find' : expected_depth:int -> key -> key Bin.t option) v = + Stats.incr_inode_of_raw (); + let rec find ~expected_depth h = + Option.map (I.of_bin layout) (find' ~expected_depth h) + and layout = I.Partial find in + Partial (layout, I.of_bin layout v) + + let recompute_hash t = + apply t { f = (fun layout v -> I.recompute_hash layout v) } + + let to_raw t = + apply t { f = (fun layout v -> I.to_bin layout Bin.Ptr_key v) } + + let stable t = apply t { f = (fun _ v -> I.is_stable v) } + let length t = apply t { f = (fun _ v -> I.length v) } + let clear t = apply t { f = (fun layout v -> I.clear layout v) } + let nb_children t = apply t { f = (fun _ v -> I.nb_children v) } + let index ~depth s = I.index ~depth (Child_ordering.key s) + + let integrity_check t = + let f layout v = + let check_stable () = + let check () = I.check_stable layout v in + let n = length t in + if n > Conf.stable_hash then (not (stable t)) && check () + else stable t && check () + in + let contains_empty_map_non_root () = + let check () = I.contains_empty_map layout v in + (* we are only looking for empty maps that are not at the root *) + if I.is_tree v then check () else false + in + check_stable () && not (contains_empty_map_non_root ()) + in + apply t { f } + + let merge ~contents ~node : t Irmin.Merge.t = + let merge = Node.merge ~contents ~node in + let to_node t = of_seq (Node.seq t) in + let of_node n = Node.of_seq (seq n) in + Irmin.Merge.like t merge of_node to_node + + let with_handler f_env t = + match t with + | Total _ -> t + | Truncated _ -> t + | Partial ((I.Partial find as la), v) -> + (* [f_env] works on [Val.t] while [find] in [Partial find] works on + [Val_impl.t], hence the following wrapping (before applying + [f_env]) and unwrapping (after [f_env]). *) + let find_v ~expected_depth h = + match find ~expected_depth h with + | None -> None + | Some v -> Some (Partial (la, v)) + in + let find = f_env find_v in + let find_ptr ~expected_depth h = + match find ~expected_depth h with + | Some (Partial (_, v)) -> Some v + | _ -> None + in + let la = I.Partial find_ptr in + Partial (la, v) + + let head t = + let f la (v : _ I.t) = + if Val_impl.is_stable v then + (* To preserve the stable hash, the proof needs to contain + all the underlying values. *) + let elts = + I.seq la v + |> List.of_seq + |> List.fast_sort (fun (x, _) (y, _) -> compare_step x y) + in + `Node elts + else + match v.v with + | I.Values n -> `Node (List.of_seq (StepMap.to_seq n)) + | I.Tree v -> + let entries = ref [] in + for i = Array.length v.entries - 1 downto 0 do + match v.entries.(i) with + | None -> () + | Some ptr -> + let h = I.Ptr.val_ref la ptr |> Val_ref.to_hash in + entries := (i, h) :: !entries + done; + `Inode (v.length, !entries) + in + apply t { f } + end + + module Val = struct + include Val_portable + + module Portable = struct + include Val_portable + + type node_key = hash [@@deriving irmin] + type contents_key = hash [@@deriving irmin] + + type value = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin] + + let of_node t = t + + let of_list bindings = + bindings + |> List.map (fun (k, v) -> (k, unsafe_keyvalue_of_hashvalue v)) + |> of_list + + let of_seq bindings = + bindings + |> Seq.map (fun (k, v) -> (k, unsafe_keyvalue_of_hashvalue v)) + |> of_seq + + let seq ?offset ?length ?cache t = + seq ?offset ?length ?cache t + |> Seq.map (fun (k, v) -> (k, hashvalue_of_keyvalue v)) + + let add : t -> step -> value -> t = + fun t s v -> add t s (unsafe_keyvalue_of_hashvalue v) + + let list ?offset ?length ?cache t = + list ?offset ?length ?cache t + |> List.map (fun (s, v) -> (s, hashvalue_of_keyvalue v)) + + let find ?cache t s = find ?cache t s |> Option.map hashvalue_of_keyvalue + + let merge = + let promote_merge : + hash option Irmin.Merge.t -> key option Irmin.Merge.t = + fun t -> + Irmin.Merge.like [%typ: key option] t (Option.map Key.to_hash) + (Option.map Key.unfindable_of_hash) + in + fun ~contents ~node -> + merge ~contents:(promote_merge contents) ~node:(promote_merge node) + + module Proof = I.Proof + + type proof = I.Proof.t [@@deriving irmin] + + let to_proof (t : t) : proof = + apply t { f = (fun la v -> I.Proof.to_proof la v) } + + let of_proof ~depth (p : proof) = + let find ~expected_depth:_ k = + raise_dangling_hash "of_proof@find" (Key.to_hash k) + in + (* A [Partial] should be built instead of a [Truncated] because we need a + [find] function that will be hooked by the proof env and that will + raise the above exception in case of miss in the env. *) + let la = I.Partial find in + Option.map (fun v -> Partial (la, v)) (I.Proof.of_proof la ~depth p) + + type 'a find = expected_depth:int -> 'a -> t option + + let with_handler : (hash find -> hash find) -> t -> t = + let to_hash : key find -> hash find = + fun find ~expected_depth h -> + find ~expected_depth (Key.unfindable_of_hash h) + in + let to_key : hash find -> key find = + fun find ~expected_depth k -> find ~expected_depth (Key.to_hash k) + in + fun f_env t -> + with_handler (fun find -> find |> to_hash |> f_env |> to_key) t + + let head t = + match head t with + | `Inode _ as x -> x + | `Node l -> `Node (List.map Proof.weaken_step_value l) + end + + let to_concrete t = + apply t { f = (fun la v -> I.to_concrete ~force:true la v) } + + let of_concrete t = + match I.of_concrete Truncated ~depth:0 t with + | Ok t -> Ok (Truncated t) + | Error _ as e -> e + + module Snapshot = I.Snapshot + module Concrete = I.Concrete + + let of_snapshot t ~index find' = + let rec find ~expected_depth h = + match find' ~expected_depth h with + | None -> None + | Some v -> Some (I.of_bin layout v) + and layout = I.Partial find in + Partial (layout, I.of_snapshot layout t ~index) + end +end + +module Make + (H : Irmin.Hash.S) + (Key : Irmin.Key.S with type hash = H.t) + (Node : Irmin.Node.Generic_key.S + with type hash = H.t + and type contents_key = Key.t + and type node_key = Key.t) + (Inter : Internal + with type hash = H.t + and type key = Key.t + and type Snapshot.metadata = Node.metadata + and type Val.step = Node.step) + (Pack : Indexable.S + with type hash = H.t + and type key = Key.t + and type value = Inter.Raw.t) = +struct + module Hash = H + module Key = Key + module Val = Inter.Val + + type 'a t = 'a Pack.t + type key = Key.t [@@deriving irmin ~equal] + type hash = Hash.t + type value = Inter.Val.t + + let mem t k = Pack.mem t k + let index t k = Pack.index t k + + exception Invalid_depth = Inter.Raw.Invalid_depth + + let pp_value = Irmin.Type.pp Inter.Raw.t + + let pp_invalid_depth ppf (expected, got, v) = + Fmt.pf ppf "Invalid depth: got %d, expecting %d (%a)" got expected pp_value + v + + let check_depth_opt ~expected_depth:expected = function + | None -> () + | Some v -> ( + match Inter.Raw.depth v with + | None -> () + | Some got -> + if got <> expected then raise (Invalid_depth { expected; got; v })) + + let unsafe_find ~check_integrity t k = + match Pack.unsafe_find ~check_integrity t k with + | None -> None + | Some v -> + let find ~expected_depth k = + let v = Pack.unsafe_find ~check_integrity t k in + check_depth_opt ~expected_depth v; + v + in + let v = Val.of_raw find v in + Some v + + let find t k = unsafe_find ~check_integrity:true t k |> Lwt.return + + let save ?allow_non_root t v = + let add k v = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false t k v + in + Val.save ?allow_non_root ~add ~index:(Pack.index_direct t) + ~mem:(Pack.unsafe_mem t) v + + let hash_exn = Val.hash_exn + let add t v = Lwt.return (save t v) + let equal_hash = Irmin.Type.(unstage (equal H.t)) + + let check_hash expected got = + if equal_hash expected got then () + else + Fmt.invalid_arg "corrupted value: got %a, expecting %a" Inter.pp_hash + expected Inter.pp_hash got + + let unsafe_add t k v = + check_hash k (hash_exn v); + Lwt.return (save t v) + + let batch = Pack.batch + let close = Pack.close + let decode_bin_length = Inter.Raw.decode_bin_length + + let protect_from_invalid_depth_exn f = + Lwt.catch f (function + | Invalid_depth { expected; got; v } -> + let msg = Fmt.to_to_string pp_invalid_depth (expected, got, v) in + Lwt.return (Error msg) + | e -> Lwt.fail e) + + let integrity_check_inodes t k = + protect_from_invalid_depth_exn @@ fun () -> + find t k >|= function + | None -> + (* we are traversing the node graph, should find all values *) + assert false + | Some v -> + if Inter.Val.integrity_check v then Ok () + else + let msg = + Fmt.str "Problematic inode %a" (Irmin.Type.pp Inter.Val.t) v + in + Error msg +end diff --git a/vendors/irmin/src/irmin-pack/inode.mli b/vendors/irmin/src/irmin-pack/inode.mli new file mode 100644 index 000000000000..ec0d06308542 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/inode.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Inode_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/inode_intf.ml b/vendors/irmin/src/irmin-pack/inode_intf.ml new file mode 100644 index 000000000000..cfe0917d9703 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/inode_intf.ml @@ -0,0 +1,297 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type Child_ordering = sig + type step + type key + + val key : step -> key + val index : depth:int -> key -> int +end + +module type Snapshot = sig + type hash + type metadata + + type kinded_hash = Contents of hash * metadata | Node of hash + [@@deriving irmin] + + type entry = { step : string; hash : kinded_hash } [@@deriving irmin] + + type inode_tree = { depth : int; length : int; pointers : (int * hash) list } + [@@deriving irmin] + + type v = Inode_tree of inode_tree | Inode_value of entry list + [@@deriving irmin] + + type inode = { v : v; root : bool } [@@deriving irmin] +end + +module type Value = sig + type key + + include + Irmin.Node.Generic_key.S + with type node_key = key + and type contents_key = key + + val pred : + t -> + (step option + * [ `Node of node_key | `Inode of node_key | `Contents of contents_key ]) + list + + module Portable : + Irmin.Node.Portable.S + with type node := t + and type hash = hash + and type step := step + and type metadata := metadata + + val nb_children : t -> int + + val recompute_hash : t -> hash + (** Recompute hash for inodes, used in eager integrity checks.*) +end + +module type Raw = sig + include Pack_value.S + + val depth : t -> int option + + exception Invalid_depth of { expected : int; got : int; v : t } + + val decode_children_offsets : + entry_of_offset:(int63 -> 'a) -> + entry_of_hash:(hash -> 'a) -> + string -> + int ref -> + 'a list +end + +module type S = sig + include Irmin.Indexable.S + module Hash : Irmin.Hash.S with type t = hash + + val unsafe_find : check_integrity:bool -> [< read ] t -> key -> value option + + module Val : + Value + with type t = value + and type key = key + and type hash = Hash.t + and type Portable.hash := hash + + val decode_bin_length : string -> int -> int + val integrity_check_inodes : [ `Read ] t -> key -> (unit, string) result Lwt.t + val save : ?allow_non_root:bool -> 'a t -> value -> key +end + +module type Compress = sig + type step + type hash + type metadata + type dict_key = int + type pack_offset = int63 + type name = Indirect of dict_key | Direct of step + type address = Offset of pack_offset | Hash of hash + type ptr = { index : dict_key; hash : address } + type tree = { depth : dict_key; length : dict_key; entries : ptr list } + type value = Contents of name * address * metadata | Node of name * address + type v = Values of value list | Tree of tree + type v1 = { mutable length : int; v : v } + + type tagged_v = + | V0_stable of v + | V0_unstable of v + | V1_root of v1 + | V1_nonroot of v1 + + type t = { hash : hash; tv : tagged_v } [@@deriving irmin] +end + +(** Unstable internal API agnostic about the underlying storage. Use it only to + implement or test inodes. *) +module type Internal = sig + type hash + type key + + val pp_hash : hash Fmt.t + + module Snapshot : Snapshot with type hash = hash + module Raw : Raw with type hash = hash and type key = key + + module Val : sig + include + Value + with type hash = hash + and type key = key + and type metadata = Snapshot.metadata + + val of_raw : (expected_depth:int -> key -> Raw.t option) -> Raw.t -> t + val to_raw : t -> Raw.t + + val save : + ?allow_non_root:bool -> + add:(hash -> Raw.t -> key) -> + index:(hash -> key option) -> + mem:(key -> bool) -> + t -> + key + + val stable : t -> bool + val length : t -> int + val index : depth:int -> step -> int + + val integrity_check : t -> bool + (** Checks the integrity of an inode. *) + + module Concrete : sig + (** {1 Concrete trees} *) + + (** The type for pointer kinds. *) + type kinded_key = + | Contents of contents_key + | Contents_x of metadata * contents_key + | Node of node_key + [@@deriving irmin] + + type entry = { name : step; key : kinded_key } [@@deriving irmin] + (** The type of entries. *) + + type 'a pointer = { index : int; pointer : hash; tree : 'a } + [@@deriving irmin] + (** The type for internal pointers between concrete {!tree}s. *) + + type 'a tree = { depth : int; length : int; pointers : 'a pointer list } + [@@deriving irmin] + (** The type for trees. *) + + (** The type for concrete trees. *) + type t = Tree of t tree | Values of entry list | Blinded + [@@deriving irmin] + + type len := [ `Eq of int | `Ge of int ] + + type error = + [ `Invalid_hash of hash * hash * t + | `Invalid_depth of int * int * t + | `Invalid_length of len * int * t + | `Duplicated_entries of t + | `Duplicated_pointers of t + | `Unsorted_entries of t + | `Unsorted_pointers of t + | `Blinded_root + | `Too_large_values of t + | `Empty ] + [@@deriving irmin] + (** The type for errors. *) + + val pp_error : error Fmt.t + (** [pp_error] is the pretty-printer for errors. *) + end + + val to_concrete : t -> Concrete.t + (** [to_concrete t] is the concrete inode tree equivalent to [t]. *) + + val of_concrete : Concrete.t -> (t, Concrete.error) result + (** [of_concrete c] is [Ok t] iff [c] and [t] are equivalent. + + The result is [Error e] when a subtree tree of [c] has an integrity + error. *) + + module Portable : sig + (* Extend to the portable signature *) + include module type of Portable + + module Proof : sig + val of_concrete : Concrete.t -> proof + + val to_concrete : proof -> Concrete.t + (** This function produces unfindable keys. Only use in tests *) + end + end + + val of_snapshot : + Snapshot.inode -> + index:(hash -> key) -> + (expected_depth:int -> key -> Raw.t option) -> + t + end + + val to_snapshot : Raw.t -> Snapshot.inode + + module Compress : + Compress + with type hash := hash + and type step := Val.step + and type metadata := Val.metadata + + module Child_ordering : Child_ordering with type step := Val.step +end + +module type Sigs = sig + module type S = S + module type Internal = Internal + module type Child_ordering = Child_ordering + module type Raw = Raw + module type Snapshot = Snapshot + + exception Max_depth of int + + module Make_internal + (Conf : Conf.S) + (H : Irmin.Hash.S) (Key : sig + include Irmin.Key.S with type hash = H.t + + val unfindable_of_hash : hash -> t + end) + (Node : Irmin.Node.Generic_key.S + with type hash = H.t + and type contents_key = Key.t + and type node_key = Key.t) : + Internal + with type hash = H.t + and type key = Key.t + and type Snapshot.metadata = Node.metadata + and type Val.step = Node.step + + module Make + (H : Irmin.Hash.S) + (Key : Irmin.Key.S with type hash = H.t) + (Node : Irmin.Node.Generic_key.S + with type hash = H.t + and type contents_key = Key.t + and type node_key = Key.t) + (Inter : Internal + with type hash = H.t + and type key = Key.t + and type Snapshot.metadata = Node.metadata + and type Val.step = Node.step) + (Pack : Indexable.S + with type key = Key.t + and type hash = H.t + and type value = Inter.Raw.t) : + S + with type 'a t = 'a Pack.t + and type key = Key.t + and type hash = H.t + and type Val.metadata = Node.metadata + and type Val.step = Node.step + and type value = Inter.Val.t +end diff --git a/vendors/irmin/src/irmin-pack/irmin_pack.ml b/vendors/irmin/src/irmin-pack/irmin_pack.ml new file mode 100644 index 000000000000..59dde7fda74e --- /dev/null +++ b/vendors/irmin/src/irmin-pack/irmin_pack.ml @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin_pack_intf + +let config = Conf.init + +module Indexing_strategy = Indexing_strategy +module Indexable = Indexable +module Atomic_write = Atomic_write +module Hash = Irmin.Hash.BLAKE2B +module Path = Irmin.Path.String_list +module Metadata = Irmin.Metadata.None +module Version = Version +module Conf = Conf +module Stats = Stats +module Layout = Layout +module Inode = Inode +module Pack_key = Pack_key +module Pack_value = Pack_value diff --git a/vendors/irmin/src/irmin-pack/irmin_pack.mli b/vendors/irmin/src/irmin-pack/irmin_pack.mli new file mode 100644 index 000000000000..621f0967c91a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/irmin_pack.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin_pack_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/irmin_pack_intf.ml b/vendors/irmin/src/irmin-pack/irmin_pack_intf.ml new file mode 100644 index 000000000000..cb58765aeafb --- /dev/null +++ b/vendors/irmin/src/irmin-pack/irmin_pack_intf.ml @@ -0,0 +1,121 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +exception RO_not_allowed + +module type Checkable = sig + type 'a t + type hash + + val integrity_check : + offset:int63 -> + length:int -> + hash -> + _ t -> + (unit, [ `Wrong_hash | `Absent_value ]) result +end + +module type S = Irmin.Generic_key.S + +module S_is_a_store (X : S) : Irmin.Generic_key.S = X + +module type Maker = sig + type endpoint = unit + + include Irmin.Key.Store_spec.S + + module Make (Schema : Irmin.Schema.Extended) : + S + (* We can't have `with module Schema = Schema` here, since the Schema + on the RHS contains more information than the one on the LHS. We _want_ + to do something like `with module Schema = (Schema : Irmin.Schema.S)`, + but this isn't supported. + + TODO: extract these extensions as a separate functor argument instead. *) + with type Schema.Hash.t = Schema.Hash.t + and type Schema.Branch.t = Schema.Branch.t + and type Schema.Metadata.t = Schema.Metadata.t + and type Schema.Path.t = Schema.Path.t + and type Schema.Path.step = Schema.Path.step + and type Schema.Contents.t = Schema.Contents.t + and type Schema.Info.t = Schema.Info.t + and type contents_key = (Schema.Hash.t, Schema.Contents.t) contents_key + and type node_key = Schema.Hash.t node_key + and type commit_key = Schema.Hash.t commit_key + and type Backend.Remote.endpoint = endpoint +end + +module type Sigs = sig + (** A space-optimiezed, on-disk store inspired by + {{:https://git-scm.com/book/en/v2/Git-Internals-Packfiles} Git Packfiles}. *) + + (** {1 Configuration} *) + + module Indexing_strategy = Indexing_strategy + module Conf = Conf + + val config : + ?fresh:bool -> + ?readonly:bool -> + ?lru_size:int -> + ?index_log_size:int -> + ?merge_throttle:Conf.merge_throttle -> + ?indexing_strategy:Indexing_strategy.t -> + ?use_fsync:bool -> + ?dict_auto_flush_threshold:int -> + ?suffix_auto_flush_threshold:int -> + ?no_migrate:bool -> + ?lower_root:string option -> + string -> + Irmin.config + (** Configuration options for stores. See {!Irmin_pack.Conf} for more details. *) + + (** {1 Inode} *) + + module Inode = Inode + + (** {1 Keys and Values} *) + + module Pack_key = Pack_key + module Pack_value = Pack_value + + (** {1 Store} *) + + exception RO_not_allowed + + module type S = S + module type Maker = Maker + + (** {1 Integrity Check} *) + + module type Checkable = Checkable + + (** {1 Metrics} *) + + module Stats = Stats + + (** {1 Low-level Stores} *) + + module Indexable = Indexable + module Atomic_write = Atomic_write + + (** {1 On-disk format} *) + + module Layout = Layout + module Version = Version +end diff --git a/vendors/irmin/src/irmin-pack/layout.ml b/vendors/irmin/src/irmin-pack/layout.ml new file mode 100644 index 000000000000..e96d49fe6291 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/layout.ml @@ -0,0 +1,153 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let toplevel name ~root = Filename.(concat root name) + +module V1_and_v2 = struct + let pack = toplevel "store.pack" + let branch = toplevel "store.branches" + let dict = toplevel "store.dict" + let all ~root = [ pack ~root; branch ~root; dict ~root ] +end + +module V3 = struct + let branch = toplevel "store.branches" + let dict = toplevel "store.dict" + let control = toplevel "store.control" + + let suffix ~generation = + toplevel ("store." ^ string_of_int generation ^ ".suffix") + + let gc_result ~generation = + toplevel ("store." ^ string_of_int generation ^ ".out") + + let reachable ~generation = + toplevel ("store." ^ string_of_int generation ^ ".reachable") + + let sorted ~generation = + toplevel ("store." ^ string_of_int generation ^ ".sorted") + + let mapping ~generation = + toplevel ("store." ^ string_of_int generation ^ ".mapping") + + let prefix ~generation = + toplevel ("store." ^ string_of_int generation ^ ".prefix") + + let all ~generation ~root = + [ suffix ~generation ~root; branch ~root; dict ~root; control ~root ] +end + +module V4 = struct + let branch = toplevel "store.branches" + let dict = toplevel "store.dict" + let control = toplevel "store.control" + let control_tmp = toplevel "store.control.tmp" + + let suffix_chunk ~chunk_idx = + toplevel ("store." ^ string_of_int chunk_idx ^ ".suffix") + + let gc_result ~generation = + toplevel ("store." ^ string_of_int generation ^ ".out") + + let reachable ~generation = + toplevel ("store." ^ string_of_int generation ^ ".reachable") + + let sorted ~generation = + toplevel ("store." ^ string_of_int generation ^ ".sorted") + + let mapping ~generation = + toplevel ("store." ^ string_of_int generation ^ ".mapping") + + let prefix ~generation = + toplevel ("store." ^ string_of_int generation ^ ".prefix") +end + +module V5 = struct + include V4 + + module Volume = struct + let directory ~idx = toplevel ("volume." ^ string_of_int idx) + let control = toplevel "volume.control" + + let control_gc_tmp ~generation = + toplevel ("volume." ^ string_of_int generation ^ ".control") + + let mapping = toplevel "volume.mapping" + let data = toplevel "volume.data" + end +end + +(** [is_number] is a less generic than [Stdlib.int_of_string_opt]. It matches + this equivalent regex: {v "([1-9][0-9]*|0)" v}. *) +let is_number s = + match String.to_seq s |> List.of_seq with + | [] -> false + | '0' :: _ :: _ -> false + | l -> + List.fold_left + (fun acc char -> + let is_digit = match char with '0' .. '9' -> true | _ -> false in + acc && is_digit) + true l + +module Classification = struct + module Upper = struct + type t = + [ `Branch + | `Control + | `Control_tmp + | `Dict + | `Gc_result of int + | `Mapping of int + | `Prefix of int + | `Reachable of int + | `Sorted of int + | `Suffix of int + | `V1_or_v2_pack + | `Unknown ] + [@@deriving irmin] + + let v s : t = + match String.split_on_char '.' s with + | [ "store"; "pack" ] -> `V1_or_v2_pack + | [ "store"; "branches" ] -> `Branch + | [ "store"; "control" ] -> `Control + | [ "store"; "control"; "tmp" ] -> `Control_tmp + | [ "store"; "dict" ] -> `Dict + | [ "store"; g; "out" ] when is_number g -> `Gc_result (int_of_string g) + | [ "store"; g; "reachable" ] when is_number g -> + `Reachable (int_of_string g) + | [ "store"; g; "sorted" ] when is_number g -> `Sorted (int_of_string g) + | [ "store"; g; "mapping" ] when is_number g -> `Mapping (int_of_string g) + | [ "store"; g; "prefix" ] when is_number g -> `Prefix (int_of_string g) + | [ "store"; g; "suffix" ] when is_number g -> `Suffix (int_of_string g) + | _ -> `Unknown + end + + module Volume = struct + type t = [ `Mapping | `Data | `Control | `Control_tmp of int | `Unknown ] + [@@deriving irmin] + + let v s : t = + match String.split_on_char '.' s with + | [ "volume"; "control" ] -> `Control + | [ "volume"; g; "control" ] when is_number g -> + `Control_tmp (int_of_string g) + | [ "volume"; "mapping" ] -> `Mapping + | [ "volume"; "data" ] -> `Data + | _ -> `Unknown + end +end diff --git a/vendors/irmin/src/irmin-pack/mem/dune b/vendors/irmin/src/irmin-pack/mem/dune new file mode 100644 index 000000000000..98d920991491 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/mem/dune @@ -0,0 +1,8 @@ +(library + (public_name irmin-pack.mem) + (name irmin_pack_mem) + (libraries irmin-pack irmin.mem) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-pack/mem/import.ml b/vendors/irmin/src/irmin-pack/mem/import.ml new file mode 100644 index 000000000000..d4aa41686a2e --- /dev/null +++ b/vendors/irmin/src/irmin-pack/mem/import.ml @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends +module Int63 = Optint.Int63 + +let src = Logs.Src.create "irmin-pack.mem" ~doc:"irmin-pack mem backend" + +module Log = (val Logs.src_log src : Logs.LOG) + +type int63 = Int63.t diff --git a/vendors/irmin/src/irmin-pack/mem/indexable.ml b/vendors/irmin/src/irmin-pack/mem/indexable.ml new file mode 100644 index 000000000000..840e5e82686c --- /dev/null +++ b/vendors/irmin/src/irmin-pack/mem/indexable.ml @@ -0,0 +1,135 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Pool : sig + type ('k, 'v) t + (** Reference-counted pool of values with corresponding keys. *) + + val create : alloc:('k -> 'v) -> ('k, 'v) t + (** Get an empty pool, given a function for allocating new instances from IDs. *) + + val take : ('k, 'v) t -> 'k -> 'v + (** Get an instance from the pool by its key, allocating it if necessary. *) + + val drop : ('k, 'v) t -> 'k -> unit + (** Reduce the reference count of an element, discarding it if the reference + count drops to 0. *) +end = struct + type 'v elt = { mutable refcount : int; instance : 'v } + type ('k, 'v) t = { instances : ('k, 'v elt) Hashtbl.t; alloc : 'k -> 'v } + + let create ~alloc = { instances = Hashtbl.create 0; alloc } + + let take t k = + match Hashtbl.find_opt t.instances k with + | Some elt -> + elt.refcount <- succ elt.refcount; + elt.instance + | None -> + let instance = t.alloc k in + Hashtbl.add t.instances k { instance; refcount = 1 }; + instance + + let drop t k = + match Hashtbl.find_opt t.instances k with + | None -> failwith "Pool.drop: double free" + | Some { refcount; _ } when refcount <= 0 -> assert false + | Some { refcount = 1; _ } -> Hashtbl.remove t.instances k + | Some elt -> elt.refcount <- pred elt.refcount +end + +module Maker (K : Irmin.Hash.S) = struct + type key = K.t + + module Make + (Val : Irmin_pack.Pack_value.S with type hash := K.t and type key := K.t) = + struct + (* TODO(craigfe): We could use the keys to skip traversal of the map on + lookup. This wasn't done originally due to complications with implementing + the [clear] function, but this has since been removed. (See #1794.) *) + module Key = Irmin.Key.Of_hash (K) + + module KMap = Map.Make (struct + type t = K.t + + let compare = Irmin.Type.(unstage (compare K.t)) + end) + + type hash = K.t + type key = Key.t + type value = Val.t + type 'a t = { name : string; mutable t : value KMap.t } + + let index_direct _ h = Some h + let index t h = Lwt.return (index_direct t h) + let instances = Pool.create ~alloc:(fun name -> { name; t = KMap.empty }) + let v name = Lwt.return (Pool.take instances name) + let equal_key = Irmin.Type.(unstage (equal K.t)) + + let close t = + [%log.debug "close"]; + Pool.drop instances t.name; + Lwt.return_unit + + let cast t = (t :> read_write t) + let batch t f = f (cast t) + let pp_hash = Irmin.Type.pp K.t + + let check_key k v = + let k' = Val.hash v in + if equal_key k k' then Ok () else Error (k, k') + + let find t k = + try + let v = KMap.find k t.t in + check_key k v |> Result.map (fun () -> Some v) + with Not_found -> Ok None + + let unsafe_find ~check_integrity:_ t k = + [%log.debug "unsafe find %a" pp_hash k]; + find t k |> function + | Ok r -> r + | Error (k, k') -> + Fmt.invalid_arg "corrupted value: got %a, expecting %a" pp_hash k' + pp_hash k + + let find t k = + [%log.debug "find %a" pp_hash k]; + find t k |> function + | Ok r -> Lwt.return r + | Error (k, k') -> + Fmt.kstr Lwt.fail_invalid_arg "corrupted value: got %a, expecting %a" + pp_hash k' pp_hash k + + let unsafe_mem t k = + [%log.debug "mem %a" pp_hash k]; + KMap.mem k t.t + + let mem t k = Lwt.return (unsafe_mem t k) + + let unsafe_append ~ensure_unique:_ ~overcommit:_ t k v = + [%log.debug "add -> %a" pp_hash k]; + t.t <- KMap.add k v t.t; + k + + let unsafe_add t k v = + Lwt.return (unsafe_append ~ensure_unique:true ~overcommit:true t k v) + + let add t v = unsafe_add t (Val.hash v) v + end +end diff --git a/vendors/irmin/src/irmin-pack/mem/indexable.mli b/vendors/irmin/src/irmin-pack/mem/indexable.mli new file mode 100644 index 000000000000..20ac827fc30f --- /dev/null +++ b/vendors/irmin/src/irmin-pack/mem/indexable.mli @@ -0,0 +1,31 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) +open! Import + +module Maker (K : Irmin.Hash.S) : sig + type key = K.t + + module Make + (Val : Irmin_pack.Pack_value.S with type hash := K.t and type key := K.t) : sig + include + Irmin_pack.Indexable.S + with type hash = K.t + and type key = K.t + and type value = Val.t + + val v : string -> read t Lwt.t + end +end diff --git a/vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.ml b/vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.ml new file mode 100644 index 000000000000..608a35fa1d9a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.ml @@ -0,0 +1,170 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Atomic_write (K : Irmin.Type.S) (V : Irmin.Hash.S) = struct + module AW = Irmin_mem.Atomic_write (K) (V) + include AW + + let v () = AW.v (Irmin_mem.config ()) + let flush _t = () +end + +module Indexable_mem + (Hash : Irmin.Hash.S) + (Value : Irmin_pack.Pack_value.S + with type hash := Hash.t + and type key = Hash.t) = +struct + module Pack = Indexable.Maker (Hash) + module Indexable_mem = Pack.Make (Value) + include Irmin_pack.Indexable.Closeable (Indexable_mem) + + let v x = Indexable_mem.v x >|= make_closeable +end + +module Maker (Config : Irmin_pack.Conf.S) = struct + type endpoint = unit + + include Irmin.Key.Store_spec.Hash_keyed + + module Make (Schema : Irmin.Schema.Extended) = struct + module H = Schema.Hash + module C = Schema.Contents + module P = Schema.Path + module M = Schema.Metadata + module B = Schema.Branch + module Pack = Indexable.Maker (H) + + module XKey = struct + include Irmin.Key.Of_hash (H) + + let unfindable_of_hash x = x + end + + module X = struct + module Schema = Schema + module Hash = H + module Info = Schema.Info + + module Contents = struct + module Pack_value = + Irmin_pack.Pack_value.Of_contents (Config) (H) (XKey) (C) + + module Indexable = Indexable_mem (H) (Pack_value) + include Irmin.Contents.Store_indexable (Indexable) (H) (C) + end + + module Node = struct + module Value = Schema.Node (XKey) (XKey) + + module Indexable = struct + module Inter = + Irmin_pack.Inode.Make_internal (Config) (H) (XKey) (Value) + + module CA = Pack.Make (Inter.Raw) + include Irmin_pack.Inode.Make (H) (XKey) (Value) (Inter) (CA) + + let v = CA.v + end + + include + Irmin.Node.Generic_key.Store (Contents) (Indexable) (H) + (Indexable.Val) + (M) + (P) + end + + module Node_portable = Node.Indexable.Val.Portable + + module Commit = struct + module Value = struct + include Schema.Commit (Node.Key) (XKey) + module Info = Schema.Info + + type hash = Hash.t [@@deriving irmin] + end + + module Pack_value = Irmin_pack.Pack_value.Of_commit (H) (XKey) (Value) + module Indexable = Indexable_mem (H) (Pack_value) + + include + Irmin.Commit.Generic_key.Store (Info) (Node) (Indexable) (H) (Value) + end + + module Commit_portable = Irmin.Commit.Portable.Of_commit (Commit.Value) + + module Branch = struct + module Key = B + + module Val = struct + include H + include Commit.Key + end + + module AW = Atomic_write (Key) (Val) + include Irmin_pack.Atomic_write.Closeable (AW) + + let v () = AW.v () >|= make_closeable + end + + module Slice = Irmin.Backend.Slice.Make (Contents) (Node) (Commit) + module Remote = Irmin.Backend.Remote.None (H) (B) + + module Repo = struct + type t = { + config : Irmin.Backend.Conf.t; + contents : read Contents.Indexable.t; + node : read Node.Indexable.t; + commit : read Commit.Indexable.t; + branch : Branch.t; + } + + let contents_t t : 'a Contents.t = t.contents + let node_t t : 'a Node.t = (contents_t t, t.node) + let commit_t t : 'a Commit.t = (node_t t, t.commit) + let branch_t t = t.branch + let config t = t.config + + let batch t f = + Commit.Indexable.batch t.commit (fun commit -> + Node.Indexable.batch t.node (fun node -> + Contents.Indexable.batch t.contents (fun contents -> + let contents : 'a Contents.t = contents in + let node : 'a Node.t = (contents, node) in + let commit : 'a Commit.t = (node, commit) in + f contents node commit))) + + let v config = + let root = Irmin_pack.Conf.root config in + let* contents = Contents.Indexable.v root in + let* node = Node.Indexable.v root in + let* commit = Commit.Indexable.v root in + let+ branch = Branch.v () in + { contents; node; commit; branch; config } + + let close t = + Contents.Indexable.close (contents_t t) >>= fun () -> + Node.Indexable.close (snd (node_t t)) >>= fun () -> + Commit.Indexable.close (snd (commit_t t)) >>= fun () -> + Branch.close t.branch + end + end + + include Irmin.Of_backend (X) + end +end diff --git a/vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.mli b/vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.mli new file mode 100644 index 000000000000..a73beaab0b3d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/mem/irmin_pack_mem.mli @@ -0,0 +1,25 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** A fully in-memory implementation of the [Irmin_pack] flavour of Irmin + backend, intended for users that must be interoperable with the + idiosyncrasies of the persistent implementation. *) + +module Maker (_ : Irmin_pack.Conf.S) : + Irmin_pack.Maker + with type ('h, _) contents_key = 'h + and type 'h node_key = 'h + and type 'h commit_key = 'h diff --git a/vendors/irmin/src/irmin-pack/pack_key.ml b/vendors/irmin/src/irmin-pack/pack_key.ml new file mode 100644 index 000000000000..fa57edc0e4b7 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/pack_key.ml @@ -0,0 +1,29 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + include Irmin.Key.S + + val null : t + + val unfindable_of_hash : hash -> t + (** [unfindable_of_hash h] is a key [k] such that [to_hash k = h], with an + unspecified internal representation. This function enables an efficient + implmentation of "portable" inodes, but is otherwise unused. Attempting to + dereference a key constructed in this way results in undefined behaviour. *) +end diff --git a/vendors/irmin/src/irmin-pack/pack_value.ml b/vendors/irmin/src/irmin-pack/pack_value.ml new file mode 100644 index 000000000000..d346a8fdaa64 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/pack_value.ml @@ -0,0 +1,240 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Pack_value_intf + +module Kind = struct + type t = + | Commit_v1 + | Commit_v2 + | Contents + | Inode_v1_unstable + | Inode_v1_stable + | Inode_v2_root + | Inode_v2_nonroot + | Dangling_parent_commit + + let to_magic = function + | Commit_v1 -> 'C' + | Commit_v2 -> 'D' + | Contents -> 'B' + | Inode_v1_unstable -> 'I' + | Inode_v1_stable -> 'N' + | Inode_v2_root -> 'R' + | Inode_v2_nonroot -> 'O' + | Dangling_parent_commit -> 'P' + + let of_magic_exn = function + | 'C' -> Commit_v1 + | 'D' -> Commit_v2 + | 'B' -> Contents + | 'I' -> Inode_v1_unstable + | 'N' -> Inode_v1_stable + | 'R' -> Inode_v2_root + | 'O' -> Inode_v2_nonroot + | 'P' -> Dangling_parent_commit + | c -> Fmt.failwith "Kind.of_magic: unexpected magic char %C" c + + let all = + [ + Commit_v1; + Commit_v2; + Contents; + Inode_v1_unstable; + Inode_v1_stable; + Inode_v2_root; + Inode_v2_nonroot; + Dangling_parent_commit; + ] + + let to_enum = function + | Commit_v1 -> 0 + | Commit_v2 -> 1 + | Contents -> 2 + | Inode_v1_unstable -> 3 + | Inode_v1_stable -> 4 + | Inode_v2_root -> 5 + | Inode_v2_nonroot -> 6 + | Dangling_parent_commit -> 7 + + let pp = + Fmt.of_to_string (function + | Commit_v1 -> "Commit_v1" + | Commit_v2 -> "Commit_v2" + | Contents -> "Contents" + | Inode_v1_unstable -> "Inode_v1_unstable" + | Inode_v1_stable -> "Inode_v1_stable" + | Inode_v2_root -> "Inode_v2_root" + | Inode_v2_nonroot -> "Inode_v2_nonroot" + | Dangling_parent_commit -> "Dangling_parent_commit") + + let length_header_exn : t -> length_header = + let some_varint = Some `Varint in + function + | Commit_v1 | Inode_v1_unstable | Inode_v1_stable -> None + | Commit_v2 | Inode_v2_root | Inode_v2_nonroot | Dangling_parent_commit -> + some_varint + | Contents -> + Fmt.failwith + "Can't determine length header for user-defined codec Contents" + + let t = Irmin.Type.map ~pp Irmin.Type.char of_magic_exn to_magic +end + +type ('h, 'a) value = { hash : 'h; kind : Kind.t; v : 'a } [@@deriving irmin] + +module type S = S with type kind := Kind.t + +let get_dynamic_sizer_exn : type a. a Irmin.Type.t -> string -> int -> int = + fun typ -> + match Irmin.Type.(Size.of_encoding typ) with + | Unknown -> + Fmt.failwith "Type must have a recoverable encoded length: %a" + Irmin.Type.pp_ty typ + | Static n -> fun _ _ -> n + | Dynamic f -> f + +module Of_contents + (Conf : Config) + (Hash : Irmin.Hash.S) + (Key : T) + (Data : Irmin.Type.S) = +struct + module Hash = Irmin.Hash.Typed (Hash) (Data) + + type t = Data.t [@@deriving irmin ~size_of] + type key = Key.t + type hash = Hash.t + + let hash = Hash.hash + let kind = Kind.Contents + let length_header = Fun.const Conf.contents_length_header + let value = [%typ: (Hash.t, Data.t) value] + let encode_value = Irmin.Type.(unstage (encode_bin value)) + let decode_value = Irmin.Type.(unstage (decode_bin value)) + + let encode_bin ~dict:_ ~offset_of_key:_ hash v f = + encode_value { kind; hash; v } f + + let decode_bin ~dict:_ ~key_of_offset:_ ~key_of_hash:_ s off = + let t = decode_value s off in + t.v + + let decode_bin_length = get_dynamic_sizer_exn value + let kind _ = kind + + let weight = + (* Normalise the weight of the blob, assuming that the 'average' + size for a blob is 1k bytes. *) + let normalise n = max 1 (n / 1_000) in + match Irmin.Type.Size.of_value t with + | Unknown -> + (* this should not happen unless the user has specified a very + weird content type. *) + Fun.const max_int + | Dynamic f -> fun v -> normalise (f v) + | Static n -> Fun.const (normalise n) +end + +module Of_commit + (Hash : Irmin.Hash.S) + (Key : Irmin.Key.S with type hash = Hash.t) + (Commit : Irmin.Commit.Generic_key.S + with type node_key = Key.t + and type commit_key = Key.t) = +struct + module Hash = Irmin.Hash.Typed (Hash) (Commit) + + type t = Commit.t [@@deriving irmin] + type key = Key.t + type hash = Hash.t [@@deriving irmin ~encode_bin ~decode_bin] + + let hash = Hash.hash + let kind _ = Kind.Commit_v2 + let weight _ = 1 + + (* A commit implementation that uses integer offsets for addresses where possible. *) + module Commit_direct = struct + type address = Offset of int63 | Hash of Hash.t [@@deriving irmin] + + type t = { + node_offset : address; + parent_offsets : address list; + info : Commit.Info.t; + } + [@@deriving irmin ~encode_bin ~to_bin_string ~decode_bin] + + let size_of = + match Irmin.Type.Size.of_value t with + | Dynamic f -> f + | Static _ | Unknown -> assert false + end + + module Entry = struct + module V0 = struct + type t = (hash, Commit.t) value [@@deriving irmin ~decode_bin] + end + + module V1 = struct + type data = { length : int; v : Commit_direct.t } [@@deriving irmin] + type t = (hash, data) value [@@deriving irmin ~encode_bin ~decode_bin] + end + end + + let length_header = function + | Kind.Contents -> assert false + | x -> Kind.length_header_exn x + + let encode_bin ~dict:_ ~offset_of_key hash v f = + let address_of_key k : Commit_direct.address = + match offset_of_key k with + | None -> Hash (Key.to_hash k) + | Some k -> Offset k + in + let v = + let info = Commit.info v in + let node_offset = address_of_key (Commit.node v) in + let parent_offsets = List.map address_of_key (Commit.parents v) in + { Commit_direct.node_offset; parent_offsets; info } + in + let length = Commit_direct.size_of v in + Entry.V1.encode_bin { hash; kind = Commit_v2; v = { length; v } } f + + let decode_bin ~dict:_ ~key_of_offset ~key_of_hash s off = + let key_of_address : Commit_direct.address -> Key.t = function + | Offset x -> key_of_offset x + | Hash x -> key_of_hash x + in + match Kind.of_magic_exn s.[!off + Hash.hash_size] with + | Commit_v1 -> (Entry.V0.decode_bin s off).v + | Commit_v2 | Dangling_parent_commit -> + let { v = { Entry.V1.v = commit; _ }; _ } = Entry.V1.decode_bin s off in + let info = commit.info in + let node = key_of_address commit.node_offset in + let parents = List.map key_of_address commit.parent_offsets in + Commit.v ~info ~node ~parents + | _ -> assert false + + let decode_bin_length = + let of_v0_entry = get_dynamic_sizer_exn Entry.V0.t + and of_v1_entry = get_dynamic_sizer_exn Entry.V1.t in + fun s off -> + match Kind.of_magic_exn s.[off + Hash.hash_size] with + | Commit_v1 -> of_v0_entry s off + | Commit_v2 -> of_v1_entry s off + | _ -> assert false +end diff --git a/vendors/irmin/src/irmin-pack/pack_value.mli b/vendors/irmin/src/irmin-pack/pack_value.mli new file mode 100644 index 000000000000..cb8363e34be4 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/pack_value.mli @@ -0,0 +1,46 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** This module defines abstractions over entries in the pack file, which are + encoded as follows: + + {v + ┌────────┬────────┬──────────────┬─────────┐ + │ Hash │ Kind │ Len(Value)? │ Value │ + └────────┴────────┴──────────────┴─────────┘ + ┆<┄ H ┄┄>┆<┄ K ┄┄>┆<┄┄┄┄ L? ┄┄┄┄>┆<┄┄ V ┄┄>┆ + ┆<┄┄┄┄┄┄┄┄┄┄┄ entry length, E ┄┄┄┄┄┄┄┄┄┄┄┄>┆ + v} + + The fields are as follows: + + - [Hash]: the (fixed-length) hash of the data stored in this entry; + + - [Kind]: the {i kind} of data being stored (contents, nodes, commits etc.), + encoded as a single "magic" character; + + - [Len(Value)]: an optional length header for the [Value] section of the + entry ({i not} including the length of the length header itself), encoded + using a variable-length encoding (LEB128). The presence of a length header + is determined by the [Kind] character. + + - [Value]: the data itself. + + The length of the overall pack {i entry}, as referenced in the {!Pack_index} + or in a direct {!Pack_key.t}, is equal to [E = H + K + L + V]. *) + +include Pack_value_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/pack_value_intf.ml b/vendors/irmin/src/irmin-pack/pack_value_intf.ml new file mode 100644 index 000000000000..aab06a0582b3 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/pack_value_intf.ml @@ -0,0 +1,116 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +type length_header = [ `Varint ] option + +module type S = sig + include Irmin.Type.S + + type hash + type key + type kind + + val hash : t -> hash + val kind : t -> kind + + val length_header : kind -> length_header + (** Describes the length header formats for the {i data} sections of pack + entries. *) + + val weight : t -> int + (** [weight t] is the [t]'s LRU weight. *) + + val encode_bin : + dict:(string -> int option) -> + offset_of_key:(key -> int63 option) -> + hash -> + t Irmin.Type.encode_bin + + val decode_bin : + dict:(int -> string option) -> + key_of_offset:(int63 -> key) -> + key_of_hash:(hash -> key) -> + t Irmin.Type.decode_bin + + val decode_bin_length : string -> int -> int +end + +module type T = sig + type t +end + +(* A subset of [Irmin_pack.Conf.S] relevant to the format of pack entries, + copied here to avoid cyclic dependencies. *) +module type Config = sig + val contents_length_header : length_header +end + +module type Sigs = sig + module Kind : sig + type t = + | Commit_v1 + | Commit_v2 + | Contents + | Inode_v1_unstable + | Inode_v1_stable + | Inode_v2_root + | Inode_v2_nonroot + | Dangling_parent_commit + [@@deriving irmin] + + val all : t list + val to_enum : t -> int + val to_magic : t -> char + val of_magic_exn : char -> t + val pp : t Fmt.t + + val length_header_exn : t -> length_header + (** Raises an exception on [Contents], as the availability of a length + header is user defined. *) + end + + module type S = S with type kind := Kind.t + module type Config = Config + + module Of_contents + (_ : Config) + (Hash : Irmin.Hash.S) + (Key : T) + (Contents : Irmin.Contents.S) : + S with type t = Contents.t and type hash = Hash.t and type key = Key.t + + module Of_commit + (Hash : Irmin.Hash.S) + (Key : Irmin.Key.S with type hash = Hash.t) + (Commit : Irmin.Commit.Generic_key.S + with type node_key = Key.t + and type commit_key = Key.t) : sig + include S with type t = Commit.t and type hash = Hash.t and type key = Key.t + + module Commit_direct : sig + type address = Offset of int63 | Hash of hash [@@deriving irmin] + + type t = { + node_offset : address; + parent_offsets : address list; + info : Commit.Info.t; + } + [@@deriving irmin] + end + end +end diff --git a/vendors/irmin/src/irmin-pack/stats.ml b/vendors/irmin/src/irmin-pack/stats.ml new file mode 100644 index 000000000000..6dc2aeda4689 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/stats.ml @@ -0,0 +1,116 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Metrics = Irmin.Metrics + +module Inode = struct + type Metrics.origin += Inode_stats + + type field = + | Inode_add + | Inode_remove + | Inode_of_seq + | Inode_of_raw + | Inode_rec_add + | Inode_rec_remove + | Inode_to_binv + | Inode_decode_bin + | Inode_encode_bin + + type t = { + mutable inode_add : int; + mutable inode_remove : int; + mutable inode_of_seq : int; + mutable inode_of_raw : int; + mutable inode_rec_add : int; + mutable inode_rec_remove : int; + mutable inode_to_binv : int; + mutable inode_decode_bin : int; + mutable inode_encode_bin : int; + } + [@@deriving irmin] + + type stat = t Metrics.t + + let create_inode () = + { + inode_add = 0; + inode_remove = 0; + inode_of_seq = 0; + inode_of_raw = 0; + inode_rec_add = 0; + inode_rec_remove = 0; + inode_to_binv = 0; + inode_decode_bin = 0; + inode_encode_bin = 0; + } + + let clear m = + let v = Metrics.state m in + v.inode_add <- 0; + v.inode_remove <- 0; + v.inode_of_seq <- 0; + v.inode_of_raw <- 0; + v.inode_rec_add <- 0; + v.inode_rec_remove <- 0; + v.inode_to_binv <- 0; + v.inode_decode_bin <- 0; + v.inode_encode_bin <- 0 + + let init () = + let initial_state = create_inode () in + Metrics.v ~origin:Inode_stats ~name:"inode_metric" ~initial_state t + + let export m = Metrics.state m + + let update ~field pack = + let f v = + match field with + | Inode_add -> v.inode_add <- succ v.inode_add + | Inode_remove -> v.inode_remove <- succ v.inode_remove + | Inode_of_seq -> v.inode_of_seq <- succ v.inode_of_seq + | Inode_of_raw -> v.inode_of_raw <- succ v.inode_of_raw + | Inode_rec_add -> v.inode_rec_add <- succ v.inode_rec_add + | Inode_rec_remove -> v.inode_rec_remove <- succ v.inode_rec_remove + | Inode_to_binv -> v.inode_to_binv <- succ v.inode_to_binv + | Inode_decode_bin -> v.inode_decode_bin <- succ v.inode_decode_bin + | Inode_encode_bin -> v.inode_encode_bin <- succ v.inode_encode_bin + in + let mut = Metrics.Mutate f in + Metrics.update pack mut +end + +type t = { inode : Inode.stat } + +let s = { inode = Inode.init () } +let get () = s +let reset_stats () = Inode.clear s.inode +let incr_inode_add () = Inode.update ~field:Inode.Inode_add s.inode +let incr_inode_remove () = Inode.update ~field:Inode.Inode_remove s.inode +let incr_inode_of_seq () = Inode.update ~field:Inode.Inode_of_seq s.inode +let incr_inode_of_raw () = Inode.update ~field:Inode.Inode_of_raw s.inode +let incr_inode_rec_add () = Inode.update ~field:Inode.Inode_rec_add s.inode + +let incr_inode_rec_remove () = + Inode.update ~field:Inode.Inode_rec_remove s.inode + +let incr_inode_to_binv () = Inode.update ~field:Inode.Inode_to_binv s.inode + +let incr_inode_decode_bin () = + Inode.update ~field:Inode.Inode_decode_bin s.inode + +let incr_inode_encode_bin () = + Inode.update ~field:Inode.Inode_encode_bin s.inode diff --git a/vendors/irmin/src/irmin-pack/stats.mli b/vendors/irmin/src/irmin-pack/stats.mli new file mode 100644 index 000000000000..180c2227878a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/stats.mli @@ -0,0 +1,68 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Inode : sig + type field = + | Inode_add + | Inode_remove + | Inode_of_seq + | Inode_of_raw + | Inode_rec_add + | Inode_rec_remove + | Inode_to_binv + | Inode_decode_bin + | Inode_encode_bin + + type t = private { + mutable inode_add : int; + mutable inode_remove : int; + mutable inode_of_seq : int; + mutable inode_of_raw : int; + mutable inode_rec_add : int; + mutable inode_rec_remove : int; + mutable inode_to_binv : int; + mutable inode_decode_bin : int; + mutable inode_encode_bin : int; + } + [@@deriving irmin] + (** The type for stats for a store S. + + - [inode_add + inode_remove + inode_of_seq + inode_of_raw] is the total + number of [Inode.Val.t] built; + - [inode_rec_add + inode_rec_remove] are witnesses of the quantity of work + that is done modifying inodes; + - [inode_to_binv] is the number of [Inode.Bin.v] built; + - [inode_encode_bin] is the number of [Bin] to [Compress] conversions; + - [inode_decode_bin] is the number of [Compress] to [Bin] conversions; *) + + type stat + + val export : stat -> t +end + +type t = { inode : Inode.stat } + +val reset_stats : unit -> unit +val get : unit -> t +val incr_inode_add : unit -> unit +val incr_inode_remove : unit -> unit +val incr_inode_of_seq : unit -> unit +val incr_inode_of_raw : unit -> unit +val incr_inode_rec_add : unit -> unit +val incr_inode_rec_remove : unit -> unit +val incr_inode_to_binv : unit -> unit +val incr_inode_decode_bin : unit -> unit +val incr_inode_encode_bin : unit -> unit diff --git a/vendors/irmin/src/irmin-pack/unix/append_only_file.ml b/vendors/irmin/src/irmin-pack/unix/append_only_file.ml new file mode 100644 index 000000000000..1f2151742b92 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/append_only_file.ml @@ -0,0 +1,175 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Append_only_file_intf + +module Make (Io : Io.S) (Errs : Io_errors.S with module Io = Io) = struct + module Io = Io + module Errs = Errs + + type t = { + io : Io.t; + mutable persisted_end_poff : int63; + dead_header_size : int63; + rw_perm : rw_perm option; + } + + and auto_flush_procedure = [ `Internal | `External of t -> unit ] + + and rw_perm = { + buf : Buffer.t; + auto_flush_threshold : int; + auto_flush_procedure : auto_flush_procedure; + } + (** [rw_perm] contains the data necessary to operate in readwrite mode. *) + + let create_rw ~path ~overwrite ~auto_flush_threshold ~auto_flush_procedure = + let open Result_syntax in + let+ io = Io.create ~path ~overwrite in + let persisted_end_poff = Int63.zero in + let buf = Buffer.create 0 in + { + io; + persisted_end_poff; + dead_header_size = Int63.zero; + rw_perm = Some { buf; auto_flush_threshold; auto_flush_procedure }; + } + + (** A store is consistent if the real offset of the suffix/dict files is the + one recorded in the control file. When opening the store, the offset from + the control file is passed as the [end_poff] argument to the [open_ro], + [open_rw] functions. The [end_poff] from the control file is then used as + the real offset. + + In case of a crash, we can only recover if the [end_poff] is smaller than + the real offset. We cannot recover otherwise, because we have no + guarantees that the last object fsynced to disk is written entirely to + disk. *) + let check_consistent_store ~end_poff ~dead_header_size io = + let open Result_syntax in + let* real_offset = Io.read_size io in + let dead_header_size = Int63.of_int dead_header_size in + let real_offset_without_header = + Int63.Syntax.(real_offset - dead_header_size) + in + if real_offset_without_header < end_poff then Error `Inconsistent_store + else ( + if real_offset_without_header > end_poff then + [%log.warn + "The end offset in the control file %a is smaller than the offset on \ + disk %a for %s; the store was closed in a inconsistent state." + Int63.pp end_poff Int63.pp real_offset_without_header (Io.path io)]; + Ok ()) + + let open_rw ~path ~end_poff ~dead_header_size ~auto_flush_threshold + ~auto_flush_procedure = + let open Result_syntax in + let* io = Io.open_ ~path ~readonly:false in + let+ () = check_consistent_store ~end_poff ~dead_header_size io in + let persisted_end_poff = end_poff in + let dead_header_size = Int63.of_int dead_header_size in + let buf = Buffer.create 0 in + { + io; + persisted_end_poff; + dead_header_size; + rw_perm = Some { buf; auto_flush_threshold; auto_flush_procedure }; + } + + let open_ro ~path ~end_poff ~dead_header_size = + let open Result_syntax in + let* io = Io.open_ ~path ~readonly:true in + let+ () = check_consistent_store ~end_poff ~dead_header_size io in + let persisted_end_poff = end_poff in + let dead_header_size = Int63.of_int dead_header_size in + { io; persisted_end_poff; dead_header_size; rw_perm = None } + + let empty_buffer = function + | { rw_perm = Some { buf; _ }; _ } when Buffer.length buf > 0 -> false + | _ -> true + + let close t = + if not @@ empty_buffer t then Error `Pending_flush else Io.close t.io + + let readonly t = Io.readonly t.io + let path t = Io.path t.io + + let auto_flush_threshold = function + | { rw_perm = None; _ } -> None + | { rw_perm = Some rw_perm; _ } -> Some rw_perm.auto_flush_threshold + + let end_poff t = + match t.rw_perm with + | None -> t.persisted_end_poff + | Some rw_perm -> + let open Int63.Syntax in + t.persisted_end_poff + (Buffer.length rw_perm.buf |> Int63.of_int) + + let refresh_end_poff t new_end_poff = + match t.rw_perm with + | Some _ -> Error `Rw_not_allowed + | None -> + t.persisted_end_poff <- new_end_poff; + Ok () + + let flush t = + match t.rw_perm with + | None -> Error `Ro_not_allowed + | Some rw_perm -> + let open Result_syntax in + let open Int63.Syntax in + let s = Buffer.contents rw_perm.buf in + let off = t.persisted_end_poff + t.dead_header_size in + let+ () = Io.write_string t.io ~off s in + t.persisted_end_poff <- + t.persisted_end_poff + (String.length s |> Int63.of_int); + (* [truncate] is semantically identical to [clear], except that + [truncate] doesn't deallocate the internal buffer. We use + [clear] in legacy_io. *) + Buffer.truncate rw_perm.buf 0 + + let fsync t = Io.fsync t.io + + let read_exn t ~off ~len b = + let open Int63.Syntax in + let off' = off + Int63.of_int len in + if off' > t.persisted_end_poff then + raise (Errors.Pack_error `Read_out_of_bounds); + let off = off + t.dead_header_size in + Io.read_exn t.io ~off ~len b + + let read_to_string t ~off ~len = + let open Int63.Syntax in + let off' = off + Int63.of_int len in + if off' > t.persisted_end_poff then Error `Read_out_of_bounds + else + let off = off + t.dead_header_size in + Io.read_to_string t.io ~off ~len + + let append_exn t s = + match t.rw_perm with + | None -> raise Errors.RO_not_allowed + | Some rw_perm -> ( + assert (Buffer.length rw_perm.buf < rw_perm.auto_flush_threshold); + Buffer.add_string rw_perm.buf s; + if Buffer.length rw_perm.buf >= rw_perm.auto_flush_threshold then + match rw_perm.auto_flush_procedure with + | `Internal -> flush t |> Errs.raise_if_error + | `External cb -> + cb t; + assert (empty_buffer t)) +end diff --git a/vendors/irmin/src/irmin-pack/unix/append_only_file.mli b/vendors/irmin/src/irmin-pack/unix/append_only_file.mli new file mode 100644 index 000000000000..47ec6aea4031 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/append_only_file.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Append_only_file_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/append_only_file_intf.ml b/vendors/irmin/src/irmin-pack/unix/append_only_file_intf.ml new file mode 100644 index 000000000000..c7aa00e03475 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/append_only_file_intf.ml @@ -0,0 +1,192 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type S = sig + (** Abstraction for irmin-pack's append only files (i.e. suffix and dict). + + It is parameterized with [Io], a file system abstraction (e.g. unix, + mirage, eio_linux). + + It comprises a persistent file, an append buffer and take care of + automatically shifting offsets to deal with legacy file headers. *) + + module Io : Io.S + module Errs : Io_errors.S + + type t + + type auto_flush_procedure = [ `Internal | `External of t -> unit ] + (** [auto_flush_procedure] defines behavior when the flush threshold is + reached. + + - Use [`Internal] to have the buffer automatically flushed. + - Use [`External f] to have [f] called when the flush threshold is + reached. It is the responsibility of [f] to call flush, in addition to + any other processing it does. *) + + val create_rw : + path:string -> + overwrite:bool -> + auto_flush_threshold:int -> + auto_flush_procedure:auto_flush_procedure -> + (t, [> Io.create_error ]) result + (** Create a rw instance of [t] by creating the file at [path]. *) + + val open_rw : + path:string -> + end_poff:int63 -> + dead_header_size:int -> + auto_flush_threshold:int -> + auto_flush_procedure:auto_flush_procedure -> + ( t, + [> Io.open_error + | `Closed + | `Invalid_argument + | `Read_out_of_bounds + | `Inconsistent_store ] ) + result + (** Create a rw instance of [t] by opening an existing file at [path]. + + {3 End Offset} + + The file has an end offset at which new data will be saved. While this + information could be computed by looking at the size of the file, we + prefer storing that information elsewhere (i.e. in the control file). This + is why [open_rw] and [open_ro] take an [end_poff] parameter, and also why + [refresh_end_poff] exists. The abstractions above [Append_only_file] are + responsible for reading/writing the offsets from/to the control file. + + {3 [dead_header_size]} + + Designates a small area at the beginning of the file that should be + ignored. The offsets start after that area. + + The actual persisted size of a file is [end_poff + dead_header_size]. + + This concept exists in order to keep supporting [`V1] and [`V2] pack + stores with [`V3]. + + {3 Auto Flushes} + + One of the goals of the [Append_only_file] abstraction is to provide + buffered appends. [auto_flush_threshold] is the soft cap after which the + buffer should be flushed. When a call to [append_exn] fills the buffer, + either the buffer will be flushed automatically, if + [auto_flush_procedure = `Internal], or the supplied external function [f] + will be called, if [auto_flush_procedure = `External f]. *) + + val open_ro : + path:string -> + end_poff:int63 -> + dead_header_size:int -> + ( t, + [> Io.open_error + | `Closed + | `Inconsistent_store + | `Invalid_argument + | `Read_out_of_bounds ] ) + result + (** Create a ro instance of [t] by opening an existing file at [path] *) + + val close : t -> (unit, [> Io.close_error | `Pending_flush ]) result + (** Close the underlying file. + + The internal buffer is expected to be in a flushed state when [close] is + called. Otherwise, an error is returned. *) + + val end_poff : t -> int63 + (** [end_poff t] is the number of bytes of the file. That function doesn't + perform IO. + + {3 RW mode} + + It also counts the bytes not flushed yet. + + {3 RO mode} + + This information originates from the latest reload of the control file. + Calling [refresh_end_poff t] updates [end_poff]. *) + + val read_to_string : + t -> off:int63 -> len:int -> (string, [> Io.read_error ]) result + + val read_exn : t -> off:int63 -> len:int -> bytes -> unit + (** [read_exn t ~off ~len b] puts the [len] bytes of [t] at [off] to [b]. + + [read_to_string] should always be favored over [read_exn], except when + performences matter. + + It is not possible to read from an offset further than [end_poff t]. + + Raises [Io.Read_error] and [Errors.Pack_error `Read_out_of_bounds]. + + {3 RW mode} + + Attempting to read from the append buffer results in an + [`Read_out_of_bounds] error. This feature could easily be implemented in + the future if ever needed. It was not needed with io_legacy. *) + + val append_exn : t -> string -> unit + (** [append_exn t ~off b] writes [b] to the end of [t]. Might trigger an auto + flush. + + Grows [end_poff], but the parent abstraction is expected to persist this + somewhere (e.g. in the control file). + + Post-condition: [end_poff t - end_poff (old t) = String.length b]. + + Raises [Io.Write_error] + + {3 RW mode} + + Always raises [Errors.RO_not_allowed] *) + + val flush : t -> (unit, [> Io.write_error ]) result + (** Flush the append buffer. Does not call [fsync]. + + {3 RO mode} + + Always returns [Error `Ro_not_allowed]. *) + + val fsync : t -> (unit, [> Io.write_error ]) result + (** Tell the os to fush its internal buffers. Does not call [flush]. + + {3 RO mode} + + Always returns [Error `Ro_not_allowed]. *) + + val refresh_end_poff : t -> int63 -> (unit, [> `Rw_not_allowed ]) result + (** Ingest the new end offset of the file. Typically happens in RO mode when + the control file has been re-read. + + {3 RW mode} + + Always returns [Error `Rw_not_allowed]. *) + + val readonly : t -> bool + val auto_flush_threshold : t -> int option + val empty_buffer : t -> bool + val path : t -> string +end + +module type Sigs = sig + module type S = S + + module Make (Io : Io.S) (Errs : Io_errors.S with module Io = Io) : + S with module Io = Io and module Errs = Errs +end diff --git a/vendors/irmin/src/irmin-pack/unix/async.ml b/vendors/irmin/src/irmin-pack/unix/async.ml new file mode 100644 index 000000000000..e0cf47cb0807 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/async.ml @@ -0,0 +1,121 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Async_intf + +module Unix = struct + let kill_no_err pid = + try Unix.kill pid Sys.sigkill + with Unix.Unix_error (e, s1, s2) -> + [%log.warn + "Killing process with pid %d failed with error (%s, %s, %s)" pid + (Unix.error_message e) s1 s2] + + (** [Exit] is a stack of PIDs that will be killed [at_exit]. *) + module Exit = struct + let proc_list = ref [] + let m = Mutex.create () + + let add pid = + Mutex.lock m; + proc_list := pid :: !proc_list; + Mutex.unlock m + + let remove pid = + Mutex.lock m; + proc_list := List.filter (fun pid' -> pid <> pid') !proc_list; + Mutex.unlock m + + let () = at_exit @@ fun () -> List.iter kill_no_err !proc_list + end + + type outcome = [ `Success | `Cancelled | `Failure of string ] + [@@deriving irmin] + + type status = [ `Running | `Success | `Cancelled | `Failure of string ] + [@@deriving irmin] + + type t = { pid : int; mutable status : status } + + module Exit_code = struct + let success = 0 + let unhandled_exn = 42 + end + + let async f = + Stdlib.flush_all (); + match Lwt_unix.fork () with + | 0 -> + Lwt_main.Exit_hooks.remove_all (); + Lwt_main.abandon_yielded_and_paused (); + let exit_code = + match f () with + | () -> Exit_code.success + | exception e -> + [%log.err + "Unhandled exception in child process %s" (Printexc.to_string e)]; + Exit_code.unhandled_exn + in + (* Use [Unix._exit] to avoid calling [at_exit] hooks. *) + Unix._exit exit_code + | pid -> + Exit.add pid; + { pid; status = `Running } + + let status_of_process_outcome = function + | Lwt_unix.WEXITED n when n = Exit_code.success -> `Success + | Lwt_unix.WEXITED n when n = Exit_code.unhandled_exn -> + `Failure "Unhandled exception" + | Lwt_unix.WSIGNALED n -> `Failure (Fmt.str "Signaled %d" n) + | Lwt_unix.WEXITED n -> `Failure (Fmt.str "Exited %d" n) + | Lwt_unix.WSTOPPED n -> `Failure (Fmt.str "Stopped %d" n) + + let cancel t = + match t.status with + | `Running -> + let pid, _ = Unix.waitpid [ Unix.WNOHANG ] t.pid in + if pid = 0 then ( + (* Child process is still running. *) + kill_no_err t.pid; + Exit.remove t.pid; + t.status <- `Cancelled; + true) + else false + | _ -> false + + let status t = + match t.status with + | `Running -> + let pid, status = Unix.waitpid [ Unix.WNOHANG ] t.pid in + if pid = 0 then `Running + else + let s = status_of_process_outcome status in + Exit.remove pid; + t.status <- s; + s + | #outcome as s -> s + + let await t = + match t.status with + | `Running -> + let+ pid, status = Lwt_unix.waitpid [] t.pid in + let s = status_of_process_outcome status in + Exit.remove pid; + t.status <- s; + s + | #outcome as s -> Lwt.return s +end diff --git a/vendors/irmin/src/irmin-pack/unix/async.mli b/vendors/irmin/src/irmin-pack/unix/async.mli new file mode 100644 index 000000000000..ab3aa6f09808 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/async.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Async_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/async_intf.ml b/vendors/irmin/src/irmin-pack/unix/async_intf.ml new file mode 100644 index 000000000000..03876a773aea --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/async_intf.ml @@ -0,0 +1,51 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** Basic abstraction for a worker. *) + + type t + (** A task *) + + type outcome = [ `Success | `Cancelled | `Failure of string ] + [@@deriving irmin] + + type status = [ outcome | `Running ] [@@deriving irmin] + + val async : (unit -> unit) -> t + (** Start a task. *) + + val await : t -> [> outcome ] Lwt.t + (** If running, wait for a task to finish and return its outcome. + + If not running, return the oucome of the task. *) + + val status : t -> [> status ] + (** If running, refresh the status of the task, without blocking. + + If not running, return the oucome of the task. *) + + val cancel : t -> bool + (** If running, cancel the task and return [true]. + + If not running, do nothing and return [false]. *) +end + +module type Sigs = sig + module type S = S + + module Unix : S +end diff --git a/vendors/irmin/src/irmin-pack/unix/atomic_write.ml b/vendors/irmin/src/irmin-pack/unix/atomic_write.ml new file mode 100644 index 000000000000..ec71b30822a3 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/atomic_write.ml @@ -0,0 +1,195 @@ +open Import +include Irmin_pack.Atomic_write + +let current_version = `V1 + +module Table (K : Irmin.Type.S) = Hashtbl.Make (struct + type t = K.t [@@deriving irmin ~short_hash ~equal] + + let hash = short_hash ?seed:None +end) + +module Make_persistent (K : Irmin.Type.S) (V : Value.S) = struct + module Tbl = Table (K) + module W = Irmin.Backend.Watch.Make (K) (V) + module Io_legacy = Io_legacy.Unix + + type key = K.t [@@deriving irmin ~pp ~to_bin_string ~of_bin_string] + type value = V.t [@@deriving irmin ~equal ~decode_bin ~of_bin_string] + type watch = W.watch + + type t = { + index : int63 Tbl.t; + cache : V.t Tbl.t; + block : Io_legacy.t; + w : W.t; + } + + let decode_bin = Irmin.Type.(unstage (decode_bin int32)) + + let read_length32 ~file_pos block = + let buf = Bytes.create 4 in + let n = Io_legacy.read block ~off:!file_pos buf in + assert (n = 4); + (file_pos := Int63.Syntax.(!file_pos + Int63.of_int 4)); + let pos_ref = ref 0 in + (* Bytes.unsafe_to_string usage: We assume Io_legacy.read_block returns unique + ownership of buf back to this function (this assumption holds currently; subsequent + modifications of that code need to ensure this remains the case); then in call to + Bytes.unsafe_to_string we give up ownership of buf (we do not modify the buffer + afterwards) and get ownership of resulting string; so this use is safe. *) + let v = decode_bin (Bytes.unsafe_to_string buf) pos_ref in + assert (!pos_ref = 4); + Int32.to_int v + + let entry = Irmin.Type.(pair (string_of `Int32) V.t) + let entry_to_bin_string = Irmin.Type.(unstage (to_bin_string entry)) + + let set_entry t ?off k v = + let k = key_to_bin_string k in + let buf = entry_to_bin_string (k, v) in + let () = + match off with + | None -> Io_legacy.append t.block buf + | Some off -> Io_legacy.set t.block buf ~off + in + Io_legacy.flush t.block + + let value_encoded_size = + match Irmin.Type.Size.of_value V.t with + | Repr.Size.Static n -> n + | Dynamic _ | Unknown -> + failwith + "Irmin_pack.Atomic_write: supplied value type must have a \ + fixed-width binary encoding" + + let refill t ~to_ ~from = + let file_pos = ref from in + let rec aux () = + if !file_pos >= to_ then () + else + let start = !file_pos in + let key_encoded_size = read_length32 ~file_pos t.block in + let buf_size = key_encoded_size + value_encoded_size in + let buf = + let buf = Bytes.create buf_size in + let n = Io_legacy.read t.block ~off:!file_pos buf in + assert (n = buf_size); + let open Int63.Syntax in + file_pos := !file_pos + Int63.of_int buf_size; + Bytes.unsafe_to_string buf + in + let key = + match String.sub buf 0 key_encoded_size |> key_of_bin_string with + | Ok k -> k + | Error (`Msg e) -> failwith e + in + let value = + let pos_ref = ref key_encoded_size in + let v = decode_bin_value buf pos_ref in + assert (!pos_ref = buf_size); + v + in + if not (equal_value value V.null) then Tbl.add t.cache key value; + Tbl.add t.index key start; + (aux [@tailcall]) () + in + aux () + + let sync_offset t = + let former_offset = Io_legacy.offset t.block in + let offset = Io_legacy.force_offset t.block in + if offset > former_offset then refill t ~to_:offset ~from:former_offset + + let unsafe_find t k = + [%log.debug "[branches] find %a" pp_key k]; + if Io_legacy.readonly t.block then sync_offset t; + try Some (Tbl.find t.cache k) with Not_found -> None + + let find t k = Lwt.return (unsafe_find t k) + + let unsafe_mem t k = + [%log.debug "[branches] mem %a" pp_key k]; + try Tbl.mem t.cache k with Not_found -> false + + let mem t v = Lwt.return (unsafe_mem t v) + + let unsafe_remove t k = + Tbl.remove t.cache k; + try + let off = Tbl.find t.index k in + set_entry t ~off k V.null + with Not_found -> () + + let remove t k = + [%log.debug "[branches] remove %a" pp_key k]; + unsafe_remove t k; + W.notify t.w k None + + let watches = W.v () + + let v ?(fresh = false) ?(readonly = false) file = + let block = + Io_legacy.v ~fresh ~version:(Some current_version) ~readonly file + in + let cache = Tbl.create 997 in + let index = Tbl.create 997 in + let t = { cache; index; block; w = watches } in + let offset = Io_legacy.force_offset block in + refill t ~to_:offset ~from:Int63.zero; + Lwt.return t + + let clear _ = Fmt.failwith "Unsupported operation" + + let unsafe_set t k v = + try + let off = Tbl.find t.index k in + Tbl.replace t.cache k v; + set_entry t ~off k v + with Not_found -> + let offset = Io_legacy.offset t.block in + set_entry t k v; + Tbl.add t.cache k v; + Tbl.add t.index k offset + + let set t k v = + [%log.debug "[branches %s] set %a" (Io_legacy.name t.block) pp_key k]; + unsafe_set t k v; + W.notify t.w k (Some v) + + let equal_v_opt = Irmin.Type.(unstage (equal (option V.t))) + + let unsafe_test_and_set t k ~test ~set = + let v = try Some (Tbl.find t.cache k) with Not_found -> None in + if not (equal_v_opt v test) then Lwt.return_false + else + let return () = Lwt.return_true in + match set with + | None -> unsafe_remove t k |> return + | Some v -> unsafe_set t k v |> return + + let test_and_set t k ~test ~set = + [%log.debug "[branches] test-and-set %a" pp_key k]; + unsafe_test_and_set t k ~test ~set >>= function + | true -> W.notify t.w k set >|= fun () -> true + | false -> Lwt.return_false + + let list t = + [%log.debug "[branches] list"]; + let keys = Tbl.fold (fun k _ acc -> k :: acc) t.cache [] in + Lwt.return keys + + let watch_key t = W.watch_key t.w + let watch t = W.watch t.w + let unwatch t = W.unwatch t.w + + let unsafe_close t = + Tbl.reset t.index; + Tbl.reset t.cache; + if not (Io_legacy.readonly t.block) then Io_legacy.flush t.block; + Io_legacy.close t.block; + W.clear t.w + + let close t = unsafe_close t + let flush t = Io_legacy.flush t.block +end diff --git a/vendors/irmin/src/irmin-pack/unix/atomic_write.mli b/vendors/irmin/src/irmin-pack/unix/atomic_write.mli new file mode 100644 index 000000000000..ddb81eebbe8f --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/atomic_write.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include module type of Irmin_pack.Atomic_write + +module Make_persistent (K : Irmin.Type.S) (V : Value.S) : + Persistent with type key = K.t and type value = V.t diff --git a/vendors/irmin/src/irmin-pack/unix/checks.ml b/vendors/irmin/src/irmin-pack/unix/checks.ml new file mode 100644 index 000000000000..79c44bafbd5d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/checks.ml @@ -0,0 +1,802 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Checks_intf + +let setup_log = + let init style_renderer level = + let format_reporter = + let report _src level ~over k msgf = + let k _ = + over (); + k () + in + msgf @@ fun ?header:_ ?tags:_ fmt -> + match level with + | Logs.App -> + Fmt.kpf k Fmt.stderr + ("@[%a" ^^ fmt ^^ "@]@.") + Fmt.(styled `Bold (styled (`Fg `Cyan) string)) + ">> " + | _ -> Fmt.kpf k Fmt.stdout ("@[" ^^ fmt ^^ "@]@.") + in + { Logs.report } + in + Fmt_tty.setup_std_outputs ?style_renderer (); + Logs.set_level level; + Logs.set_reporter format_reporter + in + Cmdliner.Term.(const init $ Fmt_cli.style_renderer () $ Logs_cli.level ()) + +let path = + let open Cmdliner.Arg in + required + @@ pos 0 (some string) None + @@ info ~doc:"Path to the Irmin store on disk" ~docv:"PATH" [] + +let deprecated_info = (Cmdliner.Term.info [@alert "-deprecated"]) + +let ppf_or_null ppf = + let null = + match Sys.os_type with + | "Unix" | "Cygwin" -> "/dev/null" + | "Win32" -> "NUL" + | _ -> invalid_arg "invalid os type" + in + match ppf with + | Some p -> p + | None -> open_out null |> Format.formatter_of_out_channel + +module Make (Store : Store) = struct + module Hash = Store.Hash + module Index = Pack_index.Make (Hash) + + (** Read basic metrics from an existing store. *) + module Stat = struct + type size = Bytes of int [@@deriving irmin] + + type io = { size : size; offset : int63; version : Version.t } + [@@deriving irmin] + + type objects = { nb_commits : int; nb_nodes : int; nb_contents : int } + [@@deriving irmin] + + type t = { hash_size : size; log_size : int; objects : objects } + [@@deriving irmin] + + let traverse_index ~root log_size = + let index = Index.v_exn ~readonly:true ~fresh:false ~log_size root in + let ppf = Format.err_formatter in + let bar, (progress_contents, progress_nodes, progress_commits) = + Utils.Object_counter.start ppf + in + let f _ (_, _, (kind : Pack_value.Kind.t)) = + match kind with + | Contents -> progress_contents () + | Inode_v1_stable | Inode_v1_unstable | Inode_v2_root | Inode_v2_nonroot + -> + progress_nodes () + | Commit_v1 | Commit_v2 -> progress_commits () + | Dangling_parent_commit -> assert false + in + Index.iter f index; + let nb_contents, nb_nodes, nb_commits = + Utils.Object_counter.finalise_with_stats bar + in + { nb_contents; nb_nodes; nb_commits } + + let conf root = Conf.init ~readonly:true ~fresh:false ~no_migrate:true root + + let run ~root = + [%logs.app "Getting statistics for store: `%s'@," root]; + let log_size = conf root |> Conf.index_log_size in + let objects = traverse_index ~root log_size in + { hash_size = Bytes Hash.hash_size; log_size; objects } + |> Irmin.Type.pp_json ~minify:false t Fmt.stdout; + Lwt.return_unit + + let term_internal = + Cmdliner.Term.(const (fun root () -> Lwt_main.run (run ~root)) $ path) + + let term = + let doc = "Print high-level statistics about the store." in + Cmdliner.Term.(term_internal $ setup_log, deprecated_info ~doc "stat") + end + + module Reconstruct_index = struct + let conf ~index_log_size root = + Conf.init ~readonly:false ~fresh:false ?index_log_size ~no_migrate:true + root + + let dest = + let open Cmdliner.Arg in + value + & pos 1 (some string) None + @@ info ~doc:"Path to the new index file" ~docv:"DEST" [] + + let index_log_size = + let open Cmdliner.Arg in + value + & opt (some int) None + @@ info ~doc:"Size of the index log file" [ "index-log-size" ] + + let run ~root ~output ?index_log_size () = + let conf = conf ~index_log_size root in + match output with + | None -> Store.traverse_pack_file (`Reconstruct_index `In_place) conf + | Some p -> Store.traverse_pack_file (`Reconstruct_index (`Output p)) conf + + let term_internal = + Cmdliner.Term.( + const (fun root output index_log_size () -> + run ~root ~output ?index_log_size ()) + $ path + $ dest + $ index_log_size) + + let term = + let doc = "Reconstruct index from an existing pack file." in + Cmdliner.Term. + (term_internal $ setup_log, deprecated_info ~doc "reconstruct-index") + end + + module Integrity_check_index = struct + let conf root = Conf.init ~readonly:true ~fresh:false ~no_migrate:true root + + let run ~root ~auto_repair () = + let conf = conf root in + if auto_repair then Store.traverse_pack_file `Check_and_fix_index conf + else Store.traverse_pack_file `Check_index conf + + let auto_repair = + let open Cmdliner.Arg in + value + & (flag @@ info ~doc:"Add missing entries in index" [ "auto-repair" ]) + + let term_internal = + Cmdliner.Term.( + const (fun root auto_repair () -> run ~root ~auto_repair ()) + $ path + $ auto_repair) + + let term = + let doc = "Check index integrity." in + Cmdliner.Term. + (term_internal $ setup_log, deprecated_info ~doc "integrity-check-index") + end + + module Integrity_check = struct + let conf root always = + let indexing_strategy = + if always then Irmin_pack.Indexing_strategy.always + else Irmin_pack.Indexing_strategy.minimal + in + Conf.init ~readonly:false ~fresh:false ~no_migrate:true ~indexing_strategy + root + + let handle_result ?ppf ?name res = + let ppf = ppf_or_null ppf in + let name = match name with Some x -> x ^ ": " | None -> "" in + match res with + | Ok (`Fixed n) -> Fmt.pf ppf "%sOk -- fixed %d\n%!" name n + | Ok `No_error -> Fmt.pf ppf "%sOk\n%!" name + | Error (`Cannot_fix x) -> + Printf.eprintf "%sError -- cannot fix: %s\n%!" name x + | Error (`Corrupted x) -> + Printf.eprintf "%sError -- corrupted: %d\n%!" name x + + let run ?ppf ~root ~auto_repair ~always ~heads () = + let conf = conf root always in + let* repo = Store.Repo.v conf in + let* heads = + match heads with + | None -> Store.Repo.heads repo + | Some heads -> + Lwt_list.filter_map_s + (fun x -> + match Repr.of_string Store.Hash.t x with + | Ok x -> Store.Commit.of_hash repo x + | Error (`Msg m) -> Fmt.kstr Lwt.fail_with "Invalid hash %S" m) + heads + in + let* result = Store.integrity_check ?ppf ~auto_repair ~heads repo in + let+ () = Store.Repo.close repo in + handle_result ?ppf ?name:None result + + let heads = + let open Cmdliner.Arg in + value + & opt (some (list ~sep:',' string)) None + & info [ "heads" ] ~doc:"List of head commit hashes" ~docv:"HEADS" + + let auto_repair = + let open Cmdliner.Arg in + value & (flag @@ info ~doc:"Automatically repair issues" [ "auto-repair" ]) + + let always = + let open Cmdliner.Arg in + value & (flag @@ info ~doc:"Use always indexing strategy" [ "always" ]) + + let term_internal = + Cmdliner.Term.( + const (fun root auto_repair always heads () -> + Lwt_main.run + (run ~ppf:Format.err_formatter ~root ~auto_repair ~always ~heads + ())) + $ path + $ auto_repair + $ always + $ heads) + + let term = + let doc = "Check integrity of an existing store." in + Cmdliner.Term. + (term_internal $ setup_log, deprecated_info ~doc "integrity-check") + end + + module Integrity_check_inodes = struct + let conf root = Conf.init ~readonly:true ~fresh:false ~no_migrate:true root + + let heads = + let open Cmdliner.Arg in + value + & opt (some (list ~sep:',' string)) None + & info [ "heads" ] ~doc:"List of head commit hashes" ~docv:"HEADS" + + let run ~root ~heads = + let conf = conf root in + let* repo = Store.Repo.v conf in + let* heads = + match heads with + | None -> Store.Repo.heads repo + | Some heads -> + Lwt_list.filter_map_s + (fun x -> + match Repr.of_string Store.Hash.t x with + | Ok x -> Store.Commit.of_hash repo x + | Error (`Msg m) -> Fmt.kstr Lwt.fail_with "Invalid hash %S" m) + heads + in + let* () = + Store.integrity_check_inodes ~heads repo >|= function + | Ok `No_error -> [%logs.app "Ok"] + | Error (`Cannot_fix msg) -> Fmt.failwith "Error: %s" msg + in + Store.Repo.close repo + + let term_internal = + Cmdliner.Term.( + const (fun root heads () -> Lwt_main.run (run ~root ~heads)) + $ path + $ heads) + + let term = + let doc = "Check integrity of inodes in an existing store." in + Cmdliner.Term. + ( term_internal $ setup_log, + deprecated_info ~doc "integrity-check-inodes" ) + end + + module Stats_commit = struct + let conf root = Conf.init ~readonly:true ~fresh:false ~no_migrate:true root + + let commit = + let open Cmdliner.Arg in + value + & opt (some string) None + & info [ "commit" ] ~doc:"The commit whose underlying tree is traversed." + ~docv:"COMMIT" + + let dump_blob_paths_to = + let open Cmdliner.Arg in + value + & opt (some string) None + & info [ "dump_blob_paths_to" ] + ~doc:"Print all paths to a blob in the tree in a file." + + let run ~root ~commit ~dump_blob_paths_to () = + let conf = conf root in + let* repo = Store.Repo.v conf in + let* commit = + match commit with + | None -> ( + let* heads = Store.Repo.heads repo in + match heads with + | [] -> Lwt.fail_with "No heads found" + | [ head ] -> Lwt.return head + | ls -> + Fmt.kstr Lwt.fail_with + "Several heads found, please specify one. Heads = %a" + Fmt.(list ~sep:comma Store.Commit.pp_hash) + ls) + | Some hash -> ( + match Repr.of_string Store.Hash.t hash with + | Ok x -> ( + Store.Commit.of_hash repo x >>= function + | None -> + Fmt.kstr Lwt.fail_with "Commit with hash %s not found" hash + | Some x -> Lwt.return x) + | Error (`Msg m) -> Fmt.kstr Lwt.fail_with "Invalid hash %S" m) + in + let* () = Store.stats ~dump_blob_paths_to ~commit repo in + Store.Repo.close repo + + let term_internal = + Cmdliner.Term.( + const (fun root commit dump_blob_paths_to () -> + Lwt_main.run (run ~root ~commit ~dump_blob_paths_to ())) + $ path + $ commit + $ dump_blob_paths_to) + + let term = + let doc = + "Traverse one commit, specified with the --commit argument, in the \ + store for stats. If no commit is specified the current head is used." + in + Cmdliner.Term. + (term_internal $ setup_log, deprecated_info ~doc "stat-store") + end + + module Cli = struct + open Cmdliner + + let main + ?(terms = + [ + Stat.term; + Reconstruct_index.term; + Integrity_check.term; + Integrity_check_inodes.term; + Integrity_check_index.term; + Stats_commit.term; + ]) () : empty = + let default = + let default_info = + let doc = "Check Irmin data-stores." in + deprecated_info ~doc "irmin-fsck" + in + Term.(ret (const (`Help (`Auto, None))), default_info) + in + let deprecated_eval_choice = (Term.eval_choice [@alert "-deprecated"]) in + let deprecated_exit = (Term.exit [@alert "-deprecated"]) in + deprecated_eval_choice default terms |> deprecated_exit; + assert false + end + + let cli = Cli.main +end + +module Integrity_checks + (XKey : Pack_key.S) + (X : Irmin.Backend.S + with type Commit.key = XKey.t + and type Node.key = XKey.t + and type Schema.Hash.t = XKey.hash) + (Index : Pack_index.S) = +struct + let check_always ?ppf ~auto_repair ~check index = + let ppf = ppf_or_null ppf in + Fmt.pf ppf "Running the integrity_check.\n%!"; + let nb_absent = ref 0 in + let nb_corrupted = ref 0 in + let exception Cannot_fix in + let counter, (progress_contents, progress_nodes, progress_commits) = + Utils.Object_counter.start ppf + in + let f (k, (offset, length, (kind : Pack_value.Kind.t))) = + match kind with + | Contents -> + progress_contents (); + check ~kind:`Contents ~offset ~length k + | Inode_v1_stable | Inode_v1_unstable | Inode_v2_root | Inode_v2_nonroot + -> + progress_nodes (); + check ~kind:`Node ~offset ~length k + | Commit_v1 | Commit_v2 -> + progress_commits (); + check ~kind:`Commit ~offset ~length k + | Dangling_parent_commit -> assert false + in + let result = + if auto_repair then + try + Index.filter index (fun binding -> + match f binding with + | Ok () -> true + | Error `Wrong_hash -> raise Cannot_fix + | Error `Absent_value -> + incr nb_absent; + false); + if !nb_absent = 0 then Ok `No_error else Ok (`Fixed !nb_absent) + with Cannot_fix -> Error (`Cannot_fix "Not implemented") + else ( + Index.iter + (fun k v -> + match f (k, v) with + | Ok () -> () + | Error `Wrong_hash -> incr nb_corrupted + | Error `Absent_value -> incr nb_absent) + index; + if !nb_absent = 0 && !nb_corrupted = 0 then Ok `No_error + else Error (`Corrupted (!nb_corrupted + !nb_absent))) + in + Utils.Object_counter.finalise counter; + result + + let check_minimal ?ppf ~pred ~iter ~check ~recompute_hash t = + let ppf = ppf_or_null ppf in + Fmt.pf ppf "Running the integrity_check.\n%!"; + let errors = ref [] in + let counter, (progress_contents, progress_nodes, progress_commits) = + Utils.Object_counter.start ppf + in + let pp_hash = Irmin.Type.pp X.Hash.t in + let equal_hash = Irmin.Type.(unstage (equal X.Hash.t)) in + let add_error err hash = + let msg = + match err with + | `Wrong_hash -> Fmt.str "Wrong_hash %a" pp_hash hash + | `Absent_value -> Fmt.str "Absent_value for hash %a" pp_hash hash + in + errors := msg :: !errors + in + let check_contents key = + match Pack_key.inspect key with + | Indexed _hash -> + (* TODO: The goal here is to check a "one commit" store, generated + by a gc, in which indexed keys cannot occur. We might want to + extends this to stores that have both indexed and direct keys. *) + Lwt.fail_with + "Not supported for stores which have entries obtained with irmin < \ + 3.0. If all entries were added with irmin < 3.0, please use \ + [integrity_check] instead." + | Direct { offset; length; hash; _ } -> ( + let result = check ~offset ~length hash in + match result with + | Ok () -> Lwt.return_unit + | Error err -> + add_error err hash; + Lwt.return_unit) + in + (* Commits are read from disk and checked by the [find] function in [pred]. + We need to explicitly check the contents and the nodes. *) + let contents key = + progress_contents (); + check_contents key + in + let pred_node repo key = + try + X.Node.find (X.Repo.node_t repo) key >|= function + | None -> + Fmt.failwith "node with hash %a not found" pp_hash + (XKey.to_hash key) + | Some v -> + let preds = pred v in + List.rev_map + (function + | s, `Inode x -> + assert (s = None); + `Node x + | _, `Node x -> `Node x + | _, `Contents x -> `Contents x) + preds + with _exn -> + add_error `Wrong_hash (XKey.to_hash key); + Lwt.return [] + in + let check_nodes key = + X.Node.find (X.Repo.node_t t) key >|= function + | None -> + Fmt.failwith "node with hash %a not found" pp_hash (XKey.to_hash key) + | Some v -> + let h = XKey.to_hash key in + let h' = recompute_hash v in + if not (equal_hash h h') then add_error `Wrong_hash h + in + let node key = + progress_nodes (); + check_nodes key + in + (* Only visit the nodes of the commits and not the parents of the commit. *) + let pred_commit repo k = + try + progress_commits (); + X.Commit.find (X.Repo.commit_t repo) k >|= function + | None -> [] + | Some c -> + let node = X.Commit.Val.node c in + [ `Node node ] + with _exn -> + add_error `Wrong_hash (XKey.to_hash k); + Lwt.return [] + in + + let+ () = iter ~contents ~node ~pred_node ~pred_commit t in + Utils.Object_counter.finalise counter; + if !errors = [] then Ok `No_error + else + Fmt.kstr + (fun x -> Error (`Cannot_fix x)) + "Inconsistencies found: %a" + Fmt.(list ~sep:comma string) + !errors + + let check_inodes ?ppf ~iter ~pred ~check t = + let ppf = ppf_or_null ppf in + Fmt.pf ppf "Check integrity for inodes.\n%!"; + let counter, (_, progress_nodes, progress_commits) = + Utils.Object_counter.start ppf + in + let errors = ref [] in + let pred_node repo key = + Lwt.catch + (fun () -> pred repo key) + (fun _ -> + errors := "Error in repo iter" :: !errors; + Lwt.return []) + in + let node k = + progress_nodes (); + check k >|= function Ok () -> () | Error msg -> errors := msg :: !errors + in + let commit _ = + progress_commits (); + Lwt.return_unit + in + let+ () = iter ~pred_node ~node ~commit t in + Utils.Object_counter.finalise counter; + if !errors = [] then Ok `No_error + else + Fmt.kstr + (fun x -> Error (`Cannot_fix x)) + "Inconsistent inodes found %a" + Fmt.(list ~sep:comma string) + !errors +end + +module Stats (S : sig + type step + + val step_t : step Irmin.Type.t + + module Hash : Irmin.Hash.S +end) = +struct + type step = Node of S.step | Inode + type path = step list + + module Metrics : sig + type max + type node + + val max_length : node -> int + val all_paths : node -> path list + val mp : node -> max + val maximum : max -> int + val maximal_count : max -> int + val representative : max -> path + + val v : + ?maximal_count:int -> maximum:int -> representative:path -> unit -> max + + val empty_root_node : node + val empty_node : node + val empty_max : max + val update_node : node -> node -> step -> int -> node + val update_width : node -> int -> max -> max + val pp : max Fmt.t + val pp_all_paths : node Fmt.t + end = struct + type max = { maximum : int; maximal_count : int; representative : path } + + type node = { + all_paths : path list; + (* All paths to a node. *) + max_length : int; + (* The max length of a path to a node. *) + mp : max; + (* The maximum size of a membership proof: the number of siblings at + every level along the path. *) + } + + let max_length { max_length; _ } = max_length + let all_paths { all_paths; _ } = all_paths + let mp { mp; _ } = mp + let maximum { maximum; _ } = maximum + let representative { representative; _ } = representative + let maximal_count { maximal_count; _ } = maximal_count + + let v ?(maximal_count = 1) ~maximum ~representative () = + { maximum; maximal_count; representative } + + let empty_max = { maximum = 0; maximal_count = 0; representative = [] } + + let empty_root_node = + let mp = empty_max in + { all_paths = [ [] ]; max_length = 0; mp } + + let empty_node = + let mp = empty_max in + { all_paths = []; max_length = 0; mp } + + let incr ({ maximal_count; _ } as t) = + { t with maximal_count = maximal_count + 1 } + + let update_mp stat_k stat_pred step nb_siblings = + let mp = stat_k.maximum + nb_siblings in + if stat_pred.maximum > mp then stat_pred + else if stat_pred.maximum = mp && not (mp = 0) then incr stat_pred + else + let path_to_k = stat_k.representative in + let new_path_to_pred = step :: path_to_k in + v ~maximum:mp ~representative:new_path_to_pred () + + let update_width stat_k width_k max_width = + if max_width.maximum > width_k then max_width + else if max_width.maximum = width_k then incr max_width + else + let representative = List.hd stat_k.all_paths in + v ~maximum:width_k ~representative () + + let update_path paths_to_k step_k_to_n paths_to_n = + let new_paths_to_n = + List.rev_map (fun rev_path -> step_k_to_n :: rev_path) paths_to_k + in + List.rev_append new_paths_to_n paths_to_n + + let update_node stat_k stat_pred step_k_to_pred nb_siblings = + let all_paths, max_length = + match step_k_to_pred with + | Inode -> + (* Do not update if pred is an inode. *) + (stat_k.all_paths, stat_k.max_length) + | Node _ -> + let paths_to_pred = + update_path stat_k.all_paths step_k_to_pred stat_pred.all_paths + in + let length = + (* The new current length to pred. *) + let lk = stat_k.max_length + 1 in + (* The previous max length to pred. *) + let ln = stat_pred.max_length in + max lk ln + in + (paths_to_pred, length) + in + let mp = update_mp stat_k.mp stat_pred.mp step_k_to_pred nb_siblings in + let stat_pred' = { all_paths; max_length; mp } in + stat_pred' + + let pp_step ppf = function + | Inode -> Fmt.pf ppf "-" + | Node x -> Fmt.pf ppf "%a" (Irmin.Type.pp S.step_t) x + + let pp_path = Fmt.list ~sep:(Fmt.any "/") pp_step + + let pp_all_paths fmt stats = + List.iter + (fun l -> Fmt.pf fmt "%a\n" pp_path (List.rev l)) + stats.all_paths + + let pp = + let open Fmt.Dump in + record + [ + field "maximum" (fun t -> t.maximum) Fmt.int; + field "maximal_count" (fun t -> t.maximal_count) Fmt.int; + field "representative" (fun t -> List.rev t.representative) pp_path; + ] + end + + type t = { + visited : (S.Hash.t, Metrics.node) Hashtbl.t; + mutable max_width : Metrics.max; + mutable max_mp : int; + mutable max_length : int; + } + + let v () = + let visited = Hashtbl.create 100 in + let max_width = Metrics.empty_max in + { visited; max_width; max_length = 0; max_mp = 0 } + + let get t k = + try Hashtbl.find t.visited k with Not_found -> Metrics.empty_node + + let visit_node t k preds ~nb_children ~width = + let preds = + List.map + (function None, x -> (Inode, x) | Some s, x -> (Node s, x)) + preds + in + let stat_k = get t k in + let visit step pred = + let stat_pred = get t pred in + let nb_siblings = nb_children - 1 in + let stat_pred' = Metrics.update_node stat_k stat_pred step nb_siblings in + Hashtbl.replace t.visited pred stat_pred' + in + let () = + List.iter + (function + | Inode, `Inode x -> visit Inode x + | Node s, `Node x -> visit (Node s) x + | Node s, `Contents x -> visit (Node s) x + | _ -> assert false) + preds + in + (* Once we updated its preds we can remove the node from the + table. If its a max width, we update the max_width stats. *) + Hashtbl.remove t.visited k; + t.max_width <- Metrics.update_width stat_k width t.max_width + + let visit_commit t root_node = + let stat = Metrics.empty_root_node in + Hashtbl.replace t.visited root_node stat + + (* Update the max length and max_mp while traversing the contents. *) + let visit_contents t k = + let stat = get t k in + let max_length = Metrics.max_length stat in + if max_length > t.max_length then t.max_length <- max_length; + let maximum = Metrics.mp stat |> Metrics.maximum in + if maximum > t.max_mp then t.max_mp <- maximum + + let pp_results ~dump_blob_paths_to t = + [%log.app "Max width = %a" Metrics.pp t.max_width]; + let maximal_count, representative = + Hashtbl.fold + (fun _ (stat : Metrics.node) ((counter, _) as acc) -> + let maximum = Metrics.mp stat |> Metrics.maximum in + if maximum = t.max_mp then + let maximal_count = Metrics.mp stat |> Metrics.maximal_count in + let counter' = counter + maximal_count in + let repr = Metrics.mp stat |> Metrics.representative in + (counter', repr) + else acc) + t.visited (0, []) + in + let max_mp = + Metrics.v ~maximal_count ~representative ~maximum:t.max_mp () + in + [%log.app "Max number of path-adjacent nodes = %a" Metrics.pp max_mp]; + (* Count all paths that have max length. *) + let maximal_count, representative = + Hashtbl.fold + (fun _ (stat : Metrics.node) acc -> + if Metrics.max_length stat = t.max_length then + List.fold_left + (fun ((counter, _) as acc) l -> + if List.length l = t.max_length then (counter + 1, l) else acc) + acc (Metrics.all_paths stat) + else acc) + t.visited (0, []) + in + let max_length = + Metrics.v ~maximal_count ~representative ~maximum:t.max_length () + in + [%log.app "Max length = %a" Metrics.pp max_length]; + match dump_blob_paths_to with + | None -> () + | Some filename -> + let chan = open_out filename in + let fmt = Format.formatter_of_out_channel chan in + Hashtbl.iter (fun _ stats -> Metrics.pp_all_paths fmt stats) t.visited; + Fmt.flush fmt (); + close_out chan +end diff --git a/vendors/irmin/src/irmin-pack/unix/checks.mli b/vendors/irmin/src/irmin-pack/unix/checks.mli new file mode 100644 index 000000000000..e8b7970d40fd --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/checks.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Offline stats for Irmin stores. *) + +include Checks_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/checks_intf.ml b/vendors/irmin/src/irmin-pack/unix/checks_intf.ml new file mode 100644 index 000000000000..60149772fd3c --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/checks_intf.ml @@ -0,0 +1,224 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +type empty = | + +module type Subcommand = sig + type run + + val run : run + + val term_internal : (unit -> unit) Cmdliner.Term.t + (** A pre-packaged [Cmdliner] term for executing {!run}. *) + + val term : (unit Cmdliner.Term.t * Cmdliner.Term.info[@alert "-deprecated"]) + (** [term] is {!term_internal} plus documentation and logs initialisation *) +end + +module type S = sig + (** Reads basic metrics from an existing store and prints them to stdout. *) + module Stat : sig + include Subcommand with type run := root:string -> unit Lwt.t + + (** Internal implementation utilities exposed for use in other integrity + checks. *) + + type size = Bytes of int [@@deriving irmin] + + type objects = { nb_commits : int; nb_nodes : int; nb_contents : int } + [@@deriving irmin] + + val traverse_index : root:string -> int -> objects + end + + module Reconstruct_index : + Subcommand + with type run := + root:string -> + output:string option -> + ?index_log_size:int -> + unit -> + unit + (** Rebuilds an index for an existing pack file *) + + (** Checks the integrity of a store *) + module Integrity_check : sig + include + Subcommand + with type run := + ?ppf:Format.formatter -> + root:string -> + auto_repair:bool -> + always:bool -> + heads:string list option -> + unit -> + unit Lwt.t + + val handle_result : + ?ppf:Format.formatter -> + ?name:string -> + ( [< `Fixed of int | `No_error ], + [< `Cannot_fix of string | `Corrupted of int ] ) + result -> + unit + end + + (** Checks the integrity of the index in a store *) + module Integrity_check_index : sig + include + Subcommand + with type run := root:string -> auto_repair:bool -> unit -> unit + end + + (** Checks the integrity of inodes in a store *) + module Integrity_check_inodes : sig + include + Subcommand + with type run := root:string -> heads:string list option -> unit Lwt.t + end + + (** Traverses a commit to get stats on its underlying tree. *) + module Stats_commit : sig + include + Subcommand + with type run := + root:string -> + commit:string option -> + dump_blob_paths_to:string option -> + unit -> + unit Lwt.t + end + + val cli : + ?terms: + ((unit Cmdliner.Term.t * Cmdliner.Term.info)[@alert "-deprecated"]) list -> + unit -> + empty + (** Run a [Cmdliner] binary containing tools for running offline checks. + [terms] defaults to the set of checks in this module. *) +end + +module type Store = sig + include Irmin.S + include Store_intf.S with type repo := repo and type commit := commit +end + +type integrity_error = [ `Wrong_hash | `Absent_value ] + +module type Sigs = sig + type integrity_error = [ `Wrong_hash | `Absent_value ] + type nonrec empty = empty + + val setup_log : unit Cmdliner.Term.t + val path : string Cmdliner.Term.t + + module type Subcommand = Subcommand + module type S = S + + module Make (_ : Store) : S + + module Integrity_checks + (XKey : Pack_key.S) + (X : Irmin.Backend.S + with type Commit.key = XKey.t + and type Node.key = XKey.t + and type Schema.Hash.t = XKey.hash) + (Index : Pack_index.S) : sig + val check_always : + ?ppf:Format.formatter -> + auto_repair:bool -> + check: + (kind:[> `Commit | `Contents | `Node ] -> + offset:int63 -> + length:int -> + Index.key -> + (unit, [< `Absent_value | `Wrong_hash ]) result) -> + Index.t -> + ( [> `Fixed of int | `No_error ], + [> `Cannot_fix of string | `Corrupted of int ] ) + result + + val check_minimal : + ?ppf:Format.formatter -> + pred: + (X.Node.value -> + (X.Node.Path.step option + * [< `Contents of XKey.t | `Inode of XKey.t | `Node of XKey.t ]) + list) -> + iter: + (contents:(XKey.hash Pack_key.t -> unit Lwt.t) -> + node:(XKey.t -> unit Lwt.t) -> + pred_node: + (X.Repo.t -> + XKey.t -> + [> `Contents of XKey.t | `Node of XKey.t ] list Lwt.t) -> + pred_commit:(X.Repo.t -> XKey.t -> [> `Node of XKey.t ] list Lwt.t) -> + X.Repo.t -> + unit Lwt.t) -> + check: + (offset:int63 -> + length:int -> + XKey.hash -> + (unit, [< `Absent_value | `Wrong_hash ]) result) -> + recompute_hash:(X.Node.value -> XKey.hash) -> + X.Repo.t -> + ([> `No_error ], [> `Cannot_fix of string ]) result Lwt.t + + val check_inodes : + ?ppf:Format.formatter -> + iter: + (pred_node: + (X.Repo.t -> + XKey.t -> + ([> `Contents of XKey.t | `Node of XKey.t ] as 'a) list Lwt.t) -> + node:(XKey.t -> unit Lwt.t) -> + commit:(XKey.t -> unit Lwt.t) -> + X.Repo.t -> + unit Lwt.t) -> + pred:(X.Repo.t -> XKey.t -> 'a list Lwt.t) -> + check:(XKey.t -> (unit, string) result Lwt.t) -> + X.Repo.t -> + ([> `No_error ], [> `Cannot_fix of string ]) result Lwt.t + end + + module Stats (S : sig + type step + + val step_t : step Irmin.Type.t + + module Hash : Irmin.Hash.S + end) : sig + type t + + val v : unit -> t + val visit_commit : t -> S.Hash.t -> unit + val visit_contents : t -> S.Hash.t -> unit + + val visit_node : + t -> + S.Hash.t -> + (S.step option + * [ `Contents of S.Hash.t | `Inode of S.Hash.t | `Node of S.Hash.t ]) + list -> + nb_children:int -> + width:int -> + unit + + val pp_results : dump_blob_paths_to:string option -> t -> unit + end +end diff --git a/vendors/irmin/src/irmin-pack/unix/chunked_suffix.ml b/vendors/irmin/src/irmin-pack/unix/chunked_suffix.ml new file mode 100644 index 000000000000..0167f8d64af6 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/chunked_suffix.ml @@ -0,0 +1,359 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Chunked_suffix_intf + +module Make (Io : Io.S) (Errs : Io_errors.S with module Io = Io) = struct + module Io = Io + module Errs = Errs + module Ao = Append_only_file.Make (Io) (Errs) + + type chunk = { idx : int; suffix_off : int63; ao : Ao.t } + type create_error = Io.create_error + + type open_error = + [ Io.open_error + | `Closed + | `Invalid_argument + | `Inconsistent_store + | `Read_out_of_bounds ] + + type add_new_error = + [ open_error + | Io.close_error + | `Pending_flush + | `File_exists of string + | `Multiple_empty_chunks ] + + (** A simple container for chunks. *) + module Inventory : sig + type t + + val v : int -> (int -> chunk) -> t + val appendable : t -> chunk + + val find : off:int63 -> t -> chunk * int63 + (** [find ~off t] returns the chunk that contains suffix offset [off], along + with the corresponding [poff] within the chunk. + + Raises `Read_out_of_bounds exception. *) + + val fold : + (acc:'a -> is_appendable:bool -> chunk:chunk -> 'a) -> 'a -> t -> 'a + + val open_ : + start_idx:int -> + chunk_num:int -> + open_chunk: + (chunk_idx:int -> + is_legacy:bool -> + is_appendable:bool -> + (Ao.t, open_error) result) -> + (t, [> open_error ]) result + + val close : t -> (unit, [> Io.close_error | `Pending_flush ]) result + + val add_new_appendable : + open_chunk: + (chunk_idx:int -> + is_legacy:bool -> + is_appendable:bool -> + (Ao.t, add_new_error) result) -> + t -> + (unit, [> add_new_error ]) result + + val length : t -> int63 + (** [length t] is the length of bytes for all chunks *) + + val start_idx : t -> int + (** [start_idx t] is the idx of the first chunk *) + + val count : t -> int + (** [count t] is the number of chunks *) + end = struct + type t = { mutable chunks : chunk Array.t } + + exception OpenInventoryError of open_error + + let v num create = { chunks = Array.init num create } + let appendable t = Array.get t.chunks (Array.length t.chunks - 1) + + let find ~off t = + let open Int63.Syntax in + let suffix_off_to_chunk_poff c = off - c.suffix_off in + let find c = + let end_poff = Ao.end_poff c.ao in + let poff = suffix_off_to_chunk_poff c in + Int63.zero <= poff && poff < end_poff + in + match Array.find_opt find t.chunks with + | None -> raise (Errors.Pack_error `Read_out_of_bounds) + | Some c -> (c, suffix_off_to_chunk_poff c) + + let end_offset_of_chunk start_offset ao = + let chunk_len = Ao.end_poff ao in + Int63.Syntax.(start_offset + chunk_len) + + let is_legacy chunk_idx = chunk_idx = 0 + + let fold f acc t = + let appendable_idx = (appendable t).idx in + Array.fold_left + (fun acc chunk -> + let is_appendable = chunk.idx = appendable_idx in + f ~acc ~is_appendable ~chunk) + acc t.chunks + + let open_ ~start_idx ~chunk_num ~open_chunk = + let off_acc = ref Int63.zero in + let create_chunk i = + let suffix_off = !off_acc in + let is_appendable = i = chunk_num - 1 in + let chunk_idx = start_idx + i in + let is_legacy = is_legacy chunk_idx in + let open_result = open_chunk ~chunk_idx ~is_legacy ~is_appendable in + match open_result with + | Error err -> raise (OpenInventoryError err) + | Ok ao -> + off_acc := end_offset_of_chunk suffix_off ao; + { idx = chunk_idx; suffix_off; ao } + in + try Ok (v chunk_num create_chunk) + with OpenInventoryError err -> + Error (err : open_error :> [> open_error ]) + + let close t = + (* Close immutable chunks, ignoring errors. *) + let _ = + Array.sub t.chunks 0 (Array.length t.chunks - 1) + |> Array.iter @@ fun chunk -> + let _ = Ao.close chunk.ao in + () + in + (* Close appendable chunk and keep error since this + is the one that can have a pending flush. *) + (appendable t).ao |> Ao.close + + let wrap_error result = + Result.map_error + (fun err -> (err : add_new_error :> [> add_new_error ])) + result + + let reopen_last_chunk ~open_chunk t = + (* Close the previous appendable chunk and reopen as non-appendable. *) + let open Result_syntax in + let ({ idx; ao; suffix_off } as last_chunk) = appendable t in + let is_legacy = is_legacy idx in + (* Compute the suffix_off for the following chunk. *) + let length = end_offset_of_chunk suffix_off ao in + let* () = Ao.close ao in + let* ao = + open_chunk ~chunk_idx:idx ~is_legacy ~is_appendable:false |> wrap_error + in + let pos = Array.length t.chunks - 1 in + t.chunks.(pos) <- { last_chunk with ao }; + Ok length + + let create_appendable_chunk ~open_chunk t suffix_off = + let open Result_syntax in + let next_id = succ (appendable t).idx in + let* ao = + open_chunk ~chunk_idx:next_id ~is_legacy:false ~is_appendable:true + in + Ok { idx = next_id; suffix_off; ao } + + let add_new_appendable ~open_chunk t = + let open Result_syntax in + let* next_suffix_off = reopen_last_chunk ~open_chunk t in + let* chunk = + create_appendable_chunk ~open_chunk t next_suffix_off |> wrap_error + in + t.chunks <- Array.append t.chunks [| chunk |]; + Ok () + + let length t = + let open Int63.Syntax in + Array.fold_left (fun sum c -> sum + Ao.end_poff c.ao) Int63.zero t.chunks + + let count t = Array.length t.chunks + let start_idx t = t.chunks.(0).idx + end + + type t = { inventory : Inventory.t; root : string; dead_header_size : int } + + let chunk_path = Layout.V4.suffix_chunk + + let create_rw ~root ~start_idx ~overwrite ~auto_flush_threshold + ~auto_flush_procedure = + let open Result_syntax in + let chunk_idx = start_idx in + let path = chunk_path ~root ~chunk_idx in + let+ ao = + Ao.create_rw ~path ~overwrite ~auto_flush_threshold ~auto_flush_procedure + in + let chunk = { idx = chunk_idx; suffix_off = Int63.zero; ao } in + let inventory = Inventory.v 1 (Fun.const chunk) in + { inventory; root; dead_header_size = 0 } + + (** A module to adjust values when mapping from chunks to append-only files *) + module Ao_shim = struct + type t = { dead_header_size : int; end_poff : int63 } + + let v ~path ~appendable_chunk_poff ~dead_header_size ~is_legacy + ~is_appendable = + let open Result_syntax in + (* Only use the legacy dead_header_size for legacy chunks. *) + let dead_header_size = if is_legacy then dead_header_size else 0 in + (* The appendable chunk uses the provided [appendable_chunk_poff]; but the others + read their size on disk. TODO: this is needed for the Ao module's current + APIs but could perhaps be removed by future Ao API modifications. *) + let+ end_poff = + if is_appendable then Ok appendable_chunk_poff + else + match Io.size_of_path path with + (* Subtract [dead_header_size] because the poff value stored in the + control file does the same. *) + | Ok s -> Ok Int63.Syntax.(s - Int63.of_int dead_header_size) + | Error _ as e -> e + in + { dead_header_size; end_poff } + end + + let open_rw ~root ~appendable_chunk_poff ~start_idx ~chunk_num + ~dead_header_size ~auto_flush_threshold ~auto_flush_procedure = + let open Result_syntax in + let open_chunk ~chunk_idx ~is_legacy ~is_appendable = + let path = chunk_path ~root ~chunk_idx in + let* { dead_header_size; end_poff } = + Ao_shim.v ~path ~appendable_chunk_poff ~dead_header_size ~is_legacy + ~is_appendable + in + match is_appendable with + | true -> + Ao.open_rw ~path ~end_poff ~dead_header_size ~auto_flush_threshold + ~auto_flush_procedure + | false -> Ao.open_ro ~path ~end_poff ~dead_header_size + in + let+ inventory = Inventory.open_ ~start_idx ~chunk_num ~open_chunk in + { inventory; root; dead_header_size } + + let open_ro ~root ~appendable_chunk_poff ~dead_header_size ~start_idx + ~chunk_num = + let open Result_syntax in + let open_chunk ~chunk_idx ~is_legacy ~is_appendable = + let path = chunk_path ~root ~chunk_idx in + let* { dead_header_size; end_poff } = + Ao_shim.v ~path ~appendable_chunk_poff ~dead_header_size ~is_legacy + ~is_appendable + in + Ao.open_ro ~path ~end_poff ~dead_header_size + in + let+ inventory = Inventory.open_ ~start_idx ~chunk_num ~open_chunk in + { inventory; root; dead_header_size } + + let start_idx t = Inventory.start_idx t.inventory + let chunk_num t = Inventory.count t.inventory + let appendable_ao t = (Inventory.appendable t.inventory).ao + let appendable_chunk_poff t = appendable_ao t |> Ao.end_poff + let end_soff t = Inventory.length t.inventory + + let read_exn t ~off ~len buf = + let rec read progress_off suffix_off len_requested = + let open Int63.Syntax in + (* Find chunk with [suffix_off] and calculate length we can read. *) + let chunk, poff = Inventory.find ~off:suffix_off t.inventory in + let chunk_end_poff = Ao.end_poff chunk.ao in + let read_end_poff = poff + len_requested in + let len_read = + if read_end_poff > chunk_end_poff then chunk_end_poff - poff + else len_requested + in + + (* Perform read. If this is the first read, we can use [buf]; otherwise, + we create a new buffer and transfer after the read. *) + let len_i = Int63.to_int len_read in + let is_first_read = progress_off = Int63.zero in + let ao_buf = if is_first_read then buf else Bytes.create len_i in + Ao.read_exn chunk.ao ~off:poff ~len:len_i ao_buf; + if not is_first_read then + Bytes.blit ao_buf 0 buf (Int63.to_int progress_off) len_i; + + (* Read more if any is [rem]aining. *) + let rem = len_requested - len_read in + if rem > Int63.zero then + read (progress_off + len_read) (suffix_off + len_read) rem + else () + in + read Int63.zero off (Int63.of_int len) + + let read_range_exn t ~off ~min_len ~max_len buf = + let len = + let max_off = end_soff t in + let bytes_after_off = Int63.(to_int Syntax.(max_off - off)) in + if bytes_after_off < min_len then + raise (Errors.Pack_error `Read_out_of_bounds) + else if bytes_after_off > max_len then max_len + else bytes_after_off + in + read_exn t ~off ~len buf; + len + + let append_exn t s = Ao.append_exn (appendable_ao t) s + + let add_chunk ~auto_flush_threshold ~auto_flush_procedure t = + let open Result_syntax in + let* () = + let end_poff = appendable_chunk_poff t in + if Int63.(equal end_poff zero) then Error `Multiple_empty_chunks + else Ok () + in + let root = t.root in + let dead_header_size = t.dead_header_size in + let open_chunk ~chunk_idx ~is_legacy ~is_appendable = + let path = chunk_path ~root ~chunk_idx in + let* { dead_header_size; end_poff } = + Ao_shim.v ~path ~appendable_chunk_poff:Int63.zero ~dead_header_size + ~is_legacy ~is_appendable + in + match is_appendable with + | true -> + Ao.create_rw ~path ~overwrite:true ~auto_flush_threshold + ~auto_flush_procedure + | false -> Ao.open_ro ~path ~end_poff ~dead_header_size + in + Inventory.add_new_appendable ~open_chunk t.inventory + + let close t = Inventory.close t.inventory + let empty_buffer t = appendable_ao t |> Ao.empty_buffer + let flush t = appendable_ao t |> Ao.flush + let fsync t = appendable_ao t |> Ao.fsync + + let refresh_appendable_chunk_poff t new_poff = + Ao.refresh_end_poff (appendable_ao t) new_poff + + let readonly t = appendable_ao t |> Ao.readonly + let auto_flush_threshold t = appendable_ao t |> Ao.auto_flush_threshold + + let fold_chunks f acc t = + Inventory.fold + (fun ~acc ~is_appendable ~chunk -> + let len = Ao.end_poff chunk.ao in + let start_suffix_off = chunk.suffix_off in + let end_suffix_off = Int63.Syntax.(start_suffix_off + len) in + f ~acc ~idx:chunk.idx ~start_suffix_off ~end_suffix_off ~is_appendable) + acc t.inventory +end diff --git a/vendors/irmin/src/irmin-pack/unix/chunked_suffix.mli b/vendors/irmin/src/irmin-pack/unix/chunked_suffix.mli new file mode 100644 index 000000000000..36e443f191bc --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/chunked_suffix.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Chunked_suffix_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/chunked_suffix_intf.ml b/vendors/irmin/src/irmin-pack/unix/chunked_suffix_intf.ml new file mode 100644 index 000000000000..c294151a3ff8 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/chunked_suffix_intf.ml @@ -0,0 +1,141 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type S = sig + (** Abstraction for a chunked suffix. It is functionally equivalent to + {!Append_only_file} but with a chunked implementation that is + parameterized by + + - [start_idx] for {!create_rw} to know the starting file name, and + - [start_idx] and [chunk_num] for the open functions to know the starting + file name and how many files there are. *) + + module Io : Io.S + module Errs : Io_errors.S + module Ao : Append_only_file.S + + type t + type create_error = Io.create_error + + type open_error = + [ Io.open_error + | `Closed + | `Invalid_argument + | `Inconsistent_store + | `Read_out_of_bounds ] + + type add_new_error = + [ open_error + | Io.close_error + | `Pending_flush + | `File_exists of string + | `Multiple_empty_chunks ] + + val create_rw : + root:string -> + start_idx:int -> + overwrite:bool -> + auto_flush_threshold:int -> + auto_flush_procedure:Ao.auto_flush_procedure -> + (t, [> create_error ]) result + + val open_rw : + root:string -> + appendable_chunk_poff:int63 -> + start_idx:int -> + chunk_num:int -> + dead_header_size:int -> + auto_flush_threshold:int -> + auto_flush_procedure:Ao.auto_flush_procedure -> + (t, [> open_error ]) result + + val open_ro : + root:string -> + appendable_chunk_poff:int63 -> + dead_header_size:int -> + start_idx:int -> + chunk_num:int -> + (t, [> open_error ]) result + + val add_chunk : + auto_flush_threshold:int -> + auto_flush_procedure:Ao.auto_flush_procedure -> + t -> + (unit, [> add_new_error ]) result + + val start_idx : t -> int + val chunk_num : t -> int + val close : t -> (unit, [> Io.close_error | `Pending_flush ]) result + val empty_buffer : t -> bool + val flush : t -> (unit, [> Io.write_error ]) result + val fsync : t -> (unit, [> Io.write_error ]) result + + val appendable_chunk_poff : t -> int63 + (** [appendable_chunk_poff t] is the number of bytes of the chunk file that is + currently appendable. It does not perform IO. + + {3 RW mode} + + It also counts the bytes not flushed yet. + + {3 RO mode} + + This information originates from the latest reload of the control file. + Calling [refresh_appendable_chunk_poff t] updates [appendable_chunk_poff]. *) + + val refresh_appendable_chunk_poff : + t -> int63 -> (unit, [> `Rw_not_allowed ]) result + (** Ingest the new end offset of the appendable chunk file. Typically happens + in RO mode when the control file has been re-read. + + {3 RW mode} + + Always returns [Error `Rw_not_allowed]. *) + + val end_soff : t -> int63 + (** [end_soff t] is the end offset for the chunked suffix. The valid range of + offsets is 0 <= off < end_soff. Therefore, [end_soff] also represents the + length of the chunked suffix. *) + + val read_exn : t -> off:int63 -> len:int -> bytes -> unit + + val read_range_exn : + t -> off:int63 -> min_len:int -> max_len:int -> bytes -> int + + val append_exn : t -> string -> unit + val readonly : t -> bool + val auto_flush_threshold : t -> int option + + val fold_chunks : + (acc:'a -> + idx:int -> + start_suffix_off:int63 -> + end_suffix_off:int63 -> + is_appendable:bool -> + 'a) -> + 'a -> + t -> + 'a +end + +module type Sigs = sig + module type S = S + + module Make (Io : Io.S) (Errs : Io_errors.S with module Io = Io) : + S with module Io = Io and module Errs = Errs +end diff --git a/vendors/irmin/src/irmin-pack/unix/control_file.ml b/vendors/irmin/src/irmin-pack/unix/control_file.ml new file mode 100644 index 000000000000..289712505db4 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/control_file.ml @@ -0,0 +1,400 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Control_file_intf +module Version = Irmin_pack.Version + +module Checksum = struct + let calculate ~encode_bin ~set_checksum ~payload = + let open Checkseum in + let result = ref Adler32.default in + encode_bin (set_checksum payload Int63.zero) (fun str -> + result := Adler32.digest_string str 0 (String.length str) !result); + Int63.of_int (Optint.to_int !result) + + let calculate_and_set ~encode_bin ~set_checksum ~payload = + calculate ~encode_bin ~set_checksum ~payload |> set_checksum payload + + let is_valid ~encode_bin ~set_checksum ~get_checksum ~payload = + Int63.equal + (calculate ~encode_bin ~set_checksum ~payload) + (get_checksum payload) +end + +module Serde = struct + module type S = sig + type payload + type raw_payload + + val of_bin_string : + string -> + string -> + ( payload, + [> `Corrupted_control_file of string + | `Unknown_major_pack_version of string ] ) + result + + val raw_of_bin_string : + string -> + string -> + ( raw_payload, + [> `Corrupted_control_file of string + | `Unknown_major_pack_version of string ] ) + result + + val to_bin_string : payload -> string + end + + let extract_version_and_payload ctx s = + let open Result_syntax in + let len = String.length s in + let* left, right = + try Ok (String.sub s 0 8, String.sub s 8 (len - 8)) + with Invalid_argument _ -> Error (`Corrupted_control_file ctx) + in + let+ version = + match Version.of_bin left with + | None -> Error (`Unknown_major_pack_version left) + | Some (`V1 | `V2) -> assert false (* TODO: create specific error *) + | Some ((`V3 | `V4 | `V5) as x) -> + if len > Io.Unix.page_size then Error (`Corrupted_control_file ctx) + else Ok x + in + (version, right) + + module Upper : + S + with type payload = Payload.Upper.Latest.t + and type raw_payload = Payload.Upper.raw_payload = struct + module Data = struct + module Plv3 = struct + include Payload.Upper.V3 + + let of_bin_string = Irmin.Type.(unstage (of_bin_string t)) + end + + module Plv4 = struct + include Payload.Upper.V4 + + let is_checksum_valid payload = + let encode_bin = Irmin.Type.(unstage (pre_hash t)) in + let set_checksum payload checksum = { payload with checksum } in + let get_checksum payload = payload.checksum in + Checksum.is_valid ~payload ~encode_bin ~set_checksum ~get_checksum + + let of_bin_string = Irmin.Type.(unstage (of_bin_string t)) + end + + module Plv5 = struct + include Payload.Upper.V5 + + let checksum_encode_bin = Irmin.Type.(unstage (pre_hash t)) + let set_checksum payload checksum = { payload with checksum } + let get_checksum payload = payload.checksum + + let is_checksum_valid payload = + Checksum.is_valid ~payload ~encode_bin:checksum_encode_bin + ~set_checksum ~get_checksum + + let set_checksum payload = + Checksum.calculate_and_set ~encode_bin:checksum_encode_bin + ~set_checksum ~payload + + let of_bin_string = Irmin.Type.(unstage (of_bin_string t)) + let to_bin_string = Irmin.Type.(unstage (to_bin_string t)) + end + + type t = Payload.Upper.raw_payload = + | Valid of version + | Invalid of version + + and version = Payload.Upper.version = + | V3 of Plv3.t + | V4 of Plv4.t + | V5 of Plv5.t + + let to_bin_string = function + | Invalid _ | Valid (V3 _) | Valid (V4 _) -> assert false + | Valid (V5 payload) -> + let payload = Plv5.set_checksum payload in + Version.to_bin `V5 ^ Plv5.to_bin_string payload + + let of_bin_string ctx s = + let open Result_syntax in + let* version, payload = extract_version_and_payload ctx s in + let route_version () = + match version with + | `V3 -> + Plv3.of_bin_string payload >>= fun payload -> + Valid (V3 payload) |> Result.ok + | `V4 -> + Plv4.of_bin_string payload >>= fun payload -> + (match Plv4.is_checksum_valid payload with + | false -> Invalid (V4 payload) + | true -> Valid (V4 payload)) + |> Result.ok + | `V5 -> + Plv5.of_bin_string payload >>= fun payload -> + (match Plv5.is_checksum_valid payload with + | false -> Invalid (V5 payload) + | true -> Valid (V5 payload)) + |> Result.ok + in + match route_version () with + | Ok _ as x -> x + | Error _ -> Error (`Corrupted_control_file ctx) + end + + module Latest = Data.Plv5 + + type payload = Latest.t + type raw_payload = Data.t + + let upgrade_from_v3 (pl : Payload.Upper.V3.t) : payload = + let chunk_start_idx = ref 0 in + let status = + match pl.status with + | From_v1_v2_post_upgrade x -> Latest.From_v1_v2_post_upgrade x + | From_v3_no_gc_yet -> No_gc_yet + | From_v3_used_non_minimal_indexing_strategy -> + Used_non_minimal_indexing_strategy + | From_v3_gced x -> + chunk_start_idx := x.generation; + Gced + { + suffix_start_offset = x.suffix_start_offset; + generation = x.generation; + latest_gc_target_offset = x.suffix_start_offset; + suffix_dead_bytes = Int63.zero; + mapping_end_poff = None; + } + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 + | T14 | T15 -> + (* Unreachable *) + assert false + in + { + dict_end_poff = pl.dict_end_poff; + (* When upgrading from v3 to v4, there is only one (appendable) chunk, + which is the existing suffix, so we set the new [appendable_chunk_poff] + to [pl.suffix_end_poff]. *) + appendable_chunk_poff = pl.suffix_end_poff; + status; + upgraded_from = Some (Version.to_int `V3); + checksum = Int63.zero; + chunk_start_idx = !chunk_start_idx; + chunk_num = 1; + volume_num = 0; + } + + let upgrade_status_from_v4 = function + | Payload.Upper.V4.From_v1_v2_post_upgrade x -> + Latest.From_v1_v2_post_upgrade x + | No_gc_yet -> No_gc_yet + | Used_non_minimal_indexing_strategy -> Used_non_minimal_indexing_strategy + | Gced x -> + Gced + { + suffix_start_offset = x.suffix_start_offset; + generation = x.generation; + latest_gc_target_offset = x.latest_gc_target_offset; + suffix_dead_bytes = x.suffix_dead_bytes; + mapping_end_poff = None; + } + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + (* Unreachable *) + assert false + + let upgrade_from_v4 (pl : Payload.Upper.V4.t) : payload = + { + dict_end_poff = pl.dict_end_poff; + appendable_chunk_poff = pl.appendable_chunk_poff; + checksum = Int63.zero; + chunk_start_idx = pl.chunk_start_idx; + chunk_num = pl.chunk_num; + status = upgrade_status_from_v4 pl.status; + upgraded_from = Some (Version.to_int `V4); + volume_num = 0; + } + + let of_bin_string ctx string = + let open Result_syntax in + let* payload = Data.of_bin_string ctx string in + match payload with + | Invalid _ -> Error (`Corrupted_control_file ctx) + | Valid (V3 payload) -> Ok (upgrade_from_v3 payload) + | Valid (V4 payload) -> Ok (upgrade_from_v4 payload) + | Valid (V5 payload) -> Ok payload + + (* Similar yo [of_bin_string] but skips version upgrade *) + let raw_of_bin_string = Data.of_bin_string + let to_bin_string payload = Data.(to_bin_string (Valid (V5 payload))) + end + + module Volume : + S + with type payload = Payload.Volume.Latest.t + and type raw_payload = Payload.Volume.raw_payload = struct + module Data = struct + module Plv5 = struct + include Payload.Volume.V5 + + let checksum_encode_bin = Irmin.Type.(unstage (pre_hash t)) + let set_checksum payload checksum = { payload with checksum } + let get_checksum payload = payload.checksum + + let is_checksum_valid payload = + Checksum.is_valid ~payload ~encode_bin:checksum_encode_bin + ~set_checksum ~get_checksum + + let set_checksum payload = + Checksum.calculate_and_set ~encode_bin:checksum_encode_bin + ~set_checksum ~payload + + let of_bin_string = Irmin.Type.(unstage (of_bin_string t)) + let to_bin_string = Irmin.Type.(unstage (to_bin_string t)) + end + + type t = Payload.Volume.raw_payload = + | Valid of version + | Invalid of version + + and version = Payload.Volume.version = V5 of Plv5.t + + let to_bin_string = function + | Invalid _ -> assert false + | Valid (V5 payload) -> + let payload = Plv5.set_checksum payload in + Version.to_bin `V5 ^ Plv5.to_bin_string payload + + let of_bin_string ctx s = + let open Result_syntax in + let* version, payload = extract_version_and_payload ctx s in + let route_version () = + match version with + | `V3 | `V4 -> assert false + | `V5 -> + Plv5.of_bin_string payload >>= fun payload -> + (match Plv5.is_checksum_valid payload with + | false -> Invalid (V5 payload) + | true -> Valid (V5 payload)) + |> Result.ok + in + match route_version () with + | Ok _ as x -> x + | Error _ -> Error (`Corrupted_control_file ctx) + end + + module Payload = Data.Plv5 + + type payload = Payload.t + type raw_payload = Data.t + + let of_bin_string ctx string = + let open Result_syntax in + let* payload = Data.of_bin_string ctx string in + match payload with + | Invalid _ -> Error (`Corrupted_control_file ctx) + | Valid (V5 payload) -> Ok payload + + let raw_of_bin_string = Data.of_bin_string + let to_bin_string payload = Data.(to_bin_string (Valid (V5 payload))) + end +end + +module Make (Serde : Serde.S) (Io : Io.S) = struct + module Io = Io + + type payload = Serde.payload + + type t = { + mutable io : Io.t; + mutable payload : payload; + path : string; + tmp_path : string option; + } + + let write io payload = + let s = Serde.to_bin_string payload in + Io.write_string io ~off:Int63.zero s + + let set_payload t payload = + let open Result_syntax in + if Io.readonly t.io then Error `Ro_not_allowed + else + match t.tmp_path with + | None -> Error `No_tmp_path_provided + | Some tmp_path -> + let* () = Io.close t.io in + let* io_tmp = Io.create ~path:tmp_path ~overwrite:true in + t.io <- io_tmp; + let* () = write io_tmp payload in + let+ () = Io.move_file ~src:tmp_path ~dst:t.path in + t.payload <- payload + + let read io = + let open Result_syntax in + let* string = Io.read_all_to_string io in + Serde.of_bin_string (Io.path io) string + + let create_rw ~path ~tmp_path ~overwrite (payload : payload) = + let open Result_syntax in + let* io = Io.create ~path ~overwrite in + let+ () = write io payload in + { io; payload; path; tmp_path } + + let open_ ~path ~tmp_path ~readonly = + let open Result_syntax in + let* io = Io.open_ ~path ~readonly in + let+ payload = read io in + { io; payload; path; tmp_path } + + let close t = Io.close t.io + let readonly t = Io.readonly t.io + let payload t = t.payload + + let reload t = + let open Result_syntax in + if not @@ Io.readonly t.io then Error `Rw_not_allowed + else + let* () = Io.close t.io in + let* io = Io.open_ ~path:t.path ~readonly:true in + t.io <- io; + let+ payload = read io in + t.payload <- payload + + let read_payload ~path = + let open Result_syntax in + let* io = Io.open_ ~path ~readonly:true in + let* payload = read io in + let+ () = Io.close io in + payload + + let read_raw_payload ~path = + let open Result_syntax in + let* io = Io.open_ ~path ~readonly:true in + let* string = Io.read_all_to_string io in + let* payload = Serde.raw_of_bin_string path string in + let+ () = Io.close io in + payload + + let fsync t = Io.fsync t.io +end + +module Upper = Make (Serde.Upper) +module Volume = Make (Serde.Volume) diff --git a/vendors/irmin/src/irmin-pack/unix/control_file.mli b/vendors/irmin/src/irmin-pack/unix/control_file.mli new file mode 100644 index 000000000000..9301acc10347 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/control_file.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Control_file_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/control_file_intf.ml b/vendors/irmin/src/irmin-pack/unix/control_file_intf.ml new file mode 100644 index 000000000000..7ce02130e280 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/control_file_intf.ml @@ -0,0 +1,423 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) +open! Import + +module Payload = struct + module Upper = struct + module V3 = struct + type from_v1_v2_post_upgrade = { entry_offset_at_upgrade_to_v3 : int63 } + [@@deriving irmin] + (** [entry_offset_at_upgrade_to_v3] is the offset of the first entry that + is known to have been created using [irmin_pack_version = `V2] or + more. The entries before that point may be v1 entries. V1 entries need + an entry in index because it is the only place their lenght is stored. *) + + type from_v3_gced = { suffix_start_offset : int63; generation : int } + [@@deriving irmin] + (** [suffix_start_offset] is 0 if the suffix file was never garbage + collected. Otherwise it is the offset of the very first entry of the + suffix file. Note that offsets in the suffix file are virtual. The + garbage collections don't reset the offsets. + + [generation] is the number of past GCs. A suffix file, a prefix file + and a mapping containing that integer in their filename exist. *) + + (** [From_v1_v2_post_upgrade] corresponds to a pack store that was + upgraded to [`V3]. It contains infos related to backward + compatibility. GCs are forbidden on it. + + [From_v3_no_gc_yet] corresponds to a pack store that was created using + [`V3] code. It never underwent a GC. + + [From_v3_used_non_minimal_indexing_strategy] corresponds to a pack + store that was created using [`V3] code. It never underwent a GC and + it will never be possible to GC it because entries were pushed using a + non-minimal indexing strategy. + + [From_v3_gced] is a store that was GCed at least once. + + The [T*] tags are provisional tags that the binary decoder is aware of + and that may in the future be used to add features to the [`V3] + payload. *) + type status = + | From_v1_v2_post_upgrade of from_v1_v2_post_upgrade + | From_v3_no_gc_yet + | From_v3_used_non_minimal_indexing_strategy + | From_v3_gced of from_v3_gced + | T1 + | T2 + | T3 + | T4 + | T5 + | T6 + | T7 + | T8 + | T9 + | T10 + | T11 + | T12 + | T13 + | T14 + | T15 + [@@deriving irmin] + + type t = { + dict_end_poff : int63; + suffix_end_poff : int63; + status : status; (* must be last to allow extensions *) + } + [@@deriving irmin] + (** The [`V3] payload of the irmin-pack control file. [`V3] is a major + version. If [`V4] ever exists, it will have its own dedicated payload, + but the [`V3] definition will still have to stick in the codebase for + backward compatibilty of old pack stores. + + A store may only change its major version during an [open_rw] in + [File_manager]. Note that upgrading a major version is the only reason + why [open_rw] would modify files in an irmin-pack directory. + + For a given major version, the format of a payload may change, but + only in a backward compatible way. I.e., all versions of irmin-pack + should forever be able to decode a [`V3] control file, it allows for + control file corruption and out-of-date code to be distinguishable. + + It is legal for the payload decoder to not fully consume the input + buffer. Remaining bytes means that the definition of a payload was + changed. + + {3 Fields} + + [dict_end_poff] is the offset in the dict file just after the last + valid dict bytes. The next data to be pushed to the dict will be + pushed at this offset. + + [suffix_end_poff] is similar to [dict_end_poff] but for the suffix + file. + + [status] is a variant that encode the state of the irmin-pack + directory. This field MUST be the last field of the record, in order + to allow extensions *) + end + + module V4 = struct + type gced = { + suffix_start_offset : int63; + generation : int; + latest_gc_target_offset : int63; + suffix_dead_bytes : int63; + } + [@@deriving irmin] + (** Similar to [from_v3_gced]. New fields: + + [latest_gc_target_offset] is the commit on which the latest gc was + called on. + + [suffix_dead_bytes] is the number of bytes at the beginning of the + suffix that should be considered unreachable after a GC. *) + + (** [From_v1_v2_post_upgrade] similar to [V3.From_v1_v2_post_upgrade] + + [No_gc_yet] corresponds to a pack store that was created using [`V3] + or above. It never underwent a GC. + + [Used_non_minimal_indexing_strategy] corresponds to a pack store that + was created using [`V3] or above. It never underwent a GC and it will + never be possible to GC it because entries were pushed using a + non-minimal indexing strategy. + + [Gced] is a [`V3] or [`V4] store that was GCed at least once. + + The [T*] tags are provisional tags that the binary decoder is aware of + and that may in the future be used to add features to the [`V4] + payload. *) + type status = + | From_v1_v2_post_upgrade of V3.from_v1_v2_post_upgrade + | No_gc_yet + | Used_non_minimal_indexing_strategy + | Gced of gced + | T1 + | T2 + | T3 + | T4 + | T5 + | T6 + | T7 + | T8 + | T9 + | T10 + | T11 + | T12 + | T13 + | T14 + | T15 + [@@deriving irmin] + + type t = { + dict_end_poff : int63; + appendable_chunk_poff : int63; + upgraded_from_v3_to_v4 : bool; + checksum : int63; + chunk_start_idx : int; + chunk_num : int; + status : status; (* must be last to allow extensions *) + } + [@@deriving irmin] + (** The same as {!V3.t}, with the following modifications: + + New fields + + - [upgraded_from_v3_to_v4] recalls if the store was originally created + in [`V3]. + - [chunk_start_idx] is the index for the starting chunk of the suffix + - [chunk_num] is the number of chunks in the suffix + - [checksum] for storing a checksum of the payload + - [appendable_chunk_poff] is a value used by the chunked suffix. See + {!Chunked_suffix.S.appendable_chunk_poff} for more details. + + Removed fields + + - [suffix_end_poff] is replaced by [appendable_chunk_poff] *) + end + + module V5 = struct + type gced = { + suffix_start_offset : int63; + generation : int; + latest_gc_target_offset : int63; + suffix_dead_bytes : int63; + mapping_end_poff : int63 option; + } + [@@deriving irmin] + + type status = + | From_v1_v2_post_upgrade of V3.from_v1_v2_post_upgrade + | No_gc_yet + | Used_non_minimal_indexing_strategy + | Gced of gced + | T1 + | T2 + | T3 + | T4 + | T5 + | T6 + | T7 + | T8 + | T9 + | T10 + | T11 + | T12 + | T13 + | T14 + | T15 + [@@deriving irmin] + + type t = { + dict_end_poff : int63; + appendable_chunk_poff : int63; + upgraded_from : int option; + checksum : int63; + chunk_start_idx : int; + chunk_num : int; + volume_num : int; + status : status; (* must be last to allow extensions *) + } + [@@deriving irmin] + (** The same as {!V4.t}, with the following modifications: + + New fields + + - [volume_num] stores the number of volumes in the lower layer. + - [mapping_end_poff] stores the mapping file size (optional if missing + or unknown after a migration from V4). + + Changed fields + + - Replaced [upgraded_from_v3_to_v4] with generic field [upgraded_from] + to track version upgrades. Note, it is an [int option] since + [Version.t option] has a bug somewhere in repr that needs further + investigation. *) + end + + type version = V3 of V3.t | V4 of V4.t | V5 of V5.t [@@deriving irmin] + + type raw_payload = Valid of version | Invalid of version + [@@deriving irmin] + + module Latest = V5 + end + + module Volume = struct + module V5 = struct + type t = { + start_offset : int63; + end_offset : int63; + mapping_end_poff : int63; + checksum : int63; + } + [@@deriving irmin] + (** The payload for a control file of a volume. + + Fields + + - [start_offset] is the global offset for the start of the volume's + data. Used for routing reads. + - [end_offset] is the global offset for the end of the volume's data. + Used for routing reads. + - [mapping_end_poff] is the end offset for the mapping file. Used when + writing. *) + end + + type version = V5 of V5.t [@@deriving irmin] + + type raw_payload = Valid of version | Invalid of version + [@@deriving irmin] + + module Latest = V5 + end +end + +module type S = sig + (** Abstraction for an irmin-pack control file. + + It is parameterized with [Io], a file system abstraction (e.g. unix, + mirage, eio_linux). + + None of the functions raise exceptions. *) + + module Io : Io.S + + type payload + type raw_payload + type t + + val create_rw : + path:string -> + tmp_path:string option -> + overwrite:bool -> + payload -> + (t, [> Io.create_error | Io.write_error ]) result + (** Create a rw instance of [t] by creating a control file. *) + + type open_error := + [ `Corrupted_control_file of string + | `Io_misc of Io.misc_error + | `No_such_file_or_directory of string + | `Not_a_file + | `Closed + | `Unknown_major_pack_version of string ] + + val open_ : + path:string -> + tmp_path:string option -> + readonly:bool -> + (t, [> open_error ]) result + (** Create a rw instance of [t] by reading an existing file at [path]. + [tmp_path] will be used by RW instances when updating it's content, it is + not required for RO instances or RW instances which will never be updated. *) + + val close : t -> (unit, [> Io.close_error ]) result + + val read_payload : + path:string -> (payload, [> open_error | Io.close_error ]) result + (** [read_payload ~path] reads the payload at [path]. It is a convenient way + to read the payload without needing to call {!open_}, {!payload}, + {!close}. *) + + val read_raw_payload : + path:string -> (raw_payload, [> open_error | Io.close_error ]) result + + val payload : t -> payload + (** [payload t] is the payload in [t]. + + That function doesn't perform IO. + + {3 RW mode} + + [payload t] is the payload, as it was written to the file system. + + {3 RO mode} + + [payload t] is the [payload], as it was seen during [open_] or during the + most recent [reload]. *) + + type reload_error := [ `Rw_not_allowed | open_error | Io.close_error ] + + val reload : t -> (unit, [> reload_error ]) result + (** {3 RW mode} + + Always returns an error. + + {3 RO mode} + + Reread the file on disk. + + If the file changed since the last read, the payload in [t] is updated to + match the content of the file. *) + + type move_error := [ `Sys_error of string ] + + type set_error := + [ `No_tmp_path_provided + | Io.create_error + | Io.write_error + | move_error + | Io.close_error ] + + val set_payload : t -> payload -> (unit, [> set_error ]) result + (** {3 RW mode} + + Write a new payload on disk. + + {3 RO mode} + + Always returns an error. *) + + val readonly : t -> bool + + val fsync : t -> (unit, [> Io.write_error ]) result + (** {3 RW mode} + + Tell the OS to fush its internal buffers. + + {3 RO mode} + + Always returns [Error `Ro_not_allowed]. *) +end + +module type Upper = sig + include + S + with type payload := Payload.Upper.Latest.t + and type raw_payload := Payload.Upper.raw_payload +end + +module type Volume = sig + include + S + with type payload := Payload.Volume.Latest.t + and type raw_payload := Payload.Volume.raw_payload +end + +module type Sigs = sig + module Payload = Payload + + module type S = S + module type Upper = Upper + module type Volume = Volume + + module Upper (Io : Io.S) : Upper with module Io = Io + module Volume (Io : Io.S) : Volume with module Io = Io +end diff --git a/vendors/irmin/src/irmin-pack/unix/dict.ml b/vendors/irmin/src/irmin-pack/unix/dict.ml new file mode 100644 index 000000000000..786a5fd11689 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dict.ml @@ -0,0 +1,97 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Dict_intf + +module Make (Fm : File_manager.S) = struct + module Fm = Fm + + type t = { + capacity : int; + cache : (string, int) Hashtbl.t; + index : (int, string) Hashtbl.t; + fm : Fm.t; + mutable last_refill_offset : int63; + } + + module File = struct + let append_exn t = Fm.Dict.append_exn (Fm.dict t.fm) + let offset t = Fm.Dict.end_poff (Fm.dict t.fm) + let read_to_string t = Fm.Dict.read_to_string (Fm.dict t.fm) + end + + type nonrec int32 = int32 [@@deriving irmin ~to_bin_string ~decode_bin] + + let append_string t v = + let len = Int32.of_int (String.length v) in + let buf = int32_to_bin_string len ^ v in + File.append_exn t buf + + (* Refill is only called once for a RW instance *) + let refill t = + let open Result_syntax in + let from = t.last_refill_offset in + let len = Int63.to_int Int63.Syntax.(File.offset t - from) in + t.last_refill_offset <- File.offset t; + let+ raw = File.read_to_string t ~off:from ~len in + let pos_ref = ref 0 in + let rec aux n = + if !pos_ref >= len then () + else + let v = decode_bin_int32 raw pos_ref in + let len = Int32.to_int v in + let v = String.sub raw !pos_ref len in + pos_ref := !pos_ref + len; + Hashtbl.add t.cache v n; + Hashtbl.add t.index n v; + (aux [@tailcall]) (n + 1) + in + (aux [@tailcall]) (Hashtbl.length t.cache) + + let index t v = + [%log.debug "[dict] index %S" v]; + try Some (Hashtbl.find t.cache v) + with Not_found -> + let id = Hashtbl.length t.cache in + if id > t.capacity then None + else ( + append_string t v; + Hashtbl.add t.cache v id; + Hashtbl.add t.index id v; + Some id) + + let find t id = + [%log.debug "[dict] find %d" id]; + let v = try Some (Hashtbl.find t.index id) with Not_found -> None in + v + + let default_capacity = 100_000 + + let v fm = + let open Result_syntax in + let cache = Hashtbl.create 997 in + let index = Hashtbl.create 997 in + let last_refill_offset = Int63.zero in + let t = + { capacity = default_capacity; index; cache; fm; last_refill_offset } + in + let* () = refill t in + Fm.register_dict_consumer fm ~after_reload:(fun () -> refill t); + Ok t + + let close _ = () +end diff --git a/vendors/irmin/src/irmin-pack/unix/dict.mli b/vendors/irmin/src/irmin-pack/unix/dict.mli new file mode 100644 index 000000000000..061578cb0f6d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dict.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Dict_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/dict_intf.ml b/vendors/irmin/src/irmin-pack/unix/dict_intf.ml new file mode 100644 index 000000000000..67673624344d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dict_intf.ml @@ -0,0 +1,32 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + module Fm : File_manager.S + + type t + + val find : t -> int -> string option + val index : t -> string -> int option + val v : Fm.t -> (t, [> Fm.Io.read_error ]) result + val close : t -> unit +end + +module type Sigs = sig + module type S = S + + module Make (Fm : File_manager.S) : S with module Fm = Fm +end diff --git a/vendors/irmin/src/irmin-pack/unix/dispatcher.ml b/vendors/irmin/src/irmin-pack/unix/dispatcher.ml new file mode 100644 index 000000000000..45057334e2cd --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dispatcher.ml @@ -0,0 +1,153 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Dispatcher_intf +module Payload = Control_file.Payload.Upper.Latest + +(* The following [with module Io = Io.Unix] forces unix *) +module Make (Fm : File_manager.S with module Io = Io.Unix) : + S with module Fm = Fm = struct + module Fm = Fm + module Io = Fm.Io + module Suffix = Fm.Suffix + module Sparse = Fm.Sparse + module Lower = Fm.Lower + module Errs = Fm.Errs + module Control = Fm.Control + + type t = { fm : Fm.t } + + let v fm = + let t = { fm } in + Ok t + + let get_prefix t = + match Fm.prefix t.fm with + | Some prefix -> prefix + | None -> raise (Errors.Pack_error (`Invalid_prefix_read "no prefix found")) + + let get_suffix t = Fm.suffix t.fm + + let suffix_start_offset t = + let pl = Control.payload (Fm.control t.fm) in + match pl.status with + | Payload.From_v1_v2_post_upgrade _ | Used_non_minimal_indexing_strategy + | No_gc_yet -> + Int63.zero + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + assert false + | Gced { suffix_start_offset; _ } -> suffix_start_offset + + let suffix_dead_bytes t = + let pl = Control.payload (Fm.control t.fm) in + match pl.status with + | Payload.From_v1_v2_post_upgrade _ | Used_non_minimal_indexing_strategy + | No_gc_yet -> + Int63.zero + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + assert false + | Gced { suffix_dead_bytes; _ } -> suffix_dead_bytes + + (* Adjust the read in suffix, as the global offset [off] is + [off] = [suffix_start_offset] + [soff] - [suffix_dead_bytes]. *) + let soff_of_offset t off = + let open Int63.Syntax in + let suffix_start_offset = suffix_start_offset t in + let suffix_dead_bytes = suffix_dead_bytes t in + off - suffix_start_offset + suffix_dead_bytes + + let offset_of_soff t soff = + let open Int63.Syntax in + let suffix_start_offset = suffix_start_offset t in + let suffix_dead_bytes = suffix_dead_bytes t in + suffix_start_offset + soff - suffix_dead_bytes + + let end_offset t = + let end_soff = Suffix.end_soff (Fm.suffix t.fm) in + offset_of_soff t end_soff + + let dispatch_suffix t ~off = + let open Int63.Syntax in + if off >= suffix_start_offset t then Some (soff_of_offset t off) else None + + let read_range_exn t ~off ~min_len ~max_len ?volume_identifier buf = + [%log.debug + "read_range_exn ~off:%a ~min_len:%i ~max_len:%i" Int63.pp off min_len + max_len]; + let read_lower ?volume lower = + let len, volume = + Lower.read_range_exn lower ?volume ~off ~min_len ~max_len buf + in + (len, Some volume) + in + let read_sparse () = + try (Sparse.read_range_exn (get_prefix t) ~off ~min_len ~max_len buf, None) + with Errors.Pack_error (`Invalid_sparse_read _) as exn -> ( + match Fm.lower t.fm with + | None -> raise exn + | Some lower -> read_lower lower) + in + match dispatch_suffix t ~off with + | Some off -> + (Suffix.read_range_exn (get_suffix t) ~off ~min_len ~max_len buf, None) + | None -> ( + match (volume_identifier, Fm.lower t.fm) with + | None, _ -> read_sparse () + | volume, Some lower -> read_lower ?volume lower + | Some _, None -> assert false) + + let read_exn t ~off ~len ?volume_identifier buf = + let _, volume = + read_range_exn t ~off ~min_len:len ~max_len:len ?volume_identifier buf + in + volume + + let read_seq_exn t ~off ~len = + let len = Int63.to_int len in + if len <= 0 then Seq.empty + else + let max_read_size = min 8192 len in + let buffer = Bytes.create max_read_size in + let rec aux ~off ~len () = + if len <= 0 then Seq.Nil + else + let read_len = min len max_read_size in + let read_len, _ = + read_range_exn t ~off ~min_len:1 ~max_len:read_len buffer + in + Seq.Cons + ( Bytes.sub_string buffer 0 read_len, + aux + ~off:Int63.Syntax.(off + Int63.of_int read_len) + ~len:(len - read_len) ) + in + aux ~off ~len + + let read_bytes_exn t ~f ~off ~len = Seq.iter f (read_seq_exn t ~off ~len) + + let next_valid_offset t ~off = + let open Int63.Syntax in + match dispatch_suffix t ~off with + | Some soff when soff >= Suffix.end_soff (get_suffix t) -> None + | Some _ -> Some off + | None -> ( + match Sparse.next_valid_offset (get_prefix t) ~off with + | None -> Some (suffix_start_offset t) + | some_off -> some_off) +end diff --git a/vendors/irmin/src/irmin-pack/unix/dispatcher.mli b/vendors/irmin/src/irmin-pack/unix/dispatcher.mli new file mode 100644 index 000000000000..db2f1f3a4b73 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dispatcher.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Dispatcher_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/dispatcher_intf.ml b/vendors/irmin/src/irmin-pack/unix/dispatcher_intf.ml new file mode 100644 index 000000000000..6b1ed8862256 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dispatcher_intf.ml @@ -0,0 +1,105 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type S = sig + module Fm : File_manager.S + + type t + + val v : Fm.t -> (t, [> Fm.Errs.t ]) result + + val read_exn : + t -> + off:int63 -> + len:int -> + ?volume_identifier:Lower.volume_identifier -> + bytes -> + Lower.volume_identifier option + (** [read_exn t ~off ~len buffer] writes into [buffer] the bytes from [off] to + [off+len]. If the read occurred, in a lower volume, its identifier is + returned. + + If you know which volume to read from in the lower, provide + [volume_identifier] to skip checking the prefix. + + Note: [read_exn] is the only read function that supports reading in the + lower. *) + + val read_range_exn : + t -> + off:int63 -> + min_len:int -> + max_len:int -> + ?volume_identifier:Lower.volume_identifier -> + bytes -> + int * Lower.volume_identifier option + (** Same as [read_exn], the amount read is [max_len] if possible or at least + [min_len] if reading more would step over a hole in the sparse file. + Returns the actually read length and optionnaly the volume where the data + was found. *) + + val end_offset : t -> int63 + (** [end_offset] is the end offsets of the pack entries, counting that the + prefix doesn't start at 0. It counts the entries not yet flushed from the + prefix. *) + + val suffix_start_offset : t -> int63 + (** [suffix_start_offset] is the offsets of the first pack entry in the + suffix. All pack entries in the prefix fit below [suffix_start_offset]. *) + + val offset_of_soff : t -> int63 -> int63 + (** [offset_of_soff t suffix_off] converts a suffix offset into a (global) + offset. *) + + val soff_of_offset : t -> int63 -> int63 + (** [soff_of_offset t global_offset] converts a global offset to a suffix + offset. *) + + val read_seq_exn : t -> off:int63 -> len:int63 -> string Seq.t + + val read_bytes_exn : t -> f:(string -> unit) -> off:int63 -> len:int63 -> unit + (** [read_bytes_exn] reads a slice of the global offset space defined by [off] + and [len]. + + The calls to [f] ignore the objects boundaries (i.e. the string passed to + [f] will most of the time not be the beginning of an object). + + The strings passed to [f] are safe. They can be kept around, they are not + the result of an [unsafe_to_string] conversion. + + The call will fail if the [(off, len)] range is invalid. It will succeed + in these cases: + + - If the range designates a slice of the suffix. + - If the range designates a slice of contiguous live bytes in the prefix + - If the range designates a slice of contiguous live bytes that starts in + the prefix and ends in the suffix. This implies that the last chunk of + the prefix is contiguous to the start of the suffix. *) + + val next_valid_offset : t -> off:int63 -> int63 option + (** [next_valid_offset t ~off] returns an offset greater or equal to [off] + that can be read. Used to iterate over the entries while skipping over the + holes in the sparse file. *) +end + +module type Sigs = sig + module type S = S + + module Make (Fm : File_manager.S with module Io = Io.Unix) : + S with module Fm = Fm +end diff --git a/vendors/irmin/src/irmin-pack/unix/dune b/vendors/irmin/src/irmin-pack/unix/dune new file mode 100644 index 000000000000..aaf19e4f82b6 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/dune @@ -0,0 +1,22 @@ +(library + (public_name irmin-pack.unix) + (name irmin_pack_unix) + (libraries + fmt + index + index.unix + irmin + irmin-pack + logs + lwt + lwt.unix + mtime + cmdliner + optint + checkseum + checkseum.ocaml + rusage) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-pack/unix/errors.ml b/vendors/irmin/src/irmin-pack/unix/errors.ml new file mode 100644 index 000000000000..37ab6a5269fa --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/errors.ml @@ -0,0 +1,169 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +(** Finaliser for a function that returns a result and doesn't raise exceptions. + + If the finaliser fails, it is recommended to log the error. *) +let finalise finaliser f = + let res = f () in + finaliser res; + res + +(** Finaliser for a function that might raise exceptions. *) +let finalise_exn finaliser f = + try + let res = f () in + finaliser (Some res); + res + with exn -> + finaliser None; + raise exn + +type base_error = + [ `Double_close + | `File_exists of string + | `Invalid_parent_directory + | `No_such_file_or_directory of string + | `Not_a_file + | `Read_out_of_bounds + | `Invalid_argument + | `Decoding_error + | `Not_a_directory of string + | `Index_failure of string + | `Invalid_layout + | `Corrupted_legacy_file + | `Corrupted_mapping_file of string + | `Pending_flush + | `Rw_not_allowed + | `Migration_needed + | `Migration_to_lower_not_allowed + | `Corrupted_control_file of string + | `Sys_error of string + | `V3_store_from_the_future + | `Gc_forbidden_during_batch + | `Unknown_major_pack_version of string + | `Only_minimal_indexing_strategy_allowed + | `Commit_key_is_dangling of string + | `Dangling_key of string + | `Gc_disallowed of string + | `Node_or_contents_key_is_indexed of string + | `Gc_process_error of string + | `Corrupted_gc_result_file of string + | `Gc_process_died_without_result_file of string + | `Gc_forbidden_on_32bit_platforms + | `Invalid_prefix_read of string + | `Invalid_sparse_read of [ `After | `Before | `Hole ] * int63 + | `Invalid_volume_read of [ `Empty | `Closed ] * int63 + | `Inconsistent_store + | `Split_forbidden_during_batch + | `Split_disallowed + | `Multiple_empty_chunks + | `Forbidden_during_gc + | `Multiple_empty_volumes + | `Volume_missing of string + | `Add_volume_forbidden_during_gc + | `Add_volume_requires_lower + | `Volume_history_newer_than_archived_data of int63 * int63 + | `Lower_has_no_volume + | `Volume_not_found of string + | `No_tmp_path_provided ] +[@@deriving irmin ~pp] +(** [base_error] is the type of most errors that can occur in a [result], except + for errors that have associated exceptions (see below) and backend-specific + errors (see {!Io_errors}). *) + +type closed_error = [ `Closed ] [@@deriving irmin ~pp] +type read_only_error = [ `Ro_not_allowed ] [@@deriving irmin ~pp] +type error = [ base_error | closed_error | read_only_error ] + +exception Pack_error of base_error +exception Closed = Irmin.Closed +exception RO_not_allowed = Irmin_pack.RO_not_allowed + +(** Error manager *) +module type S = sig + type t = error + + val pp : Format.formatter -> [< t ] -> unit + val raise_error : [< t ] -> 'a + val log_error : string -> [< t ] -> unit + val catch : (unit -> 'a) -> ('a, [> t ]) result + val raise_if_error : ('a, [< t ]) result -> 'a + val log_if_error : string -> (unit, [< t ]) result -> unit + val to_json_string : (int63, [< t ]) result -> string + val of_json_string : string -> (int63, [> t ]) result +end + +module Base : S with type t = error = struct + type t = error + + let pp ppf = function + | #read_only_error as e -> pp_read_only_error ppf e + | #closed_error as e -> pp_closed_error ppf e + | #base_error as e -> pp_base_error ppf e + + let raise_error = function + | #read_only_error -> raise RO_not_allowed + | #closed_error -> raise Closed + | #base_error as e -> raise (Pack_error e) + + let log_error context e = [%log.err "%s failed: %a" context pp e] + + let catch f = + try Ok (f ()) with + | Pack_error e -> Error (e : base_error :> [> t ]) + | RO_not_allowed -> Error `Ro_not_allowed + | Closed -> Error `Closed + + let raise_if_error = function Ok x -> x | Error e -> raise_error e + + let log_if_error context = function + | Ok _ -> () + | Error e -> log_error context e + + type err = Pack_error of base_error | Ro_not_allowed | Closed + [@@deriving irmin] + + let t_to_err = function + | #read_only_error -> Ro_not_allowed + | #closed_error -> Closed + | #base_error as e -> Pack_error e + + let err_to_t = function + | Closed -> `Closed + | Ro_not_allowed -> `Ro_not_allowed + | Pack_error e -> (e : base_error :> [> t ]) + + let err_result = Irmin.Type.(result int63 err_t) + + let to_json_string result = + let convert = Result.map_error t_to_err in + convert result |> Irmin.Type.to_json_string err_result + + let of_json_string string = + match (Irmin.Type.of_json_string err_result) string with + | Error (`Msg _) -> Error `Decoding_error + | Ok result -> Result.map_error err_to_t result +end + +let () = + Printexc.register_printer (function + | Pack_error e -> Some (Fmt.str "Pack_error: %a" pp_base_error e) + | RO_not_allowed -> Some "RO_not_allowed" + | Closed -> Some "Closed" + | _ -> None) diff --git a/vendors/irmin/src/irmin-pack/unix/file_manager.ml b/vendors/irmin/src/irmin-pack/unix/file_manager.ml new file mode 100644 index 000000000000..fa296a80a740 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/file_manager.ml @@ -0,0 +1,1063 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +module Payload = Control_file.Payload.Upper.Latest +include File_manager_intf + +let legacy_io_header_size = 16 + +module Make + (Io : Io.S) + (Index : Pack_index.S with module Io = Io) + (Errs : Io_errors.S with module Io = Io) = +struct + module Io = Errs.Io + module Index = Index + module Errs = Io_errors.Make (Io) + module Control = Control_file.Upper (Io) + module Dict = Append_only_file.Make (Io) (Errs) + module Suffix = Chunked_suffix.Make (Io) (Errs) + module Sparse = Sparse_file.Make (Io) + module Lower = Lower.Make (Io) (Errs) + + type after_reload_consumer = { after_reload : unit -> (unit, Errs.t) result } + type after_flush_consumer = { after_flush : unit -> unit } + + type t = { + dict : Dict.t; + control : Control.t; + mutable suffix : Suffix.t; + mutable prefix : Sparse.t option; + lower : Lower.t option; + index : Index.t; + mutable dict_consumers : after_reload_consumer list; + mutable prefix_consumers : after_reload_consumer list; + mutable suffix_consumers : after_flush_consumer list; + indexing_strategy : Irmin_pack.Indexing_strategy.t; + use_fsync : bool; + root : string; + } + + let control t = t.control + let dict t = t.dict + let suffix t = t.suffix + let index t = t.index + let prefix t = t.prefix + let lower t = t.lower + + let close t = + let open Result_syntax in + let* () = Dict.close t.dict in + let* () = Control.close t.control in + let* () = Suffix.close t.suffix in + let* () = Option.might Sparse.close t.prefix in + let+ () = Index.close t.index in + () + + let register_dict_consumer t ~after_reload = + t.dict_consumers <- { after_reload } :: t.dict_consumers + + let register_prefix_consumer t ~after_reload = + t.prefix_consumers <- { after_reload } :: t.prefix_consumers + + let register_suffix_consumer t ~after_flush = + t.suffix_consumers <- { after_flush } :: t.suffix_consumers + + let get_gced = function Payload.Gced x -> Some x | _ -> None + + let generation payload = + match get_gced payload with Some x -> x.generation | None -> 0 + + let mapping_size payload = + match get_gced payload with Some x -> x.mapping_end_poff | None -> None + + let notify_reload_consumers consumers = + List.fold_left + (fun acc { after_reload } -> Result.bind acc after_reload) + (Ok ()) consumers + |> Result.map_error (fun err -> (err : Errs.t :> [> Errs.t ])) + + (** Flush stages ************************************************************* + + The irmin-pack files are only mutated during calls to one of the 3 + following functions. Exceptions: + + - During [create] and [open_rw]. + - During a GC. + - When the branch store is modified. *) + + (** Flush stage 1 *) + let flush_dict t = + let open Result_syntax in + if Dict.empty_buffer t.dict then Ok () + else + let* () = + Stats.incr_fm_field Dict_flushes; + Dict.flush t.dict + in + let* () = if t.use_fsync then Dict.fsync t.dict else Ok () in + let* () = + let pl : Payload.t = Control.payload t.control in + let pl = { pl with dict_end_poff = Dict.end_poff t.dict } in + Control.set_payload t.control pl + in + let+ () = if t.use_fsync then Control.fsync t.control else Ok () in + () + + (** Flush stage 2 *) + let flush_suffix_and_its_deps ?hook t = + let open Result_syntax in + let* () = flush_dict t in + (match hook with Some h -> h `After_dict | None -> ()); + if Suffix.empty_buffer t.suffix then Ok () + else + let* () = + Stats.incr_fm_field Suffix_flushes; + Suffix.flush t.suffix + in + let* () = if t.use_fsync then Suffix.fsync t.suffix else Ok () in + let* () = + let pl : Payload.t = Control.payload t.control in + let status = + match pl.status with + | From_v1_v2_post_upgrade _ -> pl.status + | Gced _ -> pl.status + | No_gc_yet -> + if Irmin_pack.Indexing_strategy.is_minimal t.indexing_strategy + then pl.status + else ( + [%log.warn + "Updating the control file to \ + [Used_non_minimal_indexing_strategy]. It won't be possible \ + to GC this irmin-pack store anymore."]; + Payload.Used_non_minimal_indexing_strategy) + | Used_non_minimal_indexing_strategy -> pl.status + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 + | T14 | T15 -> + assert false + in + let pl = + { + pl with + appendable_chunk_poff = Suffix.appendable_chunk_poff t.suffix; + status; + } + in + Control.set_payload t.control pl + in + let+ () = if t.use_fsync then Control.fsync t.control else Ok () in + List.iter (fun { after_flush } -> after_flush ()) t.suffix_consumers + + (** Flush stage 3 *) + let flush_index_and_its_deps ?hook t = + let open Result_syntax in + let* () = flush_suffix_and_its_deps ?hook t in + (match hook with Some h -> h `After_suffix | None -> ()); + let+ () = + Stats.incr_fm_field Index_flushes; + Index.flush ~with_fsync:t.use_fsync t.index + in + () + + (* Auto flushes *********************************************************** *) + + (** Is expected to be called by the dict when its append buffer is full so + that the file manager flushes. *) + let dict_requires_a_flush_exn t = + Stats.incr_fm_field Auto_dict; + flush_dict t |> Errs.raise_if_error + + (** Is expected to be called by the suffix when its append buffer is full so + that the file manager flushes. *) + let suffix_requires_a_flush_exn t = + Stats.incr_fm_field Auto_suffix; + flush_suffix_and_its_deps t |> Errs.raise_if_error + + (** Is expected to be called by the index when its append buffer is full so + that the dependendies of index are flushes. When the function returns, + index will flush itself. *) + let index_is_about_to_auto_flush_exn t = + Stats.incr_fm_field Auto_index; + flush_suffix_and_its_deps t |> Errs.raise_if_error + + (* Explicit flush ********************************************************* *) + + let flush ?hook t = + Stats.incr_fm_field Flush; + flush_index_and_its_deps ?hook t + + (* Explicit fsync ********************************************************* *) + + let fsync t = + let open Result_syntax in + let* () = Dict.fsync t.dict in + let* () = Suffix.fsync t.suffix in + let* () = Control.fsync t.control in + Index.flush ~with_fsync:true t.index + + (* Constructors *********************************************************** *) + + module Layout = Irmin_pack.Layout.V5 + + let open_prefix ~root ~generation ~mapping_size = + let open Result_syntax in + if generation = 0 then Ok None + else + let mapping = Layout.mapping ~generation ~root in + let data = Layout.prefix ~root ~generation in + let* mapping_size = + match mapping_size with + | Some size -> Ok size + | None -> Io.size_of_path mapping + in + let mapping_size = Int63.to_int mapping_size in + let+ prefix = Sparse.open_ro ~mapping_size ~mapping ~data in + Some prefix + + let reopen_prefix t ~generation ~mapping_size = + let open Result_syntax in + let* some_prefix = open_prefix ~root:t.root ~generation ~mapping_size in + match some_prefix with + | None -> Ok () + | Some _ -> + let prev_prefix = t.prefix in + t.prefix <- some_prefix; + let* () = notify_reload_consumers t.prefix_consumers in + Option.might Sparse.close prev_prefix + + let reopen_suffix t ~chunk_start_idx ~chunk_num ~appendable_chunk_poff = + let open Result_syntax in + (* Invariant: reopen suffix is only called on V3 (and above) suffix files, + for which dead_header_size is 0. *) + let dead_header_size = 0 in + [%log.debug + "reopen_suffix chunk_start_idx:%d chunk_num:%d appendable_chunk_poff:%d" + chunk_start_idx chunk_num + (Int63.to_int appendable_chunk_poff)]; + let readonly = Suffix.readonly t.suffix in + let* suffix1 = + let root = t.root in + let start_idx = chunk_start_idx in + [%log.debug "reload: generation changed, opening suffix"]; + if readonly then + Suffix.open_ro ~root ~appendable_chunk_poff ~dead_header_size ~start_idx + ~chunk_num + else + let auto_flush_threshold = + match Suffix.auto_flush_threshold t.suffix with + | None -> assert false + | Some x -> x + in + let cb _ = suffix_requires_a_flush_exn t in + Suffix.open_rw ~root ~appendable_chunk_poff ~dead_header_size ~start_idx + ~chunk_num ~auto_flush_threshold ~auto_flush_procedure:(`External cb) + in + let suffix0 = t.suffix in + t.suffix <- suffix1; + Suffix.close suffix0 + + let reload_lower t ~volume_num = + match t.lower with + | Some lower -> Lower.reload ~volume_num lower + | None -> Ok () + + let cleanup ~root ~generation ~chunk_start_idx ~chunk_num ~lower = + let () = + Sys.readdir root + |> Array.to_list + |> List.filter (fun filename -> + match Irmin_pack.Layout.Classification.Upper.v filename with + | `Unknown | `Branch | `Control | `Dict | `V1_or_v2_pack -> false + | `Prefix g | `Mapping g -> g <> generation + | `Suffix idx -> + idx < chunk_start_idx || idx > chunk_start_idx + chunk_num + | `Reachable _ | `Sorted _ | `Gc_result _ | `Control_tmp -> true) + |> List.iter (fun residual -> + let filename = Filename.concat root residual in + [%log.debug "Remove residual file %s" filename]; + match Io.unlink filename with + | Ok () -> () + | Error (`Sys_error error) -> + [%log.warn + "Could not remove residual file %s: %s" filename error]) + in + Option.might (Lower.cleanup ~generation) lower + + let add_volume_and_update_control lower control = + let open Result_syntax in + (* Step 1. Add volume *) + let* _ = Lower.add_volume lower in + (* Step 2. Update control file *) + let pl = Control.payload control in + let pl = { pl with volume_num = Lower.volume_num lower } in + [%log.debug "add_volume: update control_file volume_num:%d" pl.volume_num]; + Control.set_payload control pl + + let finish_constructing_rw config control ~make_dict ~make_suffix ~make_index + ~make_lower = + let open Result_syntax in + let root = Irmin_pack.Conf.root config in + let use_fsync = Irmin_pack.Conf.use_fsync config in + let indexing_strategy = Conf.indexing_strategy config in + let pl : Payload.t = Control.payload control in + let generation, mapping_size = + match pl.status with + | From_v1_v2_post_upgrade _ | No_gc_yet + | Used_non_minimal_indexing_strategy -> + (0, None) + | Gced x -> (x.generation, x.mapping_end_poff) + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + assert false + in + let chunk_start_idx = pl.chunk_start_idx in + let chunk_num = pl.chunk_num in + (* 1. Create a ref for dependency injections for auto flushes *) + let instance = ref None in + let get_instance () = + match !instance with + | None -> + [%log.warn + "%s: instance was accessed whilst None; this is unexpected during \ + normal node operation" + __FILE__]; + [%log.warn + "%s: the stack trace is %s" __FILE__ + Printexc.(get_callstack 20 |> raw_backtrace_to_string)]; + (* get_instance is used by the callback functions below; if we reach this point, a + callback was invoked whilst instance was None; it should be the case that we + can ignore the callback *) + assert false + | Some x -> x + in + (* 2. Open the other files *) + let* suffix = + let auto_flush_threshold = + Irmin_pack.Conf.suffix_auto_flush_threshold config + in + let cb _ = suffix_requires_a_flush_exn (get_instance ()) in + make_suffix ~auto_flush_threshold ~auto_flush_procedure:(`External cb) + in + let* prefix = open_prefix ~root ~generation ~mapping_size in + let* dict = + let path = Layout.dict ~root in + let auto_flush_threshold = + Irmin_pack.Conf.dict_auto_flush_threshold config + in + let cb _ = dict_requires_a_flush_exn (get_instance ()) in + make_dict ~path ~auto_flush_threshold ~auto_flush_procedure:(`External cb) + in + let* index = + let log_size = Conf.index_log_size config in + let throttle = Conf.merge_throttle config in + let cb () = + (* when creating the index, the index may call flush_callback, see + https://github.com/mirage/irmin/issues/1963; so we can't assume that instance + is set to Some _ in get_instance(); instead, we check instance, and just ignore + the callback if the instance is None *) + match !instance with + | None -> () + | Some _ -> index_is_about_to_auto_flush_exn (get_instance ()) + in + (* [cb] will not be called during calls to [index.flush] because we will + use [~no_callback:()] *) + make_index ~flush_callback:cb ~readonly:false ~throttle ~log_size root + in + (* 3. Open lower layer *) + let* lower = make_lower () in + (* 4. Perform any GC-related cleanups *) + let* () = cleanup ~root ~generation ~chunk_start_idx ~chunk_num ~lower in + let t = + { + dict; + control; + suffix; + prefix; + lower; + use_fsync; + index; + dict_consumers = []; + prefix_consumers = []; + suffix_consumers = []; + indexing_strategy; + root; + } + in + instance := Some t; + Ok t + + let create_control_file ~overwrite config pl = + let root = Irmin_pack.Conf.root config in + let path = Layout.control ~root in + let tmp_path = Layout.control_tmp ~root in + Control.create_rw ~path ~tmp_path:(Some tmp_path) ~overwrite pl + + (* Reload ***************************************************************** *) + + let reload ?hook t = + let open Result_syntax in + (* Step 1. Reread index *) + let* () = Index.reload t.index in + (match hook with Some h -> h `After_index | None -> ()); + let pl0 = Control.payload t.control in + (* Step 2. Reread control file *) + let* () = Control.reload t.control in + (match hook with Some h -> h `After_control | None -> ()); + let pl1 : Payload.t = Control.payload t.control in + if pl0 = pl1 then Ok () + else + (* Step 3. Reopen files if generation or chunk_num changed. *) + let* () = + let gen0 = generation pl0.status in + let gen1 = generation pl1.status in + let chunk_num0 = pl0.chunk_num in + let chunk_num1 = pl1.chunk_num in + let chunk_start_idx0 = pl0.chunk_start_idx in + let chunk_start_idx1 = pl1.chunk_start_idx in + (* Step 3.1. Potentially reload suffix *) + let* () = + if chunk_num0 <> chunk_num1 || chunk_start_idx0 <> chunk_start_idx1 + then + let appendable_chunk_poff = pl1.appendable_chunk_poff in + reopen_suffix t ~chunk_start_idx:chunk_start_idx1 + ~appendable_chunk_poff ~chunk_num:chunk_num1 + else Ok () + in + (* Step 3.2. Potentially reload prefix *) + let* () = + if gen0 = gen1 then Ok () + else + reopen_prefix t ~generation:gen1 + ~mapping_size:(mapping_size pl1.status) + in + (* Step 3.3. Potentially reload lower *) + if gen0 = gen1 && pl0.volume_num = pl1.volume_num then Ok () + else reload_lower t ~volume_num:pl1.volume_num + in + (* Step 4. Update end offsets *) + let* () = + Suffix.refresh_appendable_chunk_poff t.suffix pl1.appendable_chunk_poff + in + (match hook with Some h -> h `After_suffix | None -> ()); + let* () = Dict.refresh_end_poff t.dict pl1.dict_end_poff in + (* Step 5. Notify the dict consumers that they must reload *) + let* () = notify_reload_consumers t.dict_consumers in + Ok () + + (* File creation ********************************************************** *) + + let create_lower_if_needed ~lower_root ~overwrite = + match lower_root with + | None -> Ok () + | Some path -> ( + match (Io.classify_path path, overwrite) with + | `Directory, false -> Ok () + | `Directory, true -> + (* TODO: implement recursive delete for lower root *) + failwith + (Fmt.str + "Lower root already exists but fresh = true in configuration. \ + Please manually remove %s." + path) + | `No_such_file_or_directory, _ -> Io.mkdir path + | (`File | `Other), _ -> Errs.raise_error (`Not_a_directory path)) + + let create_rw ~overwrite config = + let open Result_syntax in + let root = Irmin_pack.Conf.root config in + let lower_root = Irmin_pack.Conf.lower_root config in + let* () = + match (overwrite, Io.classify_path root) with + | _, (`File | `Other) -> Error (`Not_a_directory root) + | false, `Directory -> Error (`File_exists root) + | true, `Directory -> Ok () + | _, `No_such_file_or_directory -> Io.mkdir root + in + let* () = create_lower_if_needed ~lower_root ~overwrite in + let* control = + let open Payload in + let status = No_gc_yet in + let pl = + let z = Int63.zero in + { + dict_end_poff = z; + appendable_chunk_poff = z; + checksum = z; + status; + upgraded_from = None; + chunk_start_idx = 0; + chunk_num = 1; + volume_num = 0; + } + in + create_control_file ~overwrite config pl + in + let make_dict = Dict.create_rw ~overwrite in + let make_suffix = Suffix.create_rw ~root ~overwrite ~start_idx:0 in + let make_index ~flush_callback ~readonly ~throttle ~log_size root = + (* [overwrite] is ignored for index *) + Index.v ~fresh:true ~flush_callback ~readonly ~throttle ~log_size root + in + let make_lower () = + match lower_root with + | None -> Ok None + | Some path -> + let* l = Lower.v ~readonly:false ~volume_num:0 path in + let+ _ = add_volume_and_update_control l control in + Some l + in + finish_constructing_rw config control ~make_dict ~make_suffix ~make_index + ~make_lower + + (* Open rw **************************************************************** *) + + let dead_header_size_of_status = function + | Payload.From_v1_v2_post_upgrade _ -> legacy_io_header_size + | No_gc_yet | Gced _ | Used_non_minimal_indexing_strategy -> 0 + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + failwith "invalid status: T1..T15" + + let can_migrate_to_lower (payload : Payload.t) = + match payload.status with + | No_gc_yet | Used_non_minimal_indexing_strategy | From_v1_v2_post_upgrade _ + -> + payload.chunk_num = 1 && payload.volume_num = 0 + | Gced _ -> false + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + failwith "invalid status: T1..T15" + + let migrate_to_lower ~root ~lower_root ~control (payload : Payload.t) = + let open Result_syntax in + (* Step 1. Create a lower by moving the suffix file. *) + let suffix_file = + Layout.suffix_chunk ~root ~chunk_idx:payload.chunk_start_idx + in + let dead_header_size = dead_header_size_of_status payload.status in + let end_offset = payload.appendable_chunk_poff in + let* () = + Lower.create_from ~src:suffix_file ~dead_header_size ~size:end_offset + lower_root + in + (* Step 2. Create a new empty suffix for the upper. *) + let chunk_start_idx = payload.chunk_start_idx + 1 in + let* () = + Suffix.create_rw ~root ~overwrite:false ~auto_flush_threshold:1_000_000 + ~auto_flush_procedure:`Internal ~start_idx:chunk_start_idx + >>= Suffix.close + in + (* Step 3. Create a new empty prefix for the upper. *) + let generation = 1 in + let* () = + let mapping = Layout.mapping ~generation ~root in + let data = Layout.prefix ~root ~generation in + Sparse.Ao.create ~mapping ~data >>= Sparse.Ao.close + in + (* Step 4. Remove dead header from dict (if needed) *) + let* dict_end_poff, after_payload_write = + if dead_header_size > 0 then ( + let dict_path = Layout.dict ~root in + let tmp_dict_path = Filename.temp_file ~temp_dir:root "store" "dict" in + let* dict_file = Io.open_ ~path:dict_path ~readonly:false in + let* len = Io.read_size dict_file in + let* tmp_dict_file = Io.open_ ~path:tmp_dict_path ~readonly:false in + let contents_len = Int63.to_int len - dead_header_size in + let* contents = + Io.read_to_string dict_file + ~off:(Int63.of_int dead_header_size) + ~len:contents_len + in + Io.write_exn tmp_dict_file ~off:Int63.zero ~len:contents_len contents; + let* _ = Io.close dict_file in + let* _ = Io.close tmp_dict_file in + (* Delay moving the temp file until after the payload is written so + that we do not try to remove the dead header twice after a failure. *) + Ok + ( Int63.of_int contents_len, + fun () -> Io.move_file ~src:tmp_dict_path ~dst:dict_path )) + else Ok (payload.dict_end_poff, Fun.const (Ok ())) + in + (* Step 5. Update the upper control file. *) + let payload = + { + payload with + dict_end_poff; + chunk_start_idx; + appendable_chunk_poff = Int63.zero; + volume_num = 1; + status = + Gced + { + suffix_start_offset = end_offset; + generation; + latest_gc_target_offset = Int63.zero; + suffix_dead_bytes = Int63.zero; + mapping_end_poff = Some Int63.zero; + }; + } + in + let* () = Control.set_payload control payload in + let* () = after_payload_write () in + Ok payload + + let load_payload ~config ~root ~lower_root ~control = + let payload = Control.payload control in + match lower_root with + | Some lower_root when payload.volume_num = 0 -> + if Irmin_pack.Conf.no_migrate config then Error `Migration_needed + else if not (can_migrate_to_lower payload) then + Error `Migration_to_lower_not_allowed + else migrate_to_lower ~root ~lower_root ~control payload + | _ -> Ok payload + + let open_rw_with_control_file config = + let open Result_syntax in + let root = Irmin_pack.Conf.root config in + let lower_root = Irmin_pack.Conf.lower_root config in + let* () = create_lower_if_needed ~lower_root ~overwrite:false in + let* control = + let path = Layout.control ~root in + let tmp_path = Layout.control_tmp ~root in + Control.open_ ~readonly:false ~path ~tmp_path:(Some tmp_path) + in + let* Payload. + { + status; + appendable_chunk_poff; + chunk_start_idx = start_idx; + chunk_num; + dict_end_poff; + volume_num; + _; + } = + load_payload ~config ~root ~lower_root ~control + in + let* dead_header_size = + match status with + | From_v1_v2_post_upgrade _ -> Ok legacy_io_header_size + | Gced _ -> + let indexing_strategy = Conf.indexing_strategy config in + if Irmin_pack.Indexing_strategy.is_minimal indexing_strategy then Ok 0 + else Error `Only_minimal_indexing_strategy_allowed + | No_gc_yet | Used_non_minimal_indexing_strategy -> Ok 0 + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + Error `V3_store_from_the_future + in + let make_dict = Dict.open_rw ~end_poff:dict_end_poff ~dead_header_size in + let make_suffix = + Suffix.open_rw ~root ~appendable_chunk_poff ~start_idx ~chunk_num + ~dead_header_size + in + let make_index ~flush_callback ~readonly ~throttle ~log_size root = + Index.v ~fresh:false ~flush_callback ~readonly ~throttle ~log_size root + in + let make_lower () = + match lower_root with + | None -> Ok None + | Some lower_root -> + assert (volume_num > 0); + let+ l = Lower.v ~readonly:false ~volume_num lower_root in + Some l + in + finish_constructing_rw config control ~make_dict ~make_suffix ~make_index + ~make_lower + + let read_offset_from_legacy_file path = + let open Result_syntax in + (* Bytes 0-7 contains the offset. Bytes 8-15 contain the version. *) + let* io = Io.open_ ~path ~readonly:true in + Errors.finalise (fun _ -> + Io.close io |> Errs.log_if_error "FM: read_offset_from_legacy_file") + @@ fun () -> + let* s = Io.read_to_string io ~off:Int63.zero ~len:8 in + let x = Int63.decode ~off:0 s in + Ok x + + let read_version_from_legacy_file path = + let open Result_syntax in + (* Bytes 0-7 contains the offset. Bytes 8-15 contain the version. *) + let* io = Io.open_ ~path ~readonly:true in + Errors.finalise (fun _ -> + Io.close io |> Errs.log_if_error "FM: read_version_from_legacy_file") + @@ fun () -> + let off = Int63.of_int 8 in + let* s = Io.read_to_string io ~off ~len:8 in + match Version.of_bin s with + | Some x -> Ok x + | None -> Error `Corrupted_legacy_file + + let open_rw_migrate_from_v1_v2 config = + let open Result_syntax in + let root = Irmin_pack.Conf.root config in + let src = Irmin_pack.Layout.V1_and_v2.pack ~root in + let chunk_start_idx = 0 in + let dst = Layout.suffix_chunk ~root ~chunk_idx:chunk_start_idx in + let* suffix_end_poff = read_offset_from_legacy_file src in + let* dict_end_poff = + let path = Layout.dict ~root in + read_offset_from_legacy_file path + in + let* () = Io.move_file ~src ~dst in + let* control = + let open Payload in + let status = + From_v1_v2_post_upgrade + { entry_offset_at_upgrade_to_v3 = suffix_end_poff } + in + let pl = + { + dict_end_poff; + appendable_chunk_poff = suffix_end_poff; + checksum = Int63.zero; + status; + upgraded_from = None; + chunk_start_idx; + chunk_num = 1; + volume_num = 0; + } + in + create_control_file ~overwrite:false config pl + in + let* () = Control.close control in + open_rw_with_control_file config + + let open_rw_no_control_file config = + let root = Irmin_pack.Conf.root config in + let suffix_path = Irmin_pack.Layout.V1_and_v2.pack ~root in + match Io.classify_path suffix_path with + | `Directory | `No_such_file_or_directory | `Other -> Error `Invalid_layout + | `File -> open_rw_migrate_from_v1_v2 config + + let open_rw config = + let root = Irmin_pack.Conf.root config in + let no_migrate = Irmin_pack.Conf.no_migrate config in + match Io.classify_path root with + | `File | `Other -> Error (`Not_a_directory root) + | `No_such_file_or_directory -> Error (`No_such_file_or_directory root) + | `Directory -> ( + let path = Layout.control ~root in + match Io.classify_path path with + | `File -> open_rw_with_control_file config + | `No_such_file_or_directory -> + if no_migrate then Error `Migration_needed + else open_rw_no_control_file config + | `Directory | `Other -> Error `Invalid_layout) + + (* Open ro **************************************************************** *) + + let open_ro config = + let open Result_syntax in + let indexing_strategy = Conf.indexing_strategy config in + let root = Irmin_pack.Conf.root config in + let lower_root = Irmin_pack.Conf.lower_root config in + let use_fsync = Irmin_pack.Conf.use_fsync config in + (* 1. Open the control file *) + let* control = + let path = Layout.control ~root in + Control.open_ ~readonly:true ~path ~tmp_path:None + (* If no control file, then check whether the store is in v1 or v2. *) + |> Result.map_error (function + | `No_such_file_or_directory _ -> ( + let pack = Irmin_pack.Layout.V1_and_v2.pack ~root in + match Io.classify_path pack with + | `File -> `Migration_needed + | `No_such_file_or_directory -> `No_such_file_or_directory pack + | `Directory | `Other -> `Invalid_layout) + | error -> error) + in + let Payload. + { + status; + appendable_chunk_poff; + chunk_start_idx = start_idx; + chunk_num; + dict_end_poff; + volume_num; + _; + } = + Control.payload control + in + let dead_header_size = dead_header_size_of_status status in + let generation = generation status in + (* 2. Open the other files *) + let* suffix = + Suffix.open_ro ~root ~appendable_chunk_poff ~start_idx ~chunk_num + ~dead_header_size + in + let* prefix = + open_prefix ~root ~generation ~mapping_size:(mapping_size status) + in + let* dict = + let path = Layout.dict ~root in + Dict.open_ro ~path ~end_poff:dict_end_poff ~dead_header_size + in + let* index = + let log_size = Conf.index_log_size config in + let throttle = Conf.merge_throttle config in + Index.v ~fresh:false ~readonly:true ~throttle ~log_size root + in + (* 3. Open lower layer *) + let* lower = + match lower_root with + | None -> Ok None + | Some path -> + let+ l = Lower.v ~readonly:true ~volume_num path in + Some l + in + (* 4. return with success *) + Ok + { + dict; + control; + suffix; + prefix; + lower; + use_fsync; + indexing_strategy; + index; + dict_consumers = []; + prefix_consumers = []; + suffix_consumers = []; + root; + } + + (* MISC. ****************************************************************** *) + + let version ~root = + let v2_or_v1 () = + let path = Irmin_pack.Layout.V1_and_v2.pack ~root in + match read_version_from_legacy_file path with + | Ok v -> Ok v + | Error `Double_close | Error `Invalid_argument | Error `Closed -> + assert false + | Error (`No_such_file_or_directory _) -> Error `Invalid_layout + | Error `Not_a_file -> Error `Invalid_layout + | Error `Corrupted_legacy_file | Error `Read_out_of_bounds -> + Error `Corrupted_legacy_file + | Error (`Io_misc _) as e -> e + in + match Io.classify_path root with + | `No_such_file_or_directory -> Error (`No_such_file_or_directory root) + | `File | `Other -> Error (`Not_a_directory root) + | `Directory -> ( + let path = Layout.control ~root in + match Control.open_ ~path ~tmp_path:None ~readonly:true with + | Ok _ -> Ok `V3 + | Error (`No_such_file_or_directory _) -> v2_or_v1 () + | Error `Not_a_file -> Error `Invalid_layout + | Error `Closed -> assert false + | Error + ( `Io_misc _ | `Corrupted_control_file _ + | `Unknown_major_pack_version _ ) as e -> + e) + + let swap t ~generation ~mapping_size ~suffix_start_offset ~chunk_start_idx + ~chunk_num ~suffix_dead_bytes ~latest_gc_target_offset ~volume = + let open Result_syntax in + [%log.debug + "Gc in main: swap gen %d; suffix start %a; chunk start idx %d; chunk num \ + %d; suffix dead bytes %a" + generation Int63.pp suffix_start_offset chunk_start_idx chunk_num Int63.pp + suffix_dead_bytes]; + let c0 = Mtime_clock.counter () in + let pl = Control.payload t.control in + + (* Step 1. Reopen files *) + let mapping_size = Some mapping_size in + let* () = reopen_prefix t ~generation ~mapping_size in + let* () = + reopen_suffix t ~chunk_start_idx ~chunk_num + ~appendable_chunk_poff:pl.appendable_chunk_poff + in + let span1 = Mtime_clock.count c0 |> Mtime.Span.to_us in + + (* Step 2. Update the control file *) + let* () = + let pl = + let open Payload in + let status = + match pl.status with + | From_v1_v2_post_upgrade _ -> assert false + | Used_non_minimal_indexing_strategy -> assert false + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 + | T14 | T15 -> + assert false + | Gced _ | No_gc_yet -> + Gced + { + suffix_start_offset; + generation; + latest_gc_target_offset; + suffix_dead_bytes; + mapping_end_poff = mapping_size; + } + in + + { pl with status; chunk_start_idx; chunk_num } + in + [%log.debug "GC: writing new control_file"]; + Control.set_payload t.control pl + in + + (* Step 3. Swap volume and reload lower if needed *) + let* () = + match volume with + | None -> Ok () + | Some volume -> ( + match t.lower with + | None -> + assert false + (* Programmer error if lower does not exist but volume is given *) + | Some lower -> + Lower.swap ~volume ~generation ~volume_num:pl.volume_num lower) + in + + let span2 = Mtime_clock.count c0 |> Mtime.Span.to_us in + [%log.debug + "Gc reopen files, update control: %.0fus, %.0fus" span1 (span2 -. span1)]; + Ok () + + let readonly t = Suffix.readonly t.suffix + + let generation t = + let pl = Control.payload t.control in + match pl.status with + | From_v1_v2_post_upgrade _ | Used_non_minimal_indexing_strategy -> 0 + | No_gc_yet -> 0 + | Gced x -> x.generation + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 | T14 + | T15 -> + (* Unreachable *) + assert false + + let gc_behaviour t = match t.lower with Some _ -> `Archive | None -> `Delete + + let gc_destination t = + match gc_behaviour t with + | `Delete -> `Delete + | `Archive -> `Archive (Option.get t.lower) + + let gc_allowed t = + let pl = Control.payload t.control in + let action = gc_behaviour t in + match (action, pl.status) with + | `Delete, (From_v1_v2_post_upgrade _ | Used_non_minimal_indexing_strategy) + -> + false + | `Delete, (No_gc_yet | Gced _) -> true + | `Archive, _ -> true + | ( _, + ( T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 + | T14 | T15 ) ) -> + (* Unreachable *) + assert false + + let split t = + let open Result_syntax in + (* Step 1. Create a new chunk file *) + let auto_flush_threshold = + match Suffix.auto_flush_threshold t.suffix with + | None -> assert false + | Some x -> x + in + let cb _ = suffix_requires_a_flush_exn t in + let* () = + Suffix.add_chunk ~auto_flush_threshold + ~auto_flush_procedure:(`External cb) t.suffix + in + + (* Step 2. Update the control file *) + let pl = Control.payload t.control in + let pl = + let open Payload in + let chunk_num = succ pl.chunk_num in + (* Update the control file with the poff of the last chunk. As last chunk + is fresh, the poff is zero. *) + let appendable_chunk_poff = Int63.zero in + { pl with chunk_num; appendable_chunk_poff } + in + [%log.debug + "split: update control_file chunk_start_idx:%d chunk_num:%d" + pl.chunk_start_idx pl.chunk_num]; + Control.set_payload t.control pl + + let add_volume t = + match t.lower with + | None -> Error `Add_volume_requires_lower + | Some lower -> add_volume_and_update_control lower t.control + + let cleanup t = + let root = t.root in + let pl : Payload.t = Control.payload t.control in + let generation = generation t in + let chunk_start_idx = pl.chunk_start_idx in + let chunk_num = pl.chunk_num in + let lower = t.lower in + cleanup ~root ~generation ~chunk_start_idx ~chunk_num ~lower + + let create_one_commit_store t config gced commit_key = + let open Result_syntax in + let src_root = t.root in + let dst_root = Irmin_pack.Conf.root config in + (* Step 1. Copy the dict *) + let src_dict = Layout.dict ~root:src_root in + let dst_dict = Layout.dict ~root:dst_root in + let* () = Io.copy_file ~src:src_dict ~dst:dst_dict in + (* Step 2. Create an empty suffix and close it. *) + let* suffix = + Suffix.create_rw ~root:dst_root ~overwrite:false + ~auto_flush_threshold:1_000_000 ~auto_flush_procedure:`Internal + ~start_idx:1 + in + let* () = Suffix.close suffix in + (* Step 3. Create the control file and close it. *) + let status = Payload.Gced gced in + let dict_end_poff = Io.size_of_path dst_dict |> Errs.raise_if_error in + let pl = + { + Payload.dict_end_poff; + appendable_chunk_poff = Int63.zero; + checksum = Int63.zero; + status; + upgraded_from = None; + chunk_num = 1; + chunk_start_idx = 1; + volume_num = 0; + } + in + let path = Layout.control ~root:dst_root in + let* control = Control.create_rw ~path ~tmp_path:None ~overwrite:false pl in + let* () = Control.close control in + (* Step 4. Create the index. *) + let* index = + let log_size = Conf.index_log_size config in + let throttle = Conf.merge_throttle config in + Index.v ~fresh:true ~flush_callback:Fun.id ~readonly:false ~throttle + ~log_size dst_root + in + (* Step 5. Add the commit to the index, close the index. *) + let () = + match Pack_key.inspect commit_key with + | Pack_key.Direct { hash; offset; length; _ } -> + Index.add index hash (offset, length, Pack_value.Kind.Commit_v2) + | Indexed _ -> assert false + in + let* () = Index.close index in + Ok () +end diff --git a/vendors/irmin/src/irmin-pack/unix/file_manager.mli b/vendors/irmin/src/irmin-pack/unix/file_manager.mli new file mode 100644 index 000000000000..e4174c98ccee --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/file_manager.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include File_manager_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/file_manager_intf.ml b/vendors/irmin/src/irmin-pack/unix/file_manager_intf.ml new file mode 100644 index 000000000000..a8f2700703ba --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/file_manager_intf.ml @@ -0,0 +1,313 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type S = sig + (** Abstraction that governs the lifetime of the various files that are part + of a pack store (except the branch store). + + The file manager (FM) handles the files one by one and makes explicit all + the interactions between them (except the index which is handled from a + high level API). This allows to gain confidence on SWMR consistency and + crash consistency. + + {2 Two types of guarantees} + + Irmin_pack_unix supports the SWMR access scheme. It means that it is + undefined for the files to be opened twice in RW mode by 2 FMs. It also + means that it is undefined for a FM in RW mode to be used simultaneously + from 2 different fibers. + + Irmin_pack_unix aims to be (crash) consistent (in the ACID sense). In case + of a system failure (e.g. power outage), the files should be left in a + consistent state for later uses. + + Ensuring SWMR consistency is easier than ensuring crash consistency + because the of the OS's shared page cache. + + {2 Files mutations} + + Here are all the moments where the files managed may be mutated: + + - 1. During [create_rw]. + - 2. During [open_rw] if a major version upgrade is necessary. + - 3. During the flush routines in file_manager. + - 4. During a GC, from the worker. + - 5. At the end of a GC, from the RW fiber, in [swap]. + - 6. During integrity check routines. + + 1. 2. and 6. don't support SWMR and leave the store in an undefined state + in case of crash. + + 4. operates on files private to the worker. It doesn't necessitate to + worry about crash concistency and SWMR. + + 3. and 5. are highly critical. *) + + module Io : Io.S + module Control : Control_file.Upper with module Io = Io + module Dict : Append_only_file.S with module Io = Io + module Suffix : Chunked_suffix.S with module Io = Io + module Index : Pack_index.S + module Errs : Io_errors.S with module Io = Io + module Sparse : Sparse_file.S with module Io = Io + module Lower : Lower.S with module Io = Io + + type t + + (** A series of getters to the underlying files managed. *) + + val control : t -> Control.t + val dict : t -> Dict.t + val suffix : t -> Suffix.t + val index : t -> Index.t + val prefix : t -> Sparse.t option + val lower : t -> Lower.t option + + type create_error := + [ Io.create_error + | Io.write_error + | Io.open_error + | Io.mkdir_error + | `Corrupted_mapping_file of string + | `Corrupted_control_file of string + | `Double_close + | `Unknown_major_pack_version of string + | `Volume_missing of string + | `Not_a_directory of string + | `Multiple_empty_volumes + | `Index_failure of string + | `Sys_error of string + | `No_tmp_path_provided ] + + val create_rw : + overwrite:bool -> Irmin.Backend.Conf.t -> (t, [> create_error ]) result + (** Create a rw instance of [t] by creating the files. + + Note on SWMR consistency: It is undefined for a reader to attempt an + opening before [create_rw] is over. + + Note on crash consistency: Crashing during [create_rw] leaves the storage + in an undefined state. + + Note on errors: If [create_rw] returns an error, the storage is left in an + undefined state and some file descriptors might not be closed. *) + + type open_rw_error := + [ `Corrupted_control_file of string + | `Corrupted_mapping_file of string + | `Double_close + | `Closed + | `File_exists of string + | `Index_failure of string + | `Invalid_argument + | `Invalid_layout + | `Io_misc of Io.misc_error + | `Migration_needed + | `Migration_to_lower_not_allowed + | `No_such_file_or_directory of string + | `Not_a_directory of string + | `Not_a_file + | `No_tmp_path_provided + | `Read_out_of_bounds + | `Ro_not_allowed + | `Sys_error of string + | `V3_store_from_the_future + | `Only_minimal_indexing_strategy_allowed + | `Unknown_major_pack_version of string + | `Index_failure of string + | `Sys_error of string + | `Inconsistent_store + | `Volume_missing of string + | `Multiple_empty_volumes + | `Invalid_parent_directory + | `Pending_flush ] + + val open_rw : Irmin.Backend.Conf.t -> (t, [> open_rw_error ]) result + (** Create a rw instance of [t] by opening existing files. + + If the pack store has already been garbage collected, opening with a + non-minimal indexing strategy will return an error. + + If [no_migrate = false] in the config, the store will undergo a major + version upgrade if necessary. + + Note on SWMR consistency: It is undefined for a reader to attempt an + opening during an [open_rw], because of major version upgrades. + + Note on crash consistency: If [open_rw] crashes during a major version + upgrade, the storage is left in an undefined state. Otherwise the storage + is unaffected. + + Note on errors: If [open_rw] returns an error during a major version + upgrade, the storage is left in an undefined state. Otherwise the storage + is unaffected. Anyhow, some file descriptors might not be closed. *) + + type open_ro_error := + [ `Corrupted_control_file of string + | `Corrupted_mapping_file of string + | `Io_misc of Io.misc_error + | `Migration_needed + | `No_such_file_or_directory of string + | `Not_a_file + | `Double_close + | `Closed + | `V3_store_from_the_future + | `Index_failure of string + | `Unknown_major_pack_version of string + | `Inconsistent_store + | `Invalid_argument + | `Read_out_of_bounds + | `Invalid_layout + | `Volume_missing of string ] + + val open_ro : Irmin.Backend.Conf.t -> (t, [> open_ro_error ]) result + (** Create a ro instance of [t] by opening existing files. + + Note on SWMR consistency: [open_ro] is supposed to work whichever the + state of the pack store and the writer, with 2 exceptions: 1. the files + must exist and [create_rw] must be over and 2. during a major version + upgrade of the files (which occurs during a [open_rw]). + + Note on crash consistency: Crashes during [open_ro] cause no issues + because it doesn't mutate the storage. + + Note on errors: The storage is never mutated. Some file descriptors might + not be closed. *) + + type close_error := + [ `Double_close + | `Index_failure of string + | `Io_misc of Io.misc_error + | `Pending_flush + | `Ro_not_allowed ] + + val close : t -> (unit, [> close_error ]) result + (** Close all the files. + + This call fails if the append buffers are not in a flushed stated. This + situation will most likely never occur because the append buffers will + contain data only during the scope of a batch function. *) + + type flush_error := + [ `Index_failure of string + | `Io_misc of Io.misc_error + | `Ro_not_allowed + | `Closed + | `Double_close + | `File_exists of string + | `Sys_error of string + | `No_tmp_path_provided ] + + type flush_stages := [ `After_dict | `After_suffix ] + type 'a hook := 'a -> unit + + val flush : ?hook:flush_stages hook -> t -> (unit, [> flush_error ]) result + (** Execute the flush routine. Note that this routine may be automatically + triggered when buffers are filled. *) + + type fsync_error := flush_error + + val fsync : t -> (unit, [> fsync_error ]) result + (** [fsync] executes an fsync for all files of the file manager. + + Note: This function exists primarily for operations like snapshot imports. + If fsync is enabled for the store (see {!Irmin_pack.Config.use_fsync}), + calls to {!flush} will also call fsync and therefore there is little need + to call this function directly. *) + + type reload_stages := [ `After_index | `After_control | `After_suffix ] + + val reload : ?hook:reload_stages hook -> t -> (unit, [> Errs.t ]) result + (** Execute the reload routine. + + Is a no-op if the control file did not change. *) + + val register_dict_consumer : + t -> after_reload:(unit -> (unit, Errs.t) result) -> unit + + val register_prefix_consumer : + t -> after_reload:(unit -> (unit, Errs.t) result) -> unit + + val register_suffix_consumer : t -> after_flush:(unit -> unit) -> unit + + type version_error := + [ `Corrupted_control_file of string + | `Corrupted_legacy_file + | `Invalid_layout + | `Io_misc of Io.misc_error + | `No_such_file_or_directory of string + | `Not_a_directory of string + | `Unknown_major_pack_version of string ] + + val version : root:string -> (Import.Version.t, [> version_error ]) result + (** [version ~root] is the version of the pack stores at [root]. *) + + val cleanup : t -> (unit, [> `Sys_error of string ]) result + (** [cleanup t] performs cleanup operations for files related to GC. *) + + val swap : + t -> + generation:int -> + mapping_size:int63 -> + suffix_start_offset:int63 -> + chunk_start_idx:int -> + chunk_num:int -> + suffix_dead_bytes:int63 -> + latest_gc_target_offset:int63 -> + volume:Lower.volume_identifier option -> + (unit, [> Errs.t ]) result + (** Swaps to using files from the GC [generation]. The values + [suffix_start_offset], [chunk_start_idx], [chunk_num], and + [suffix_dead_bytes] are used to properly load and read the suffix after a + GC. The value [volume] is used to reload the lower if it was modified by + the GC. The control file is also updated on disk. *) + + val readonly : t -> bool + val generation : t -> int + val gc_allowed : t -> bool + val split : t -> (unit, [> Errs.t ]) result + val add_volume : t -> (unit, [> Errs.t ]) result + + val gc_behaviour : t -> [ `Delete | `Archive ] + (** Decides if the GC will delete or archive the garbage data, depending on + the presence of a lower layer. *) + + val gc_destination : t -> [ `Delete | `Archive of Lower.t ] + (** Returns where data discarded by the GC will end up. (see {!gc_behaviour}). *) + + val create_one_commit_store : + t -> + Irmin.Backend.Conf.t -> + Control_file.Payload.Upper.Latest.gced -> + Index.key Pack_key.t -> + (unit, [> open_rw_error | close_error ]) result + (** [create_one_commit_store t conf generation new_store_root key] is called + when creating a new store at [new_store_root] from the existing one, + containing only one commit, specified by the [key]. Ths new store will use + configuration options from [conf] and set to [generation]. *) +end + +module type Sigs = sig + module type S = S + + module Make + (Io : Io.S) + (Index : Pack_index.S with module Io = Io) + (Errs : Io_errors.S with module Io = Io) : + S with module Io = Io and module Index = Index and module Errs = Errs +end diff --git a/vendors/irmin/src/irmin-pack/unix/gc.ml b/vendors/irmin/src/irmin-pack/unix/gc.ml new file mode 100644 index 000000000000..c61ba8c2b52d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc.ml @@ -0,0 +1,342 @@ +(* + * Copyright (c) 2022-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +(** Maker for a module that can manage GC processes. *) +module Make (Args : Gc_args.S) = struct + module Args = Args + open Args + module Io = Fm.Io + module Ao = Append_only_file.Make (Io) (Errs) + module Worker = Gc_worker.Make (Args) + + type t = { + root : string; + generation : int; + task : Async.t; + unlink : bool; + new_suffix_start_offset : int63; + resolver : (Stats.Latest_gc.stats, Errs.t) result Lwt.u; + promise : (Stats.Latest_gc.stats, Errs.t) result Lwt.t; + dispatcher : Dispatcher.t; + fm : Fm.t; + contents : read Contents_store.t; + node : read Node_store.t; + commit : read Commit_store.t; + mutable partial_stats : Gc_stats.Main.t; + mutable resulting_stats : Stats.Latest_gc.stats option; + latest_gc_target_offset : int63; + } + + let v ~root ~lower_root ~output ~generation ~unlink ~dispatcher ~fm ~contents + ~node ~commit commit_key = + let open Result_syntax in + let new_suffix_start_offset, latest_gc_target_offset = + let state : _ Pack_key.state = Pack_key.inspect commit_key in + match state with + | Direct x -> + let len = x.length |> Int63.of_int in + (Int63.Syntax.(x.offset + len), x.offset) + | Indexed _ -> + (* The caller of this function lifted the key to a direct one. *) + assert false + in + let status = Fm.control fm |> Fm.Control.payload |> fun p -> p.status in + (* Ensure we are calling GC on a commit strictly newer than last GC commit + Only checking when the output is the root (it is not a snapshot export) *) + let* () = + match (output, status) with + | `Root, Gced previous + when Int63.Syntax.( + previous.latest_gc_target_offset >= latest_gc_target_offset) -> + Error + (`Gc_disallowed + (Fmt.str "%a is less than or equal to previous GC offset of %a" + Int63.pp latest_gc_target_offset Int63.pp + previous.latest_gc_target_offset)) + | _ -> Ok () + in + let new_files_path = + match output with `Root -> root | `External path -> path + in + (* Since we can call GC on commits in the lower, ensure we do not provide a + [new_suffix_start_offset] that is older than our current starting offset. *) + let new_suffix_start_offset = + match status with + | Gced { suffix_start_offset; _ } + when Int63.Syntax.(suffix_start_offset >= latest_gc_target_offset) -> + suffix_start_offset + | _ -> new_suffix_start_offset + in + let partial_stats = + let commit_offset = latest_gc_target_offset in + let before_suffix_start_offset = + Dispatcher.suffix_start_offset dispatcher + in + let before_suffix_end_offset = Dispatcher.end_offset dispatcher in + Gc_stats.Main.create "worker startup" ~commit_offset ~generation + ~before_suffix_start_offset ~before_suffix_end_offset + ~after_suffix_start_offset:new_suffix_start_offset + in + let unlink_result_file () = + let result_file = Irmin_pack.Layout.V4.gc_result ~root ~generation in + match Io.classify_path result_file with + | `File -> + Io.unlink_dont_wait + ~on_exn:(fun exn -> + [%log.warn + "Unlinking temporary files from previous failed gc. Failed \ + with error %s" + (Printexc.to_string exn)]) + result_file + | `Directory | `No_such_file_or_directory | `Other -> () + in + (* Unlink next gc's result file, in case it is on disk, for instance + after a failed gc. *) + unlink_result_file (); + (* internal promise for gc *) + let promise, resolver = Lwt.wait () in + (* start worker task *) + let task = + Async.async (fun () -> + Worker.run_and_output_result root commit_key new_suffix_start_offset + ~lower_root ~generation ~new_files_path) + in + let partial_stats = + Gc_stats.Main.finish_current_step partial_stats "before finalise" + in + Ok + { + root; + generation; + unlink; + new_suffix_start_offset; + task; + promise; + resolver; + dispatcher; + fm; + contents; + node; + commit; + partial_stats; + resulting_stats = None; + latest_gc_target_offset; + } + + let swap_and_purge t (gc_results : Worker.gc_results) = + let removable_chunk_num = List.length gc_results.removable_chunk_idxs in + let { generation; latest_gc_target_offset; _ } = t in + let Worker. + { + start_offset = suffix_start_offset; + chunk_start_idx; + dead_bytes = suffix_dead_bytes; + } = + gc_results.suffix_params + in + (* Calculate chunk num in main process since more chunks could have been + added while GC was running. GC process only tells us how many chunks are + to be removed. *) + let suffix = Fm.suffix t.fm in + let chunk_num = Fm.Suffix.chunk_num suffix - removable_chunk_num in + (* Assert that we have at least one chunk (the appendable chunk), which + is guaranteed by the GC process. *) + assert (chunk_num >= 1); + + Fm.swap t.fm ~generation ~mapping_size:gc_results.mapping_size + ~suffix_start_offset ~chunk_start_idx ~chunk_num ~suffix_dead_bytes + ~latest_gc_target_offset ~volume:gc_results.modified_volume + + let unlink_all { root; generation; _ } removable_chunk_idxs = + (* Unlink suffix chunks *) + let () = + removable_chunk_idxs + |> List.iter (fun chunk_idx -> + let path = Irmin_pack.Layout.V4.suffix_chunk ~root ~chunk_idx in + Io.unlink_dont_wait + ~on_exn:(fun exn -> + [%log.warn + "Unlinking chunk_idxs files after gc, failed with error %s" + (Printexc.to_string exn)]) + path) + in + if generation >= 2 then ( + (* Unlink previous prefix. *) + let prefix = + Irmin_pack.Layout.V4.prefix ~root ~generation:(generation - 1) + in + Io.unlink_dont_wait + ~on_exn:(fun exn -> + [%log.warn + "Unlinking previous prefix after gc, failed with error %s" + (Printexc.to_string exn)]) + prefix; + + (* Unlink previous mapping. *) + let mapping = + Irmin_pack.Layout.V4.mapping ~root ~generation:(generation - 1) + in + Io.unlink_dont_wait + ~on_exn:(fun exn -> + [%log.warn + "Unlinking previous mapping after gc, failed with error %s" + (Printexc.to_string exn)]) + mapping); + + (* Unlink current gc's result.*) + let result = Irmin_pack.Layout.V4.gc_result ~root ~generation in + Io.unlink_dont_wait + ~on_exn:(fun exn -> + [%log.warn + "Unlinking current gc's result after gc, failed with error %s" + (Printexc.to_string exn)]) + result + + let gc_errors status gc_output = + let extend_error s = function + | `Gc_process_error str -> `Gc_process_error (Fmt.str "%s %s" s str) + | `Corrupted_gc_result_file str -> + `Gc_process_died_without_result_file (Fmt.str "%s %s" s str) + in + match (status, gc_output) with + | `Failure s, Error e -> Error (extend_error s e) + | `Cancelled, Error e -> Error (extend_error "cancelled" e) + | `Success, Error e -> Error (extend_error "success" e) + | `Cancelled, Ok _ -> Error (`Gc_process_error "cancelled") + | `Failure s, Ok _ -> Error (`Gc_process_error s) + | `Success, Ok _ -> assert false + + let read_gc_output ~root ~generation = + let open Result_syntax in + let read_file () = + let path = Irmin_pack.Layout.V4.gc_result ~root ~generation in + let* io = Io.open_ ~path ~readonly:true in + let* len = Io.read_size io in + let len = Int63.to_int len in + let* string = Io.read_to_string io ~off:Int63.zero ~len in + let* () = Io.close io in + Ok string + in + let read_error err = + `Corrupted_gc_result_file (Irmin.Type.to_string Errs.t err) + in + let gc_error err = `Gc_process_error (Irmin.Type.to_string Errs.t err) in + let* s = read_file () |> Result.map_error read_error in + match Irmin.Type.of_json_string Worker.gc_output_t s with + | Error (`Msg error) -> Error (`Corrupted_gc_result_file error) + | Ok ok -> ok |> Result.map_error gc_error + + let clean_after_abort t = + Fm.cleanup t.fm |> Errs.log_if_error "clean_after_abort" + + let finalise ~wait t = + match t.resulting_stats with + | Some partial_stats -> Lwt.return_ok (`Finalised partial_stats) + | None -> ( + let partial_stats = t.partial_stats in + let partial_stats = + Gc_stats.Main.finish_current_step partial_stats "worker wait" + in + let go status = + let partial_stats = + Gc_stats.Main.finish_current_step partial_stats "read output" + in + + let gc_output = + read_gc_output ~root:t.root ~generation:t.generation + in + + let result = + let open Result_syntax in + match (status, gc_output) with + | `Success, Ok gc_results -> + let partial_stats = + Gc_stats.Main.finish_current_step partial_stats + "swap and purge" + in + let* () = swap_and_purge t gc_results in + let partial_stats = + Gc_stats.Main.finish_current_step partial_stats "unlink" + in + if t.unlink then unlink_all t gc_results.removable_chunk_idxs; + + let stats = + let after_suffix_end_offset = + Dispatcher.end_offset t.dispatcher + in + Gc_stats.Main.finalise partial_stats gc_results.stats + ~after_suffix_end_offset + in + Stats.report_latest_gc stats; + t.resulting_stats <- Some stats; + + [%log.debug + "Gc ended successfully. %a" + (Irmin.Type.pp Stats.Latest_gc.stats_t) + stats]; + let () = Lwt.wakeup_later t.resolver (Ok stats) in + Ok (`Finalised stats) + | _ -> + clean_after_abort t; + let err = gc_errors status gc_output in + let () = Lwt.wakeup_later t.resolver err in + err + in + Lwt.return result + in + if wait then + let* status = Async.await t.task in + go status + else + match Async.status t.task with + | `Running -> Lwt.return_ok `Running + | #Async.outcome as status -> go status) + + let finalise_without_swap t = + let* status = Async.await t.task in + let gc_output = read_gc_output ~root:t.root ~generation:t.generation in + match (status, gc_output) with + | `Success, Ok gc_results -> + Lwt.return + { + Control_file_intf.Payload.Upper.Latest.generation = + Fm.generation t.fm + 1; + latest_gc_target_offset = t.latest_gc_target_offset; + suffix_start_offset = t.new_suffix_start_offset; + suffix_dead_bytes = Int63.zero; + mapping_end_poff = Some gc_results.mapping_size; + } + | _ -> + let r = gc_errors status gc_output |> Errs.raise_if_error in + Lwt.return r + + let on_finalise t f = + (* Ignore returned promise since the purpose of this + function is to add asynchronous callbacks to the GC + process -- this promise binding is an internal + implementation detail. This is safe since the callback + [f] is attached to [t.running_gc.promise], which is + referenced for the lifetime of a GC process. *) + let _ = Lwt.bind t.promise f in + () + + let cancel t = + let cancelled = Async.cancel t.task in + if cancelled then clean_after_abort t; + cancelled +end diff --git a/vendors/irmin/src/irmin-pack/unix/gc.mli b/vendors/irmin/src/irmin-pack/unix/gc.mli new file mode 100644 index 000000000000..8e09c754f99e --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc.mli @@ -0,0 +1,63 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +(** [Make] returns a module that can manage GC processes. *) +module Make (Args : Gc_args.S) : sig + module Args : Gc_args.S + + type t + (** A running GC process. *) + + val v : + root:string -> + lower_root:string option -> + output:[ `External of string | `Root ] -> + generation:int -> + unlink:bool -> + dispatcher:Args.Dispatcher.t -> + fm:Args.Fm.t -> + contents:read Args.Contents_store.t -> + node:read Args.Node_store.t -> + commit:read Args.Commit_store.t -> + Args.key -> + (t, [> `Gc_disallowed of string ]) result + (** Creates and starts a new GC process. *) + + val finalise : + wait:bool -> + t -> + ([> `Running | `Finalised of Stats.Latest_gc.stats ], Args.Errs.t) result + Lwt.t + (** [finalise ~wait t] returns the state of the GC process. + + If [wait = true], the call will block until GC finishes. *) + + val on_finalise : + t -> ((Stats.Latest_gc.stats, Args.Errs.t) result -> unit Lwt.t) -> unit + (** Attaches a callback to the GC process, which will be called when the GC + finalises. *) + + val cancel : t -> bool + + val finalise_without_swap : + t -> Control_file_intf.Payload.Upper.Latest.gced Lwt.t + (** Waits for the current gc to finish and returns immediately without + swapping the files and doing the other finalisation steps from [finalise]. + Returns the [gced] status to create a fresh control file for the snapshot. *) +end +with module Args = Args diff --git a/vendors/irmin/src/irmin-pack/unix/gc_args.ml b/vendors/irmin/src/irmin-pack/unix/gc_args.ml new file mode 100644 index 000000000000..6ade79bf3189 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc_args.ml @@ -0,0 +1,83 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + module Fm : File_manager.S with module Io = Io.Unix + module Async : Async.S + module Dict : Dict.S with module Fm = Fm + module Errs : Io_errors.S with module Io = Fm.Io + module Dispatcher : Dispatcher.S with module Fm = Fm + + type hash + type key = hash Pack_key.t [@@deriving irmin] + + module Hash : sig + val hash_size : int + end + + module Contents_store : sig + type 'a t + + val purge_lru : 'a t -> unit + end + + module Node_value : sig + type t + type step + + val pred : + t -> + (step option * [ `Contents of key | `Inode of key | `Node of key ]) list + end + + module Node_store : sig + type 'a t + + val v : + config:Irmin.Backend.Conf.t -> + fm:Fm.t -> + dict:Dict.t -> + dispatcher:Dispatcher.t -> + read t + + val unsafe_find : + check_integrity:bool -> [< read ] t -> key -> Node_value.t option + + val key_of_offset : [< read ] t -> int63 -> key + val unsafe_find_no_prefetch : 'a t -> key -> Node_value.t option + val purge_lru : 'a t -> unit + val get_offset : 'a t -> key -> int63 + val get_length : 'a t -> key -> int + end + + module Commit_value : sig + type t + + val node : t -> key + val parents : t -> key list + end + + module Commit_store : + Pack_store.S + with type value = Commit_value.t + and type key = key + and type file_manager = Fm.t + and type dict = Dict.t + and type dispatcher = Dispatcher.t + and type hash = hash +end diff --git a/vendors/irmin/src/irmin-pack/unix/gc_stats.ml b/vendors/irmin/src/irmin-pack/unix/gc_stats.ml new file mode 100644 index 000000000000..f2bbbd81c907 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc_stats.ml @@ -0,0 +1,292 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Steps_timer = struct + type duration = Stats.Latest_gc.duration = { + wall : float; + sys : float; + user : float; + } + + type t = { timer : duration; prev_stepname : string } + + let get_wtime () = + (Mtime_clock.now () |> Mtime.to_uint64_ns |> Int64.to_float) /. 1e9 + + let get_stime () = Rusage.((get Self).stime) + let get_utime () = Rusage.((get Self).utime) + + let create first_stepname = + let wall = get_wtime () in + let sys = get_stime () in + let user = get_utime () in + let timer = { wall; sys; user } in + { timer; prev_stepname = first_stepname } + + let progress prev next_stepname = + let wall = get_wtime () in + let sys = get_stime () in + let user = get_utime () in + let next = { wall; sys; user } in + + let wall = next.wall -. prev.timer.wall in + let sys = next.sys -. prev.timer.sys in + let user = next.user -. prev.timer.user in + let delta = (prev.prev_stepname, { wall; sys; user }) in + + let next = { timer = next; prev_stepname = next_stepname } in + (next, delta) +end + +module Main = struct + module S = Stats.Latest_gc + + type t = { stats : S.stats; timer : Steps_timer.t } + (** [t] is the running state while computing the stats *) + + let create first_stepname ~generation ~commit_offset + ~before_suffix_start_offset ~before_suffix_end_offset + ~after_suffix_start_offset = + let stats = Irmin.Type.(random S.stats_t |> unstage) () in + (* [repr] provides doesn't provide a generator that fills a type with + zeroes but it provides a random generator. Let's use it for our initial + value. *) + let stats = + S. + { + stats with + generation; + steps = []; + commit_offset; + before_suffix_start_offset; + before_suffix_end_offset; + after_suffix_start_offset; + } + in + let timer = Steps_timer.create first_stepname in + { stats; timer } + + let finish_current_step t next_stepname = + let timer, prev_step = Steps_timer.progress t.timer next_stepname in + let stats = { t.stats with steps = prev_step :: t.stats.steps } in + { stats; timer } + + let finalise t worker ~after_suffix_end_offset = + let t = finish_current_step t "will not appear in the stats" in + { + t.stats with + S.worker; + after_suffix_end_offset; + steps = List.rev t.stats.steps; + } +end + +module Worker = struct + module S = Stats.Latest_gc + + type t = { + stats : S.worker; + current_stepname : string; + prev_wtime : float; + prev_stime : float; + prev_utime : float; + prev_rusage : S.rusage; + prev_ocaml_gc : S.ocaml_gc; + } + (** [t] is the running state while computing the stats *) + + let is_darwin = + lazy + (try + match Unix.open_process_in "uname" |> input_line with + | "Darwin" -> true + | _ -> false + with Unix.Unix_error _ -> false) + + let get_wtime () = + (Mtime_clock.now () |> Mtime.to_uint64_ns |> Int64.to_float) /. 1e9 + + let get_stime () = Rusage.((get Self).stime) + let get_utime () = Rusage.((get Self).utime) + + let get_rusage : unit -> S.rusage = + fun () -> + let Rusage.{ maxrss; minflt; majflt; inblock; oublock; nvcsw; nivcsw; _ } = + Rusage.(get Self) + in + let maxrss = + if Lazy.force is_darwin then Int64.div maxrss 1000L else maxrss + in + S.{ maxrss; minflt; majflt; inblock; oublock; nvcsw; nivcsw } + + let get_ocaml_gc : unit -> S.ocaml_gc = + fun () -> + let open Stdlib.Gc in + let v = quick_stat () in + S. + { + minor_words = v.minor_words; + promoted_words = v.promoted_words; + major_words = v.major_words; + minor_collections = v.minor_collections; + major_collections = v.major_collections; + heap_words = v.heap_words; + compactions = v.compactions; + top_heap_words = v.top_heap_words; + stack_size = v.stack_size; + } + + let create : string -> t = + fun first_stepname -> + (* Reseting all irmin-pack stats. We'll reset again at every step. + + Since the GC worker lives alone in a fork, these global variable mutations + will not interfere with the rest of the world. *) + Stats.reset_stats (); + Irmin_pack.Stats.reset_stats (); + + let wtime = get_wtime () in + let stime = get_stime () in + let utime = get_utime () in + let rusage = get_rusage () in + let ocaml_gc = get_ocaml_gc () in + + let stats = + S. + { + initial_maxrss = rusage.maxrss; + initial_heap_words = ocaml_gc.heap_words; + initial_top_heap_words = ocaml_gc.top_heap_words; + initial_stack_size = ocaml_gc.stack_size; + steps = []; + files = []; + objects_traversed = Int63.zero; + suffix_transfers = []; + } + in + { + stats; + current_stepname = first_stepname; + prev_utime = utime; + prev_wtime = wtime; + prev_stime = stime; + prev_rusage = rusage; + prev_ocaml_gc = ocaml_gc; + } + + let set_objects_traversed t v = + let stats = { t.stats with objects_traversed = Int63.of_int v } in + { t with stats } + + let add_suffix_transfer t count = + let stats = + { t.stats with suffix_transfers = count :: t.stats.suffix_transfers } + in + { t with stats } + + let finish_current_step t next_stepname = + let wtime = get_wtime () in + let stime = get_stime () in + let utime = get_utime () in + let duration = + let wall = wtime -. t.prev_wtime in + let sys = stime -. t.prev_stime in + let user = utime -. t.prev_utime in + S.{ wall; sys; user } + in + + let prev_rusage, rusage = + let x = t.prev_rusage in + let y = get_rusage () in + let ( - ) = Int64.sub in + ( y, + S. + { + y with + minflt = y.minflt - x.minflt; + majflt = y.majflt - x.majflt; + inblock = y.inblock - x.inblock; + oublock = y.oublock - x.oublock; + nvcsw = y.nvcsw - x.nvcsw; + nivcsw = y.nivcsw - x.nivcsw; + } ) + in + let prev_ocaml_gc, ocaml_gc = + let x = t.prev_ocaml_gc in + let y = get_ocaml_gc () in + ( y, + S. + { + y with + minor_words = y.minor_words -. x.minor_words; + promoted_words = y.promoted_words -. x.promoted_words; + major_words = y.major_words -. x.major_words; + minor_collections = y.minor_collections - x.minor_collections; + major_collections = y.major_collections - x.major_collections; + compactions = y.compactions - x.compactions; + } ) + in + + (* [clone] duplicates a value. Used below to snapshot mutable values. *) + let clone typerepr v = + match + Irmin.Type.to_string typerepr v |> Irmin.Type.of_string typerepr + with + | Error _ -> assert false + | Ok v -> v + in + let pack_store = + Stats.((get ()).pack_store |> Pack_store.export |> clone Pack_store.t) + in + Stats.report_index (); + let index = Stats.((get ()).index |> Index.export |> clone Index.t) in + let inode = + Irmin_pack.Stats.((get ()).inode |> Inode.export |> clone Inode.t) + in + Stats.reset_stats (); + Irmin_pack.Stats.reset_stats (); + + let step = S.{ duration; rusage; ocaml_gc; index; pack_store; inode } in + + (* The [steps] list is built in reverse order and reversed in [finalise] *) + let steps = (t.current_stepname, step) :: t.stats.steps in + + let stats = { t.stats with steps } in + { + current_stepname = next_stepname; + stats; + prev_wtime = wtime; + prev_stime = stime; + prev_utime = utime; + prev_rusage; + prev_ocaml_gc; + } + + let add_file_size t file_name size = + let stats = { t.stats with files = (file_name, size) :: t.stats.files } in + { t with stats } + + let finalise : t -> S.worker = + fun t -> + let t = finish_current_step t "will not appear in the stats" in + { + t.stats with + steps = List.rev t.stats.steps; + suffix_transfers = List.rev t.stats.suffix_transfers; + } +end diff --git a/vendors/irmin/src/irmin-pack/unix/gc_stats.mli b/vendors/irmin/src/irmin-pack/unix/gc_stats.mli new file mode 100644 index 000000000000..96680dfc637b --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc_stats.mli @@ -0,0 +1,51 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +(** Stat collection during GC *) + +module Main : sig + type t + + val create : + string -> + generation:int -> + commit_offset:int63 -> + before_suffix_start_offset:int63 -> + before_suffix_end_offset:int63 -> + after_suffix_start_offset:int63 -> + t + + val finish_current_step : t -> string -> t + + val finalise : + t -> + Stats.Latest_gc.worker -> + after_suffix_end_offset:int63 -> + Stats.Latest_gc.stats +end + +module Worker : sig + type t + + val create : string -> t + val set_objects_traversed : t -> int -> t + val add_suffix_transfer : t -> int63 -> t + val add_file_size : t -> string -> int63 -> t + val finish_current_step : t -> string -> t + val finalise : t -> Stats.Latest_gc.worker +end diff --git a/vendors/irmin/src/irmin-pack/unix/gc_worker.ml b/vendors/irmin/src/irmin-pack/unix/gc_worker.ml new file mode 100644 index 000000000000..39ffe19fed89 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc_worker.ml @@ -0,0 +1,436 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Payload = Control_file.Payload.Upper.Latest + +exception Pack_error = Errors.Pack_error + +module Make (Args : Gc_args.S) = struct + open Args + module Io = Fm.Io + module Lower = Fm.Lower + module Sparse = Dispatcher.Fm.Sparse + module Ao = Append_only_file.Make (Fm.Io) (Errs) + + let string_of_key = Irmin.Type.to_string key_t + + module Priority_queue = struct + module Offset_rev = struct + type t = int63 + + let equal = Int63.equal + let hash (t : t) = Hashtbl.hash t + let compare a b = Int63.compare b a + end + + module Table = Hashtbl.Make (Offset_rev) + module Pq = Binary_heap.Make (Offset_rev) + + type 'a t = { pq : Pq.t; marks : 'a Table.t } + + let create size = + { pq = Pq.create ~dummy:Int63.zero size; marks = Table.create size } + + let is_empty t = Pq.is_empty t.pq + + let pop { pq; marks } = + let elt = Pq.pop_minimum pq in + let payload = Table.find marks elt in + Table.remove marks elt; + (elt, payload) + + let add { pq; marks } elt payload = + if not (Table.mem marks elt) then ( + Table.add marks elt payload; + Pq.add pq elt) + end + + type kind = Contents | Node | Commit + + (** [iter_reachable ~parents ~min_offset commit_key commit_store node_store] + returns the list of compacted [(offset, length)] of the reachable tree + objects and parent commits from [commit_key] in [commit_store] and + [node_store]. + + - If [parents] is true, then parents commits and their tree objects are + traversed recursively. Otherwise, only the immediate parent are included + (but not their tree objects). + - [min_offset] restricts the traversal to objects/commits with a larger or + equal offset. *) + let iter_reachable ~parents ~min_offset commit_key commit_store node_store = + let live = Ranges.make () in + let todos = Priority_queue.create 1024 in + let rec loop () = + if not (Priority_queue.is_empty todos) then ( + let offset, kind = Priority_queue.pop todos in + iter_node offset kind; + loop ()) + and iter_node off = function + | (Contents | Node) as kind -> ( + let node_key = Node_store.key_of_offset node_store off in + let len = Node_store.get_length node_store node_key in + Ranges.add live ~off ~len; + if kind = Node then + match Node_store.unsafe_find_no_prefetch node_store node_key with + | None -> + raise (Pack_error (`Dangling_key (string_of_key node_key))) + | Some node -> + List.iter + (fun (_step, kinded_key) -> schedule_kinded kinded_key) + (Node_value.pred node)) + | Commit -> ( + let commit_key = Commit_store.key_of_offset commit_store off in + let len = Commit_store.get_length commit_store commit_key in + Ranges.add live ~off ~len; + match + Commit_store.unsafe_find ~check_integrity:false commit_store + commit_key + with + | None -> + raise (Pack_error (`Dangling_key (string_of_key commit_key))) + | Some commit -> + List.iter schedule_commit (Commit_value.parents commit); + schedule_kinded (`Node (Commit_value.node commit))) + and schedule_kinded kinded_key = + let key, kind = + match kinded_key with + | `Contents key -> (key, Contents) + | `Inode key | `Node key -> (key, Node) + in + match Node_store.get_offset node_store key with + | offset -> schedule ~offset kind + | exception Pack_store.Dangling_hash -> () + and schedule_commit key = + match Commit_store.get_offset commit_store key with + | offset -> + let kind = + if parents then Commit + else + (* Include the commit parents in the reachable file, but not their children. + The parent(s) of [commit] must be included in the iteration + because, when decoding the [Commit_value.t] at [commit], the + parents will have to be read in order to produce a key for them. *) + Contents + in + schedule ~offset kind + | exception Pack_store.Dangling_hash -> () + and schedule ~offset kind = + if offset >= min_offset then Priority_queue.add todos offset kind + in + let offset = Commit_store.get_offset commit_store commit_key in + schedule ~offset Commit; + loop (); + live + + (** [snaphshot_commit commit_key commit_store node_store] returns the list of + compacted [(offset, length)] of the reachable tree objects and its direct + parent commits. *) + let snapshot_commit commit_key commit_store node_store = + iter_reachable ~parents:false ~min_offset:Int63.zero commit_key commit_store + node_store + + (** [traverse_range ~min_offset commit_key commit_store node_store] returns + the list of compacted [(offset, length)] of the recursively reachable tree + objects and parent commits, such that [offset >= min_offset]. *) + let traverse_range ~min_offset commit_key commit_store node_store = + iter_reachable ~parents:true ~min_offset commit_key commit_store node_store + + (* Dangling_parent_commit are the parents of the gced commit. They are kept on + disk in order to correctly deserialised the gced commit. *) + let magic_parent = + Pack_value.Kind.to_magic Pack_value.Kind.Dangling_parent_commit + |> String.make 1 + + (* Transfer the commit with a different magic. Note that this is modifying + existing written data. *) + let transfer_parent_commit_exn ~write_exn key = + match Pack_key.inspect key with + | Indexed _ -> + (* Its possible that some parents are referenced by hash. *) + () + | Direct { offset = off; _ } -> + (* Targeted write to change the parent commit kind to dangling. *) + let off = Int63.(Syntax.(off + of_int Hash.hash_size)) in + write_exn ~off ~len:1 magic_parent + + let prefix_file_sizes ~root ~generation = + let open Result_syntax in + let* prefix_size = + if generation = 0 then Ok Int63.zero + else Irmin_pack.Layout.V3.prefix ~root ~generation |> Io.size_of_path + in + let+ mapping_size = + if generation = 0 then Ok Int63.zero + else Irmin_pack.Layout.V3.mapping ~root ~generation |> Io.size_of_path + in + (mapping_size, prefix_size) + + let report_old_file_sizes ~root ~generation stats = + let open Result_syntax in + let+ mapping_size, prefix_size = prefix_file_sizes ~root ~generation in + stats := Gc_stats.Worker.add_file_size !stats "old_prefix" prefix_size; + stats := Gc_stats.Worker.add_file_size !stats "old_mapping" mapping_size + + let report_new_file_sizes ~root ~generation stats = + let open Result_syntax in + let+ mapping_size, prefix_size = prefix_file_sizes ~root ~generation in + stats := Gc_stats.Worker.add_file_size !stats "prefix" prefix_size; + stats := Gc_stats.Worker.add_file_size !stats "mapping" mapping_size + + type suffix_params = { + start_offset : int63; + chunk_start_idx : int; + dead_bytes : int63; + } + [@@deriving irmin] + + type gc_results = { + suffix_params : suffix_params; + mapping_size : int63; + removable_chunk_idxs : int list; + modified_volume : Lower.volume_identifier option; + stats : Stats.Latest_gc.worker; + } + [@@deriving irmin] + + type gc_output = (gc_results, Args.Errs.t) result [@@deriving irmin] + + let run ~lower_root ~generation ~new_files_path root commit_key + new_suffix_start_offset = + let open Result_syntax in + let config = + Irmin_pack.Conf.init ~fresh:false ~readonly:true ~lru_size:0 ~lower_root + root + in + + (* Step 1. Open the files *) + [%log.debug "GC: opening files in RO mode"]; + let stats = ref (Gc_stats.Worker.create "open files") in + let () = + report_old_file_sizes ~root ~generation:(generation - 1) stats |> ignore + in + + let fm = Fm.open_ro config |> Errs.raise_if_error in + Errors.finalise_exn (fun _outcome -> + Fm.close fm |> Errs.log_if_error "GC: Close File_manager") + @@ fun () -> + let dict = Dict.v fm |> Errs.raise_if_error in + let dispatcher = Dispatcher.v fm |> Errs.raise_if_error in + let node_store = Node_store.v ~config ~fm ~dict ~dispatcher in + let commit_store = Commit_store.v ~config ~fm ~dict ~dispatcher in + + (* Step 2. Load commit which will make [commit_key] [Direct] if it's not + already the case. *) + stats := Gc_stats.Worker.finish_current_step !stats "load commit"; + let commit = + match + Commit_store.unsafe_find ~check_integrity:false commit_store commit_key + with + | None -> + Errs.raise_error (`Commit_key_is_dangling (string_of_key commit_key)) + | Some commit -> commit + in + + (* Step 3. Compute the list of [offset, length] ranges of live objects + reachable from the GC commit. *) + let live_entries = + stats := Gc_stats.Worker.finish_current_step !stats "mapping: start"; + let live_entries = snapshot_commit commit_key commit_store node_store in + stats := + Gc_stats.Worker.finish_current_step !stats "mapping: of reachable"; + stats := + Gc_stats.Worker.set_objects_traversed !stats (Ranges.count live_entries); + live_entries + in + + let mapping_size = + (* Step 4. Create the new prefix. *) + stats := Gc_stats.Worker.finish_current_step !stats "prefix: start"; + let mapping = + Irmin_pack.Layout.V4.mapping ~root:new_files_path ~generation + in + let data = Irmin_pack.Layout.V4.prefix ~root:new_files_path ~generation in + let mapping_size = + let prefix = Sparse.Ao.create ~mapping ~data |> Errs.raise_if_error in + (* Step 5. Transfer to the new prefix, flush and close. *) + [%log.debug "GC: transfering to the new prefix"]; + stats := Gc_stats.Worker.finish_current_step !stats "prefix: transfer"; + Errors.finalise_exn (fun _ -> + Sparse.Ao.flush prefix + >>= (fun _ -> Sparse.Ao.close prefix) + |> Errs.log_if_error "GC: Close prefix after data copy") + @@ fun () -> + (* Step 5.1. Transfer all. *) + Ranges.iter + (fun ~off ~len -> + let str = Dispatcher.read_seq_exn dispatcher ~off ~len in + Sparse.Ao.append_seq_exn prefix ~off str) + live_entries; + Int63.to_int (Sparse.Ao.mapping_size prefix) + in + let () = + (* Step 5.2. Update the parent commits to be dangling: reopen the new + prefix, this time in write-only as we have to + modify data inside the file. *) + stats := + Gc_stats.Worker.finish_current_step !stats + "prefix: rewrite commit parents"; + let prefix = + Sparse.Wo.open_wo ~mapping_size ~mapping ~data |> Errs.raise_if_error + in + Errors.finalise_exn (fun _outcome -> + Sparse.Wo.fsync prefix + >>= (fun _ -> Sparse.Wo.close prefix) + |> Errs.log_if_error "GC: Close prefix after parent rewrite") + @@ fun () -> + let write_exn = Sparse.Wo.write_exn prefix in + List.iter + (fun key -> transfer_parent_commit_exn ~write_exn key) + (Commit_value.parents commit) + in + Int63.of_int mapping_size + in + let () = report_new_file_sizes ~root ~generation stats |> ignore in + + (* Step 6. Calculate post-GC suffix parameters. *) + let suffix_params, mapping_size, removable_chunk_idxs = + stats := + Gc_stats.Worker.finish_current_step !stats + "suffix: calculate new values"; + let suffix = Fm.suffix fm in + let soff = Dispatcher.soff_of_offset dispatcher new_suffix_start_offset in + assert (Int63.Syntax.(soff >= Int63.zero)); + (* Step 6.1. Calculate chunks that we have GCed. *) + let open struct + type chunk = { idx : int; end_suffix_off : int63 } + end in + let removable_chunks = + match Fm.Suffix.chunk_num suffix with + | 1 -> [] (* We never remove a single chunk. *) + | _ -> + Fm.Suffix.fold_chunks + (fun ~acc ~idx ~start_suffix_off ~end_suffix_off ~is_appendable -> + (* Remove chunks that end at or before our new split point. + This will leave the chunk that starts with (or contains) the + split point but remove all previous chunks. + We never remove empty or appendable chunks. *) + let is_empty = start_suffix_off = end_suffix_off in + let ends_with_or_is_before_soff = end_suffix_off <= soff in + let is_removable = + (not is_appendable) + && (not is_empty) + && ends_with_or_is_before_soff + in + if is_removable then { idx; end_suffix_off } :: acc else acc) + [] suffix + in + (* Step 6.2. Calculate the new chunk starting idx. *) + let chunk_start_idx = + match removable_chunks with + | [] -> Fm.Suffix.start_idx suffix + | last_removed_chunk :: _ -> succ last_removed_chunk.idx + in + (* Step 6.3. Calculate new dead bytes at the beginning of the suffix. *) + let suffix_dead_bytes = + match removable_chunks with + (* If no chunks are GCed, the dead bytes are equivalent to the physical + offset of new suffix offset. *) + | [] -> Dispatcher.soff_of_offset dispatcher new_suffix_start_offset + (* Otherwise, it is the difference between the last chunk removed's end offset + and the new start offset. *) + | last_removed_chunk :: _ -> + let removed_end_offset = + last_removed_chunk.end_suffix_off + |> Dispatcher.offset_of_soff dispatcher + in + Int63.Syntax.(new_suffix_start_offset - removed_end_offset) + in + (* Step 6.4. Assertions and record construction. *) + assert (Int63.Syntax.(suffix_dead_bytes >= Int63.zero)); + let removable_chunk_idxs = + removable_chunks |> List.map (fun c -> c.idx) + in + ( { + start_offset = new_suffix_start_offset; + dead_bytes = suffix_dead_bytes; + chunk_start_idx; + }, + mapping_size, + removable_chunk_idxs ) + in + + (* Step 7. If we have a lower, archive the removed chunks *) + let modified_volume = + match Fm.gc_destination fm with + | `Delete -> None + | `Archive lower -> + [%log.debug "GC: archiving into lower"]; + stats := + Gc_stats.Worker.finish_current_step !stats "archive: iter reachable"; + let min_offset = Dispatcher.suffix_start_offset dispatcher in + let to_archive = ref [] in + Ranges.iter + (fun ~off ~len -> + to_archive := + (off, Dispatcher.read_seq_exn dispatcher ~off ~len) + :: !to_archive) + (traverse_range ~min_offset commit_key commit_store node_store); + let to_archive = List.rev !to_archive in + stats := + Gc_stats.Worker.finish_current_step !stats "archive: copy to lower"; + Lower.set_readonly lower false; + let vol = + Lower.archive_seq_exn ~upper_root:root ~generation ~to_archive lower + in + Lower.set_readonly lower true; + Some vol + in + + (* Step 8. Finalise stats and return. *) + let stats = Gc_stats.Worker.finalise !stats in + { + suffix_params; + mapping_size; + removable_chunk_idxs; + modified_volume; + stats; + } + + let write_gc_output ~root ~generation output = + let open Result_syntax in + let path = Irmin_pack.Layout.V4.gc_result ~root ~generation in + let* io = Io.create ~path ~overwrite:true in + let out = Irmin.Type.to_json_string gc_output_t output in + let* () = Io.write_string io ~off:Int63.zero out in + let* () = Io.fsync io in + Io.close io + + (* No one catches errors when this function terminates. Write the result in a + file and terminate. *) + let run_and_output_result ~lower_root ~generation ~new_files_path root + commit_key new_suffix_start_offset = + let result = + Errs.catch (fun () -> + run ~lower_root ~generation ~new_files_path root commit_key + new_suffix_start_offset) + in + Errs.log_if_error "gc run" result; + let write_result = write_gc_output ~root ~generation result in + write_result |> Errs.log_if_error "writing gc output" + (* No need to raise or log if [result] is [Error _], we've written it in + the file. *) +end diff --git a/vendors/irmin/src/irmin-pack/unix/gc_worker.mli b/vendors/irmin/src/irmin-pack/unix/gc_worker.mli new file mode 100644 index 000000000000..3201109cfd34 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/gc_worker.mli @@ -0,0 +1,52 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Code for running in an async GC worker thread. *) + +open! Import +module Payload = Control_file.Payload.Upper.Latest + +module Make (Args : Gc_args.S) : sig + module Args : Gc_args.S + + val run_and_output_result : + lower_root:string option -> + generation:int -> + new_files_path:string -> + string -> + Args.key -> + int63 -> + unit + + type suffix_params = { + start_offset : int63; + chunk_start_idx : int; + dead_bytes : int63; + } + [@@deriving irmin] + + type gc_results = { + suffix_params : suffix_params; + mapping_size : int63; + removable_chunk_idxs : int list; + modified_volume : Lower.volume_identifier option; + stats : Stats.Latest_gc.worker; + } + [@@deriving irmin] + + type gc_output = (gc_results, Args.Errs.t) result [@@deriving irmin] +end +with module Args := Args diff --git a/vendors/irmin/src/irmin-pack/unix/import.ml b/vendors/irmin/src/irmin-pack/unix/import.ml new file mode 100644 index 000000000000..ed3b6bf420c7 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/import.ml @@ -0,0 +1,85 @@ +(* + * Copyright (c)2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends + +let src = Logs.Src.create "irmin-pack.unix" ~doc:"irmin-pack unix backend" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Array = struct + include Array + + let find_opt p a = + let n = length a in + let rec loop i = + if i = n then None + else + let x = get a i in + if p x then Some x else loop (succ i) + in + loop 0 +end + +module List = struct + include List + + let rec iter_result f = function + | [] -> Ok () + | hd :: tl -> Result.bind (f hd) (fun () -> iter_result f tl) +end + +module Int63 = struct + include Optint.Int63 + + let t = Irmin.Type.int63 + + module Syntax = struct + let ( + ) = add + let ( - ) = sub + let ( * ) = mul + let ( / ) = div + let ( < ) a b = compare a b < 0 + let ( <= ) a b = compare a b <= 0 + let ( > ) a b = compare a b > 0 + let ( >= ) a b = compare a b >= 0 + let ( = ) = equal + end +end + +type int63 = Int63.t [@@deriving irmin] + +module Version = Irmin_pack.Version + +module type S = Irmin_pack.S + +module Conf = Irmin_pack.Conf +module Layout = Irmin_pack.Layout +module Indexable = Irmin_pack.Indexable + +module Result_syntax = struct + let ( let+ ) res f = Result.map f res + let ( let* ) = Result.bind + let ( >>= ) = Result.bind +end + +module Varint = struct + type t = int [@@deriving irmin ~decode_bin] + + (** LEB128 stores 7 bits per byte. An OCaml [int] has at most 63 bits. + [63 / 7] equals [9]. *) + let max_encoded_size = 9 +end diff --git a/vendors/irmin/src/irmin-pack/unix/inode.ml b/vendors/irmin/src/irmin-pack/unix/inode.ml new file mode 100644 index 000000000000..f6f34279f6f8 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/inode.ml @@ -0,0 +1,74 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin_pack.Inode +include Inode_intf + +module Make_persistent + (H : Irmin.Hash.S) + (Node : Irmin.Node.Generic_key.S + with type hash = H.t + and type contents_key = H.t Pack_key.t + and type node_key = H.t Pack_key.t) + (Inter : Internal + with type hash = H.t + and type key = H.t Pack_key.t + and type Snapshot.metadata = Node.metadata + and type Val.step = Node.step) + (Pack : Pack_store.S + with type hash = H.t + and type key = H.t Pack_key.t + and type value = Inter.Raw.t) = +struct + module Raw = Inter.Raw + module Pack = Pack + + type file_manager = Pack.file_manager + type dict = Pack.dict + type dispatcher = Pack.dispatcher + + let to_snapshot = Inter.to_snapshot + + module XKey = Pack_key.Make (H) + include Make (H) (XKey) (Node) (Inter) (Pack) + module Snapshot = Inter.Snapshot + + let of_snapshot t ~index v = + let find ~expected_depth:_ k = + let v = Pack.unsafe_find ~check_integrity:true t k in + v + in + Inter.Val.of_snapshot ~index v find + + let v = Pack.v + let integrity_check = Pack.integrity_check + let purge_lru = Pack.purge_lru + let key_of_offset = Pack.key_of_offset + + let unsafe_find_no_prefetch t key = + match Pack.unsafe_find_no_prefetch t key with + | None -> None + | Some v -> + let find ~expected_depth:_ k = + (* TODO: Remove this dead code. Can the GC traverse `Raw` values? *) + Pack.unsafe_find ~check_integrity:false t k + in + let v = Inter.Val.of_raw find v in + Some v + + let get_offset t k = Pack.get_offset t k + let get_length t k = Pack.get_length t k +end diff --git a/vendors/irmin/src/irmin-pack/unix/inode.mli b/vendors/irmin/src/irmin-pack/unix/inode.mli new file mode 100644 index 000000000000..e1569840bf14 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/inode.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Inode_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/inode_intf.ml b/vendors/irmin/src/irmin-pack/unix/inode_intf.ml new file mode 100644 index 000000000000..4a97b48981e0 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/inode_intf.ml @@ -0,0 +1,94 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +open Irmin_pack.Inode + +module type Persistent = sig + include S + + type file_manager + type dict + type dispatcher + + val v : + config:Irmin.Backend.Conf.t -> + fm:file_manager -> + dict:dict -> + dispatcher:dispatcher -> + read t + + include Irmin_pack.Checkable with type 'a t := 'a t and type hash := hash + + (* val reload : 'a t -> unit *) + val integrity_check_inodes : [ `Read ] t -> key -> (unit, string) result Lwt.t + + module Pack : + Pack_store.S + with type file_manager = file_manager + and type dict = dict + and type dispatcher = dispatcher + and type key := hash Pack_key.t + and type hash := hash + and type 'a t = 'a t + + module Raw : + Raw + with type t = Pack.value + and type hash := hash + and type key := hash Pack_key.t + + module Snapshot : + Snapshot with type hash = hash and type metadata = Val.metadata + + val to_snapshot : Raw.t -> Snapshot.inode + val of_snapshot : 'a t -> index:(hash -> key) -> Snapshot.inode -> value + val purge_lru : 'a t -> unit + val key_of_offset : 'a t -> int63 -> key + val unsafe_find_no_prefetch : 'a t -> key -> value option + val get_offset : 'a t -> key -> int63 + val get_length : 'a t -> key -> int +end + +module type Sigs = sig + module type S = S + module type Persistent = Persistent + + module Make_persistent + (H : Irmin.Hash.S) + (Node : Irmin.Node.Generic_key.S + with type hash = H.t + and type contents_key = H.t Pack_key.t + and type node_key = H.t Pack_key.t) + (Inter : Internal + with type hash = H.t + and type key = H.t Pack_key.t + and type Snapshot.metadata = Node.metadata + and type Val.step = Node.step) + (Pack : Pack_store.S + with type hash = H.t + and type key = H.t Pack_key.t + and type value = Inter.Raw.t) : + Persistent + with type key = H.t Pack_key.t + and type hash = H.t + and type Val.metadata = Node.metadata + and type Val.step = Node.step + and type file_manager = Pack.file_manager + and type dict = Pack.dict + and type dispatcher = Pack.dispatcher + and type value = Inter.Val.t +end diff --git a/vendors/irmin/src/irmin-pack/unix/io.ml b/vendors/irmin/src/irmin-pack/unix/io.ml new file mode 100644 index 000000000000..5bf022d1e9e6 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io.ml @@ -0,0 +1,298 @@ +(* + * Copyright (c) 2022-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Io_intf +module Syscalls = Index_unix.Syscalls + +(* File utils, taken from index.unix package. + + These functions need to read from a loop because the underlying + implementation will not read/write more than a constant called + [UNIX_BUFFER_SIZE]. *) +module Util = struct + let really_write fd fd_offset buffer buffer_offset length = + let rec aux fd_offset buffer_offset length = + let w = Syscalls.pwrite ~fd ~fd_offset ~buffer ~buffer_offset ~length in + if w = 0 || w = length then () + else + (aux [@tailcall]) + Int63.Syntax.(fd_offset + Int63.of_int w) + (buffer_offset + w) (length - w) + in + aux fd_offset buffer_offset length + + let really_read fd fd_offset length buffer = + let rec aux fd_offset buffer_offset length = + let r = Syscalls.pread ~fd ~fd_offset ~buffer ~buffer_offset ~length in + if r = 0 then buffer_offset (* end of file *) + else if r = length then buffer_offset + r + else + (aux [@tailcall]) + Int63.Syntax.(fd_offset + Int63.of_int r) + (buffer_offset + r) (length - r) + in + aux fd_offset 0 length +end + +module type S = S + +module Unix = struct + type misc_error = Unix.error * string * string + + let unix_error_t = + Irmin.Type.(map string (fun _str -> assert false) Unix.error_message) + + let misc_error_t = Irmin.Type.(triple unix_error_t string string) + + type create_error = [ `Io_misc of misc_error | `File_exists of string ] + + type open_error = + [ `Io_misc of misc_error + | `No_such_file_or_directory of string + | `Not_a_file ] + + type read_error = + [ `Io_misc of misc_error + | `Read_out_of_bounds + | `Closed + | `Invalid_argument ] + + type write_error = [ `Io_misc of misc_error | `Ro_not_allowed | `Closed ] + type close_error = [ `Io_misc of misc_error | `Double_close ] + + type mkdir_error = + [ `Io_misc of misc_error + | `File_exists of string + | `No_such_file_or_directory of string + | `Invalid_parent_directory ] + + let raise_misc_error (x, y, z) = raise (Unix.Unix_error (x, y, z)) + + let catch_misc_error f = + try Ok (f ()) + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2)) + + type t = { + fd : Unix.file_descr; + mutable closed : bool; + readonly : bool; + path : string; + } + + let classify_path p = + Unix.( + try + match (stat p).st_kind with + | S_REG -> `File + | S_DIR -> `Directory + | _ -> `Other + with _ -> `No_such_file_or_directory) + + let default_create_perm = 0o644 + let default_open_perm = 0o644 + let default_mkdir_perm = 0o755 + + let create ~path ~overwrite = + try + match Sys.file_exists path with + | false -> + let fd = + Unix.( + openfile path + [ O_CREAT; O_RDWR; O_EXCL; O_CLOEXEC ] + default_create_perm) + in + Ok { fd; closed = false; readonly = false; path } + | true -> ( + match overwrite with + | true -> + (* The file exists, truncate it and use it. An exception will be + triggered if we don't have the permissions *) + let fd = + Unix.( + openfile path + [ O_RDWR; O_CLOEXEC; O_TRUNC ] + default_create_perm) + in + Ok { fd; closed = false; readonly = false; path } + | false -> Error (`File_exists path)) + with + | Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2)) + | Sys_error _ -> assert false + + let open_ ~path ~readonly = + match classify_path path with + | `Directory | `Other -> Error `Not_a_file + | `No_such_file_or_directory -> Error (`No_such_file_or_directory path) + | `File -> ( + let mode = Unix.(if readonly then O_RDONLY else O_RDWR) in + try + let fd = Unix.(openfile path [ mode; O_CLOEXEC ] default_open_perm) in + Ok { fd; closed = false; readonly; path } + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2))) + + let close t = + match t.closed with + | true -> Error `Double_close + | false -> ( + t.closed <- true; + (* mark [t] as closed, even if [Unix.close] fails, since it is recommended + to not retry after an error. see: https://man7.org/linux/man-pages/man2/close.2.html *) + try + Unix.close t.fd; + Ok () + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2))) + + let write_exn t ~off ~len s = + if String.length s < len then raise (Errors.Pack_error `Invalid_argument); + match (t.closed, t.readonly) with + | true, _ -> raise Errors.Closed + | _, true -> raise Errors.RO_not_allowed + | _ -> + (* Bytes.unsafe_of_string usage: s has shared ownership; we assume that + Util.really_write does not mutate buf (i.e., only needs shared ownership). This + usage is safe. *) + let buf = Bytes.unsafe_of_string s in + let () = Util.really_write t.fd off buf 0 len in + Index.Stats.add_write len; + () + + let write_string t ~off s = + let len = String.length s in + try Ok (write_exn t ~off ~len s) with + | Errors.Closed -> Error `Closed + | Errors.RO_not_allowed -> Error `Ro_not_allowed + | Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2)) + + let fsync t = + match (t.closed, t.readonly) with + | true, _ -> Error `Closed + | _, true -> Error `Ro_not_allowed + | _ -> ( + try + Unix.fsync t.fd; + Ok () + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2))) + + let read_exn t ~off ~len buf = + if len > Bytes.length buf then raise (Errors.Pack_error `Invalid_argument); + match t.closed with + | true -> raise Errors.Closed + | false -> + let nread = Util.really_read t.fd off len buf in + Index.Stats.add_read nread; + if nread <> len then + (* didn't manage to read the desired amount; in this case the interface seems to + require we return `Read_out_of_bounds FIXME check this, because it is unusual + - the normal API allows return of a short string *) + raise (Errors.Pack_error `Read_out_of_bounds) + + let read_to_string t ~off ~len = + let buf = Bytes.create len in + try + read_exn t ~off ~len buf; + (* Bytes.unsafe_to_string usage: buf is local to this function, so uniquely + owned. We assume read_exn returns unique ownership of buf to this function. Then + at the call to Bytes.unsafe_to_string we give up unique ownership of buf for + ownership of the string. This is safe. *) + Ok (Bytes.unsafe_to_string buf) + with + | Errors.Pack_error ((`Invalid_argument | `Read_out_of_bounds) as e) -> + Error e + | Errors.Closed -> Error `Closed + | Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2)) + + let page_size = 4096 + + let read_all_to_string t = + let open Result_syntax in + let* () = if t.closed then Error `Closed else Ok () in + let buf = Buffer.create 0 in + let len = page_size in + let bytes = Bytes.create len in + let rec aux ~off = + let nread = + Syscalls.pread ~fd:t.fd ~fd_offset:off ~buffer:bytes ~buffer_offset:0 + ~length:len + in + if nread > 0 then ( + Index.Stats.add_read nread; + Buffer.add_subbytes buf bytes 0 nread; + if nread = len then aux ~off:Int63.(add off (of_int nread))) + in + try + aux ~off:Int63.zero; + Ok (Buffer.contents buf) + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2)) + + let read_size t = + match t.closed with + | true -> Error `Closed + | false -> ( + try Ok Unix.LargeFile.((fstat t.fd).st_size |> Int63.of_int64) + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2))) + + let size_of_path s = + let open Result_syntax in + let* io = open_ ~path:s ~readonly:true in + let res = + match read_size io with + | Error `Closed -> assert false + | Error (`Io_misc _) as x -> x + | Ok _ as x -> x + in + match close io with + | Error `Double_close -> assert false + | Error (`Io_misc _) as x -> x + | Ok () -> res + + let readonly t = t.readonly + let path t = t.path + + let move_file ~src ~dst = + try + Sys.rename src dst; + Ok () + with Sys_error msg -> Error (`Sys_error msg) + + let copy_file ~src ~dst = + let cmd = Filename.quote_command "cp" [ "-p"; src; dst ] in + match Sys.command cmd with + | 0 -> Ok () + | n -> Error (`Sys_error (Int.to_string n)) + + let mkdir path = + match (classify_path (Filename.dirname path), classify_path path) with + | `Directory, `No_such_file_or_directory -> ( + try + Unix.mkdir path default_mkdir_perm; + Ok () + with Unix.Unix_error (e, s1, s2) -> Error (`Io_misc (e, s1, s2))) + | `Directory, (`File | `Directory | `Other) -> Error (`File_exists path) + | `No_such_file_or_directory, `No_such_file_or_directory -> + Error (`No_such_file_or_directory path) + | _ -> Error `Invalid_parent_directory + + let unlink path = + try + Sys.remove path; + Ok () + with Sys_error msg -> Error (`Sys_error msg) + + let unlink_dont_wait ~on_exn path = + Lwt.dont_wait (fun () -> Lwt_unix.unlink path) on_exn +end diff --git a/vendors/irmin/src/irmin-pack/unix/io.mli b/vendors/irmin/src/irmin-pack/unix/io.mli new file mode 100644 index 000000000000..f6ec8493a227 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Io_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/io_errors.ml b/vendors/irmin/src/irmin-pack/unix/io_errors.ml new file mode 100644 index 000000000000..51c939e53b82 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io_errors.ml @@ -0,0 +1,109 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +open Errors + +(** Error manager for errors and exceptions defined in {!Errors} and + {!Io.S.misc_error} *) +module type S = sig + module Io : Io.S + + type t = [ Base.t | `Io_misc of Io.misc_error ] [@@deriving irmin] + + val raise_error : [< t ] -> 'a + val log_error : string -> [< t ] -> unit + val catch : (unit -> 'a) -> ('a, t) result + val raise_if_error : ('a, [< t ]) result -> 'a + val log_if_error : string -> ('a, [< t ]) result -> unit +end + +module Make (Io : Io.S) : S with module Io = Io = struct + module Io = Io + + (* Inline the definition of the polymorphic variant for the ppx. *) + type t = + [ `Double_close + | `File_exists of string + | `Invalid_parent_directory + | `No_such_file_or_directory of string + | `Not_a_file + | `Read_out_of_bounds + | `Invalid_argument + | `Decoding_error + | `Not_a_directory of string + | `Index_failure of string + | `Invalid_layout + | `Corrupted_legacy_file + | `Corrupted_mapping_file of string + | `Pending_flush + | `Rw_not_allowed + | `Migration_needed + | `Migration_to_lower_not_allowed + | `Corrupted_control_file of string + | `Sys_error of string + | `V3_store_from_the_future + | `Gc_forbidden_during_batch + | `Unknown_major_pack_version of string + | `Only_minimal_indexing_strategy_allowed + | `Commit_key_is_dangling of string + | `Dangling_key of string + | `Gc_disallowed of string + | `Node_or_contents_key_is_indexed of string + | `Gc_process_error of string + | `Corrupted_gc_result_file of string + | `Gc_process_died_without_result_file of string + | `Gc_forbidden_on_32bit_platforms + | `Invalid_prefix_read of string + | `Invalid_sparse_read of [ `After | `Before | `Hole ] * int63 + | `Invalid_volume_read of [ `Empty | `Closed ] * int63 + | `Inconsistent_store + | `Closed + | `Ro_not_allowed + | `Io_misc of Io.misc_error + | `Split_forbidden_during_batch + | `Split_disallowed + | `Multiple_empty_chunks + | `Forbidden_during_gc + | `Multiple_empty_volumes + | `Volume_missing of string + | `Volume_history_newer_than_archived_data of int63 * int63 + | `Lower_has_no_volume + | `Add_volume_forbidden_during_gc + | `Add_volume_requires_lower + | `Volume_not_found of string + | `No_tmp_path_provided ] + [@@deriving irmin] + + let raise_error = function + | `Io_misc e -> Io.raise_misc_error e + | #error as e -> Base.raise_error e + + let log_error context e = + [%log.err "%s failed: %a" context (Irmin.Type.pp t) (e :> t)] + + let catch f = + match Base.catch (fun () -> Io.catch_misc_error f) with + | Ok (Ok v) -> Ok v + | Ok (Error e) -> Error (e :> t) + | Error e -> Error (e :> t) + + let raise_if_error = function Ok x -> x | Error e -> raise_error e + + let log_if_error context = function + | Ok _ -> () + | Error e -> log_error context e +end diff --git a/vendors/irmin/src/irmin-pack/unix/io_intf.ml b/vendors/irmin/src/irmin-pack/unix/io_intf.ml new file mode 100644 index 000000000000..4d3b42bcbca4 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io_intf.ml @@ -0,0 +1,162 @@ +(* + * Copyright (c) 2022-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type S = sig + (** Low level IO abstraction. A typical implementation is unix. This + abstraction is meant to be dead simple. Not a lot of documentation is + required. + + It is not resistant to race condictions. There should not be concurrent + modifications of the files. + + These functions are essentially invoking the underlying functions from + {!Unix} directly; there is no buffering for example. *) + + type t + + (** {1 Errors} *) + + type misc_error [@@deriving irmin] + (** An abstract error type that contains the IO-backend specific errors. (e.g. + [Unix.error]) *) + + type create_error = [ `Io_misc of misc_error | `File_exists of string ] + + type open_error = + [ `Io_misc of misc_error + | `No_such_file_or_directory of string + | `Not_a_file ] + + type read_error = + [ `Io_misc of misc_error + | `Read_out_of_bounds + | `Closed + | `Invalid_argument ] + + type write_error = [ `Io_misc of misc_error | `Ro_not_allowed | `Closed ] + type close_error = [ `Io_misc of misc_error | `Double_close ] + + type mkdir_error = + [ `Io_misc of misc_error + | `File_exists of string + | `No_such_file_or_directory of string + | `Invalid_parent_directory ] + + (** {1 Safe Functions} + + None of the functions in this section raise exceptions. They may however + perform effects that are always continued. + + {2 Life Cycle} *) + + val create : path:string -> overwrite:bool -> (t, [> create_error ]) result + val open_ : path:string -> readonly:bool -> (t, [> open_error ]) result + val close : t -> (unit, [> close_error ]) result + + (** {2 Write Functions} *) + + val write_string : t -> off:int63 -> string -> (unit, [> write_error ]) result + (** [write_string t ~off s] writes [s] at [offset] in [t]. *) + + val fsync : t -> (unit, [> write_error ]) result + (** [fsync t] persists to the file system the effects of previous [create] or + write. *) + + val move_file : + src:string -> dst:string -> (unit, [> `Sys_error of string ]) result + + val copy_file : + src:string -> dst:string -> (unit, [> `Sys_error of string ]) result + + val mkdir : string -> (unit, [> mkdir_error ]) result + val unlink : string -> (unit, [> `Sys_error of string ]) result + + val unlink_dont_wait : on_exn:(exn -> unit) -> string -> unit + (** [unlink_dont_wait file] attempts to unlink the named file but doesn't wait + for the completion of the unlink operation. + + If unlink raises an exception it is passed to [on_exn]. *) + + (** {2 Read Functions} *) + + val read_to_string : + t -> off:int63 -> len:int -> (string, [> read_error ]) result + (** [read_to_string t ~off ~len] are the [len] bytes of [t] at [off]. *) + + val read_all_to_string : + t -> (string, [> `Io_misc of misc_error | `Closed ]) result + (** [read_to_string t] is the contents full contents of the file. + + The individual pages are not guaranteed to be read atomically. *) + + val read_size : t -> (int63, [> read_error ]) result + (** [read_size t] is the number of bytes of the file handled by [t]. + + This function is expensive in the unix implementation because it performs + syscalls. *) + + val size_of_path : + string -> + ( int63, + [> `Io_misc of misc_error + | `No_such_file_or_directory of string + | `Not_a_file ] ) + result + + val classify_path : + string -> [> `File | `Directory | `No_such_file_or_directory | `Other ] + + (** {1 MISC.} *) + + val readonly : t -> bool + val path : t -> string + val page_size : int + + (** {1 Unsafe Functions} + + These functions are equivalents to exising safe ones, but using exceptions + instead of the result monad for performances reasons. *) + + val read_exn : t -> off:int63 -> len:int -> bytes -> unit + (** [read_exn t ~off ~len b] reads the [len] bytes of [t] at [off] to [b]. + + Raises [Errors.Pack_error] and [Errors.RO_not_allowed]. + + Also raises backend-specific exceptions (e.g. [Unix.Unix_error] for the + unix backend). *) + + val write_exn : t -> off:int63 -> len:int -> string -> unit + (** [write_exn t ~off ~len b] writes the first [len] bytes pf [b] to [t] at + offset [off]. + + Raises [Errors.Pack_error] and [Errors.RO_not_allowed]. + + Also raises backend-specific exceptions (e.g. [Unix.Unix_error] for the + unix backend). *) + + val raise_misc_error : misc_error -> 'a + + val catch_misc_error : + (unit -> 'a) -> ('a, [> `Io_misc of misc_error ]) result +end + +module type Sigs = sig + module type S = S + + module Unix : S with type misc_error = Unix.error * string * string +end diff --git a/vendors/irmin/src/irmin-pack/unix/io_legacy.ml b/vendors/irmin/src/irmin-pack/unix/io_legacy.ml new file mode 100644 index 000000000000..2597edb22095 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io_legacy.ml @@ -0,0 +1,206 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Io_legacy_intf + +module Unix : S = struct + module Raw = Index_unix.Private.Raw + + type t = { + file : string; + raw : Raw.t; + mutable offset : int63; + mutable flushed : int63; + readonly : bool; + mutable version : Version.t; + buf : Buffer.t; + } + + let name t = t.file + let header_size = (* offset + version *) Int63.of_int 16 + + let unsafe_flush t = + [%log.debug "IO flush %s" t.file]; + let buf = Buffer.contents t.buf in + if buf = "" then () + else + let offset = t.offset in + Buffer.clear t.buf; + Raw.unsafe_write t.raw ~off:t.flushed buf 0 (String.length buf); + Raw.Offset.set t.raw offset; + let open Int63.Syntax in + (* concurrent append might happen so here t.offset might differ + from offset *) + if + not (t.flushed + Int63.of_int (String.length buf) = header_size + offset) + then + Fmt.failwith "reload error: %s flushed=%a offset+header=%a\n%!" t.file + Int63.pp t.flushed Int63.pp (offset + header_size); + t.flushed <- offset + header_size + + let flush t = + if t.readonly then raise Irmin_pack.RO_not_allowed; + unsafe_flush t + + let auto_flush_limit = Int63.of_int 1_000_000 + + let append t buf = + Buffer.add_string t.buf buf; + let len = Int63.of_int (String.length buf) in + let open Int63.Syntax in + t.offset <- t.offset + len; + if t.offset - t.flushed > auto_flush_limit then flush t + + let set t ~off buf = + if t.readonly then raise Irmin_pack.RO_not_allowed; + unsafe_flush t; + let buf_len = String.length buf in + let open Int63.Syntax in + Raw.unsafe_write t.raw ~off:(header_size + off) buf 0 buf_len; + assert ( + let len = Int63.of_int buf_len in + let off = header_size + off + len in + off <= t.flushed) + + exception Invalid_read of string + + let raise_invalid_read fmt = Fmt.kstr (fun s -> raise (Invalid_read s)) fmt + + let read_buffer t ~off ~buf ~len = + let open Int63.Syntax in + let off = header_size + off in + if (not t.readonly) && off > t.flushed then + raise_invalid_read + "Requested read of %d bytes at offset %a, but only flushed to %a" len + Int63.pp off Int63.pp t.flushed; + Raw.unsafe_read t.raw ~off ~len buf + + let read t ~off buf = read_buffer t ~off ~buf ~len:(Bytes.length buf) + let offset t = t.offset + + let force_offset t = + t.offset <- Raw.Offset.get t.raw; + t.offset + + let version t = + [%log.debug + "[%s] version: %a" (Filename.basename t.file) Version.pp t.version]; + t.version + + let set_version t v = + [%log.debug + "[%s] set_version: %a -> %a" (Filename.basename t.file) Version.pp + t.version Version.pp v]; + Raw.Version.set t.raw (Version.to_bin v); + t.version <- v + + let readonly t = t.readonly + + let protect_unix_exn = function + | Unix.Unix_error _ as e -> failwith (Printexc.to_string e) + | e -> raise e + + let ignore_enoent = function + | Unix.Unix_error (Unix.ENOENT, _, _) -> () + | e -> raise e + + let protect f x = try f x with e -> protect_unix_exn e + let safe f x = try f x with e -> ignore_enoent e + + let mkdir dirname = + let rec aux dir k = + if Sys.file_exists dir && Sys.is_directory dir then k () + else ( + if Sys.file_exists dir then safe Unix.unlink dir; + (aux [@tailcall]) (Filename.dirname dir) (fun () -> + protect (Unix.mkdir dir) 0o755; + k ())) + in + aux dirname (fun () -> ()) + + let raw ~flags ~version ~offset file = + let x = Unix.openfile file flags 0o644 in + let raw = Raw.v x in + let header = + { Raw.Header_prefix.version = Version.to_bin version; offset } + in + Raw.Header_prefix.set raw header; + raw + + let v ~version ~fresh ~readonly file = + let get_version () = + match version with + | Some v -> v + | None -> + Fmt.invalid_arg + "Must supply an explicit version when creating a new store ({ file \ + = %s })" + file + in + let v ~offset ~version raw = + { + version; + file; + offset; + raw; + readonly; + buf = Buffer.create (4 * 1024); + flushed = Int63.Syntax.(header_size + offset); + } + in + let mode = Unix.(if readonly then O_RDONLY else O_RDWR) in + mkdir (Filename.dirname file); + match Sys.file_exists file with + | false -> + let version = get_version () in + let raw = + raw + ~flags:[ O_CREAT; mode; O_CLOEXEC ] + ~version ~offset:Int63.zero file + in + v ~offset:Int63.zero ~version raw + | true -> + let x = Unix.openfile file Unix.[ O_EXCL; mode; O_CLOEXEC ] 0o644 in + let raw = Raw.v x in + if fresh then ( + let version = get_version () in + let header = + { + Raw.Header_prefix.version = Version.to_bin version; + offset = Int63.zero; + } + in + Raw.Header_prefix.set raw header; + v ~offset:Int63.zero ~version raw) + else + let actual_version = + let v_string = Raw.Version.get raw in + match Version.of_bin v_string with + | Some v -> v + | None -> Version.invalid_arg v_string + in + (match version with + | Some v when Version.compare actual_version v > 0 -> + raise (Version.Invalid { expected = v; found = actual_version }) + | _ -> ()); + let offset = Raw.Offset.get raw in + v ~offset ~version:actual_version raw + + let close t = Raw.close t.raw + let exists file = Sys.file_exists file + let size { raw; _ } = (Raw.fstat raw).st_size +end diff --git a/vendors/irmin/src/irmin-pack/unix/io_legacy.mli b/vendors/irmin/src/irmin-pack/unix/io_legacy.mli new file mode 100644 index 000000000000..13251fd978e7 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io_legacy.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Io_legacy_intf.Sigs diff --git a/vendors/irmin/src/irmin-pack/unix/io_legacy_intf.ml b/vendors/irmin/src/irmin-pack/unix/io_legacy_intf.ml new file mode 100644 index 000000000000..098a13f6148d --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/io_legacy_intf.ml @@ -0,0 +1,48 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + type t + type path := string + + val v : version:Version.t option -> fresh:bool -> readonly:bool -> path -> t + val name : t -> string + val append : t -> string -> unit + val set : t -> off:int63 -> string -> unit + val read : t -> off:int63 -> bytes -> int + val read_buffer : t -> off:int63 -> buf:bytes -> len:int -> int + val offset : t -> int63 + val force_offset : t -> int63 + val readonly : t -> bool + val flush : t -> unit + val close : t -> unit + val exists : string -> bool + val size : t -> int + val mkdir : string -> unit + + (* {2 Versioning} *) + + val version : t -> Version.t + val set_version : t -> Version.t -> unit +end + +module type Sigs = sig + module type S = S + + module Unix : S +end diff --git a/vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.ml b/vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.ml new file mode 100644 index 000000000000..6546fff59382 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.ml @@ -0,0 +1,62 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** {1 Store} *) + +module type S = Store_intf.S + +module Maker = Store.Maker + +module KV (Config : Irmin_pack.Conf.S) = struct + type endpoint = unit + type hash = Irmin.Schema.default_hash + + include Pack_key.Store_spec + module Maker = Maker (Config) + + type metadata = Irmin.Metadata.None.t + + module Make (C : Irmin.Contents.S) = Maker.Make (Irmin.Schema.KV (C)) +end + +(** {1 Key and Values} *) + +module Pack_key = Pack_key +module Pack_value = Pack_value + +(** {1 Internal} *) + +module Stats = Stats +module Index = Pack_index +module Inode = Inode +module Pack_store = Pack_store +module Io_legacy = Io_legacy +module Checks = Checks +module Atomic_write = Atomic_write +module Dict = Dict +module Dispatcher = Dispatcher +module Io = Io +module Async = Async +module Errors = Errors +module Io_errors = Io_errors +module Control_file = Control_file +module Append_only_file = Append_only_file +module Chunked_suffix = Chunked_suffix +module Ranges = Ranges +module Sparse_file = Sparse_file +module File_manager = File_manager +module Lower = Lower +module Utils = Utils diff --git a/vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.mli b/vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.mli new file mode 100644 index 000000000000..348875e9576e --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/irmin_pack_unix.mli @@ -0,0 +1,67 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** The [irmin-pack-unix] package provides an implementation of {!Irmin_pack} + for Unix systems. + + [irmin-pack-unix] provides advanced features such as garbage collection, + snapshoting, integrity checks. *) + +(** {1 Store} *) + +module type S = Store.S + +module Maker (Config : Irmin_pack.Conf.S) : Store.Maker +module KV (Config : Irmin_pack.Conf.S) : Store.KV + +(** {1 Key and Values} *) + +(* module Pack_store = Pack_store *) +module Pack_key = Pack_key +module Pack_value = Pack_value + +(** {1 Integrity Checks} *) + +module Checks = Checks + +(** {1 Statistics} *) + +module Stats = Stats + +(** {1 Internal Functors and Utilities} *) + +(** Following functors and modules are instantiated automatically or used + internally when creating a store with {!Maker} or {!KV}.*) + +module Index = Pack_index +module Inode = Inode +module Pack_store = Pack_store +module Io_legacy = Io_legacy +module Atomic_write = Atomic_write +module Dict = Dict +module Dispatcher = Dispatcher +module Io = Io +module Async = Async +module Errors = Errors +module Io_errors = Io_errors +module Control_file = Control_file +module Append_only_file = Append_only_file +module Chunked_suffix = Chunked_suffix +module Ranges = Ranges +module Sparse_file = Sparse_file +module File_manager = File_manager +module Lower = Lower +module Utils = Utils diff --git a/vendors/irmin/src/irmin-pack/unix/lower.ml b/vendors/irmin/src/irmin-pack/unix/lower.ml new file mode 100644 index 000000000000..a30f7079bc56 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/lower.ml @@ -0,0 +1,418 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Lower_intf +module Layout = Irmin_pack.Layout.V5.Volume +module Payload = Control_file.Payload.Volume.Latest + +module Make_volume (Io : Io.S) (Errs : Io_errors.S with module Io = Io) = struct + module Io = Io + module Errs = Errs + module Control = Control_file.Volume (Io) + module Sparse = Sparse_file.Make (Io) + + type t = + | Empty of { path : string } + | Nonempty of { + path : string; + control : Payload.t; + mutable sparse : Sparse.t option; + } + + type open_error = + [ Io.open_error + | `Closed + | `Double_close + | `Corrupted_control_file of string + | `Unknown_major_pack_version of string ] + + let v volume_path = + let open Result_syntax in + let* control = + let path = Layout.control ~root:volume_path in + match Io.classify_path path with + | `File -> + let+ payload = Control.read_payload ~path in + Some payload + | `Directory | `Other | `No_such_file_or_directory -> Ok None + in + Ok + (let path = volume_path in + match control with + | None -> Empty { path } + | Some control -> Nonempty { path; control; sparse = None }) + + let create_empty volume_path = + let open Result_syntax in + (* 0. Validate volume directory does not already exist *) + let* () = + match Io.classify_path volume_path with + | `Directory | `File | `Other -> Error (`File_exists volume_path) + | `No_such_file_or_directory -> Ok () + in + (* 1. Make directory *) + let* () = Io.mkdir volume_path in + (* 2. Make empty mapping *) + let* () = + Io.create ~path:(Layout.mapping ~root:volume_path) ~overwrite:true + >>= Io.close + in + (* 3. Make empty data *) + let* () = + Io.create ~path:(Layout.data ~root:volume_path) ~overwrite:true + >>= Io.close + in + (* TODO: handle failure to create all artifacts, either here or in a cleanup + when the store starts. *) + v volume_path + + let create_from ~src ~dead_header_size ~size lower_root = + let open Result_syntax in + let root = Layout.directory ~root:lower_root ~idx:0 in + let data = Layout.data ~root in + let mapping = Layout.mapping ~root in + let* () = Io.mkdir root in + let* () = Io.move_file ~src ~dst:data in + let* mapping_end_poff = + Sparse.Wo.create_from_data ~mapping ~dead_header_size ~size ~data + in + let payload = + { + Payload.start_offset = Int63.zero; + end_offset = size; + mapping_end_poff; + checksum = Int63.zero; + } + in + let control = Layout.control ~root in + Control.create_rw ~path:control ~tmp_path:None ~overwrite:false payload + >>= Control.close + + let path = function Empty { path } -> path | Nonempty { path; _ } -> path + + let control = function + | Empty _ -> None + | Nonempty { control; _ } -> Some control + + let is_empty = function Empty _ -> true | Nonempty _ -> false + + let contains ~off = function + | Empty _ -> false + | Nonempty { control; _ } -> + let open Int63.Syntax in + control.start_offset <= off && off < control.end_offset + + let open_ = function + | Empty _ -> Ok () (* Opening an empty volume is a no-op *) + | Nonempty ({ path = root; sparse; control; _ } as t) -> ( + match sparse with + | Some _ -> Ok () (* Sparse file is already open *) + | None -> + let open Result_syntax in + let mapping = Layout.mapping ~root in + let data = Layout.data ~root in + let mapping_size = Int63.to_int control.Payload.mapping_end_poff in + let+ sparse = Sparse.open_ro ~mapping_size ~mapping ~data in + t.sparse <- Some sparse) + + let close = function + | Empty _ -> Ok () (* Closing an empty volume is a no-op *) + | Nonempty ({ sparse; _ } as t) -> ( + match sparse with + | None -> Error `Double_close + | Some s -> + let open Result_syntax in + let+ () = Sparse.close s in + t.sparse <- None) + + let identifier t = path t + let identifier_eq ~id t = String.equal (identifier t) id + let eq a b = identifier_eq ~id:(identifier b) a + + let read_range_exn ~off ~min_len ~max_len b = function + | Empty _ -> Errs.raise_error (`Invalid_volume_read (`Empty, off)) + | Nonempty { sparse; _ } -> ( + match sparse with + | None -> Errs.raise_error (`Invalid_volume_read (`Closed, off)) + | Some s -> Sparse.read_range_exn s ~off ~min_len ~max_len b) + + let archive_seq ~upper_root ~generation ~is_first ~to_archive ~first_off t = + let open Result_syntax in + let root = path t in + let* () = + match t with + | Empty _ -> Ok () + | Nonempty { control; _ } -> + if control.end_offset <= first_off then Ok () + else + Error + (`Volume_history_newer_than_archived_data + (control.end_offset, first_off)) + in + let mapping = Irmin_pack.Layout.V5.Volume.mapping ~root in + let data = Irmin_pack.Layout.V5.Volume.data ~root in + let* mapping_size = + match t with + | Empty _ when is_first -> Ok Int63.zero + | Empty _ -> + (* If this is a new volume (and not the first), + copy pre-GC prefix/mapping as new volume *) + let old_generation = pred generation in + let old_mapping = + Irmin_pack.Layout.V5.mapping ~root:upper_root + ~generation:old_generation + in + let old_prefix = + Irmin_pack.Layout.V5.prefix ~root:upper_root + ~generation:old_generation + in + let* () = Io.copy_file ~src:old_prefix ~dst:data in + let* () = Io.copy_file ~src:old_mapping ~dst:mapping in + Io.size_of_path mapping + | Nonempty { control; _ } -> Ok control.mapping_end_poff + in + (* Append archived data *) + let* ao = Sparse.Ao.open_ao ~mapping_size ~mapping ~data in + List.iter + (fun (off, seq) -> Sparse.Ao.append_seq_exn ao ~off seq) + to_archive; + let end_offset = Sparse.Ao.end_off ao in + let mapping_end_poff = Sparse.Ao.mapping_size ao in + let* () = Sparse.Ao.flush ao in + let* () = Sparse.Ao.close ao in + (* Prepare new control file *) + let start_offset = + match t with + | Empty _ -> first_off + | Nonempty { control; _ } -> control.start_offset + in + let new_control = + Control_file.Payload.Volume.V5. + { start_offset; end_offset; mapping_end_poff; checksum = Int63.zero } + in + (* Write into temporary file on disk *) + let control_gc_tmp = + Irmin_pack.Layout.V5.Volume.control_gc_tmp ~generation ~root + in + let* c = + Control.create_rw ~path:control_gc_tmp ~tmp_path:None ~overwrite:true + new_control + in + let* () = Control.close c in + Ok (identifier t) + + let archive_seq ~upper_root ~generation ~is_first ~to_archive t = + match to_archive with + | [] -> + [%log.warn + "Lower.archive_seq: Nothing to archive! volume=%S generation=%i \ + is_first=%b" + (identifier t) generation is_first]; + Ok (identifier t) + | (first_off, _) :: _ -> + archive_seq ~upper_root ~generation ~is_first ~to_archive ~first_off t + + let swap ~generation t = + let root = path t in + let control_tmp = + Irmin_pack.Layout.V5.Volume.control_gc_tmp ~generation ~root + in + let control = Irmin_pack.Layout.V5.Volume.control ~root in + match Io.classify_path control_tmp with + | `File -> Io.move_file ~src:control_tmp ~dst:control + | `No_such_file_or_directory -> + [%log.info "No tmp volume control file to swap. %s" control]; + Ok () + | `Directory | `Other -> assert false + + let cleanup ~generation t = + let clean filename = + match Irmin_pack.Layout.Classification.Volume.v filename with + | `Control_tmp g when g = generation -> swap ~generation t + | `Control_tmp g when g <> generation -> + Io.unlink filename + |> Errs.log_if_error (Printf.sprintf "unlink %s" filename) + |> Result.ok + | _ -> Ok () + in + path t |> Sys.readdir |> Array.to_list |> List.iter_result clean +end + +module Make (Io : Io.S) (Errs : Io_errors.S with module Io = Io) = struct + module Io = Io + module Errs = Errs + module Volume = Make_volume (Io) (Errs) + + type t = { + root : string; + mutable readonly : bool; + mutable volumes : Volume.t array; + mutable open_volume : Volume.t option; + } + + type open_error = [ Volume.open_error | `Volume_missing of string ] + type close_error = [ | Io.close_error ] + type nonrec volume_identifier = volume_identifier [@@deriving irmin] + + type add_error = + [ open_error + | `Ro_not_allowed + | `Multiple_empty_volumes + | `File_exists of string + | `Invalid_parent_directory ] + + let close_open_volume t = + match t.open_volume with + | None -> Ok () + | Some v -> + let open Result_syntax in + let+ _ = Volume.close v in + t.open_volume <- None + + exception LoadVolumeError of open_error + + let load_volumes ~volume_num t = + let open Result_syntax in + let* () = close_open_volume t in + let* volumes = + let root = t.root in + let volume i = + let path = Layout.directory ~root ~idx:i in + match Io.classify_path path with + | `File | `Other | `No_such_file_or_directory -> + raise (LoadVolumeError (`Volume_missing path)) + | `Directory -> ( + match Volume.v path with + | Error e -> raise (LoadVolumeError e) + | Ok v -> v) + in + try Ok (Array.init volume_num volume) + with LoadVolumeError err -> Error (err : open_error :> [> open_error ]) + in + t.volumes <- volumes; + Ok t + + let v ~readonly ~volume_num root = + load_volumes ~volume_num + { root; readonly; volumes = [||]; open_volume = None } + + let reload ~volume_num t = + let open Result_syntax in + let* _ = load_volumes ~volume_num t in + Ok () + + let set_readonly t flag = t.readonly <- flag + let close = close_open_volume + let volume_num t = Array.length t.volumes + + let appendable_volume t = + match volume_num t with 0 -> None | num -> Some t.volumes.(num - 1) + + let add_volume t = + let open Result_syntax in + let* () = if t.readonly then Error `Ro_not_allowed else Ok () in + let* () = + match appendable_volume t with + | None -> Ok () + | Some v -> + if Volume.is_empty v then Error `Multiple_empty_volumes else Ok () + in + let volume_path = + let next_idx = volume_num t in + Layout.directory ~root:t.root ~idx:next_idx + in + let* vol = Volume.create_empty volume_path in + t.volumes <- Array.append t.volumes [| vol |]; + Ok vol + + let find_volume ~off t = Array.find_opt (Volume.contains ~off) t.volumes + + let find_volume_by_offset_exn ~off t = + match find_volume ~off t with + | None -> + let err = Fmt.str "Looking for offset %d" (Int63.to_int off) in + Errs.raise_error (`Volume_not_found err) + | Some v -> v + + let find_volume_by_identifier ~id t = + match Array.find_opt (Volume.identifier_eq ~id) t.volumes with + | None -> + let err = Fmt.str "Looking for identifier %s" id in + Error (`Volume_not_found err) + | Some v -> Ok v + + let find_volume_by_identifier_exn ~id t = + find_volume_by_identifier ~id t |> Errs.raise_if_error + + let read_range_exn ~off ~min_len ~max_len ?volume t b = + [%log.debug + "read_range_exn ~off:%a ~min_len:%i ~max_len:%i" Int63.pp off min_len + max_len]; + let set_open_volume t v = + (* Maintain one open volume at a time. *) + let open Result_syntax in + let* () = + match t.open_volume with + | None -> Ok () + | Some v0 -> if Volume.eq v0 v then Ok () else close_open_volume t + in + let+ _ = Volume.open_ v in + t.open_volume <- Some v + in + let volume = + match volume with + | None -> find_volume_by_offset_exn t ~off + | Some id -> find_volume_by_identifier_exn t ~id + in + set_open_volume t volume |> Errs.raise_if_error; + let len = Volume.read_range_exn ~off ~min_len ~max_len b volume in + (len, Volume.identifier volume) + + let archive_seq_exn ~upper_root ~generation ~to_archive t = + Errs.raise_if_error + (let open Result_syntax in + let* () = if t.readonly then Error `Ro_not_allowed else Ok () in + let* v = + match appendable_volume t with + | None -> Error `Lower_has_no_volume + | Some v -> Ok v + in + let* () = + match t.open_volume with + | None -> Ok () + | Some v0 -> if Volume.eq v0 v then close_open_volume t else Ok () + in + let is_first = volume_num t = 1 in + Volume.archive_seq ~upper_root ~generation ~to_archive ~is_first v) + + let read_exn ~off ~len ?volume t b = + let _, volume = read_range_exn ~off ~min_len:len ~max_len:len ?volume t b in + volume + + let create_from = Volume.create_from + + let swap ~volume ~generation ~volume_num t = + let open Result_syntax in + let* vol = find_volume_by_identifier ~id:volume t in + let* () = Volume.swap ~generation vol in + reload ~volume_num t + + let cleanup ~generation t = + match appendable_volume t with + | None -> Ok [%log.warn "Attempted to cleanup but lower has no volumes"] + | Some v -> Volume.cleanup ~generation v +end diff --git a/vendors/irmin/src/irmin-pack/unix/lower.mli b/vendors/irmin/src/irmin-pack/unix/lower.mli new file mode 100644 index 000000000000..1db18f08e88e --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/lower.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Lower_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/lower_intf.ml b/vendors/irmin/src/irmin-pack/unix/lower_intf.ml new file mode 100644 index 000000000000..1103181711b1 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/lower_intf.ml @@ -0,0 +1,191 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +type volume_identifier = string [@@deriving irmin] + +module type Volume = sig + module Io : Io.S + module Errs : Io_errors.S + module Sparse : Sparse_file.S + + type t + + type open_error = + [ Io.open_error + | `Closed + | `Double_close + | `Corrupted_control_file of string + | `Unknown_major_pack_version of string ] + + val v : string -> (t, [> open_error ]) result + (** [v path] loads the volume at [path] in read-only. *) + + val path : t -> string + (** [path t] is the directory that contains the volume. *) + + val is_empty : t -> bool + (** [is_empty t] returns whether [t] is empty or not. *) + + val control : t -> Control_file.Payload.Volume.Latest.t option + (** [control t] returns the control file payload for the volume. *) + + val identifier : t -> volume_identifier + (** [identifier t] is a unique idendifier for the volume. *) +end + +module type S = sig + module Io : Io.S + module Errs : Io_errors.S + module Volume : Volume with module Io = Io + + type t + type open_error = [ Volume.open_error | `Volume_missing of string ] + type close_error = [ | Io.close_error ] + type nonrec volume_identifier = volume_identifier [@@deriving irmin] + + type add_error = + [ open_error + | `Ro_not_allowed + | `Multiple_empty_volumes + | `File_exists of string + | `Invalid_parent_directory ] + + val v : + readonly:bool -> volume_num:int -> string -> (t, [> open_error ]) result + (** [v ~readonly ~volume_num lower_root] loads all volumes located in the + directory [lower_root]. + + [volume_num] is the number of volumes that are expected in [lower_root]. 0 + is valid for an empty lower. + + [Error `Volume_missing path] is returned if an expected volume is not on + disk, with the path to first volume that is missing. This can happen if + [volume_num] is larger than the number of volumes on disk, or if one of + the volume directories has been renamed accidentally. + + If [readonly] is false, no write operations are allowed. *) + + val reload : volume_num:int -> t -> (unit, [> open_error ]) result + (** [reload ~volume_num t] reloads volumes located in the root directory of + [t], using [volume_num] as the expected number of volumes. *) + + val close : t -> (unit, [> close_error ]) result + (** [close t] closes all resources opened by [t]. *) + + val volume_num : t -> int + (** [volume_num t] returns the number of volumes in the lower [t]. *) + + val add_volume : t -> (Volume.t, [> add_error ]) result + (** [add_volume t] adds a new empty volume to [t]. + + If there is already an empty volume, [Error `Multiple_empty_volumes] is + returned. Only one empty volume is allowed. + + If [t] is read-only, [Error `Ro_not_allowed] is returned. *) + + val find_volume : off:int63 -> t -> Volume.t option + (** [find_volume ~off t] returns the {!Volume} that contains [off]. *) + + val read_exn : + off:int63 -> + len:int -> + ?volume:volume_identifier -> + t -> + bytes -> + volume_identifier + (** [read_exn ~off ~len ~volume t b] will read [len] bytes from a global [off] + located in the volume with identifier [volume]. The volume identifier of + the volume where the read occurs is returned. + + If [volume] is not provided, {!find_volume} will be used to attempt to + locate the correct volume for the read. *) + + val set_readonly : t -> bool -> unit + (** [set_readonly t flag] changes the writing permission of the lower layer + (where [true] is read only). This should only be called by the GC worker + to temporarily allow RW before calling {!archive_seq_exn}. *) + + val archive_seq_exn : + upper_root:string -> + generation:int -> + to_archive:(int63 * string Seq.t) list -> + t -> + volume_identifier + (** [archive_seq ~upper_root ~generation ~to_archive t] is called by the GC + worker during the creation of the new [generation] to archive [to_archive] + in the lower layer and returns the identifier of the volume where data was + appended. + + It is the only write operation allowed on the lower layer, and it makes no + observable change as the control file is left untouched : instead new + changes are written to volume.gen.control, which is swapped during GC + finalization. *) + + val read_range_exn : + off:int63 -> + min_len:int -> + max_len:int -> + ?volume:volume_identifier -> + t -> + bytes -> + int * volume_identifier + (** Same as [read_exn] but will read at least [min_len] bytes and at most + [max_len]. Returns the read length and the volume identifier from which + the data was fetched. *) + + type create_error := + [ open_error | close_error | add_error | `Sys_error of string ] + + val create_from : + src:string -> + dead_header_size:int -> + size:Int63.t -> + string -> + (unit, [> create_error ]) result + (** [create_from ~src ~dead_header_size ~size lower_root] initializes the + first lower volume in the directory [lower_root] by moving the suffix file + [src] with end offset [size]. *) + + val swap : + volume:volume_identifier -> + generation:int -> + volume_num:int -> + t -> + ( unit, + [> `Volume_not_found of string | `Sys_error of string | open_error ] ) + result + (** [swap ~volume ~generation ~volume_num t] will rename a new volume control + file in [volume] for [generation] of GC and then reload the lower with + [volume_num] volumes. *) + + val cleanup : generation:int -> t -> (unit, [> `Sys_error of string ]) result + (** [cleanup ~generation t] will attempt to cleanup the appendable volume if a + GC crash has occurred. *) +end + +module type Sigs = sig + module type S = S + + type nonrec volume_identifier = volume_identifier [@@deriving irmin] + + module Make_volume (Io : Io.S) (Errs : Io_errors.S with module Io = Io) : + Volume with module Io = Io and module Errs = Errs + + module Make (Io : Io.S) (Errs : Io_errors.S with module Io = Io) : + S with module Io = Io and module Errs = Errs +end diff --git a/vendors/irmin/src/irmin-pack/unix/pack_index.ml b/vendors/irmin/src/irmin-pack/unix/pack_index.ml new file mode 100644 index 000000000000..f7d0b3f7c6eb --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_index.ml @@ -0,0 +1,122 @@ +(* + + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Pack_index_intf + +module Make (K : Irmin.Hash.S) = struct + module Key = struct + type t = K.t + [@@deriving irmin ~short_hash ~equal ~to_bin_string ~decode_bin] + + let hash = short_hash ?seed:None + let hash_size = 30 + let encode = to_bin_string + let encoded_size = K.hash_size + let decode s off = decode_bin s (ref off) + end + + module Val = struct + type t = int63 * int * Pack_value.Kind.t [@@deriving irmin] + + let encoded_size = (64 / 8) + (32 / 8) + 1 + + let encode ((off, len, kind) : t) = + let buf = Bytes.create encoded_size in + Bytes.set_int64_be buf 0 (Int63.to_int64 off); + Bytes.set_int32_be buf 8 (Int32.of_int len); + Bytes.set buf 12 (Pack_value.Kind.to_magic kind); + (* Bytes.unsafe_to_string usage: buf is local, uniquely owned. We assume the various + functions above return unique ownership of buf. Then in the call to + Bytes.unsafe_to_string we give up unique ownership of buf for ownership of the + resulting string. This is safe. *) + Bytes.unsafe_to_string buf + + let decode s pos : t = + (* Bytes.unsafe_of_string usage: s is shared ownership; buf is shared ownership (we + cannot mutate buf) and the lifetime of buf ends on return from this function; we + assume the Bytes.get... functions require only shared ownership. This usage is + safe. *) + let buf = Bytes.unsafe_of_string s in + let off = Bytes.get_int64_be buf pos |> Int63.of_int64 in + let len = Bytes.get_int32_be buf (pos + 8) |> Int32.to_int in + let kind = Bytes.get buf (pos + 12) |> Pack_value.Kind.of_magic_exn in + (off, len, kind) + end + + module Stats = Index.Stats + module I = Index + module Index = Index_unix.Make (Key) (Val) (Index.Cache.Unbounded) + include Index + module Io = Io.Unix + + let v_exn = + let cache = None in + Index.v ?cache + + let v ?flush_callback ?fresh ?readonly ?throttle ?lru_size ~log_size root = + try + Ok + (v_exn ?flush_callback ?fresh ?readonly ?throttle ?lru_size ~log_size + root) + with + | I.RO_not_allowed -> + (* Happens when [fresh = true = readonly] *) + assert false + | Index_unix.Private.Raw.Not_written -> + (* This is not expected to be raised but let's catch anyway to trigger + a more precise error instead (i.e. the [assert false] below). This + error is expected to be raised when a RO instance attemps an opening + on a non-existing file. *) + assert false + | Unix.Unix_error (x, y, z) -> Error (`Io_misc (x, y, z)) + | Failure msg -> Error (`Index_failure msg) + + let add ?overcommit t k v = replace ?overcommit t k v + let find t k = match find t k with exception Not_found -> None | h -> Some h + let close_exn t = Index.close t + + let close t = + try + close_exn t; + Ok () + with + | I.RO_not_allowed -> Error `Ro_not_allowed + | Index_unix.Private.Raw.Not_written -> assert false + | Unix.Unix_error (x, y, z) -> Error (`Io_misc (x, y, z)) + | Failure msg -> Error (`Index_failure msg) + + let reload t = + try + Index.sync t; + Ok () + with + | I.RO_not_allowed -> Error `Ro_not_allowed + | Index_unix.Private.Raw.Not_written -> assert false + | Unix.Unix_error (x, y, z) -> Error (`Io_misc (x, y, z)) + | Failure msg -> Error (`Index_failure msg) + + let flush t ~with_fsync = + try + Index.flush ~no_callback:() ~with_fsync t; + Ok () + with + | I.RO_not_allowed -> Error `Ro_not_allowed + | Index_unix.Private.Raw.Not_written -> assert false + | Unix.Unix_error (x, y, z) -> Error (`Io_misc (x, y, z)) + | Failure msg -> Error (`Index_failure msg) +end diff --git a/vendors/irmin/src/irmin-pack/unix/pack_index.mli b/vendors/irmin/src/irmin-pack/unix/pack_index.mli new file mode 100644 index 000000000000..68fad1731cdc --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_index.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Pack_index_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/pack_index_intf.ml b/vendors/irmin/src/irmin-pack/unix/pack_index_intf.ml new file mode 100644 index 000000000000..c1d74e02749c --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_index_intf.ml @@ -0,0 +1,75 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + (** An abstraction on top of the index library that exposes an API that better + fits the irmin-pack use case. *) + + type t + type key + type value = int63 * int * Pack_value.Kind.t + + include Index.S with type value := value and type t := t and type key := key + module Io : Io.S + + val v_exn : + ?flush_callback:(unit -> unit) -> + ?fresh:bool -> + ?readonly:bool -> + ?throttle:[ `Block_writes | `Overcommit_memory ] -> + ?lru_size:int -> + log_size:int -> + string -> + t + + type create_error := [ `Index_failure of string | `Io_misc of Io.misc_error ] + + type write_error := + [ `Index_failure of string | `Io_misc of Io.misc_error | `Ro_not_allowed ] + + val v : + ?flush_callback:(unit -> unit) -> + ?fresh:bool -> + ?readonly:bool -> + ?throttle:[ `Block_writes | `Overcommit_memory ] -> + ?lru_size:int -> + log_size:int -> + string -> + (t, [> create_error ]) result + + val reload : t -> (unit, [> write_error ]) result + val close : t -> (unit, [> write_error ]) result + val close_exn : t -> unit + val flush : t -> with_fsync:bool -> (unit, [> write_error ]) result + val find : t -> key -> value option + val add : ?overcommit:bool -> t -> key -> value -> unit + val merge : t -> unit + val mem : t -> key -> bool + val iter : (key -> value -> unit) -> t -> unit + val filter : t -> (key * value -> bool) -> unit + val try_merge : t -> unit + + module Stats = Index.Stats + module Key : Index.Key.S with type t = key +end + +module type Sigs = sig + module type S = S + + module Make (K : Irmin.Hash.S) : S with type key = K.t and module Io = Io.Unix +end diff --git a/vendors/irmin/src/irmin-pack/unix/pack_key.ml b/vendors/irmin/src/irmin-pack/unix/pack_key.ml new file mode 100644 index 000000000000..444b1dbff48a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_key.ml @@ -0,0 +1,168 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Pack_key_intf + +type safe = SAFE +type unsafe = UNSAFE + +type (_, _) unsafe_state = + | Direct : { + hash : 'hash; + offset : int63; + length : int; + volume_identifier : Lower.volume_identifier option; + } + -> ('hash, safe) unsafe_state + | Indexed : 'hash -> ('hash, safe) unsafe_state + | Offset : int63 -> ('hash, unsafe) unsafe_state + +type 'hash state = ('hash, safe) unsafe_state +type 'hash t = State : { mutable state : ('hash, _) unsafe_state } -> 'hash t + +let inspect (State t) = + match t.state with + | Offset _ -> failwith "inspect unsafe Offset" + | Direct d -> Direct d + | Indexed d -> Indexed d + +let to_hash (State t) = + match t.state with + | Direct t -> t.hash + | Indexed h -> h + | Offset _ -> failwith "Hash unavailable" + +let to_offset (State t) = + match t.state with + | Direct t -> Some t.offset + | Offset offset -> Some offset + | Indexed _ -> None + +let to_length (State t) = + match t.state with + | Direct t -> Some t.length + | Offset _ -> None + | Indexed _ -> None + +let promote_exn ~offset ~length ?volume_identifier (State t) = + match t.state with + | Direct _ -> failwith "Attempted to promote a key that is already Direct" + | Offset _ -> failwith "Attempted to promote an offset without hash" + | Indexed hash -> + t.state <- Direct { hash; offset; length; volume_identifier } + +let set_volume_identifier_exn ~volume_identifier (State t) = + match t.state with + | Indexed _ -> + failwith "Attempted to set volume identifier to a key that is Indexed" + | Offset _ -> + failwith "Attempted to set volume identifier to an offset without hash" + | Direct { hash; offset; length; _ } -> + t.state <- Direct { hash; offset; length; volume_identifier } + +let t : type h. h Irmin.Type.t -> h t Irmin.Type.t = + fun hash_t -> + let open Irmin.Type in + variant "t" (fun direct indexed t -> + match inspect t with + | Direct { hash; offset; length; _ } -> direct (hash, offset, length) + | Indexed x1 -> indexed x1) + |~ case1 "Direct" [%typ: hash * int63 * int] (fun (hash, offset, length) -> + State + { state = Direct { hash; offset; length; volume_identifier = None } }) + |~ case1 "Indexed" [%typ: hash] (fun x1 -> State { state = Indexed x1 }) + |> sealv + +let t (type hash) (hash_t : hash Irmin.Type.t) = + let module Hash = struct + type t = hash + [@@deriving irmin ~equal ~compare ~pre_hash ~encode_bin ~decode_bin] + + let unboxed_encode_bin = Irmin.Type.(unstage (Unboxed.encode_bin t)) + let unboxed_decode_bin = Irmin.Type.(unstage (Unboxed.decode_bin t)) + + let encoded_size = + match Irmin.Type.Size.of_value t with + | Static n -> n + | Dynamic _ | Unknown -> + failwith "Hash must have a fixed-width binary encoding" + end in + (* Equality and ordering on keys respects {i structural} equality semantics, + meaning two objects (containing keys) are considered equal even if their + children are stored at different offsets (either as duplicates in the same + pack file, or inside different pack files), or with different lengths (in + the event that the encoding environments were different). *) + let equal a b = Hash.equal (to_hash a) (to_hash b) in + let compare a b = Hash.compare (to_hash a) (to_hash b) in + (* The pre-hash image of a key is just the hash of the corresponding value. + + NOTE: it's particularly important that we discard the file offset when + computing hashes of structured values (e.g. inodes), so that this hashing + process is reproducible in different stores (w/ different offsets for the + values). *) + let pre_hash t f = Hash.pre_hash (to_hash t) f in + let encode_bin t f = Hash.encode_bin (to_hash t) f in + let unboxed_encode_bin t f = Hash.unboxed_encode_bin (to_hash t) f in + let decode_bin buf pos_ref = + State { state = Indexed (Hash.decode_bin buf pos_ref) } + in + let unboxed_decode_bin buf pos_ref = + State { state = Indexed (Hash.unboxed_decode_bin buf pos_ref) } + in + let size_of = Irmin.Type.Size.custom_static Hash.encoded_size in + Irmin.Type.like (t hash_t) ~pre_hash ~equal ~compare + ~bin:(encode_bin, decode_bin, size_of) + ~unboxed_bin:(unboxed_encode_bin, unboxed_decode_bin, size_of) + +let v_direct ~offset ~length ?volume_identifier hash = + State { state = Direct { hash; offset; length; volume_identifier } } + +let v_indexed hash = State { state = Indexed hash } +let v_offset offset = State { state = Offset offset } + +module type S = sig + type hash + + include Irmin_pack.Pack_key.S with type t = hash t and type hash := hash +end + +module Make (Hash : Irmin.Hash.S) = struct + type nonrec t = Hash.t t [@@deriving irmin] + type hash = Hash.t [@@deriving irmin ~of_bin_string] + + let to_hash = to_hash + let null_offset = Int63.minus_one + let null_length = -1 + + let null = + let buf = String.make Hash.hash_size '\000' in + let hash = + match hash_of_bin_string buf with Ok x -> x | Error _ -> assert false + in + v_direct ~offset:null_offset ~length:null_length hash + + let unfindable_of_hash hash = + v_direct ~offset:null_offset ~length:null_length hash +end + +module type Store_spec = sig + type ('h, _) contents_key = 'h t + type 'h node_key = 'h t + type 'h commit_key = 'h t +end + +module rec Store_spec : Store_spec = Store_spec diff --git a/vendors/irmin/src/irmin-pack/unix/pack_key.mli b/vendors/irmin/src/irmin-pack/unix/pack_key.mli new file mode 100644 index 000000000000..e7b62520a318 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_key.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Pack_key_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/pack_key_intf.ml b/vendors/irmin/src/irmin-pack/unix/pack_key_intf.ml new file mode 100644 index 000000000000..1d84885ffc61 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_key_intf.ml @@ -0,0 +1,128 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type Sigs = sig + type 'hash t + (** The type of {i keys} referencing values stored in the [irmin-pack] + backend. *) + + type safe = SAFE + and unsafe = UNSAFE + + (** The internal state of a key (read with {!inspect}). + + Invariant: keys of the form {!Indexed} always reference values that have + entries in the index (as otherwise these keys could not be dereferenced). *) + type ('hash, _) unsafe_state = private + | Direct : { + hash : 'hash; + offset : int63; + length : int; + volume_identifier : Lower.volume_identifier option; + } + -> ('hash, safe) unsafe_state + (** A "direct" pointer to a value stored at [offset] in the pack-file + (with hash [hash] and length [length]). Such keys can be + dereferenced from the store with a single IO read, without needing + to consult the index. + + They are built in-memory (e.g. after adding a fresh value to the + pack file), but have no corresponding encoding format, as the pack + format keeps length information with the values themselves. + + When decoding a inode, which references its children as single + offsets, we fetch the length information of the child at the same + time as fetching its hash (which we must do anyway in order to do an + integrity check), creating keys of this form. *) + | Indexed : 'hash -> ('hash, safe) unsafe_state + (** A pointer to an object in the pack file that is indexed. Reading the + object necessitates consulting the index, after which the key can be + promoted to {!Direct}. + + Such keys result from decoding pointers to other store objects + (nodes or commits) from commits or from the branch store. *) + | Offset : int63 -> ('hash, unsafe) unsafe_state + (** Same as [Direct], but the hash and length of the object have not + been fetched. Only used to speed up the GC traversal. *) + + type 'hash state = ('hash, safe) unsafe_state + + (** {2 Undereferencable keys} + + A key [k] is "undereferencable" with respect to some store handle [t] if + [find t k <> Some _]. Such keys should not arise during regular operation + of a single Irmin repository, but are still technically constructible in + the following ways: + + - {b storage corruption}. When decoding a key from disk, we may not + immediately check that it is dereferenceable for performance reasons. In + this case, any corruption to the key (or the referenced section of the + store) will be discovered on attempted [find] (or [mem]). + + - {b passing keys between store handles}. Read-only handles on a pack + store must explicitly {i reload} to observe recent writes to the store. + This means that any keys built by a read-write instance and passed to a + read-only instance will be undereferencable until that reader has + reloaded. + + - {b passing keys between repositories}. Keys created for one Irmin + repository may not be dereferenced with respect to another by design. *) + + val inspect : 'hash t -> 'hash state + + val v_direct : + offset:int63 -> + length:int -> + ?volume_identifier:Lower.volume_identifier -> + 'h -> + 'h t + + val v_indexed : 'h -> 'h t + val v_offset : int63 -> 'h t + + val promote_exn : + offset:int63 -> + length:int -> + ?volume_identifier:Lower.volume_identifier -> + 'h t -> + unit + + val set_volume_identifier_exn : + volume_identifier:Lower.volume_identifier option -> 'h t -> unit + + val to_offset : 'h t -> int63 option + val to_hash : 'h t -> 'h + val to_length : 'h t -> int option + + module type S = sig + type hash + + (** @inline *) + include Irmin_pack.Pack_key.S with type t = hash t and type hash := hash + end + + module Make (Hash : Irmin.Hash.S) : S with type hash = Hash.t + + module type Store_spec = sig + type ('h, _) contents_key = 'h t + type 'h node_key = 'h t + type 'h commit_key = 'h t + end + + module Store_spec : Store_spec +end diff --git a/vendors/irmin/src/irmin-pack/unix/pack_store.ml b/vendors/irmin/src/irmin-pack/unix/pack_store.ml new file mode 100644 index 000000000000..2bff9b4ec096 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_store.ml @@ -0,0 +1,560 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Pack_store_intf + +exception Invalid_read of string +exception Corrupted_store of string +exception Dangling_hash + +let invalid_read fmt = Fmt.kstr (fun s -> raise (Invalid_read s)) fmt +let corrupted_store fmt = Fmt.kstr (fun s -> raise (Corrupted_store s)) fmt + +module Table (K : Irmin.Hash.S) = Hashtbl.Make (struct + type t = K.t + + let hash = K.short_hash + let equal = Irmin.Type.(unstage (equal K.t)) +end) + +module Make_without_close_checks + (Fm : File_manager.S) + (Dict : Dict.S) + (Dispatcher : Dispatcher.S with module Fm = Fm) + (Hash : Irmin.Hash.S with type t = Fm.Index.key) + (Val : Pack_value.Persistent + with type hash := Hash.t + and type key := Hash.t Pack_key.t) + (Errs : Io_errors.S with module Io = Fm.Io) = +struct + module Tbl = Table (Hash) + module Control = Fm.Control + module Suffix = Fm.Suffix + module Index = Fm.Index + module Key = Pack_key.Make (Hash) + + module Lru = Irmin.Backend.Lru.Make (struct + include Int63 + + let hash = Hashtbl.hash + end) + + type file_manager = Fm.t + type dict = Dict.t + type dispatcher = Dispatcher.t + + type 'a t = { + lru : Val.t Lru.t; + staging : Val.t Tbl.t; + indexing_strategy : Irmin_pack.Indexing_strategy.t; + fm : Fm.t; + dict : Dict.t; + dispatcher : Dispatcher.t; + } + + type hash = Hash.t [@@deriving irmin ~pp ~equal ~decode_bin] + type key = Key.t [@@deriving irmin ~pp] + type value = Val.t [@@deriving irmin ~pp] + + let get_location t k = + match Pack_key.inspect k with + | Indexed hash -> ( + match Index.find (Fm.index t.fm) hash with + | None -> raise Dangling_hash + | Some (off, len, _kind) -> + Pack_key.promote_exn k ~offset:off ~length:len; + (off, len, None)) + | Direct { offset; length; volume_identifier; _ } -> + (offset, length, volume_identifier) + + let get_offset t k = + match Pack_key.to_offset k with + | Some off -> off + | None -> + let off, _, _ = get_location t k in + off + + let get_length t k = + match Pack_key.to_length k with + | Some len -> len + | None -> + let _, len, _ = get_location t k in + len + + let len_of_direct_key k = + match Pack_key.inspect k with + | Indexed _ -> assert false + | Direct { length; _ } -> length + + let off_of_direct_key k = + match Pack_key.to_offset k with + | None -> assert false + | Some offset -> offset + + let index_direct_with_kind t hash = + [%log.debug "index %a" pp_hash hash]; + match Index.find (Fm.index t.fm) hash with + | None -> None + | Some (offset, length, kind) -> + let key = Pack_key.v_direct ~offset ~length hash in + Some (key, kind) + + let index_direct t hash = + index_direct_with_kind t hash |> Option.map (fun (key, _) -> key) + + let index t hash = Lwt.return (index_direct t hash) + + let v ~config ~fm ~dict ~dispatcher = + let indexing_strategy = Conf.indexing_strategy config in + let lru_size = Conf.lru_size config in + let staging = Tbl.create 127 in + let weight v = + (* if a value is bigger than 10% of the total capacity, + we skip it by giving it a large weight. *) + let w = Val.weight v in + if w > lru_size / 10 then max_int else w + in + let lru = Lru.create ~weight lru_size in + Fm.register_suffix_consumer fm ~after_flush:(fun () -> Tbl.clear staging); + Fm.register_prefix_consumer fm ~after_reload:(fun () -> Ok (Lru.clear lru)); + { lru; staging; indexing_strategy; fm; dict; dispatcher } + + module Entry_prefix = struct + type t = { + hash : hash; + kind : Pack_value.Kind.t; + size_of_value_and_length_header : int option; + (** Remaining bytes in the entry after reading the hash and the kind + (i.e. the length of the length header + the value of the length + header), if the entry has a length header (otherwise [None]). + + NOTE: the length stored in the index and in direct pack keys is + the {!total_entry_length} (including the hash and the kind). See + [pack_value.mli] for a description. *) + } + [@@deriving irmin ~pp_dump] + + let min_length = Hash.hash_size + 1 + let max_length = Hash.hash_size + 1 + Varint.max_encoded_size + + let total_entry_length t = + Option.map (fun len -> min_length + len) t.size_of_value_and_length_header + end + + let read_and_decode_entry_prefix ~off ?volume_identifier dispatcher = + let buf = Bytes.create Entry_prefix.max_length in + let _len, _volume = + try + (* We may read fewer then [Entry_prefix.max_length] bytes when reading the + final entry in the pack file (if the data section of the entry is + shorter than [Varint.max_encoded_size]. In this case, an invalid read + may be discovered below when attempting to decode the length header. *) + Dispatcher.read_range_exn dispatcher ?volume_identifier ~off + ~min_len:Entry_prefix.min_length ~max_len:Entry_prefix.max_length buf + with Errors.Pack_error `Read_out_of_bounds -> + invalid_read + "Attempted to read an entry at offset %a in the pack file, but got \ + less than %d bytes" + Int63.pp off Entry_prefix.max_length + in + let hash = + (* Bytes.unsafe_to_string usage: buf is created locally, so we have unique + ownership; we assume Dispatcher.read_at_most_exn returns unique + ownership; use of Bytes.unsafe_to_string converts buffer to shared + ownership; the rest of the code seems to require only shared ownership + (buffer is read, but not mutated). This is safe. *) + decode_bin_hash (Bytes.unsafe_to_string buf) (ref 0) + in + let kind = Pack_value.Kind.of_magic_exn (Bytes.get buf Hash.hash_size) in + let size_of_value_and_length_header = + match Val.length_header kind with + | None -> None + | Some `Varint -> + let length_header_start = Entry_prefix.min_length in + (* The bytes starting at [length_header_start] are a + variable-length length field (if they exist / were read + correctly): *) + let pos_ref = ref length_header_start in + (* Bytes.unsafe_to_string usage: buf is shared at this point; we assume + Varint.decode_bin requires only shared ownership. This usage is safe. *) + let length_header = + Varint.decode_bin (Bytes.unsafe_to_string buf) pos_ref + in + let length_header_length = !pos_ref - length_header_start in + Some (length_header_length + length_header) + in + { Entry_prefix.hash; kind; size_of_value_and_length_header } + + (* This function assumes magic is written at hash_size + 1 for every + object. *) + let gced t buf = + let kind = Pack_value.Kind.of_magic_exn (Bytes.get buf Hash.hash_size) in + match (kind, Fm.gc_behaviour t.fm) with + | kind, `Delete -> kind = Pack_value.Kind.Dangling_parent_commit + | _, `Archive -> false + + let pack_file_contains_key t k = + let off, _, volume_identifier = get_location t k in + let len = Hash.hash_size + 1 in + let buf = Bytes.create len in + let (_volume : Lower.volume_identifier option) = + Dispatcher.read_exn t.dispatcher ~off ~len ?volume_identifier buf + in + if gced t buf then false + else + (* Bytes.unsafe_to_string usage: [buf] is local and never reused after + the call to [decode_bin_hash]. *) + let hash = decode_bin_hash (Bytes.unsafe_to_string buf) (ref 0) in + if not (equal_hash hash (Key.to_hash k)) then + invalid_read + "invalid key %a checked for membership (read hash %a at this offset \ + instead)" + pp_key k pp_hash hash; + (* At this point we consider the key to be contained in the pack + file. However, we could also be in the presence of a forged (or + unlucky) key that points to an offset that mimics a real pack + entry (e.g. in the middle of a blob). *) + true + + let pack_file_contains_key t k = + try pack_file_contains_key t k with + | Dangling_hash -> false + | Errors.Pack_error `Read_out_of_bounds -> + (* Can't fit an entry into this suffix of the store, so this key + isn't (yet) valid. If we're a read-only instance, the key may + become valid on [reload]; otherwise we know that this key wasn't + constructed for this store. *) + (if not (Control.readonly (Fm.control t.fm)) then + let io_offset = Dispatcher.end_offset t.dispatcher in + invalid_read "invalid key %a checked for membership (IO offset = %a)" + pp_key k Int63.pp io_offset); + false + | Errors.Pack_error (`Invalid_sparse_read _) -> false + | Errors.Pack_error (`Invalid_prefix_read _) -> false + + let unsafe_mem t k = + [%log.debug "[pack] mem %a" pp_key k]; + match Pack_key.inspect k with + | Indexed hash -> + (* The key doesn't contain an offset, let's skip the lookup in [lru] and + go straight to disk read. *) + Tbl.mem t.staging hash || pack_file_contains_key t k + | Direct { offset; hash; _ } -> + Tbl.mem t.staging hash + || Lru.mem t.lru offset + || pack_file_contains_key t k + + let mem t k = + let b = unsafe_mem t k in + Lwt.return b + + let check_hash h v = + let h' = Val.hash v in + if equal_hash h h' then Ok () else Error (h, h') + + let check_key k v = check_hash (Key.to_hash k) v + + (** Produce a key from an offset in the context of decoding inode and commit + children. *) + let key_of_offset ?volume_identifier t offset = + [%log.debug "key_of_offset: %a" Int63.pp offset]; + (* Attempt to eagerly read the length at the same time as reading the + hash in order to save an extra IO read when dereferencing the key: *) + let entry_prefix = + read_and_decode_entry_prefix ?volume_identifier ~off:offset t.dispatcher + in + (* This function is called on the parents of a commit when deserialising + it. Dangling_parent_commit are usually treated as removed objects, + except here, where in order to correctly deserialise the gced commit, + they are treated as kept commits. + + Volume identifier is excplicitly set to [None] for dangling parent commits + so that its data will not be read from the volume (or prefix). When it is + read, the routing will try to find its location in a previous volume. + *) + let kind, volume_identifier = + match entry_prefix.kind with + | Pack_value.Kind.Dangling_parent_commit -> + (Pack_value.Kind.Commit_v2, None) + | kind -> (kind, volume_identifier) + in + let key = + let entry_prefix = { entry_prefix with kind } in + match Entry_prefix.total_entry_length entry_prefix with + | Some length -> + Pack_key.v_direct ~offset ~length ?volume_identifier entry_prefix.hash + | None -> + (* NOTE: we could store [offset] in this key, but since we know the + entry doesn't have a length header we'll need to check the index + when dereferencing this key anyway. {i Not} storing the offset + avoids doing another failed check in the pack file for the length + header during [find]. *) + Pack_key.v_indexed entry_prefix.hash + in + key + + let find_in_pack_file ~key_of_offset t key = + let off, len, volume_identifier = get_location t key in + let buf = Bytes.create len in + let volume_identifier = + Dispatcher.read_exn t.dispatcher ~off ~len ?volume_identifier buf + in + if gced t buf then None + else + let () = Pack_key.set_volume_identifier_exn ~volume_identifier key in + let key_of_offset = key_of_offset ?volume_identifier t in + let key_of_hash = Pack_key.v_indexed in + let dict = Dict.find t.dict in + let v = + (* Bytes.unsafe_to_string usage: buf created, uniquely owned; after + creation, we assume Dispatcher.read_if_not_gced returns unique + ownership; we give up unique ownership in call to + [Bytes.unsafe_to_string]. This is safe. *) + Val.decode_bin ~key_of_offset ~key_of_hash ~dict + (Bytes.unsafe_to_string buf) + (ref 0) + in + Some v + + let find_in_pack_file ~key_of_offset t key = + try find_in_pack_file ~key_of_offset t key with + | Dangling_hash -> None + | Errors.Pack_error `Read_out_of_bounds -> ( + (* Can't fit an entry into this suffix of the store, so this key + * isn't (yet) valid. If we're a read-only instance, the key may + * become valid on [reload]; otherwise we know that this key wasn't + * constructed for this store. *) + let io_offset = Dispatcher.end_offset t.dispatcher in + match Control.readonly (Fm.control t.fm) with + | false -> + invalid_read + "attempt to dereference invalid key %a (IO offset = %a)" pp_key + key Int63.pp io_offset + | true -> + [%log.debug + "Direct store key references an unknown starting offset %a \ + (length = %d, IO offset = %a)" + Int63.pp (off_of_direct_key key) (len_of_direct_key key) Int63.pp + io_offset]; + None) + | Errors.Pack_error (`Invalid_sparse_read _) -> None + | Errors.Pack_error (`Invalid_prefix_read _) as e -> raise e + + let unsafe_find ~check_integrity t k = + [%log.debug "[pack] find %a" pp_key k]; + let find_location = ref Stats.Pack_store.Not_found in + let find_in_pack_file_guarded ~is_indexed = + let res = find_in_pack_file ~key_of_offset t k in + Option.iter + (fun v -> + if is_indexed then find_location := Stats.Pack_store.Pack_indexed + else find_location := Stats.Pack_store.Pack_direct; + Lru.add t.lru (off_of_direct_key k) v; + if check_integrity then + check_key k v |> function + | Ok () -> () + | Error (expected, got) -> + corrupted_store "Got hash %a, expecting %a (for val: %a)." + pp_hash got pp_hash expected pp_value v) + res; + res + in + let value_opt = + match Pack_key.inspect k with + | Indexed hash -> ( + match Tbl.find t.staging hash with + | v -> + (* Hit in staging, but we don't have offset to put in LRU *) + find_location := Stats.Pack_store.Staging; + Some v + | exception Not_found -> find_in_pack_file_guarded ~is_indexed:true) + | Direct { offset; hash; _ } -> ( + match Tbl.find t.staging hash with + | v -> + Lru.add t.lru offset v; + find_location := Stats.Pack_store.Staging; + Some v + | exception Not_found -> ( + match Lru.find t.lru offset with + | v -> + find_location := Stats.Pack_store.Lru; + Some v + | exception Not_found -> + find_in_pack_file_guarded ~is_indexed:false)) + in + Stats.report_pack_store ~field:!find_location; + value_opt + + let unsafe_find_no_prefetch t key = + let key_of_offset ?volume_identifier:_ _ = Pack_key.v_offset in + find_in_pack_file ~key_of_offset t key + + let find t k = + let v = unsafe_find ~check_integrity:true t k in + Lwt.return v + + let integrity_check ~offset ~length hash t = + let k = Pack_key.v_direct ~offset ~length hash in + (* TODO: new error for reading gced objects. *) + match find_in_pack_file ~key_of_offset t k with + | exception Errors.Pack_error (`Invalid_prefix_read _) -> + Error `Absent_value + | exception Invalid_read _ -> Error `Absent_value + | None -> Error `Wrong_hash + | Some value -> ( + match check_hash hash value with + | Ok () -> Ok () + | Error _ -> Error `Wrong_hash) + + let cast t = (t :> read_write t) + + (** [batch] is required by the [Backend] signature of irmin core, but + irmin-pack is really meant to be used using the [batch] of the repo (in + [ext.ml]). The following batch exists only for compatibility, but it is + very tempting to replace the implementation by an [assert false]. *) + let batch t f = + [%log.warn + "[pack] calling batch directory on a store is not recommended. Use \ + repo.batch instead."]; + let on_success res = + Fm.flush t.fm |> Errs.raise_if_error; + Lwt.return res + in + let on_fail exn = + [%log.info + "[pack] batch failed. calling flush. (%s)" (Printexc.to_string exn)]; + let () = + match Fm.flush t.fm with + | Ok () -> () + | Error err -> + [%log.err + "[pack] batch failed and flush failed. Silencing flush fail. (%a)" + (Irmin.Type.pp Errs.t) err] + in + raise exn + in + Lwt.try_bind (fun () -> f (cast t)) on_success on_fail + + let unsafe_append ~ensure_unique ~overcommit t hash v = + let kind = Val.kind v in + let use_index = + (* the index is required for non-minimal indexing strategies and + for commits. *) + (not (Irmin_pack.Indexing_strategy.is_minimal t.indexing_strategy)) + || kind = Commit_v1 + || kind = Commit_v2 + in + let unguarded_append () = + let offset_of_key k = + match Pack_key.inspect k with + | Direct { offset; _ } -> + Stats.incr_appended_offsets (); + Some offset + | Indexed hash -> ( + (* TODO: Why don't we promote the key here? *) + match Index.find (Fm.index t.fm) hash with + | None -> + Stats.incr_appended_hashes (); + None + | Some (offset, _, _) -> + Stats.incr_appended_offsets (); + Some offset) + in + let dict = Dict.index t.dict in + let off = Dispatcher.end_offset t.dispatcher in + + (* [encode_bin] will most likely call [append] several time. One of these + call may trigger an auto flush. *) + let append = Suffix.append_exn (Fm.suffix t.fm) in + Val.encode_bin ~offset_of_key ~dict hash v append; + + let open Int63.Syntax in + let len = Int63.to_int (Dispatcher.end_offset t.dispatcher - off) in + let key = Pack_key.v_direct ~offset:off ~length:len hash in + let () = + let should_index = t.indexing_strategy ~value_length:len kind in + if should_index then + Index.add ~overcommit (Fm.index t.fm) hash (off, len, kind) + in + Tbl.add t.staging hash v; + Lru.add t.lru off v; + [%log.debug "[pack] append %a" pp_key key]; + key + in + match ensure_unique && use_index with + | false -> unguarded_append () + | true -> + let key = Pack_key.v_indexed hash in + if unsafe_mem t key then key else unguarded_append () + + let unsafe_add t hash v = + unsafe_append ~ensure_unique:true ~overcommit:false t hash v |> Lwt.return + + let add t v = unsafe_add t (Val.hash v) v + + (** This close is a noop. + + Closing the file manager would be inadequate because it is passed to [v]. + The caller should close the file manager. + + We could clear the caches here but that really is not necessary. *) + let close _ = Lwt.return () + + let purge_lru t = Lru.clear t.lru +end + +module Make + (Fm : File_manager.S) + (Dict : Dict.S) + (Dispatcher : Dispatcher.S with module Fm = Fm) + (Hash : Irmin.Hash.S with type t = Fm.Index.key) + (Val : Pack_value.Persistent + with type hash := Hash.t + and type key := Hash.t Pack_key.t) + (Errs : Io_errors.S with module Io = Fm.Io) = +struct + module Inner = + Make_without_close_checks (Fm) (Dict) (Dispatcher) (Hash) (Val) (Errs) + + include Inner + include Indexable.Closeable (Inner) + + let v ~config ~fm ~dict ~dispatcher = + Inner.v ~config ~fm ~dict ~dispatcher |> make_closeable + + let cast t = Inner.cast (get_if_open_exn t) |> make_closeable + + let integrity_check ~offset ~length k t = + Inner.integrity_check ~offset ~length k (get_if_open_exn t) + + module Entry_prefix = Inner.Entry_prefix + + let read_and_decode_entry_prefix ~off dispatcher = + Inner.read_and_decode_entry_prefix ~off dispatcher + + let index_direct_with_kind t = + Inner.index_direct_with_kind (get_if_open_exn t) + + let purge_lru t = Inner.purge_lru (get_if_open_exn t) + let key_of_offset t offset = Inner.key_of_offset (get_if_open_exn t) offset + + let unsafe_find_no_prefetch t key = + Inner.unsafe_find_no_prefetch (get_if_open_exn t) key + + let get_offset t key = Inner.get_offset (get_if_open_exn t) key + let get_length t key = Inner.get_length (get_if_open_exn t) key +end diff --git a/vendors/irmin/src/irmin-pack/unix/pack_store.mli b/vendors/irmin/src/irmin-pack/unix/pack_store.mli new file mode 100644 index 000000000000..01c030a648f8 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_store.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Pack_store_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/pack_store_intf.ml b/vendors/irmin/src/irmin-pack/unix/pack_store_intf.ml new file mode 100644 index 000000000000..d7fe84143227 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_store_intf.ml @@ -0,0 +1,107 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +(** A [Pack_store.S] is a closeable, persistent implementation of {!Indexable.S} + that uses an append-only file of variable-length data blocks. + + Certain values in the data file are indexed by hash via a {!Pack_index.S} + implementation, but not all of them need be. *) +module type S = sig + include Irmin_pack.Indexable.S + + type file_manager + type dict + type dispatcher + + val v : + config:Irmin.Backend.Conf.t -> + fm:file_manager -> + dict:dict -> + dispatcher:dispatcher -> + read t + + val cast : read t -> read_write t + + (** @inline *) + include Irmin_pack.Checkable with type 'a t := 'a t and type hash := hash + + module Entry_prefix : sig + type t = { + hash : hash; + kind : Pack_value.Kind.t; + size_of_value_and_length_header : int option; + (** Remaining bytes in the entry after reading the hash and the kind + (i.e. the length of the length header + the value of the length + header), if the entry has a length header (otherwise [None]). + + NOTE: the length stored in the index and in direct pack keys is + the {!total_entry_length} (including the hash and the kind). *) + } + + val total_entry_length : t -> int option + end + + val read_and_decode_entry_prefix : off:int63 -> dispatcher -> Entry_prefix.t + (** Read the entry prefix at offset [off]. *) + + val index_direct_with_kind : 'a t -> hash -> (key * Pack_value.Kind.t) option + (** Returns the key and the kind of an object indexed by hash. *) + + val purge_lru : 'a t -> unit + + val key_of_offset : 'a t -> int63 -> key + (** Returns the key associated with the offset. *) + + val unsafe_find_no_prefetch : 'a t -> key -> value option + (** Similar to [unsafe_find], returns the value associated with the [key] in + the store but without prefetching the [hash] and [length] of the children + (or doing any integrity check). As a result, the produced children keys + only contain their [offset] and are not usable without calling + [key_of_offset] first. This function only exists to optimize the GC + reachability traversal. *) + + val get_offset : 'a t -> key -> int63 + (** Returns the offset associated with the key. *) + + val get_length : 'a t -> key -> int + (** Returns the length of the object associated with the key. *) +end + +module type Sigs = sig + exception Invalid_read of string + exception Dangling_hash + + module type S = S + + module Make + (Fm : File_manager.S) + (Dict : Dict.S with module Fm = Fm) + (Dispatcher : Dispatcher.S with module Fm = Fm) + (Hash : Irmin.Hash.S with type t = Fm.Index.key) + (Val : Pack_value.Persistent + with type hash := Hash.t + and type key := Hash.t Pack_key.t) + (Errs : Io_errors.S with module Io = Fm.Io) : + S + with type key = Hash.t Pack_key.t + and type hash = Hash.t + and type value = Val.t + and type file_manager = Fm.t + and type dispatcher = Dispatcher.t + and type dict = Dict.t +end diff --git a/vendors/irmin/src/irmin-pack/unix/pack_value.ml b/vendors/irmin/src/irmin-pack/unix/pack_value.ml new file mode 100644 index 000000000000..a86d86dc98ff --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/pack_value.ml @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin_pack.Pack_value + +module type Persistent = sig + type hash + + include S with type hash := hash and type key = hash Pack_key.t +end diff --git a/vendors/irmin/src/irmin-pack/unix/ranges.ml b/vendors/irmin/src/irmin-pack/unix/ranges.ml new file mode 100644 index 000000000000..e719d594b9dd --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/ranges.ml @@ -0,0 +1,133 @@ +(* + * Copyright (c) 2022-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +type range = { off : int63; len : int63 } + +module Stack = struct + type t = Empty | Stack of { mutable len : int; arr : int63 array; prev : t } + + let capacity = 131_072 (* = 128*1024, a large but not too large chunk size *) + let make prev = Stack { len = 0; arr = Array.make capacity Int63.zero; prev } + let is_full = function Empty -> true | Stack s -> s.len >= capacity + + let rec push x t = + match t with + | Stack s when not (is_full t) -> + let i = s.len in + s.len <- i + 2; + s.arr.(i) <- x.off; + s.arr.(i + 1) <- x.len; + t + | _ -> push x (make t) + + let rec to_seq t () = + match t with + | Empty -> Seq.Nil + | Stack { len; arr; prev } -> + assert (len mod 2 = 0); + let rec go i () = + if i < 0 then to_seq prev () + else + let range = { off = arr.(2 * i); len = arr.((2 * i) + 1) } in + Seq.Cons (range, go (i - 1)) + in + go ((len / 2) - 1) () +end + +type t = { + mutable last : range option; + mutable ranges : Stack.t; + mutable count : int; + mutable out_of_order : range list; +} + +let make () = + { last = None; ranges = Stack.Empty; count = 0; out_of_order = [] } + +let count t = t.count + +let add ~off ~len t = + t.count <- t.count + 1; + let open Int63.Syntax in + let len = Int63.of_int len in + match t.last with + | None -> t.last <- Some { off; len } + | Some last when off + len = last.off -> + (* latest interval can be fused with the previous one *) + t.last <- Some { off; len = len + last.len } + | Some last when off + len < last.off -> + (* disjoint and strictly smaller *) + t.last <- Some { off; len }; + t.ranges <- Stack.push last t.ranges + | Some _ -> + (* latest range is not strictly smaller than previous, + * this is only expected on legacy data with wrong object ordering + * and is handled as a special case. *) + t.out_of_order <- { off; len } :: t.out_of_order + +let ranges_to_seq t () = + match t.last with + | None -> Seq.Nil + | Some range -> Seq.Cons (range, Stack.to_seq t.ranges) + +let out_of_order_to_seq t = + List.to_seq + @@ List.sort_uniq (fun a b -> Int63.compare a.off b.off) t.out_of_order + +let rec seq_merge xs ys () = + match (xs (), ys ()) with + | Seq.Nil, rest | rest, Seq.Nil -> rest + | Seq.Cons (x, xs'), Seq.Cons (y, ys') -> ( + match Int63.compare x.off y.off with + | 0 -> + assert (x.len = y.len); + Seq.Cons (x, seq_merge xs' ys') + | c when c < 0 -> Seq.Cons (x, seq_merge xs' ys) + | _ -> Seq.Cons (y, seq_merge xs ys')) + +type fused = Disjoint of range * range | Overlap of range + +let fuse fst snd = + let open Int63.Syntax in + let fst_end = fst.off + fst.len in + let snd_end = snd.off + snd.len in + if fst_end < snd.off then Disjoint (fst, snd) + else if snd_end < fst.off then Disjoint (snd, fst) + else + let start = min fst.off snd.off in + let stop = max fst_end snd_end in + Overlap { off = start; len = stop - start } + +let rec seq_fuse ?prev s () = + match (prev, s ()) with + | None, Seq.Nil -> Seq.Nil + | Some prev, Nil -> Seq.Cons (prev, Seq.empty) + | None, Cons (x, xs) -> seq_fuse ~prev:x xs () + | Some prev, Cons (x, xs) -> ( + match fuse x prev with + | Disjoint (fst, snd) -> Seq.Cons (fst, seq_fuse ~prev:snd xs) + | Overlap prev -> seq_fuse ~prev xs ()) + +let iter fn t = + let in_order = ranges_to_seq t in + let ranges = + match t.out_of_order with + | [] -> in_order + | _ -> seq_fuse (seq_merge in_order (out_of_order_to_seq t)) + in + Seq.iter (fun { off; len } -> fn ~off ~len) ranges diff --git a/vendors/irmin/src/irmin-pack/unix/ranges.mli b/vendors/irmin/src/irmin-pack/unix/ranges.mli new file mode 100644 index 000000000000..240c8926e2e2 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/ranges.mli @@ -0,0 +1,38 @@ +(* + * Copyright (c) 2022-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +type t +(** An ordered set of disjoint [(offset, length)] ranges. *) + +val make : unit -> t +(** [make ()] returns a new empty set of ranges. *) + +val add : off:int63 -> len:int -> t -> unit +(** [add ~off ~len t] inserts the range [(off, len)] into [t]. When [add] is + called multiple times sequentially, it is optimized for strictly decreasing + offsets arguments. *) + +val iter : (off:int63 -> len:int63 -> unit) -> t -> unit +(** [iter fn t] calls [fn ~off ~len] on every disjoint range [(off, len)] in the + set [t]. The function [fn ~off ~len] is called with strictly increasing + offsets. If two or more consecutive ranges [(off,len)] and [(off+len,len')] + were added to the set [t], a single call to [fn] will be performed on the + englobing interval [(off,len+len')]. *) + +val count : t -> int +(** [count t] returns the number of [add]s performed on [t]. *) diff --git a/vendors/irmin/src/irmin-pack/unix/snapshot.ml b/vendors/irmin/src/irmin-pack/unix/snapshot.ml new file mode 100644 index 000000000000..1ed1fae40fd3 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/snapshot.ml @@ -0,0 +1,344 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Snapshot_intf + +let rm_index path = + let path_index = Filename.concat path "index" in + Sys.readdir path_index + |> Array.iter (fun name -> Unix.unlink (Filename.concat path_index name)); + Unix.rmdir path_index; + Unix.rmdir path + +module Make (Args : Args) = struct + module Hashes = Irmin.Hash.Set.Make (Args.Hash) + open Args + module Inode_pack = Inode.Pack + module Pack_index = Pack_index.Make (Hash) + + let pp_hash = Irmin.Type.pp Hash.t + let pp_key = Irmin.Type.pp Inode_pack.Key.t + let pp_kind = Irmin.Type.pp Pack_value.Kind.t + let pp_snapshot = Irmin.Type.pp Inode.Snapshot.inode_t + + module Export = struct + module Value_unit = struct + type t = unit [@@deriving irmin] + + let encode _ = "" + let encoded_size = 0 + let decode _ _ = () + end + + module Index = + Index_unix.Make (Pack_index.Key) (Value_unit) (Index.Cache.Unbounded) + + type t = { + fm : Fm.t; + dispatcher : Dispatcher.t; + log_size : int; + inode_pack : read Inode_pack.t; + contents_pack : read Contents_pack.t; + } + + let v config contents_pack inode_pack = + (* In order to read from the pack files, we need to open at least two + files: suffix and control. We just open the file manager for + simplicity. *) + let fm = Fm.open_ro config |> Fm.Errs.raise_if_error in + let dispatcher = Dispatcher.v fm |> Fm.Errs.raise_if_error in + let log_size = Conf.index_log_size config in + { fm; dispatcher; log_size; inode_pack; contents_pack } + + let close t = Fm.close t.fm + + let key_of_hash hash t = + Inode_pack.index_direct_with_kind t hash |> Option.get + + let length_of_hash hash t = + let key, _ = key_of_hash hash t in + match Pack_key.inspect key with + | Indexed _ -> + (* This case cannot happen, as [key_of_hash] converts an + indexed key to a direct one. *) + assert false + | Direct { length; _ } -> length + + let io_read_and_decode_entry_prefix ~off t = + let entry_prefix : Inode_pack.Entry_prefix.t = + Inode_pack.read_and_decode_entry_prefix ~off t.dispatcher + in + let length = + match Inode_pack.Entry_prefix.total_entry_length entry_prefix with + | Some length -> length + | None -> + (* If the length is not on disk, the object is in index. *) + length_of_hash entry_prefix.hash t.inode_pack + in + let key = Pack_key.v_direct ~offset:off ~length entry_prefix.hash in + (key, entry_prefix.kind) + + (* Get the childrens offsets and then read their keys at that offset. *) + let decode_children_offsets ~off ~len t = + let buf = Bytes.create len in + let _ = Dispatcher.read_exn t.dispatcher ~off ~len buf in + let entry_of_offset offset = + [%log.debug "key_of_offset: %a" Int63.pp offset]; + io_read_and_decode_entry_prefix ~off:offset t + in + let entry_of_hash hash = key_of_hash hash t.inode_pack in + (* Bytes.unsafe_to_string usage: buf is created locally, uniquely owned; we assume + Dispatcher.read_exn returns unique ownership; then call to Bytes.unsafe_to_string + gives up unique ownership of buf. This is safe. *) + Inode.Raw.decode_children_offsets ~entry_of_offset ~entry_of_hash + (Bytes.unsafe_to_string buf) (* safe: see comment above *) + (ref 0) + + type visit = { visited : Hash.t -> bool; set_visit : Hash.t -> unit } + + let iter t v f_contents f_inodes (root_key, root_kind) = + let total_visited = ref 0 in + let set_visit h = + incr total_visited; + v.set_visit h + in + let rec aux (key, kind) = + match Pack_key.inspect key with + | Indexed _ -> + (* This case cannot happen: + - either the root key is indexed, in which case it converted to a + direct key just before the call to [aux]; + - or one of the children of a node is indexed, in which case + [Inode.Raw.decode_children_offsets] converts it to a direct key + before the call to [aux]. *) + assert false + | Direct { length; offset; hash; _ } -> + if v.visited hash then Lwt.return_unit + else ( + set_visit hash; + [%log.debug "visit hash: %a, %a" pp_hash hash pp_kind kind]; + (* [unsafe_find] decodes the values based on their kind, we need + to detect the type in order to call the correspoding + [unsafe_find].*) + match kind with + | Contents -> ( + let value = + Contents_pack.unsafe_find ~check_integrity:false + t.contents_pack key + in + match value with + | None -> + Fmt.failwith "contents not found in store. Key: %a " + pp_key key + | Some value -> + let snapshot_blob = value in + f_contents snapshot_blob) + | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root + | Inode_v2_nonroot -> ( + let children = + decode_children_offsets ~off:offset ~len:length t + in + let* () = Lwt_list.iter_s (fun key -> aux key) children in + let value = + Inode_pack.unsafe_find ~check_integrity:false t.inode_pack + key + in + match value with + | None -> + Fmt.failwith "node not found in store. Key: %a " pp_key + key + | Some value -> + let snapshot_inode = Inode.to_snapshot value in + [%log.debug + "iter inode snapshot: %a" pp_snapshot snapshot_inode]; + f_inodes snapshot_inode) + | Commit_v1 | Commit_v2 -> + (* The traversal starts with a node, it never iters over + commits. *) + assert false + | Dangling_parent_commit -> assert false) + in + (* In case the root node of a tree is indexed, we need to convert it to a + direct key first. *) + let root_key = + match Pack_key.inspect root_key with + | Indexed hash -> key_of_hash hash t.inode_pack |> fst + | Direct _ -> root_key + in + let* () = aux (root_key, root_kind) in + Lwt.return !total_visited + + let run_in_memory t f_contents f_inodes root_key = + [%log.info "iter in memory"]; + let visited_hash = Hashes.create ~initial_slots:100_000 () in + let visited h = Hashes.mem visited_hash h in + let set_visit h = + match Hashes.add visited_hash h with + | `Duplicate -> + Fmt.failwith "should not visit hash twice. Hash: %a " pp_hash h + | `Ok -> () + in + iter t { visited; set_visit } f_contents f_inodes root_key + + let run_on_disk path t f_contents f_inodes root_key = + [%log.info "iter on disk"]; + let index = + Index.v ~fresh:true ~readonly:false ~log_size:t.log_size path + in + let visited h = Index.mem index h in + let set_visit h = + if visited h then + Fmt.failwith "Should not visit hash twice. Hash: %a " pp_hash h + else Index.replace index h () + in + let* total = iter t { visited; set_visit } f_contents f_inodes root_key in + Index.close index; + rm_index path; + Lwt.return total + + let run ?on_disk = + match on_disk with + | None -> run_in_memory + | Some (`Path path) -> run_on_disk path + end + + module Import = struct + module Value = struct + type t = int63 * int [@@deriving irmin] + + let encoded_size = (64 / 8) + (32 / 8) + + let encode ((off, len) : t) = + let buf = Bytes.create encoded_size in + Bytes.set_int64_be buf 0 (Int63.to_int64 off); + Bytes.set_int32_be buf 8 (Int32.of_int len); + (* Bytes.unsafe_to_string usage: buf is local, uniquely owned; we assume the + Bytes.set... functions return unique ownership; then Bytes.unsafe_to_string + gives up unique ownership of buf to get shared ownership of the resulting + string, which is then returned. buf is no longer accessible. This is safe. *) + Bytes.unsafe_to_string buf + + let decode s pos : t = + (* Bytes.unsafe_of_string usage: s is shared; buf is shared (we cannot mutate it); + we assume Bytes.get_... functions need shared ownership only. This usage is + safe. *) + let buf = Bytes.unsafe_of_string s in + let off = Bytes.get_int64_be buf pos |> Int63.of_int64 in + let len = Bytes.get_int32_be buf (pos + 8) |> Int32.to_int in + (off, len) + end + + module Index = + Index_unix.Make (Pack_index.Key) (Value) (Index.Cache.Unbounded) + + type path = string + + type t = { + inode_pack : read Inode_pack.t; + contents_pack : read Contents_pack.t; + visited : Hash.t -> Hash.t Pack_key.t; + set_visit : Hash.t -> Hash.t Pack_key.t -> unit; + index : (path * Index.t) option; + } + + let save_contents t b : Hash.t Pack_key.t Lwt.t = + let* key = + Contents_pack.batch t.contents_pack (fun writer -> + Contents_pack.add writer b) + in + let hash = Inode.Key.to_hash key in + t.set_visit hash key; + Lwt.return key + + let save_inodes t i : Hash.t Pack_key.t Lwt.t = + let inode = Inode.of_snapshot t.inode_pack ~index:t.visited i in + let key = Inode.save ~allow_non_root:true t.inode_pack inode in + let hash = Inode.Key.to_hash key in + t.set_visit hash key; + Lwt.return key + + let hash_not_found h = + Fmt.failwith + "You are trying to save to the backend an inode that contains pointers \ + to objects unknown to the backend. Hash: %a" + pp_hash h + + let save_reuse_index inodes = + [%log.info "save reuse index "]; + (* objects are added to index by [save_contents] and [save_inodes] + functions. *) + let set_visit _ _ = () in + let visited h = + match Inode_pack.index_direct inodes h with + | Some x -> x + | None -> hash_not_found h + in + (set_visit, visited, None) + + let save_in_memory () = + [%log.info "save in memory"]; + let tbl : (Hash.t, Hash.t Pack_key.t) Hashtbl.t = Hashtbl.create 10 in + let set_visit h k = Hashtbl.add tbl h k in + let visited h = + match Hashtbl.find_opt tbl h with + | Some x -> x + | None -> hash_not_found h + in + (set_visit, visited, None) + + let save_on_disk log_size path = + (* Make sure we are not reusing the same index as irmin-pack. *) + let path = path ^ "_tmp" in + [%log.info "save on disk: %s" path]; + let index = Index.v ~fresh:true ~readonly:false ~log_size path in + + let set_visit h k = + let offset, length = + match Pack_key.inspect k with + | Direct { offset; length; _ } -> (offset, length) + | Indexed _ -> + (* Visited objects have direct keys. *) + assert false + in + Index.replace index h (offset, length) + in + let visited h = + try + let offset, length = Index.find index h in + let key = Pack_key.v_direct ~offset ~length h in + key + with Not_found -> hash_not_found h + in + (set_visit, visited, Some (path, index)) + + let v ?on_disk log_size contents_pack inode_pack = + let set_visit, visited, index = + match on_disk with + | None -> save_in_memory () + | Some (`Path path) -> save_on_disk log_size path + | Some `Reuse -> save_reuse_index inode_pack + in + { inode_pack; contents_pack; visited; set_visit; index } + + let close t = + Option.iter + (fun (path, index) -> + Index.close index; + rm_index path) + t.index + end +end diff --git a/vendors/irmin/src/irmin-pack/unix/snapshot.mli b/vendors/irmin/src/irmin-pack/unix/snapshot.mli new file mode 100644 index 000000000000..a096ffbd1d5b --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/snapshot.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Snapshot_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/snapshot_intf.ml b/vendors/irmin/src/irmin-pack/unix/snapshot_intf.ml new file mode 100644 index 000000000000..16ce2a917f3a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/snapshot_intf.ml @@ -0,0 +1,81 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type Args = sig + module Hash : Irmin.Hash.S + module Fm : File_manager.S + module Dispatcher : Dispatcher.S with module Fm = Fm + + module Inode : + Inode.Persistent + with type hash := Hash.t + and type key = Hash.t Pack_key.t + and type file_manager = Fm.t + and type dispatcher = Dispatcher.t + + module Contents_pack : + Pack_store.S + with type hash := Hash.t + and type key = Hash.t Pack_key.t + and type dispatcher = Dispatcher.t +end + +module type Sigs = sig + module Make (Args : Args) : sig + open Args + + module Export : sig + type t + + val v : Irmin.config -> read Contents_pack.t -> read Inode.Pack.t -> t + + val run : + ?on_disk:[ `Path of string ] -> + t -> + (Contents_pack.value -> unit Lwt.t) -> + (Inode.Snapshot.inode -> unit Lwt.t) -> + Hash.t Pack_key.t * Pack_value.Kind.t -> + int Lwt.t + + val close : + t -> + ( unit, + [> `Double_close + | `Index_failure of string + | `Io_misc of Fm.Io.misc_error + | `Pending_flush + | `Ro_not_allowed ] ) + result + end + + module Import : sig + type t + + val v : + ?on_disk:[ `Path of string | `Reuse ] -> + int -> + read Contents_pack.t -> + read Inode.Pack.t -> + t + + val save_contents : t -> Contents_pack.value -> Hash.t Pack_key.t Lwt.t + val save_inodes : t -> Inode.Snapshot.inode -> Hash.t Pack_key.t Lwt.t + val close : t -> unit + end + end +end diff --git a/vendors/irmin/src/irmin-pack/unix/sparse_file.ml b/vendors/irmin/src/irmin-pack/unix/sparse_file.ml new file mode 100644 index 000000000000..36f2790ada52 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/sparse_file.ml @@ -0,0 +1,304 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Sparse_file_intf +module BigArr1 = Bigarray.Array1 + +type int64_bigarray = (int64, Bigarray.int64_elt, Bigarray.c_layout) BigArr1.t + +module Int64_mmap (Io : Io.S) : sig + type t + + val open_ro : fn:string -> sz:int -> (t, [> Io.open_error ]) result + val length : t -> int + val get : t -> int -> Int64.t + val close : t -> (unit, [> Io.close_error ]) result +end = struct + type t = { + fn : string; + fd : Io.t; + loaded : bool array; + mutable arr : int64_bigarray; + } + + let sector_size = 512 + let length t = BigArr1.dim t.arr + + let open_ro ~fn ~sz = + let open Result_syntax in + assert (Sys.file_exists fn); + let+ fd = Io.open_ ~path:fn ~readonly:true in + let size = sz / 8 in + let arr = BigArr1.create Bigarray.Int64 Bigarray.c_layout size in + let loaded = Array.make (1 + (sz / sector_size)) false in + { fn; fd; arr; loaded } + + let close t = Io.close t.fd + + let load t sector_id = + if not t.loaded.(sector_id) then ( + let sector_start = sector_id * sector_size in + let nb = min sector_size (length t - sector_start) in + let len = 8 * nb in + let bytes = Bytes.create len in + Io.read_exn t.fd ~off:(Int63.of_int (8 * sector_start)) ~len bytes; + for i = 0 to nb - 1 do + t.arr.{sector_start + i} <- Bytes.get_int64_le bytes (8 * i) + done; + t.loaded.(sector_id) <- true) + + let ensure_loaded t i = + let sector_id = i / sector_size in + if not t.loaded.(sector_id) then load t sector_id + + let get t i = + ensure_loaded t i; + t.arr.{i} +end + +module Make (Io : Io.S) = struct + module Io = Io + module Errs = Io_errors.Make (Io) + + module Mapping_file = struct + module Int64_mmap = Int64_mmap (Io) + + let ( .%{} ) = Int64_mmap.get + + type t = Int64_mmap.t + + let open_map ~path ~size = + match Io.classify_path path with + | `File -> + let open Result_syntax in + let* mmap = Int64_mmap.open_ro ~fn:path ~sz:size in + if Int64_mmap.length mmap mod 3 = 0 then Ok mmap + else + Error + (`Corrupted_mapping_file + (__FILE__ ^ ": mapping mmap size did not meet size requirements")) + | _ -> Error (`No_such_file_or_directory path) + + let close = Int64_mmap.close + let entry_count t = Int64_mmap.length t / 3 + let entry_idx i = i * 3 + let entry_off t i = t.%{entry_idx i} |> Int63.of_int64 + let entry_poff t i = t.%{entry_idx i + 1} |> Int63.of_int64 + let entry_len t i = t.%{entry_idx i + 2} |> Int64.to_int + + let iter_exn t f = + for i = 0 to entry_count t - 1 do + f ~off:(entry_off t i) ~len:(entry_len t i) + done + + let iter t f = Errs.catch (fun () -> iter_exn t f) + + type entry = { off : int63; poff : int63; len : int } + + let find_nearest_geq arr off = + let get arr i = + let start = arr.%{entry_idx i} |> Int64.to_int in + let len = entry_len arr i in + start + len - 1 + in + match + Utils.nearest_geq ~arr ~get ~lo:0 + ~hi:(entry_count arr - 1) + ~key:(Int63.to_int off) + with + | None -> `After + | Some i -> + let entry = + { + off = entry_off arr i; + poff = entry_poff arr i; + len = entry_len arr i; + } + in + if i == 0 && entry.off > off then `Before entry else `Inside entry + end + + type t = { mapping : Mapping_file.t; data : Io.t } + + let open_ ~readonly ~mapping_size ~mapping ~data = + let open Result_syntax in + let* mapping = Mapping_file.open_map ~path:mapping ~size:mapping_size in + let+ data = Io.open_ ~path:data ~readonly in + { mapping; data } + + let open_ro ~mapping_size ~mapping ~data = + open_ ~readonly:true ~mapping_size ~mapping ~data + + let close t = + let open Result_syntax in + let* () = Mapping_file.close t.mapping in + Io.close t.data + + let iter t fn = Mapping_file.iter t.mapping fn + + let get_poff { mapping; _ } ~off = + match Mapping_file.find_nearest_geq mapping off with + | `After -> raise (Errors.Pack_error (`Invalid_sparse_read (`After, off))) + | `Before _ -> + raise (Errors.Pack_error (`Invalid_sparse_read (`Before, off))) + | `Inside entry when entry.off > off -> + raise (Errors.Pack_error (`Invalid_sparse_read (`Hole, off))) + | `Inside entry -> + let open Int63.Syntax in + let shift_in_entry = off - entry.off in + let max_entry_len = Int63.of_int entry.len - shift_in_entry in + let poff = entry.poff + off - entry.off in + (poff, Int63.to_int max_entry_len) + + let read_exn t ~off ~len buf = + let poff, max_entry_len = get_poff t ~off in + if max_entry_len < len then raise (Errors.Pack_error `Read_out_of_bounds); + Io.read_exn t.data ~off:poff ~len buf + + let read_range_exn t ~off ~min_len ~max_len buf = + [%log.debug + "read_range_exn ~off:%a ~min_len:%i ~max_len:%i" Int63.pp off min_len + max_len]; + let poff, max_entry_len = get_poff t ~off in + if max_entry_len < min_len then + raise (Errors.Pack_error `Read_out_of_bounds); + let len = min max_len max_entry_len in + Io.read_exn t.data ~off:poff ~len buf; + len + + let next_valid_offset { mapping; _ } ~off = + match Mapping_file.find_nearest_geq mapping off with + | `After -> None + | `Before entry -> Some entry.off + | `Inside entry -> + let open Int63.Syntax in + Some (if entry.off < off then off else entry.off) + + let make_entry ~off ~poff ~len = + if Int64.(equal zero) len then "" + else + let buf = Bytes.create (3 * 8) in + Bytes.set_int64_le buf 0 off; + Bytes.set_int64_le buf 8 poff; + Bytes.set_int64_le buf 16 len; + Bytes.unsafe_to_string buf + + module Wo = struct + type nonrec t = t + + let open_wo ~mapping_size ~mapping ~data = + open_ ~readonly:false ~mapping_size ~mapping ~data + + let write_exn t ~off ~len str = + let poff, max_entry_len = get_poff t ~off in + assert (len <= max_entry_len); + Io.write_exn t.data ~off:poff ~len str + + let fsync t = Io.fsync t.data + let close = close + + let create_from_data ~mapping ~dead_header_size ~size ~data:_ = + let open Result_syntax in + let entry = + make_entry ~off:Int64.zero + ~poff:(Int64.of_int dead_header_size) + ~len:(Int63.to_int64 size) + in + let* mapping = Io.create ~path:mapping ~overwrite:false in + let* () = Io.write_string mapping ~off:Int63.zero entry in + let+ () = Io.close mapping in + Int63.of_int (String.length entry) + end + + module Ao = struct + module Ao = Append_only_file.Make (Io) (Errs) + + type t = { mapping : Ao.t; data : Ao.t; mutable end_off : Int63.t } + + let end_off t = t.end_off + let mapping_size t = Ao.end_poff t.mapping + + let create ~mapping ~data = + let open Result_syntax in + let ao_create path = + Ao.create_rw ~path ~overwrite:false ~auto_flush_threshold:1_000_000 + ~auto_flush_procedure:`Internal + in + let* mapping = ao_create mapping in + let+ data = ao_create data in + { mapping; data; end_off = Int63.zero } + + let open_ao ~mapping_size ~mapping ~data = + let open Result_syntax in + let ao_open ~end_poff path = + Ao.open_rw ~path ~end_poff ~dead_header_size:0 + ~auto_flush_threshold:1_000_000 ~auto_flush_procedure:`Internal + in + let* ao_mapping = ao_open ~end_poff:mapping_size mapping in + let* end_off, end_poff = + if mapping_size <= Int63.zero then Ok (Int63.zero, Int63.zero) + else + let entry_len = 3 * 8 in + let+ entry = + Ao.read_to_string ao_mapping + ~off:Int63.(Syntax.(mapping_size - of_int entry_len)) + ~len:entry_len + in + let entry = Bytes.of_string entry in + let end_off = Bytes.get_int64_le entry 0 |> Int63.of_int64 in + let end_poff = Bytes.get_int64_le entry 8 |> Int63.of_int64 in + let len = Bytes.get_int64_le entry 16 |> Int63.of_int64 in + let open Int63.Syntax in + (end_off + len, end_poff + len) + in + let+ ao_data = ao_open ~end_poff data in + { mapping = ao_mapping; data = ao_data; end_off } + + let check_offset_exn { end_off; _ } ~off = + if Int63.Syntax.(end_off > off) then + Fmt.failwith + "Sparse.Ao.append_exn at offset %a, smaller than latest offset %a" + Int63.pp off Int63.pp end_off + + let append_seq_exn t ~off seq = + check_offset_exn t ~off; + let poff = Ao.end_poff t.data in + let len = + Seq.fold_left + (fun len str -> + Ao.append_exn t.data str; + len + String.length str) + 0 seq + in + let entry = + make_entry ~off:(Int63.to_int64 off) ~poff:(Int63.to_int64 poff) + ~len:(Int64.of_int len) + in + Ao.append_exn t.mapping entry; + t.end_off <- Int63.(Syntax.(off + of_int len)) + + let flush t = + let open Result_syntax in + let* () = Ao.flush t.data in + Ao.flush t.mapping + + let close t = + let open Result_syntax in + let* () = Ao.close t.data in + Ao.close t.mapping + end +end diff --git a/vendors/irmin/src/irmin-pack/unix/sparse_file.mli b/vendors/irmin/src/irmin-pack/unix/sparse_file.mli new file mode 100644 index 000000000000..c950f74a4915 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/sparse_file.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Sparse_file_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/sparse_file_intf.ml b/vendors/irmin/src/irmin-pack/unix/sparse_file_intf.ml new file mode 100644 index 000000000000..83840512de74 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/sparse_file_intf.ml @@ -0,0 +1,157 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + module Io : Io.S + module Errs : Io_errors.S with module Io = Io + + type t + type open_error := [ Io.open_error | `Corrupted_mapping_file of string ] + + val open_ro : + mapping_size:int -> + mapping:string -> + data:string -> + (t, [> open_error ]) result + (** [open_ro ~mapping_size ~mapping ~data] returns a new read-only view of the + sparse file, represented on disk by two files named [mapping] and [data]. + The mapping file is expected to have size at least [mapping_size] (and the + rest is ignored if the file is larger). *) + + val close : t -> (unit, [> Io.close_error ]) result + (** Close the underlying files. *) + + val read_exn : t -> off:int63 -> len:int -> bytes -> unit + (** [read_exn t ~off ~len buffer] writes into [buffer] the bytes from [off] to + [off+len]. *) + + val read_range_exn : + t -> off:int63 -> min_len:int -> max_len:int -> bytes -> int + (** Same as [read_exn], the amount read is [max_len] if possible or at least + [min_len] if reading more would step over a hole in the sparse file. + + Returns the actually read length. *) + + val next_valid_offset : t -> off:int63 -> int63 option + (** [next_valid_offset t ~off] returns [Some off'] such that [off'] is the + smallest readable offset larger or equal to [off]. This enables jumping + over a sparse hole to the next compact range of data. *) + + val iter : t -> (off:int63 -> len:int -> unit) -> (unit, Errs.t) result + (** [iter t f] calls [f] on each [(off,len)] pair in [mapping]. Only used for + testing and debugging. + + It is guaranteed for the offsets to be iterated in monotonic order. + + It is guaranteed that entries don't overlap. + + The exceptions raised by [f] are caught and returned (as long as they are + known by [Errs]). *) + + module Wo : sig + type t + + val open_wo : + mapping_size:int -> + mapping:string -> + data:string -> + (t, [> open_error ]) result + (** [open_wo ~mapping_size ~mapping ~data] returns a write-only instance of + the sparse file. + + Note: This is unsafe and is only used by the GC to mark the parent + commits as dangling. One must ensure that no read-only instance is + opened at the same time, as otherwise the writes would be observable by + it. *) + + val write_exn : t -> off:int63 -> len:int -> string -> unit + (** [write_exn t ~off ~len str] writes the first [len] bytes of [str] to [t] + at the virtual offset [off]. *) + + val fsync : t -> (unit, [> Io.write_error ]) result + (** [fsync t] persists to the file system the effects of previous writes. *) + + val close : t -> (unit, [> Io.close_error ]) result + (** Close the underlying files. *) + + val create_from_data : + mapping:string -> + dead_header_size:int -> + size:Int63.t -> + data:string -> + (int63, [> Io.create_error | Io.write_error | Io.close_error ]) result + (** [create_from_data ~mapping ~dead_header_size ~size ~data] initializes a + new sparse file on disk from the existing file [data], by creating the + corresponding [mapping] file. The first [dead_header_size] bytes are + ignored and the remaining [size] bytes of [data] are made available. + + On success, returns the size of the [mapping] file to be stored in the + control file for consistency checking on open. *) + end + + module Ao : sig + type t + + val end_off : t -> Int63.t + (** [end_off t] returns the largest virtual offset contained in the sparse + file [t]. Attempting to append with a strictly smaller virtual offset + will fail. *) + + val mapping_size : t -> Int63.t + (** [end_off t] returns the current size of the mapping file associated to + the sparse file [t] including additions not yet flushed to the file + system. It can be passed to {!open_ao} as [mapping_size] when opening + the file again. *) + + val create : + mapping:string -> data:string -> (t, [> Io.create_error ]) result + (** [create ~mapping ~data] initializes a new empty sparse file, represented + on disk by two files named [mapping] and [data]. *) + + val open_ao : + mapping_size:Int63.t -> + mapping:string -> + data:string -> + ( t, + [> Io.open_error + | `Closed + | `Invalid_argument + | `Read_out_of_bounds + | `Inconsistent_store ] ) + result + (** [open_ao ~mapping_size ~mapping ~data] returns an append-only instance + of the sparse file. *) + + val append_seq_exn : t -> off:int63 -> string Seq.t -> unit + (** [append_seq_exn t ~off seq] appends the sequence of strings [seq] to the + sparse file [t], at the virtual offset [off] which must be larger than + the previously appended offsets. *) + + val flush : t -> (unit, [> Io.write_error ]) result + (** Flush the append buffer. Does not call [fsync]. *) + + val close : t -> (unit, [> Io.close_error | `Pending_flush ]) result + (** Close the underlying files. *) + end +end + +module type Sigs = sig + module type S = S + + module Make (Io : Io.S) : S with module Io = Io +end diff --git a/vendors/irmin/src/irmin-pack/unix/stats.ml b/vendors/irmin/src/irmin-pack/unix/stats.ml new file mode 100644 index 000000000000..a9fb086a9cbf --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/stats.ml @@ -0,0 +1,304 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +module Metrics = Irmin.Metrics + +module Pack_store = struct + include Stats_intf.Pack_store + + type Metrics.origin += Pack_store_stats + type stat = t Metrics.t + + let create_pack_store () = + { + appended_hashes = 0; + appended_offsets = 0; + total = 0; + from_staging = 0; + from_lru = 0; + from_pack_direct = 0; + from_pack_indexed = 0; + } + + let init () = + let initial_state = create_pack_store () in + Metrics.v ~origin:Pack_store_stats ~name:"pack_store_metric" ~initial_state + t + + let clear m = + let v = Metrics.state m in + v.appended_hashes <- 0; + v.appended_offsets <- 0; + v.total <- 0; + v.from_staging <- 0; + v.from_lru <- 0; + v.from_pack_direct <- 0; + v.from_pack_indexed <- 0 + + let export m = Metrics.state m + + let update ~field finds = + let f v = + match field with + | Appended_hashes -> v.appended_hashes <- succ v.appended_hashes + | Appended_offsets -> v.appended_offsets <- succ v.appended_offsets + | Staging -> + v.total <- succ v.total; + v.from_staging <- succ v.from_staging + | Lru -> + v.total <- succ v.total; + v.from_lru <- succ v.from_lru + | Pack_direct -> + v.total <- succ v.total; + v.from_pack_direct <- succ v.from_pack_direct + | Pack_indexed -> + v.total <- succ v.total; + v.from_pack_indexed <- succ v.from_pack_indexed + | Not_found -> + v.total <- succ v.total; + () + in + let mut = Metrics.Mutate f in + Metrics.update finds mut + + let cache_misses + { + (* Total finds (hits + misses): *) + total; + (* In-memory hits: *) + from_staging; + from_lru; + _; + } = + total - (from_staging + from_lru) +end + +module Index = struct + include Stats_intf.Index + + type Metrics.origin += Index_stats + type stat = t Metrics.t + + let create_index () = + { + bytes_read = 0; + nb_reads = 0; + bytes_written = 0; + nb_writes = 0; + nb_merge = 0; + merge_durations = []; + nb_replace = 0; + replace_durations = []; + nb_sync = 0; + time_sync = 0.0; + lru_hits = 0; + lru_misses = 0; + } + + let clear (data : stat) = + let s = Metrics.state data in + Index.Stats.reset_stats (); + s.bytes_read <- 0; + s.nb_reads <- 0; + s.bytes_written <- 0; + s.nb_writes <- 0; + s.nb_merge <- 0; + s.merge_durations <- []; + s.nb_replace <- 0; + s.replace_durations <- []; + s.nb_sync <- 0; + s.time_sync <- 0.0; + s.lru_hits <- 0; + s.lru_misses <- 0 + + let init () = + let initial_state = create_index () in + Metrics.v ~origin:Index_stats ~name:"index_metric" ~initial_state t + + let report index = + let modifier = Metrics.Replace (fun _ -> Stats_intf.Index.S.get ()) in + Metrics.(update index modifier) + + let export m = Metrics.state m +end + +module File_manager = struct + include Stats_intf.File_manager + + type Metrics.origin += File_manager + + (* NOTE return a new instance each time, since fields are mutable *) + let create () = + { + dict_flushes = 0; + suffix_flushes = 0; + index_flushes = 0; + auto_dict = 0; + auto_suffix = 0; + auto_index = 0; + flush = 0; + } + + (* NOTE type [stat] is an abstract type in stats.mli *) + type stat = t Metrics.t + + let init () : stat = + let initial_state = create () in + Metrics.v ~origin:File_manager ~name:"file_manager_metric" ~initial_state t + + (* [export] reveals the [t] contained in the [Metrics.t] container *) + let export : stat -> t = fun m -> Metrics.state m + + (* support [reset_stats] function below *) + let clear' (t : t) = + t.dict_flushes <- 0; + t.suffix_flushes <- 0; + t.index_flushes <- 0; + () + + let clear (t : stat) = clear' (export t) + + (* we want to support an interface where the particular fields of type [t] are reified + as variants, so that we can call [incr_fm_field Dict_flushes] for example *) + + type field = + | Dict_flushes + | Suffix_flushes + | Index_flushes + | Auto_dict + | Auto_suffix + | Auto_index + | Flush + + let update ~field t = + let f t = + match field with + | Dict_flushes -> t.dict_flushes <- t.dict_flushes + 1 + | Suffix_flushes -> t.suffix_flushes <- t.suffix_flushes + 1 + | Index_flushes -> t.index_flushes <- t.index_flushes + 1 + | Auto_dict -> t.auto_dict <- t.auto_dict + 1 + | Auto_suffix -> t.auto_suffix <- t.auto_suffix + 1 + | Auto_index -> t.auto_index <- t.auto_index + 1 + | Flush -> t.flush <- t.flush + 1 + in + Metrics.update t (Metrics.Mutate f) +end + +module Latest_gc = struct + include Stats_intf.Latest_gc + + type Metrics.origin += Latest_gc + type stat = t Metrics.t + + (* [stats] is the latest_gc stats. + [t] is [stats option]. + [stat] is the [Metrics] wrapper around [t] *) + + let init : unit -> stat = + fun () -> + let initial_state = None in + Metrics.v ~origin:Latest_gc ~name:"latest_gc_metric" ~initial_state t + + let clear : stat -> unit = + fun m -> Metrics.update m (Metrics.Replace (fun _ -> None)) + + let export : stat -> t = Metrics.state + + let update : stats -> stat -> unit = + fun stat m -> Metrics.update m (Metrics.Replace (fun _ -> Some stat)) + + let new_suffix_end_offset_before_finalise worker = + match List.assoc_opt "suffix" worker.files with + | Some x -> x + | None -> assert false + + let finalise_duration t = + let steps = t.steps |> List.map (fun (k, v) -> (k, v.wall)) in + let duration = steps |> List.map snd |> List.fold_left Float.add 0. in + duration + -. List.assoc "worker startup" steps + -. List.assoc "before finalise" steps + + let total_duration t = + let steps = t.steps |> List.map (fun (k, v) -> (k, v.wall)) in + steps |> List.map snd |> List.fold_left Float.add 0. + + let finalise_suffix_transfer t = + let open Int63.Syntax in + let size_of_the_new_suffix_file = + t.after_suffix_end_offset - t.before_suffix_end_offset + in + let copied_by_the_worker = + t.worker.suffix_transfers |> List.fold_left Int63.add Int63.zero + in + size_of_the_new_suffix_file - copied_by_the_worker +end + +type t = { + pack_store : Pack_store.stat; + index : Index.stat; + file_manager : File_manager.stat; + latest_gc : Latest_gc.stat; +} + +let s = + { + pack_store = Pack_store.init (); + index = Index.init (); + file_manager = File_manager.init (); + latest_gc = Latest_gc.init (); + } + +let reset_stats () = + Pack_store.clear s.pack_store; + Index.clear s.index; + File_manager.clear s.file_manager; + Latest_gc.clear s.latest_gc; + () + +let get () = s +let report_pack_store ~field = Pack_store.update ~field s.pack_store +let report_index () = Index.report s.index + +let incr_appended_hashes () = + Pack_store.update ~field:Pack_store.Appended_hashes s.pack_store + +let incr_appended_offsets () = + Pack_store.update ~field:Pack_store.Appended_offsets s.pack_store + +type cache_stats = { cache_misses : float } +type offset_stats = { offset_ratio : float; offset_significance : int } + +let div_or_zero a b = if b = 0 then 0. else float_of_int a /. float_of_int b + +let get_cache_stats () = + let pack_store = Metrics.state s.pack_store in + let cache_misses = Pack_store.cache_misses pack_store in + { cache_misses = div_or_zero cache_misses pack_store.total } + +let get_offset_stats () = + let pack_store = Metrics.state s.pack_store in + { + offset_ratio = + div_or_zero pack_store.appended_offsets + (pack_store.appended_offsets + pack_store.appended_hashes); + offset_significance = + pack_store.appended_offsets + pack_store.appended_hashes; + } + +let incr_fm_field field = File_manager.update ~field s.file_manager +let report_latest_gc x = Latest_gc.update x s.latest_gc diff --git a/vendors/irmin/src/irmin-pack/unix/stats.mli b/vendors/irmin/src/irmin-pack/unix/stats.mli new file mode 100644 index 000000000000..d148fe71ac8a --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/stats.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Stats_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin-pack/unix/stats_intf.ml b/vendors/irmin/src/irmin-pack/unix/stats_intf.ml new file mode 100644 index 000000000000..9a0ce38c14da --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/stats_intf.ml @@ -0,0 +1,304 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module Pack_store = struct + type field = + | Appended_hashes + | Appended_offsets + | Staging (** Found in the store's write buffer. *) + | Lru (** Found in the store's LRU of recent [find] results. *) + | Pack_direct + (** Decoded directly from the pack file (via a direct key). *) + | Pack_indexed + (** Binding recovered from the pack file after first checking the index + for its offset and length (via an indexed key). *) + | Not_found (** Find returned [None]. *) + [@@deriving irmin] + + type t = { + mutable appended_hashes : int; + mutable appended_offsets : int; + mutable total : int; + mutable from_staging : int; + mutable from_lru : int; + mutable from_pack_direct : int; + mutable from_pack_indexed : int; + } + [@@deriving irmin] +end + +module Index = struct + module S = Index.Stats + + type t = S.t = { + mutable bytes_read : int; + mutable nb_reads : int; + mutable bytes_written : int; + mutable nb_writes : int; + mutable nb_merge : int; + mutable merge_durations : float list; + mutable nb_replace : int; + mutable replace_durations : float list; + mutable nb_sync : int; + mutable time_sync : float; + mutable lru_hits : int; + mutable lru_misses : int; + } + [@@deriving irmin] +end + +module File_manager = struct + type field = + | Dict_flushes + | Suffix_flushes + | Index_flushes + | Auto_dict + | Auto_suffix + | Auto_index + | Flush + + type t = { + mutable dict_flushes : int; + mutable suffix_flushes : int; + mutable index_flushes : int; + mutable auto_dict : int; + mutable auto_suffix : int; + mutable auto_index : int; + mutable flush : int; + } + [@@deriving irmin] +end + +module Latest_gc = struct + type rusage = { + maxrss : int64; + minflt : int64; + majflt : int64; + inblock : int64; + oublock : int64; + nvcsw : int64; + nivcsw : int64; + } + [@@deriving irmin] + + type ocaml_gc = { + minor_words : float; + promoted_words : float; + major_words : float; + minor_collections : int; + major_collections : int; + heap_words : int; + compactions : int; + top_heap_words : int; + stack_size : int; + } + [@@deriving irmin] + + type duration = { wall : float; sys : float; user : float } [@@deriving irmin] + (** Timings in seconds *) + + type step = { + duration : duration; + rusage : rusage; + ocaml_gc : ocaml_gc; + index : Index.t; + pack_store : Pack_store.t; + inode : Irmin_pack.Stats.Inode.t; + } + [@@deriving irmin] + (** Stats gathered for one worker step *) + + type worker = { + initial_maxrss : int64; + initial_heap_words : int; + initial_top_heap_words : int; + initial_stack_size : int; + steps : (string * step) list; + files : (string * int63) list; + objects_traversed : int63; + suffix_transfers : int63 list; + } + [@@deriving irmin] + (** Stats produced by the worker. They are meant to be transmited to the + parent process through the gc result JSON file. + + [steps] is the list of all step names associated with the timing of these + steps plus stats recorded at the end of the step. An association lists is + used here instead of types because in the future the exact list of tasks + may change and we don't want the rigidity of types, especially because + these informations will end up appearing in a file format. + + Since the worker lives in a fork, [rusage] and [ocaml_gc] contain stats + that are impacted by what happened in the main process, prior to the fork. + The [init_*] fields reflect this. + + The total wall time of the worker is the sum of all [wall] fields in + [steps]. + + [files] contains the size of files created by the GC. And association list + is used instead of plain types for the same reason as [steps]/ + + [suffix_transfers] contains an int for each transfer loop to the new + suffix. That integer corresponds to the number of bytes copied during that + loop. The sum of these integers is equal to the "suffix" step in [files]. *) + + type stats = { + generation : int; + commit_offset : int63; + before_suffix_start_offset : int63; + before_suffix_end_offset : int63; + after_suffix_start_offset : int63; + after_suffix_end_offset : int63; + steps : (string * duration) list; + worker : worker; + } + [@@deriving irmin] + (** All the stats for a single successful GC run. + + [commit_offset] is the offset of the commit provided by the irmin user. + + The [before_*] (and [after_*]) offsets track the state of the suffix + before (and after) the GC. + + [steps] has a similar meaning as [steps] in [worker] but for the main + process. *) + + type t = stats option [@@deriving irmin] + (** [Latest_gc.t] is an [option] type because before the first gc end, there + are no gc stats to expose. *) +end + +module type Sigs = sig + module Pack_store : sig + include module type of Pack_store with type t = Pack_store.t + + type stat + + val cache_misses : t -> int + val export : stat -> t + end + + module Index : sig + include module type of Index with type t = Index.t + + type stat + + val export : stat -> t + end + + module File_manager : sig + include module type of File_manager with type t = File_manager.t + + type stat + + val export : stat -> t + end + + module Latest_gc : sig + include + module type of Latest_gc + with type duration = Latest_gc.duration + with type ocaml_gc = Latest_gc.ocaml_gc + with type rusage = Latest_gc.rusage + with type step = Latest_gc.step + with type worker = Latest_gc.worker + with type stats = Latest_gc.stats + with type t = Latest_gc.t + + type stat + + val export : stat -> t + val new_suffix_end_offset_before_finalise : worker -> int63 + + val finalise_duration : stats -> float + (** Time taken by the GC finalisation in seconds. It includes the time it + took to wait for the worker to finish in case of [~wait:true]. *) + + val total_duration : stats -> float + (** Total wall duration of the GC in seconds, from the call to GC and to the + end of finalise. This duration contains the time it takes for the user + to trigger a finalise while the worker is over. *) + + val finalise_suffix_transfer : stats -> int63 + (** [finalise_suffix_transfer stats] is the number of bytes appended to the + new suffix by the finalise step of the GC. Before this, the worker + already appended bytes to the new suffix, this is reported in + [worker.suffix_transfers]. *) + end + + type t = { + pack_store : Pack_store.stat; + index : Index.stat; + file_manager : File_manager.stat; + latest_gc : Latest_gc.stat; + } + (** Record type for all statistics that will be collected. There is a single + instance (which we refer to as "the instance" below) which is returned by + {!get}. *) + + val reset_stats : unit -> unit + (** [reset_stats ()] will call the relevant [clear] function on each field of + the instance. This typically resets the fields (e.g. to 0 for an int + field). *) + + val get : unit -> t + (** [get ()] returns the instance of {!t} that stores the satistics. If + {!report_pack_store} or {!report_index} is not called before, the content + will be filled with default value, decided at create time (most the time, + [0]). *) + + val report_pack_store : field:Pack_store.field -> unit + (** [report_pack_store ~field] increments the [field] value in the + [pack_store] stats. It also increments the [total] field in + {!Pack_store.t} when the field is related to [finds]. *) + + val report_index : unit -> unit + (** [report_index ()] fills the [stats] with value from the {!Index.Stats} + module. This essentially copies the "current" values from {!Index.Stats} + to the [get()] instance [index] field. *) + + val incr_appended_hashes : unit -> unit + (** [incr_appended_hashes ()] increments the field [appended_hashes] for + [pack_store] in the instance. *) + + val incr_appended_offsets : unit -> unit + (** [incr_appended_offsets] increments the field [appended_offsets] for + [pack_store] in the instance. *) + + type cache_stats = { cache_misses : float } + + type offset_stats = { offset_ratio : float; offset_significance : int } + (** [offset_ratio]: [appended_offsets / (appended_offsets + appended_hashes)]; + [offset_significance]: [appended_offsets + appended_hashes] *) + + val get_cache_stats : unit -> cache_stats + (** [get_cache_stats()] uses the instance [pack_store] field to compute cache + misses. *) + + val get_offset_stats : unit -> offset_stats + (** [get_offset_stats()] uses the instance [pack_store] field to compute + offset stats. *) + + val incr_fm_field : File_manager.field -> unit + (** [incr_fm_field field] increments the chosen stats field for the + {!File_manager} *) + + val report_latest_gc : Latest_gc.stats -> unit + (** [report_latest_gc gc_stats] sets [(get ()).latest_gc] to the stats of the + latest successful GC. *) +end diff --git a/vendors/irmin/src/irmin-pack/unix/store.ml b/vendors/irmin/src/irmin-pack/unix/store.ml new file mode 100644 index 000000000000..c14ea1a47b6f --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/store.ml @@ -0,0 +1,777 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Store_intf + +module Maker (Config : Conf.S) = struct + type endpoint = unit + + include Pack_key.Store_spec + + module Make (Schema : Irmin.Schema.Extended) = struct + open struct + module P = Schema.Path + module M = Schema.Metadata + module C = Schema.Contents + module B = Schema.Branch + end + + module H = Schema.Hash + module Io = Io.Unix + module Index = Pack_index.Make (H) + module Errs = Io_errors.Make (Io) + module File_manager = File_manager.Make (Io) (Index) (Errs) + module Dict = Dict.Make (File_manager) + module Dispatcher = Dispatcher.Make (File_manager) + module XKey = Pack_key.Make (H) + + module X = struct + module Hash = H + + type 'a value = { hash : H.t; kind : Pack_value.Kind.t; v : 'a } + [@@deriving irmin] + + module Contents = struct + module Pack_value = Pack_value.Of_contents (Config) (H) (XKey) (C) + + module CA = + Pack_store.Make (File_manager) (Dict) (Dispatcher) (H) (Pack_value) + (Errs) + + include Irmin.Contents.Store_indexable (CA) (H) (C) + end + + module Node = struct + module Value = Schema.Node (XKey) (XKey) + + module CA = struct + module Inter = + Irmin_pack.Inode.Make_internal (Config) (H) (XKey) (Value) + + module Pack' = + Pack_store.Make (File_manager) (Dict) (Dispatcher) (H) (Inter.Raw) + (Errs) + + include Inode.Make_persistent (H) (Value) (Inter) (Pack') + end + + include + Irmin.Node.Generic_key.Store (Contents) (CA) (H) (CA.Val) (M) (P) + end + + module Node_portable = Node.CA.Val.Portable + + module Schema = struct + include Schema + module Node = Node + end + + module Commit = struct + module Value = struct + include Schema.Commit (Node.Key) (XKey) + module Info = Schema.Info + + type hash = Hash.t [@@deriving irmin] + end + + module Pack_value = Pack_value.Of_commit (H) (XKey) (Value) + + module CA = + Pack_store.Make (File_manager) (Dict) (Dispatcher) (H) (Pack_value) + (Errs) + + include + Irmin.Commit.Generic_key.Store (Schema.Info) (Node) (CA) (H) (Value) + end + + module Commit_portable = struct + module Hash_key = Irmin.Key.Of_hash (Hash) + include Schema.Commit (Hash_key) (Hash_key) + + let of_commit : Commit.Value.t -> t = + fun t -> + let info = Commit.Value.info t + and node = Commit.Value.node t |> XKey.to_hash + and parents = Commit.Value.parents t |> List.map XKey.to_hash in + v ~info ~node ~parents + + module Info = Schema.Info + + type hash = Hash.t [@@deriving irmin] + end + + module Branch = struct + module Key = B + module Val = XKey + module AW = Atomic_write.Make_persistent (Key) (Val) + include Atomic_write.Closeable (AW) + + let v ?fresh ?readonly path = + AW.v ?fresh ?readonly path >|= make_closeable + end + + module Slice = Irmin.Backend.Slice.Make (Contents) (Node) (Commit) + module Remote = Irmin.Backend.Remote.None (Commit.Key) (B) + + module Gc = Gc.Make (struct + module Async = Async.Unix + module Fm = File_manager + module Errs = Errs + module Dict = Dict + module Dispatcher = Dispatcher + module Hash = Schema.Hash + module Contents_store = Contents.CA + module Node_value = Node.CA.Inter.Val + module Node_store = Node.CA + module Commit_value = Commit.Value + module Commit_store = Commit.CA + + type hash = Node_value.hash + type key = Node_value.node_key [@@deriving irmin] + end) + + module Repo = struct + type running_gc = { gc : Gc.t; use_auto_finalisation : bool } + + type t = { + config : Irmin.Backend.Conf.t; + contents : read Contents.CA.t; + node : read Node.CA.t; + commit : read Commit.CA.t; + branch : Branch.t; + fm : File_manager.t; + dict : Dict.t; + dispatcher : Dispatcher.t; + mutable during_batch : bool; + mutable running_gc : running_gc option; + } + + let pp_key = Irmin.Type.pp XKey.t + let contents_t t : 'a Contents.t = t.contents + let node_t t : 'a Node.t = (contents_t t, t.node) + let commit_t t : 'a Commit.t = (node_t t, t.commit) + let branch_t t = t.branch + let config t = t.config + + let v config = + let root = Irmin_pack.Conf.root config in + let fresh = Irmin_pack.Conf.fresh config in + let fm = + let readonly = Irmin_pack.Conf.readonly config in + if readonly then File_manager.open_ro config |> Errs.raise_if_error + else + match (Io.classify_path root, fresh) with + | `No_such_file_or_directory, _ -> + File_manager.create_rw ~overwrite:false config + |> Errs.raise_if_error + | `Directory, true -> + File_manager.create_rw ~overwrite:true config + |> Errs.raise_if_error + | `Directory, false -> + File_manager.open_rw config |> Errs.raise_if_error + | (`File | `Other), _ -> Errs.raise_error (`Not_a_directory root) + in + let dict = Dict.v fm |> Errs.raise_if_error in + let dispatcher = Dispatcher.v fm |> Errs.raise_if_error in + let contents = Contents.CA.v ~config ~fm ~dict ~dispatcher in + let node = Node.CA.v ~config ~fm ~dict ~dispatcher in + let commit = Commit.CA.v ~config ~fm ~dict ~dispatcher in + let+ branch = + let root = Conf.root config in + let fresh = Conf.fresh config in + let readonly = Conf.readonly config in + let path = Irmin_pack.Layout.V4.branch ~root in + Branch.v ~fresh ~readonly path + in + let during_batch = false in + let running_gc = None in + { + config; + contents; + node; + commit; + branch; + fm; + dict; + during_batch; + running_gc; + dispatcher; + } + + let flush t = File_manager.flush ?hook:None t.fm |> Errs.raise_if_error + let fsync t = File_manager.fsync t.fm |> Errs.raise_if_error + let reload t = File_manager.reload t.fm |> Errs.raise_if_error + + module Gc = struct + let is_allowed { fm; _ } = File_manager.gc_allowed fm + let behaviour { fm; _ } = File_manager.gc_behaviour fm + + let cancel t = + match t.running_gc with + | Some { gc; _ } -> + let cancelled = Gc.cancel gc in + t.running_gc <- None; + cancelled + | None -> false + + let direct_commit_key t key = + let state : _ Pack_key.state = Pack_key.inspect key in + match state with + | Direct _ -> Ok key + | Indexed h -> ( + match Commit.CA.index_direct_with_kind t.commit h with + | None -> + Error + (`Commit_key_is_dangling + (Irmin.Type.to_string XKey.t key)) + | Some (k, _kind) -> Ok k) + + let start ~unlink ~use_auto_finalisation ~output t commit_key = + let open Result_syntax in + [%log.info "GC: Starting on %a" pp_key commit_key]; + let* () = + if t.during_batch then Error `Gc_forbidden_during_batch else Ok () + in + let* commit_key = direct_commit_key t commit_key in + let root = Conf.root t.config in + let* () = + if not (is_allowed t) then + Error (`Gc_disallowed "Store does not support GC") + else Ok () + in + let current_generation = File_manager.generation t.fm in + let next_generation = current_generation + 1 in + let lower_root = Conf.lower_root t.config in + let* gc = + Gc.v ~root ~lower_root ~generation:next_generation ~unlink + ~dispatcher:t.dispatcher ~fm:t.fm ~contents:t.contents + ~node:t.node ~commit:t.commit ~output commit_key + in + t.running_gc <- Some { gc; use_auto_finalisation }; + Ok () + + let start_exn ?(unlink = true) ?(output = `Root) + ~use_auto_finalisation t commit_key = + match t.running_gc with + | Some _ -> + [%log.info "Repo is alreadying running GC. Skipping."]; + Lwt.return false + | None -> ( + let result = + start ~unlink ~use_auto_finalisation ~output t commit_key + in + match result with + | Ok _ -> Lwt.return true + | Error e -> Errs.raise_error e) + + let finalise_exn ?(wait = false) t = + let* result = + match t.running_gc with + | None -> Lwt.return_ok `Idle + | Some { gc; _ } -> + if t.during_batch then + Lwt.return_error `Gc_forbidden_during_batch + else Gc.finalise ~wait gc + in + match result with + | Ok (`Finalised _ as x) -> + t.running_gc <- None; + Lwt.return x + | Ok waited -> Lwt.return waited + | Error e -> + t.running_gc <- None; + Errs.raise_error e + + let is_finished t = Option.is_none t.running_gc + + let on_finalise t f = + match t.running_gc with + | None -> () + | Some { gc; _ } -> Gc.on_finalise gc f + + let try_auto_finalise_exn t = + match t.running_gc with + | None | Some { use_auto_finalisation = false; _ } -> + Lwt.return_unit + | Some { use_auto_finalisation = true; _ } -> + let* _ = finalise_exn ~wait:false t in + Lwt.return_unit + + let latest_gc_target t = + let pl = File_manager.(Control.payload (control t.fm)) in + match pl.status with + | From_v1_v2_post_upgrade _ | Used_non_minimal_indexing_strategy + | No_gc_yet -> + None + | T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10 | T11 | T12 | T13 + | T14 | T15 -> + assert false + | Gced { latest_gc_target_offset = offset; _ } + when offset = Int63.zero -> + None + | Gced { latest_gc_target_offset = offset; _ } -> ( + let entry = + Commit.CA.read_and_decode_entry_prefix ~off:offset + t.dispatcher + in + match Commit.CA.Entry_prefix.total_entry_length entry with + | None -> + (* Commits on which this operation is supported have a + length in their header. *) + assert false + | Some length -> + let key = Pack_key.v_direct ~offset ~length entry.hash in + Some key) + + let create_one_commit_store t commit_key path = + let () = + match Io.classify_path path with + | `Directory -> () + | `No_such_file_or_directory -> + Io.mkdir path |> Errs.raise_if_error + | _ -> Errs.raise_error `Invalid_layout + in + let commit_key = + direct_commit_key t commit_key |> Errs.raise_if_error + in + (* The GC action here does not matter, since we'll not fully + finalise it *) + let* launched = + start_exn ~use_auto_finalisation:false ~output:(`External path) t + commit_key + in + let () = + if not launched then Errs.raise_error `Forbidden_during_gc + in + let* gced = + match t.running_gc with + | None -> assert false + | Some { gc; _ } -> Gc.finalise_without_swap gc + in + let config = Irmin.Backend.Conf.add t.config Conf.Key.root path in + let () = + File_manager.create_one_commit_store t.fm config gced commit_key + |> Errs.raise_if_error + in + let branch_path = Irmin_pack.Layout.V4.branch ~root:path in + let* branch_store = + Branch.v ~fresh:true ~readonly:false branch_path + in + let* () = Branch.close branch_store in + Lwt.return_unit + end + + let is_split_allowed = Gc.is_allowed + + let split t = + let open Result_syntax in + let readonly = Irmin_pack.Conf.readonly t.config in + let* () = + if not (is_split_allowed t) then Error `Split_disallowed else Ok () + in + let* () = if readonly then Error `Ro_not_allowed else Ok () in + let* () = + if t.during_batch then Error `Split_forbidden_during_batch + else Ok () + in + File_manager.split t.fm + + let split_exn repo = split repo |> Errs.raise_if_error + + let add_volume_exn t = + let () = + if Irmin_pack.Conf.readonly t.config then + Errs.raise_error `Ro_not_allowed; + if Gc.is_finished t = false then + Errs.raise_error `Add_volume_forbidden_during_gc + in + File_manager.add_volume t.fm |> Errs.raise_if_error + + let batch t f = + [%log.debug "[pack] batch start"]; + let readonly = Irmin_pack.Conf.readonly t.config in + if readonly then Errs.raise_error `Ro_not_allowed + else + let c0 = Mtime_clock.counter () in + let try_finalise () = Gc.try_auto_finalise_exn t in + let* _ = try_finalise () in + t.during_batch <- true; + let contents = Contents.CA.cast t.contents in + let node = Node.CA.Pack.cast t.node in + let commit = Commit.CA.cast t.commit in + let contents : 'a Contents.t = contents in + let node : 'a Node.t = (contents, node) in + let commit : 'a Commit.t = (node, commit) in + let on_success res = + let s = Mtime_clock.count c0 |> Mtime.Span.to_s in + [%log.info "[pack] batch completed in %.6fs" s]; + t.during_batch <- false; + File_manager.flush t.fm |> Errs.raise_if_error; + let* _ = try_finalise () in + Lwt.return res + in + let on_fail exn = + t.during_batch <- false; + [%log.info + "[pack] batch failed. calling flush. (%s)" + (Printexc.to_string exn)]; + let () = + match File_manager.flush t.fm with + | Ok () -> () + | Error err -> + [%log.err + "[pack] batch failed and flush failed. Silencing flush \ + fail. (%a)" + (Irmin.Type.pp Errs.t) err] + in + (* Kill gc process in at_exit. *) + raise exn + in + Lwt.try_bind (fun () -> f contents node commit) on_success on_fail + + let close t = + (* Step 1 - Kill the gc process if it is running *) + let _ = Gc.cancel t in + (* Step 2 - Close the files *) + let () = File_manager.close t.fm |> Errs.raise_if_error in + Branch.close t.branch >>= fun () -> + (* Step 3 - Close the in-memory abstractions *) + Dict.close t.dict; + Contents.CA.close (contents_t t) >>= fun () -> + Node.CA.close (snd (node_t t)) >>= fun () -> + Commit.CA.close (snd (commit_t t)) + end + end + + include Irmin.Of_backend (X) + module Integrity_checks = Checks.Integrity_checks (XKey) (X) (Index) + + let integrity_check_inodes ?heads t = + let* heads = + match heads with None -> Repo.heads t | Some m -> Lwt.return m + in + let hashes = List.map (fun x -> `Commit (Commit.key x)) heads in + let iter ~pred_node ~node ~commit t = + Repo.iter ~cache_size:1_000_000 ~min:[] ~max:hashes ~pred_node ~node + ~commit t + in + let nodes = X.Repo.node_t t |> snd in + let check = X.Node.CA.integrity_check_inodes nodes in + let pred = Repo.default_pred_node in + Integrity_checks.check_inodes ~iter ~pred ~check t + + let integrity_check_always ?ppf ~auto_repair t = + let contents = X.Repo.contents_t t in + let nodes = X.Repo.node_t t |> snd in + let commits = X.Repo.commit_t t |> snd in + let check ~kind ~offset ~length k = + match kind with + | `Contents -> X.Contents.CA.integrity_check ~offset ~length k contents + | `Node -> X.Node.CA.integrity_check ~offset ~length k nodes + | `Commit -> X.Commit.CA.integrity_check ~offset ~length k commits + in + let index = File_manager.index t.fm in + Integrity_checks.check_always ?ppf ~auto_repair ~check index + + let integrity_check_minimal ?ppf ?heads t = + let* heads = + match heads with None -> Repo.heads t | Some m -> Lwt.return m + in + let hashes = List.map (fun x -> `Commit (Commit.key x)) heads in + let iter ~contents ~node ~pred_node ~pred_commit repo = + Repo.iter ~cache_size:1_000_000 ~min:[] ~max:hashes ~contents ~node + ~pred_node ~pred_commit repo + in + let contents = X.Repo.contents_t t in + let pred = X.Node.CA.Val.pred in + let recompute_hash = X.Node.CA.Val.recompute_hash in + let check ~offset ~length k = + X.Contents.CA.integrity_check ~offset ~length k contents + in + Integrity_checks.check_minimal ?ppf ~pred ~iter ~check ~recompute_hash t + + let integrity_check ?ppf ?heads ~auto_repair t = + let is_minimal = + t.X.Repo.config + |> Conf.indexing_strategy + |> Irmin_pack.Indexing_strategy.is_minimal + in + let result = + if is_minimal then integrity_check_minimal ?ppf ?heads t + else integrity_check_always ?ppf ~auto_repair t |> Lwt.return + in + result + + module Stats_computation = struct + let pp_key = Irmin.Type.pp XKey.t + + let traverse_inodes ~dump_blob_paths_to commit repo = + let module Stats = Checks.Stats (struct + type nonrec step = step + + let step_t = step_t + + module Hash = Hash + end) in + let t = Stats.v () in + let pred_node repo k = + X.Node.find (X.Repo.node_t repo) k >|= function + | None -> Fmt.failwith "key %a not found" pp_key k + | Some v -> + let width = X.Node.Val.length v in + let nb_children = X.Node.CA.Val.nb_children v in + let preds = X.Node.CA.Val.pred v in + let () = + preds + |> List.map (function + | s, `Contents h -> (s, `Contents (XKey.to_hash h)) + | s, `Inode h -> (s, `Inode (XKey.to_hash h)) + | s, `Node h -> (s, `Node (XKey.to_hash h))) + |> Stats.visit_node t (XKey.to_hash k) ~width ~nb_children + in + List.rev_map + (function + | s, `Inode x -> + assert (s = None); + `Node x + | _, `Node x -> `Node x + | _, `Contents x -> `Contents x) + preds + in + (* We are traversing only one commit. *) + let pred_commit repo k = + X.Commit.find (X.Repo.commit_t repo) k >|= function + | None -> [] + | Some c -> + let node = X.Commit.Val.node c in + Stats.visit_commit t (XKey.to_hash node); + [ `Node node ] + in + let pred_contents _repo k = + Stats.visit_contents t (XKey.to_hash k); + Lwt.return [] + in + (* We want to discover all paths to a node, so we don't cache nodes + during traversal. *) + let* () = + Repo.breadth_first_traversal ~cache_size:0 ~pred_node ~pred_commit + ~pred_contents ~max:[ commit ] repo + in + Stats.pp_results ~dump_blob_paths_to t; + Lwt.return_unit + + let run ~dump_blob_paths_to ~commit repo = + Printexc.record_backtrace true; + let key = `Commit (Commit.key commit) in + traverse_inodes ~dump_blob_paths_to key repo + end + + let stats = Stats_computation.run + let reload = X.Repo.reload + let flush = X.Repo.flush + let fsync = X.Repo.fsync + let is_split_allowed = X.Repo.is_split_allowed + let split = X.Repo.split_exn + let add_volume = X.Repo.add_volume_exn + let create_one_commit_store = X.Repo.Gc.create_one_commit_store + + module Gc = struct + type msg = [ `Msg of string ] + + type process_state = + [ `Idle | `Running | `Finalised of Stats.Latest_gc.stats ] + + let catch_errors context error = + let err = + match error with + | Errors.Pack_error error -> + Fmt.str "Pack_error: %a" Errors.pp_base_error error + | Irmin.Closed -> "Irmin.Closed" + | Irmin_pack.RO_not_allowed -> "Irmin_pack.RO_not_allowed" + | Unix.Unix_error (err, s1, s2) -> + let pp = Irmin.Type.pp Io.misc_error_t in + Fmt.str "Unix_error: %a" pp (err, s1, s2) + | exn -> raise exn + in + let error_msg = Fmt.str "[%s] resulted in error: %s" context err in + Lwt.return_error (`Msg error_msg) + + let map_errors context (error : Errs.t) = + let err_msg = + Fmt.str "[%s] resulted in error: %a" context (Irmin.Type.pp Errs.t) + error + in + `Msg err_msg + + let finalise_exn = X.Repo.Gc.finalise_exn + + let start_exn ?unlink t = + X.Repo.Gc.start_exn ?unlink ~use_auto_finalisation:false t + + let start repo commit_key = + try + let* started = + X.Repo.Gc.start_exn ~unlink:true ~use_auto_finalisation:true repo + commit_key + in + Lwt.return_ok started + with exn -> catch_errors "Start GC" exn + + let is_finished = X.Repo.Gc.is_finished + let behaviour = X.Repo.Gc.behaviour + + let wait repo = + try + let* result = finalise_exn ~wait:true repo in + match result with + | `Running -> + assert false (* [~wait:true] should never return [Running] *) + | `Idle -> Lwt.return_ok None + | `Finalised stats -> Lwt.return_ok @@ Some stats + with exn -> catch_errors "Wait for GC" exn + + let run ?(finished = fun _ -> Lwt.return_unit) repo commit_key = + let* started = start repo commit_key in + match started with + | Ok r -> + if r then + X.Repo.Gc.on_finalise repo (fun finalisation_r -> + match finalisation_r with + | Ok _ as stats -> finished stats + | Error err -> + let err_msg = map_errors "Finalise GC" err in + finished @@ Error err_msg); + Lwt.return_ok r + | Error _ as e -> Lwt.return e + + let is_allowed = X.Repo.Gc.is_allowed + let cancel repo = X.Repo.Gc.cancel repo + let latest_gc_target = X.Repo.Gc.latest_gc_target + end + + module Traverse_pack_file = Traverse_pack_file.Make (struct + module File_manager = File_manager + module Dispatcher = Dispatcher + module Hash = H + module Index = Index + module Inode = X.Node.CA + module Dict = Dict + module Contents = X.Contents.Pack_value + module Commit = X.Commit.Pack_value + end) + + let traverse_pack_file = Traverse_pack_file.run + let test_traverse_pack_file = Traverse_pack_file.test + + module Snapshot = struct + include X.Node.CA.Snapshot + + type t = Inode of inode | Blob of Backend.Contents.Val.t + [@@deriving irmin] + + module S = Snapshot.Make (struct + module Hash = H + module Inode = X.Node.CA + module Contents_pack = X.Contents.CA + module Fm = File_manager + module Dispatcher = Dispatcher + end) + + include S + + module Export = struct + let iter ?on_disk repo f ~root_key = + [%log.debug "Iterate over a tree"]; + let contents = X.Repo.contents_t repo in + let nodes = X.Repo.node_t repo |> snd in + let export = S.Export.v repo.config contents nodes in + let f_contents x = f (Blob x) in + let f_nodes x = f (Inode x) in + match root_key with + | `Contents _ -> Fmt.failwith "[root_key] cannot be of type contents" + | `Node key -> + let* total = + Export.run ?on_disk export f_contents f_nodes + (key, Pack_value.Kind.Inode_v2_root) + in + Export.close export |> Errs.raise_if_error; + Lwt.return total + end + + let export = Export.iter + + module Import = struct + type process = Import.t + + let v ?on_disk repo = + let contents = X.Repo.contents_t repo in + let nodes = X.Repo.node_t repo |> snd in + let log_size = Conf.index_log_size repo.config in + Import.v ?on_disk log_size contents nodes + + let save_elt process elt = + match elt with + | Blob x -> Import.save_contents process x + | Inode x -> Import.save_inodes process x + + let close process repo = + flush repo; + fsync repo; + Import.close process + end + end + + module Internal = struct + module Io = Io + module Errs = Errs + module Index = Index + module File_manager = File_manager + + let file_manager (repo : X.Repo.t) = repo.fm + + module Dict = Dict + + let dict (repo : X.Repo.t) = repo.dict + + module XKey = XKey + + let suffix_commit_mem repo key = + X.Commit.CA.unsafe_find ~check_integrity:false + (snd (X.Repo.commit_t repo)) + key + |> Option.is_some + + let suffix_node_mem repo key = + X.Node.CA.unsafe_find ~check_integrity:false + (snd (X.Repo.node_t repo)) + key + |> Option.is_some + + let suffix_contents_mem repo key = + X.Contents.CA.unsafe_find ~check_integrity:false + (X.Repo.contents_t repo) key + |> Option.is_some + + let kill_gc (repo : X.Repo.t) = + match (repo.running_gc : X.Repo.running_gc option) with + | None -> false + | Some { gc; _ } -> ( + try X.Gc.cancel gc + with Unix.Unix_error (Unix.ESRCH, "kill", _) -> false) + end + end +end diff --git a/vendors/irmin/src/irmin-pack/unix/store.mli b/vendors/irmin/src/irmin-pack/unix/store.mli new file mode 100644 index 000000000000..d7a17a25f7d7 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/store.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Store_intf.Sigs +(** @inline *) + +module Maker (Config : Irmin_pack.Conf.S) : Maker diff --git a/vendors/irmin/src/irmin-pack/unix/store_intf.ml b/vendors/irmin/src/irmin-pack/unix/store_intf.ml new file mode 100644 index 000000000000..3a582b25978b --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/store_intf.ml @@ -0,0 +1,380 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +(** [Irmin-pack-unix]-specific extensions to the [Store] module type. *) + +module type S = sig + (** An [irmin-pack-unix] store. This provides the common {!Irmin} interface + with [irmin-pack-unix] specific extensions. *) + + include Irmin.Generic_key.S + (** @inline *) + + (** {1 Integrity Check} *) + + val integrity_check : + ?ppf:Format.formatter -> + ?heads:commit list -> + auto_repair:bool -> + repo -> + ( [> `Fixed of int | `No_error ], + [> `Cannot_fix of string | `Corrupted of int ] ) + result + Lwt.t + (** Checks the integrity of the repository. if [auto_repair] is [true], will + also try to fix the issues. [ppf] is a formatter for progressive + reporting. [`Fixed] and [`Corrupted] report the number of fixed/corrupted + entries. *) + + val integrity_check_inodes : + ?heads:commit list -> + repo -> + ([> `No_error ], [> `Cannot_fix of string ]) result Lwt.t + + val traverse_pack_file : + [ `Reconstruct_index of [ `In_place | `Output of string ] + | `Check_index + | `Check_and_fix_index ] -> + Irmin.config -> + unit + + val test_traverse_pack_file : + [ `Reconstruct_index of [ `In_place | `Output of string ] + | `Check_index + | `Check_and_fix_index ] -> + Irmin.config -> + unit + + (** {1 Chunking} *) + + val split : repo -> unit + (** [split t] starts a fresh chunk file for appending data. Only allowed on + stores that allow gc. + + Raises [RO_Not_Allowed] if called by a readonly instance. + + Raises [Split_forbidden_during_batch] if called inside a batch operation. + + Raises [Multiple_empty_chunks] if no data was added to the currently-used + chunk file. + + Raises [Split_disallowed] if {!is_split_allowed} is false. + + TODO: Detail exceptions raised. *) + + val is_split_allowed : repo -> bool + (** [is_split_allowed repo] returns if split is supported. Currently returns + the same value as {!Gc.is_allowed}. *) + + (** {1 Lower layer} *) + + val add_volume : repo -> unit + (** [add_volume t] creates a new empty volume in the lower layer. + + Raises [RO_Not_Allowed] if called by a readonly instance. + + Raises [Add_volume_forbidden_during_gc] if called while a GC is running. + + Raises [Multiple_empty_volumes] if there is already an empty volume. *) + + (** {1 On-disk} *) + + val reload : repo -> unit + (** [reload t] reloads a readonly pack with the files on disk. Raises + [invalid_argument] if called by a read-write pack.*) + + val flush : repo -> unit + (** [flush t] flush read-write pack on disk. Raises [RO_Not_Allowed] if called + by a readonly instance.*) + + val create_one_commit_store : repo -> commit_key -> string -> unit Lwt.t + (** [create_one_commit_store t key path] creates a new store at [path] from + the existing one, containing only one commit, specified by the [key]. Note + that this operation is blocking. + + It requires that the files existing on disk when the operation is + launched, remain on disk until the operation completes. In particular, a + Gc running in a different process could remove files from disk. *) + + (** {1 Garbage Collection} *) + + module Gc : sig + type process_state = + [ `Idle | `Running | `Finalised of Stats.Latest_gc.stats ] + (** The state of the GC process after calling {!finalise_exn} *) + + (** {1 Low-level API} *) + + val start_exn : ?unlink:bool -> repo -> commit_key -> bool Lwt.t + (** [start_exn] tries to start the GC process and returns true if the GC is + launched. If a GC is already running, a new one is not started. + + The GC process will not be automatically finalised. The caller is + responsible for calling {!finalise_exn}. + + If [unlink] is false then temporary files and files from the previous + generation will be kept on disk after the GC finished. This option is + useful for debugging. The default is [true]. + + TODO: Detail exceptions raised. *) + + val finalise_exn : ?wait:bool -> repo -> process_state Lwt.t + (** [finalise_exn ?wait repo] waits for the GC process to finish in order to + finalise it. It returns the state of the GC process from the point of + view of the function call; subsequent calls of [finalise_exn] after a + return of [`Finalised] will return [`Idle]. + + Finalising consists of mutating [repo] so that it points to the new file + and to flush the internal caches that could be referencing GCed objects. + What is done with the discarded data depends on {!behaviour}. + + If [wait = true] (the default), the call blocks until the GC process + finishes. If [wait = false], finalisation will occur if the process has + ended. + + If there are no running GCs, the call is a no-op and it returns [`Idle]. + + TODO: Detail exceptions raised. *) + + (** {1 High-level API} *) + + type msg = [ `Msg of string ] + (** Pretty-print error messages meant for informational purposes, like + logging *) + + val run : + ?finished:((Stats.Latest_gc.stats, msg) result -> unit Lwt.t) -> + repo -> + commit_key -> + (bool, msg) result Lwt.t + (** [run repo commit_key] attempts to start a GC process for a [repo] by + discarding or archiving all data prior to [commit_key] (depending on + {!behaviour}. If a GC process is already running, a new one will not be + started. + + [run] will also finalise the GC process automatically. For more detailed + control, see {!start_exn} and {!finalise_exn}. + + When the GC process is finalised, [finished] is called with the result + of finalisation. + + To monitor progress of GC, see {!wait} or {!is_finished}. + + Returns whether a GC process successfully started or not. + + All exceptions that [Irmin_pack] knows how to handle are caught and + returned as pretty-print error messages; others are re-raised. The error + messages should be used only for informational purposes, like logging. *) + + val wait : repo -> (Stats.Latest_gc.stats option, msg) result Lwt.t + (** [wait repo] blocks until GC is finished or is idle. + + If a GC finalises, its stats are returned. + + All exceptions that [Irmin_pack] knows how to handle are caught and + returned as pretty-print error messages; others are re-raised. The error + messages should be used only for informational purposes, like logging. *) + + val cancel : repo -> bool + (** [cancel repo] aborts the current GC and returns [true], or returns + [false] if no GC was running. *) + + val is_finished : repo -> bool + (** [is_finished repo] is [true] if a GC is finished (or idle) and [false] + if a GC is running for the given [repo]. *) + + val behaviour : repo -> [ `Archive | `Delete ] + (** [behaviour repo] returns the behaviour that the GC will have during + finalization. + + This depends on the presence of a lower layer in the store: if a lower + layer is present, the GC will archive old data into that lower layer. + Else, it will delete that data. *) + + val is_allowed : repo -> bool + (** [is_allowed repo] returns true if a gc can be run on the store. *) + + val latest_gc_target : repo -> commit_key option + (** [latest_gc_target] returns the commit key on which the latest, finished + gc was called on. *) + end + + (** {1 Snapshots} *) + + module Snapshot : sig + type kinded_hash = Contents of hash * metadata | Node of hash + [@@deriving irmin] + + type entry = { step : string; hash : kinded_hash } [@@deriving irmin] + + type inode_tree = { + depth : int; + length : int; + pointers : (int * hash) list; + } + [@@deriving irmin] + + type v = Inode_tree of inode_tree | Inode_value of entry list + [@@deriving irmin] + + type inode = { v : v; root : bool } [@@deriving irmin] + + type t = Inode of inode | Blob of Backend.Contents.Val.t + [@@deriving irmin] + + val export : + ?on_disk:[ `Path of string ] -> + repo -> + (t -> unit Lwt.t) -> + root_key:Tree.kinded_key -> + int Lwt.t + (** [export ?on_disk repo f ~root_key] applies [f] to all inodes and + contents in a rooted tree, with root specified by [root_key]. + + The traversal requires an index to keep track of visited elements. + + - if [on_disk] is not specified, the index is in memory. + - if [on_disk] is [`Path path], a temporary index is created at path. + + The traversal order is stable. In [Inode_tree], it is lexicographic on + the [index] function (see {!Conf.inode_child_order}). In [Inode_value], + it is lexicographic on the steps. + + [f] is called in post-order, that is [f] is first called on the leaves, + and the last call to [f] is on the root designated by [root_key]. + + The traversal skips objects that are structurally equal to objects that + were already traversed. In other words, [export] internally uses a hash + set in order to guarantee that all the objects passed to [f] don't hash + the same way. + + Returns the total number of elements visited. *) + + module Import : sig + type process + + val v : ?on_disk:[ `Path of string | `Reuse ] -> repo -> process + (** [v ?on_disk repo] create a [snaphot] instance. The traversal requires + an index to keep track of visited elements. + + - if [on_disk] is not specified, the index is in memory. + - if [on_disk] is [`Path path], a temporary index is created at path. + - if [on_disk] is [`Reuse] the store's index is reused. *) + + val save_elt : process -> t -> node_key Lwt.t + (** [save_elt snapshot elt] saves [elt] to the store. *) + + val close : process -> repo -> unit + (** [close snapshot] close the [snaphot] instance.*) + end + end + + (** {1 Statistics} *) + + val stats : + dump_blob_paths_to:string option -> commit:commit -> repo -> unit Lwt.t + + (** {1 Internals} *) + + module Internal : sig + (** Unstable internal API agnostic about the underlying storage. Use it only + to implement or test inodes. *) + + module Io = Io.Unix + module Errs : Io_errors.S with module Io = Io + module Index : Pack_index.S with type key = hash + + module File_manager : + File_manager.S + with module Io = Io + and module Errs = Errs + and module Index = Index + + val file_manager : repo -> File_manager.t + + module Dict : Dict.S + + val dict : repo -> Dict.t + + module XKey : Pack_key.S with type hash = Schema.Hash.t + + val suffix_commit_mem : repo -> XKey.t -> bool + val suffix_node_mem : repo -> XKey.t -> bool + val suffix_contents_mem : repo -> XKey.t -> bool + val kill_gc : repo -> bool + end +end + +module S_is_a_store (X : S) : Irmin.Generic_key.S = X + +module type Maker = sig + type endpoint = unit + + include Irmin.Key.Store_spec.S + + module Make (Schema : Irmin.Schema.Extended) : + S + (* We can't have `with module Schema = Schema` here, since the Schema + on the RHS contains more information than the one on the LHS. We _want_ + to do something like `with module Schema = (Schema : Irmin.Schema.S)`, + but this isn't supported. + + TODO: extract these extensions as a separate functor argument instead. *) + with type Schema.Hash.t = Schema.Hash.t + and type Schema.Branch.t = Schema.Branch.t + and type Schema.Metadata.t = Schema.Metadata.t + and type Schema.Path.t = Schema.Path.t + and type Schema.Path.step = Schema.Path.step + and type Schema.Contents.t = Schema.Contents.t + and type Schema.Info.t = Schema.Info.t + and type contents_key = (Schema.Hash.t, Schema.Contents.t) contents_key + and type node_key = Schema.Hash.t node_key + and type commit_key = Schema.Hash.t commit_key + and type Backend.Remote.endpoint = endpoint +end +with type ('h, _) contents_key = 'h Pack_key.t + and type 'h node_key = 'h Pack_key.t + and type 'h commit_key = 'h Pack_key.t + +module type KV = sig + type endpoint = unit + type hash = Irmin.Schema.default_hash + + include Pack_key.Store_spec + + type metadata = Irmin.Metadata.None.t + + module Make (C : Irmin.Contents.S) : + S + with module Schema.Contents = C + and type Schema.Metadata.t = metadata + and type Backend.Remote.endpoint = endpoint + and type Schema.Hash.t = hash + and type contents_key = (hash, C.t) contents_key + and type node_key = hash node_key + and type commit_key = hash commit_key + and type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Branch.t = string +end + +module type Sigs = sig + module type S = S + module type Maker = Maker + module type KV = KV +end diff --git a/vendors/irmin/src/irmin-pack/unix/traverse_pack_file.ml b/vendors/irmin/src/irmin-pack/unix/traverse_pack_file.ml new file mode 100644 index 000000000000..69992155f84f --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/traverse_pack_file.ml @@ -0,0 +1,437 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Io = Io.Unix + +module Stats : sig + type t + + val empty : unit -> t + val add : t -> Pack_value.Kind.t -> unit + val duplicate_entry : t -> unit + val missing_hash : t -> unit + val pp : t Fmt.t +end = struct + module Kind = Pack_value.Kind + + type t = { + pack_values : int array; + mutable duplicates : int; + mutable missing_hashes : int; + } + + let empty () = + let pack_values = Array.make (List.length Kind.all) 0 in + { pack_values; duplicates = 0; missing_hashes = 0 } + + let incr t n = t.pack_values.(n) <- t.pack_values.(n) + 1 + let add t k = incr t (Kind.to_enum k) + let duplicate_entry t = t.duplicates <- t.duplicates + 1 + let missing_hash t = t.missing_hashes <- t.missing_hashes + 1 + + let pp = + let open Fmt.Dump in + let pack_values = + ListLabels.map Kind.all ~f:(fun k -> + let name = Fmt.str "%a" Kind.pp k in + let index = Kind.to_enum k in + field name (fun t -> t.pack_values.(index)) Fmt.int) + in + record + (pack_values + @ [ + field "Duplicated entries" (fun t -> t.duplicates) Fmt.int; + field "Missing entries" (fun t -> t.missing_hashes) Fmt.int; + ]) +end + +module type Args = sig + module File_manager : File_manager.S + module Dispatcher : Dispatcher.S with module Fm = File_manager + module Hash : Irmin.Hash.S + module Index : Pack_index.S with type key := Hash.t + module Inode : Inode.S with type hash := Hash.t + module Contents : Pack_value.S + module Commit : Pack_value.S +end + +module Make (Args : Args) : sig + val run : + [ `Reconstruct_index of [ `In_place | `Output of string ] + | `Check_index + | `Check_and_fix_index ] -> + Irmin.config -> + unit + + val test : + [ `Reconstruct_index of [ `In_place | `Output of string ] + | `Check_index + | `Check_and_fix_index ] -> + Irmin.config -> + unit +end = struct + open Args + module Errs = Io_errors.Make (File_manager.Io) + + let pp_key = Irmin.Type.pp Hash.t + let decode_key = Irmin.Type.(unstage (decode_bin Hash.t)) + let decode_kind = Irmin.Type.(unstage (decode_bin Pack_value.Kind.t)) + + (* [Repr] doesn't yet support buffered binary decoders, so we hack one + together by re-interpreting [Invalid_argument _] exceptions from [Repr] + as requests for more data. *) + exception Not_enough_buffer + + type index_value = int63 * int * Pack_value.Kind.t + [@@deriving irmin ~equal ~pp] + + type index_binding = { key : Hash.t; data : index_value } + type missing_hash = { idx_pack : int; binding : index_binding } + + let pp_binding ppf x = + let off, len, kind = x.data in + Fmt.pf ppf "@[%a with hash %a@,pack offset = %a, length = %d@]" + Pack_value.Kind.pp kind pp_key x.key Int63.pp off len + + let to_index = function + | Pack_value.Kind.Commit_v2 | Commit_v1 | Dangling_parent_commit -> true + | Contents | Inode_v1_unstable | Inode_v1_stable | Inode_v2_root + | Inode_v2_nonroot -> + false + + module Index_reconstructor = struct + let create ~dest config = + let dest = + match dest with + | `Output path -> + if Sys.file_exists path then + Fmt.invalid_arg "Can't reconstruct index. File already exits."; + path + | `In_place -> + if Conf.readonly config then raise Irmin_pack.RO_not_allowed; + Conf.root config + in + let log_size = Conf.index_log_size config in + [%log.app + "Beginning index reconstruction with parameters: { log_size = %d }" + log_size]; + let index = Index.v_exn ~fresh:true ~readonly:false ~log_size dest in + index + + let iter_pack_entry ~always index key data = + let _, _, kind = data in + if always || to_index kind then Index.add index key data; + Ok () + + let finalise index () = + (* Ensure that the log file is empty, so that subsequent opens with a + smaller [log_size] don't immediately trigger a merge operation. *) + [%log.app "Completed indexing of pack entries. Running a final merge ..."]; + Index.try_merge index; + Index.close_exn index + end + + module Index_checker = struct + let create config = + let log_size = Conf.index_log_size config in + [%log.app + "Beginning index checking with parameters: { log_size = %d }" log_size]; + let index = + Index.v_exn ~fresh:false ~readonly:true ~log_size (Conf.root config) + in + (index, ref 0) + + let iter_pack_entry ~always (index, idx_ref) key data = + let _, _, kind = data in + if always || to_index kind then ( + match Index.find index key with + | None -> + Error + (`Missing_hash { idx_pack = !idx_ref; binding = { key; data } }) + | Some data' when not @@ equal_index_value data data' -> + Error `Inconsistent_entry + | Some _ -> + incr idx_ref; + Ok ()) + else Ok () + + let finalise (index, _) () = Index.close_exn index + end + + module Index_check_and_fix = struct + let create config = + let log_size = Conf.index_log_size config in + [%log.app + "Beginning index checking with parameters: { log_size = %d }" log_size]; + let root = Conf.root config in + let index = Index.v_exn ~fresh:false ~readonly:false ~log_size root in + (index, ref 0) + + let iter_pack_entry ~always (index, idx_ref) key data = + let _, _, kind = data in + if always || to_index kind then ( + match Index.find index key with + | None -> + Index.add index key data; + Error + (`Missing_hash { idx_pack = !idx_ref; binding = { key; data } }) + | Some data' when not @@ equal_index_value data data' -> + Error `Inconsistent_entry + | Some _ -> + incr idx_ref; + Ok ()) + else Ok () + + let finalise (index, _) () = + [%log.app "Completed indexing of pack entries. Running a final merge ..."]; + Index.try_merge index; + Index.close_exn index + end + + let decode_entry_length = function + | Pack_value.Kind.Contents -> Contents.decode_bin_length + | Commit_v1 | Commit_v2 | Dangling_parent_commit -> Commit.decode_bin_length + | Inode_v1_stable | Inode_v1_unstable | Inode_v2_root | Inode_v2_nonroot -> + Inode.decode_bin_length + + let decode_entry_exn ~off ~buffer ~buffer_off = + try + let buffer_pos = ref buffer_off in + (* Decode the key and kind by hand *) + let key = decode_key buffer buffer_pos in + assert (!buffer_pos = buffer_off + Hash.hash_size); + let kind = decode_kind buffer buffer_pos in + assert (!buffer_pos = buffer_off + Hash.hash_size + 1); + (* Get the length of the entire entry *) + let entry_len = decode_entry_length kind buffer buffer_off in + { key; data = (off, entry_len, kind) } + with + | Invalid_argument msg when msg = "index out of bounds" -> + raise Not_enough_buffer + | Invalid_argument msg when msg = "String.blit / Bytes.blit_string" -> + raise Not_enough_buffer + + (* duplicated code with irmin-tezos-utils *) + let decode_entry_len buffer = + let buffer = Bytes.unsafe_to_string buffer in + let i0 = 0 in + let ilength = i0 + Hash.hash_size + 1 in + let pos_ref = ref ilength in + let suffix_length = Varint.decode_bin buffer pos_ref in + let length_length = !pos_ref - ilength in + Hash.hash_size + 1 + length_length + suffix_length + + let guess_entry_len dispatcher ~off = + let min_bytes_needed_to_discover_length = Hash.hash_size + 1 in + let max_bytes_needed_to_discover_length = + min_bytes_needed_to_discover_length + Varint.max_encoded_size + in + let buffer = Bytes.create max_bytes_needed_to_discover_length in + let _len, _volume = + Dispatcher.read_range_exn dispatcher ~off + ~min_len:min_bytes_needed_to_discover_length + ~max_len:max_bytes_needed_to_discover_length buffer + in + decode_entry_len buffer + + (* Read at most [len], by checking that [(off, len)] don't go out of bounds of + the suffix file. *) + let io_read_at_most ~off ~len buffer dispatcher = + let len = + let open Int63.Syntax in + let bytes_after_off = Dispatcher.end_offset dispatcher - off in + if bytes_after_off < Int63.of_int len then Int63.to_int bytes_after_off + else len + in + Dispatcher.read_exn dispatcher ~off ~len buffer + + let on_entry { data; key } stats iter_pack_entry missing_hash = + [%log.debug "k = %a (off, len, kind) = %a" pp_key key pp_index_value data]; + match iter_pack_entry key data with + | Ok () -> Option.map Fun.id missing_hash + | Error `Inconsistent_entry -> + Stats.duplicate_entry stats; + Option.map Fun.id missing_hash + | Error (`Missing_hash x) -> + Stats.missing_hash stats; + Some x + + let ingest_data_file_after_v3 ~initial_buffer_size ~progress dispatcher + iter_pack_entry = + let stats = Stats.empty () in + let buffer = Bytes.create initial_buffer_size in + let on_entry missing_hash off = + let len = guess_entry_len dispatcher ~off in + let _ = Dispatcher.read_exn dispatcher ~off ~len buffer in + let { key; data } = + decode_entry_exn ~off + ~buffer:(Bytes.unsafe_to_string buffer) + ~buffer_off:0 + in + let off', entry_len, kind = data in + let entry_lenL = Int63.of_int entry_len in + assert (off = off'); + Stats.add stats kind; + progress entry_lenL; + (entry_len, on_entry { key; data } stats iter_pack_entry missing_hash) + in + let rec traverse off missing_hash = + match Dispatcher.next_valid_offset dispatcher ~off with + | None -> missing_hash + | Some off -> + let len, missing_hash = on_entry missing_hash off in + let after_off = + let open Int63.Syntax in + off + Int63.of_int len + in + traverse after_off missing_hash + in + let missing_hash = traverse Int63.zero None in + (stats, missing_hash) + + let ingest_data_file_before_v3 ~initial_buffer_size ~progress ~total + dispatcher iter_pack_entry = + let buffer = ref (Bytes.create initial_buffer_size) in + let refill_buffer ~from = + let buffer_len = Bytes.length !buffer in + let _ = io_read_at_most ~off:from ~len:buffer_len !buffer dispatcher in + () + in + let expand_and_refill_buffer ~from = + let length = Bytes.length !buffer in + if length > 1_000_000_000 (* 1 GB *) then + Fmt.failwith + "Couldn't decode the value at offset %a in %d of buffer space. \ + Corrupted data file?" + Int63.pp from length + else ( + buffer := Bytes.create (2 * length); + refill_buffer ~from) + in + let stats = Stats.empty () in + let rec loop_entries ~buffer_off off missing_hash = + if off >= total then (stats, missing_hash) + else + let buffer_off, off, missing_hash = + match + (* Bytes.unsafe_to_string usage: possibly safe, depending on details of + implementation of decode_entry_exn TODO either justify clearly that this is + safe, or change to use safe Bytes.to_string *) + decode_entry_exn ~off + ~buffer:(Bytes.unsafe_to_string !buffer) + ~buffer_off + with + | { key; data } -> + let off', entry_len, kind = data in + let entry_lenL = Int63.of_int entry_len in + assert (off = off'); + Stats.add stats kind; + progress entry_lenL; + let off = Int63.Syntax.(off + entry_lenL) in + let missing_hash = + on_entry { data; key } stats iter_pack_entry missing_hash + in + (buffer_off + entry_len, off, missing_hash) + | exception Not_enough_buffer -> + let () = + if buffer_off > 0 then + (* Try again with the value at the start of the buffer. *) + refill_buffer ~from:off + else + (* The entire buffer isn't enough to hold this value: expand it. *) + expand_and_refill_buffer ~from:off + in + (0, off, missing_hash) + in + loop_entries ~buffer_off off missing_hash + in + refill_buffer ~from:Int63.zero; + loop_entries ~buffer_off:0 Int63.zero None + + let run_or_test ~initial_buffer_size mode config = + let always = + Conf.indexing_strategy config + |> Irmin_pack.Indexing_strategy.is_minimal + |> not + in + let iter_pack_entry, finalise, message = + match mode with + | `Reconstruct_index dest -> + let open Index_reconstructor in + let v = create ~dest config in + (iter_pack_entry ~always v, finalise v, "Reconstructing index") + | `Check_index -> + let open Index_checker in + let v = create config in + (iter_pack_entry ~always v, finalise v, "Checking index") + | `Check_and_fix_index -> + let open Index_check_and_fix in + let v = create config in + (iter_pack_entry ~always v, finalise v, "Checking and fixing index") + in + let run_duration = Mtime_clock.counter () in + let fm = File_manager.open_ro config |> Errs.raise_if_error in + let dispatcher = Dispatcher.v fm |> Errs.raise_if_error in + let total = Dispatcher.end_offset dispatcher in + let ingest_data progress = + if File_manager.gc_allowed fm then + ingest_data_file_after_v3 ~initial_buffer_size dispatcher + iter_pack_entry ~progress + else + ingest_data_file_before_v3 ~initial_buffer_size ~total dispatcher + iter_pack_entry ~progress + in + let stats, missing_hash = + let bar = + let open Progress.Line.Using_int63 in + list + [ const message; bytes; elapsed (); bar total; percentage_of total ] + in + Progress.(with_reporter bar) ingest_data + in + finalise (); + File_manager.close fm |> Errs.raise_if_error; + let run_duration = Mtime_clock.count run_duration in + let store_stats fmt = + Fmt.pf fmt "Store statistics:@, @[%a@]" Stats.pp stats + in + match missing_hash with + | None -> + [%log.app + "%a in %a. %t" + Fmt.(styled `Green string) + "Success" Mtime.Span.pp run_duration store_stats] + | Some x -> + let msg = + match mode with + | `Check_index -> "Detected missing entries" + | `Check_and_fix_index -> + "Detected missing entries and added them to index" + | _ -> assert false + in + [%log.err + "%a in %a.@,\ + First pack entry missing from index is the %d entry of the pack:@,\ + \ %a@,\ + %t" + Fmt.(styled `Red string) + msg Mtime.Span.pp run_duration x.idx_pack pp_binding x.binding + store_stats] + + let run = run_or_test ~initial_buffer_size:1024 + let test = run_or_test ~initial_buffer_size:100 +end diff --git a/vendors/irmin/src/irmin-pack/unix/utils.ml b/vendors/irmin/src/irmin-pack/unix/utils.ml new file mode 100644 index 000000000000..486434934502 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/unix/utils.ml @@ -0,0 +1,91 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module Object_counter : sig + type t + + val start : + Format.formatter -> t * ((unit -> unit) * (unit -> unit) * (unit -> unit)) + + val finalise : t -> unit + val finalise_with_stats : t -> int * int * int +end = struct + type t = + | Object_counter : { + display : (_, _) Progress.Display.t; + nb_commits : int ref; + nb_nodes : int ref; + nb_contents : int ref; + } + -> t + + let start ppf = + let config = Progress.Config.v ~ppf () in + let nb_commits = ref 0 in + let nb_nodes = ref 0 in + let nb_contents = ref 0 in + let bar = + let open Progress.Line in + let count_to_string (contents, nodes, commits) = + Fmt.str "%dk contents / %dk nodes / %d commits" (contents / 1000) + (nodes / 1000) commits + in + using count_to_string string + in + let display = Progress.Display.start ~config (Progress.Multi.line bar) in + let [ reporter ] = Progress.Display.reporters display in + let update_fn count () = + incr count; + reporter (!nb_contents, !nb_nodes, !nb_commits) + in + let contents = update_fn nb_contents + and nodes = update_fn nb_nodes + and commits = update_fn nb_commits in + ( Object_counter { display; nb_contents; nb_nodes; nb_commits }, + (contents, nodes, commits) ) + + let finalise (Object_counter t) = Progress.Display.finalise t.display + + let finalise_with_stats (Object_counter t as t_outer) = + finalise t_outer; + (!(t.nb_contents), !(t.nb_nodes), !(t.nb_commits)) +end + +(** [nearest_geq ~arr ~get ~lo ~hi ~key] returns the index of the nearest entry + in the sorted [arr] that is [>=] the given key. Routine is based on binary + search. *) +let nearest_geq ~arr ~get ~lo ~hi ~key = + if lo > hi then None + else + match Stdlib.compare key (get arr hi) with + | 0 -> Some hi + | c when c > 0 -> None + | _ when get arr lo >= key -> Some lo + | _ -> + let rec search lo hi = + assert (lo < hi); + assert (get arr lo < key && key < get arr hi); + if lo + 1 = hi then Some hi + else + let mid = (lo + hi) / 2 in + match Stdlib.compare key (get arr mid) with + | 0 -> Some mid + | c when c < 0 -> search lo mid + | _ -> search mid hi + in + search lo hi diff --git a/vendors/irmin/src/irmin-pack/version.ml b/vendors/irmin/src/irmin-pack/version.ml new file mode 100644 index 000000000000..665621bdd0b8 --- /dev/null +++ b/vendors/irmin/src/irmin-pack/version.ml @@ -0,0 +1,80 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* For every new version, update the [version] type and [versions] + headers. *) + +type t = [ `V1 | `V2 | `V3 | `V4 | `V5 ] [@@deriving irmin] + +let latest = `V5 + +let enum = + [ + (`V1, "00000001"); + (`V2, "00000002"); + (`V3, "00000003"); + (`V4, "00000004"); + (`V5, "00000005"); + ] + +let pp = + Fmt.of_to_string (function + | `V1 -> "v1" + | `V2 -> "v2" + | `V3 -> "v3" + | `V4 -> "v4" + | `V5 -> "v5") + +let to_bin v = List.assoc v enum +let to_int = function `V1 -> 1 | `V2 -> 2 | `V3 -> 3 | `V4 -> 4 | `V5 -> 5 +let compare a b = Int.compare (to_int a) (to_int b) +let encode_bin t f = to_bin t |> f + +let decode_bin s offref = + let sub = String.sub s !offref (!offref + 8) in + let res = + match sub with + | "00000001" -> `V1 + | "00000002" -> `V2 + | "00000003" -> `V3 + | "00000004" -> `V4 + | "00000005" -> `V5 + | _ -> failwith "Couldn't decode pack version" + in + offref := !offref + 8; + res + +let size_of = Irmin.Type.Size.custom_static 8 +let bin = (encode_bin, decode_bin, size_of) +let t = Irmin.Type.like ~bin ~unboxed_bin:bin ~compare ~pp t + +let invalid_arg v = + let pp_full_version ppf v = Fmt.pf ppf "%a (%S)" pp v (to_bin v) in + Fmt.invalid_arg "invalid version: got %S, expecting %a" v + Fmt.(Dump.list pp_full_version) + (List.map fst enum) + +let of_bin b = try Some (decode_bin b (ref 0)) with Failure _ -> None + +exception Invalid of { expected : t; found : t } + +let () = + Printexc.register_printer (function + | Invalid { expected; found } -> + Some + (Fmt.str "%s.Invalid { expected = %a; found = %a }" __MODULE__ pp + expected pp found) + | _ -> None) diff --git a/vendors/irmin/src/irmin-pack/version.mli b/vendors/irmin/src/irmin-pack/version.mli new file mode 100644 index 000000000000..d22f40c0042f --- /dev/null +++ b/vendors/irmin/src/irmin-pack/version.mli @@ -0,0 +1,54 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Management of disk-format versions. + + [`V2] introduced the [*_v2] kinds and deprecated the [*_v1] ones. The + upgrade of a pack file to [`V2] was done silently the first time a used + pushed a [*_v2] entry to the pack file. + + [`V3] introduced the control file. It centralizes all the metadata that used + to be contained in the header of other files (e.g. the version of the store + used to be stored in each files, it is now solely stored in the control + file). The upgrade of a store to [`V3] was done silently when opening a + store in rw mode. + + [`V4] introduced the chunked suffix. Upgrade from [`V3] happened on first + write to the control file. + + [`V5] introduced the lower layer. Upgrade happened on first write to the + control file. *) + +type t = [ `V1 | `V2 | `V3 | `V4 | `V5 ] [@@deriving irmin] +(** The type for version numbers. *) + +val to_int : t -> int +val compare : t -> t -> int +val latest : t + +val pp : t Fmt.t +(** [pp] is the pretty-format for version numbers. *) + +val to_bin : t -> string +(** [to_bin t] is the 8-bytes binary representation of [t]. *) + +val of_bin : string -> t option +(** [of_bin s] is [Some t] is [to_bin t] is [s] and [None] otherwise. *) + +val invalid_arg : string -> 'a +(** [invalid_arg str] raises [Invalid_argument]. *) + +exception Invalid of { expected : t; found : t } diff --git a/vendors/irmin/src/irmin-test/common.ml b/vendors/irmin/src/irmin-test/common.ml new file mode 100644 index 000000000000..01436177bbdb --- /dev/null +++ b/vendors/irmin/src/irmin-test/common.ml @@ -0,0 +1,324 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +let random_char () = char_of_int (Random.int 256) + +let random_ascii () = + let chars = "0123456789abcdefghijklmnopqrstABCDEFGHIJKLMNOPQRST-_." in + chars.[Random.int @@ String.length chars] + +let random_string n = String.init n (fun _i -> random_char ()) +let long_random_string = random_string (* 1024_000 *) 10 +let random_ascii_string n = String.init n (fun _i -> random_ascii ()) +let long_random_ascii_string = random_ascii_string 1024_000 + +let merge_exn msg x = + match x with + | Ok x -> Lwt.return x + | Error (`Conflict m) -> Alcotest.failf "%s: %s" msg m + +open Astring + +module type S = + Irmin.S + with type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Contents.t = string + and type Schema.Branch.t = string + +module type Generic_key = + Irmin.Generic_key.S + with type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Contents.t = string + and type Schema.Branch.t = string + +module Schema = struct + module Hash = Irmin.Hash.SHA1 + module Commit = Irmin.Commit.Make (Hash) + module Path = Irmin.Path.String_list + module Metadata = Irmin.Metadata.None + module Node = Irmin.Node.Generic_key.Make (Hash) (Path) (Metadata) + module Branch = Irmin.Branch.String + module Info = Irmin.Info.Default + module Contents = Irmin.Contents.String +end + +let store : (module Irmin.Maker) -> (module Irmin.Metadata.S) -> (module S) = + fun (module B) (module M) -> + let module Schema = struct + include Schema + module Metadata = M + module Node = Irmin.Node.Generic_key.Make (Hash) (Path) (Metadata) + end in + let module S = B.Make (Schema) in + (module S) + +type store = S of (module S) | Generic_key of (module Generic_key) + +type t = { + name : string; + init : config:Irmin.config -> unit Lwt.t; + clean : config:Irmin.config -> unit Lwt.t; + config : Irmin.config; + store : store; + stats : (unit -> int * int) option; + (* Certain store implementations currently don't support implementing + repository state from a slice, because their slice formats contain + non-portable objects. For now, we disable the tests require this feature + for such backends. + + TODO: fix slices to always contain portable objects, and extend + [Store.import] to re-hydrate the keys in these slices (by tracking keys of + added objects), then require all backends to run thee tests. *) + import_supported : bool; +} + +module Suite = struct + type nonrec t = t + + let default_clean ~config ~store = + let (module Store : Generic_key) = + match store with + | Generic_key x -> x + | S (module S) -> (module S : Generic_key) + in + let open Lwt.Syntax in + let* repo = Store.Repo.v config in + let* branches = Store.Repo.branches repo in + let* () = Lwt_list.iter_p (Store.Branch.remove repo) branches in + Store.Repo.close repo + + let create ~name ?(init = fun ~config:_ -> Lwt.return_unit) ?clean ~config + ~store ?stats ?(import_supported = true) () = + let store = S store in + let clean = Option.value clean ~default:(default_clean ~store) in + { name; init; clean; config; store; stats; import_supported } + + let create_generic_key ~name ?(init = fun ~config:_ -> Lwt.return_unit) ?clean + ~config ~store ?stats ?(import_supported = true) () = + let store = Generic_key store in + let clean = Option.value clean ~default:(default_clean ~store) in + { name; init; clean; config; store; stats; import_supported } + + let name t = t.name + let config t = t.config + let store t = match t.store with S x -> Some x | Generic_key _ -> None + + let store_generic_key t = + match t.store with + | Generic_key x -> x + | S (module S) -> (module S : Generic_key) + + let init t = t.init + let clean t = t.clean +end + +module type Store_tests = functor (S : Generic_key) -> sig + val tests : (string * (Suite.t -> unit -> unit Lwt.t)) list +end + +module Make_helpers (S : Generic_key) = struct + module B = S.Backend + module Graph = Irmin.Node.Graph (B.Node) + + let info message = + let date = Int64.of_float 0. in + let author = Printf.sprintf "TESTS" in + S.Info.v ~author ~message date + + let infof fmt = Fmt.kstr (fun str () -> info str) fmt + + let get_contents_key = function + | `Contents key -> key + | _ -> Alcotest.fail "expecting contents_key" + + let get_node_key = function + | `Node key -> key + | _ -> Alcotest.fail "expecting node_key" + + type x = int [@@deriving irmin] + + let v repo = B.Repo.contents_t repo + let n repo = B.Repo.node_t repo + let ct repo = B.Repo.commit_t repo + let g repo = B.Repo.node_t repo + let h repo = B.Repo.commit_t repo + let b repo = B.Repo.branch_t repo + let v1 = long_random_string + let v2 = "" + let with_contents repo f = B.Repo.batch repo (fun t _ _ -> f t) + let with_node repo f = B.Repo.batch repo (fun _ t _ -> f t) + let with_commit repo f = B.Repo.batch repo (fun _ _ t -> f t) + let with_info repo n f = with_commit repo (fun h -> f h ~info:(info n)) + let kv1 ~repo = with_contents repo (fun t -> B.Contents.add t v1) + let kv2 ~repo = with_contents repo (fun t -> B.Contents.add t v2) + let normal x = `Contents (x, S.Metadata.default) + let b1 = "foo" + let b2 = "bar/toto" + + let n1 ~repo = + let* kv1 = kv1 ~repo in + with_node repo (fun t -> Graph.v t [ ("x", normal kv1) ]) + + let n2 ~repo = + let* kn1 = n1 ~repo in + with_node repo (fun t -> Graph.v t [ ("b", `Node kn1) ]) + + let n3 ~repo = + let* kn2 = n2 ~repo in + with_node repo (fun t -> Graph.v t [ ("a", `Node kn2) ]) + + let n4 ~repo = + let* kn1 = n1 ~repo in + let* kv2 = kv2 ~repo in + let* kn4 = with_node repo (fun t -> Graph.v t [ ("x", normal kv2) ]) in + let* kn5 = + with_node repo (fun t -> Graph.v t [ ("b", `Node kn1); ("c", `Node kn4) ]) + in + with_node repo (fun t -> Graph.v t [ ("a", `Node kn5) ]) + + let r1 ~repo = + let* kn2 = n2 ~repo in + S.Tree.of_key repo (`Node kn2) >>= function + | None -> Alcotest.fail "r1" + | Some tree -> + S.Commit.v repo ~info:S.Info.empty ~parents:[] (tree :> S.tree) + + let r2 ~repo = + let* kn3 = n3 ~repo in + let* kr1 = r1 ~repo in + S.Tree.of_key repo (`Node kn3) >>= function + | None -> Alcotest.fail "r2" + | Some t3 -> + S.Commit.v repo ~info:S.Info.empty + ~parents:[ S.Commit.key kr1 ] + (t3 :> S.tree) + + let ignore_thunk_errors f = Lwt.catch f (fun _ -> Lwt.return_unit) + + let run (x : Suite.t) test = + let repo_ptr = ref None in + let config_ptr = ref None in + Lwt.catch + (fun () -> + let module Conf = Irmin.Backend.Conf in + let generate_random_root config = + let id = Random.int 100 |> string_of_int in + let root_value = + match Conf.find_root config with + | None -> "test_" ^ id + | Some v -> v ^ "_" ^ id + in + let root_key = Conf.(root (spec config)) in + Conf.add config root_key root_value + in + let config = generate_random_root x.config in + config_ptr := Some config; + let* () = x.init ~config in + let* repo = S.Repo.v config in + repo_ptr := Some repo; + let* () = test repo in + let* () = + (* [test] might have already closed the repo. That + [ignore_thunk_errors] shall be removed as soon as all stores + support double closes. *) + ignore_thunk_errors (fun () -> S.Repo.close repo) + in + x.clean ~config) + (fun exn -> + (* [test] failed, attempt an errorless cleanup and forward the right + backtrace to the user. *) + let bt = Printexc.get_raw_backtrace () in + let* () = + match !repo_ptr with + | Some repo -> ignore_thunk_errors (fun () -> S.Repo.close repo) + | None -> Lwt.return_unit + in + let+ () = + match !config_ptr with + | Some config -> ignore_thunk_errors (fun () -> x.clean ~config) + | None -> Lwt.return_unit + in + Printexc.raise_with_backtrace exn bt) +end + +let filter_src src = + not + (List.mem ~equal:String.equal (Logs.Src.name src) + [ + "git.inflater.decoder"; + "git.deflater.encoder"; + "git.encoder"; + "git.decoder"; + "git.loose"; + "git.store"; + "cohttp.lwt.io"; + ]) + +let reporter ?prefix () = + Irmin.Export_for_backends.Logging.reporter ~filter_src ?prefix + (module Mtime_clock) + +let () = + Logs.set_level (Some Logs.Debug); + Logs.set_reporter (reporter ()) + +let line ppf ?color c = + let line = String.v ~len:80 (fun _ -> c) in + match color with + | Some c -> Fmt.pf ppf "%a\n%!" Fmt.(styled c string) line + | None -> Fmt.pf ppf "%s\n%!" line + +let line msg = + let line () = line Fmt.stderr ~color:`Yellow '-' in + line (); + [%logs.info "ASSERT %s" msg]; + line () + +let ( / ) = Filename.concat + +let testable t = + Alcotest.testable (Irmin.Type.pp_dump t) Irmin.Type.(unstage (equal t)) + +let check t = Alcotest.check (testable t) + +let checks t = + let t = Alcotest.slist (testable t) Irmin.Type.(unstage (compare t)) in + Alcotest.check t + +(* also in test/irmin-pack/common.ml *) +let check_raises_lwt msg exn (type a) (f : unit -> a Lwt.t) = + Lwt.catch + (fun x -> + let* (_ : a) = f x in + Alcotest.failf + "Fail %s: expected function to raise %s, but it returned instead." msg + (Printexc.to_string exn)) + (function + | e when e = exn -> Lwt.return_unit + | e -> + Alcotest.failf + "Fail %s: expected function to raise %s, but it raised %s instead." + msg (Printexc.to_string exn) (Printexc.to_string e)) + +module T = Irmin.Type + +module type Sleep = sig + val sleep : float -> unit Lwt.t +end diff --git a/vendors/irmin/src/irmin-test/dune b/vendors/irmin/src/irmin-test/dune new file mode 100644 index 000000000000..7fbcdc1c4584 --- /dev/null +++ b/vendors/irmin/src/irmin-test/dune @@ -0,0 +1,40 @@ +(library + (name irmin_test) + (public_name irmin-test) + (modules Irmin_test Node Store Store_graph Store_watch Common Import) + (preprocess + (pps ppx_irmin.internal)) + (libraries + alcotest-lwt + astring + fmt + irmin + jsonm + logs.fmt + lwt + mtime + mtime.clock.os) + (instrumentation + (backend bisect_ppx))) + +(library + (foreign_stubs + (language c) + (names rusage_stubs)) + (name irmin_bench) + (public_name irmin-test.bench) + (modules Irmin_bench Rusage) + (libraries + fmt.tty + fmt.cli + cmdliner + irmin + logs.fmt + logs.cli + lwt + lwt.unix + metrics + metrics-unix + irmin-test) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-test/helpers.ml b/vendors/irmin/src/irmin-test/helpers.ml new file mode 100644 index 000000000000..c2593ec7a605 --- /dev/null +++ b/vendors/irmin/src/irmin-test/helpers.ml @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let init_logs () = + Logs.set_level (Some Debug); + Logs.set_reporter (Common.reporter ()) diff --git a/vendors/irmin/src/irmin-test/import.ml b/vendors/irmin/src/irmin-test/import.ml new file mode 100644 index 000000000000..71053e21ba54 --- /dev/null +++ b/vendors/irmin/src/irmin-test/import.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin-test/irmin_bench.ml b/vendors/irmin/src/irmin-test/irmin_bench.ml new file mode 100644 index 000000000000..6b3872882cc8 --- /dev/null +++ b/vendors/irmin/src/irmin-test/irmin_bench.ml @@ -0,0 +1,190 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2019 Etienne Millon + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends + +type t = { + root : string; + ncommits : int; + depth : int; + tree_add : int; + display : int; + clear : bool; + gc : int; +} + +type stats = { commits : int; size : int; maxrss : int } + +let src = + let open Metrics in + let tags = Tags.[] in + let data t = + Data.v + [ + int "commits" t.commits; + int "size" ~unit:"MiB" t.size; + int "maxrss" ~unit:"MiB" t.maxrss; + ] + in + Src.v "bench" ~tags ~data + +(* cli *) + +open Cmdliner + +let deprecated_info = (Term.info [@alert "-deprecated"]) +let deprecated_exit = (Term.exit [@alert "-deprecated"]) +let deprecated_eval = (Term.eval [@alert "-deprecated"]) + +let log style_renderer level = + Fmt_tty.setup_std_outputs ?style_renderer (); + Logs.set_level level; + Logs.set_reporter (Irmin_test.reporter ()); + () + +let log = Term.(const log $ Fmt_cli.style_renderer () $ Logs_cli.level ()) + +let ncommits = + let doc = Arg.info ~doc:"Number of iterations." [ "n"; "ncommits" ] in + Arg.(value @@ opt int 1000 doc) + +let depth = + let doc = Arg.info ~doc:"Depth of the tree." [ "d"; "depth" ] in + Arg.(value @@ opt int 30 doc) + +let tree_add = + let doc = + Arg.info ~doc:"Number of tree entries added per commit" [ "a"; "tree-add" ] + in + Arg.(value @@ opt int 1000 doc) + +let display = + let doc = + Arg.info ~doc:"Number of commits after which the stats are displayed." + [ "s"; "stats" ] + in + Arg.(value @@ opt int 10 doc) + +let gc = + let doc = + Arg.info ~doc:"Number of commits after which Gc.full_major is called." + [ "gc" ] + in + Arg.(value @@ opt int 100 doc) + +let clear = + let doc = Arg.info ~doc:"Clear the tree after each commit." [ "clear" ] in + Arg.(value @@ flag doc) + +let t = + Term.( + const (fun () ncommits depth tree_add display clear gc -> + { ncommits; depth; tree_add; display; root = "."; clear; gc }) + $ log + $ ncommits + $ depth + $ tree_add + $ display + $ clear + $ gc) + +module Make (Store : Irmin.Generic_key.KV with type Schema.Contents.t = string) = +struct + let info () = Store.Info.v ~author:"author" ~message:"commit message" 0L + + let times ~n ~init f = + let rec go i k = + if i = 0 then k init else go (i - 1) (fun r -> f i r >>= k) + in + go n Lwt.return + + let path ~depth n = + let rec aux acc = function + | i when i = depth -> List.rev (string_of_int n :: acc) + | i -> aux (string_of_int i :: acc) (i + 1) + in + aux [] 0 + + let get_maxrss () = + let usage = Rusage.get SELF in + let ( / ) = Int64.div in + Int64.to_int (usage.maxrss / 1024L / 1024L) + + let no_tags x = x + + let print_stats ~commits ~size = + let maxrss = get_maxrss () in + let size = size () in + Metrics.add src no_tags (fun f -> f { size; commits; maxrss }) + + let plot_progress n t = Fmt.epr "\rcommits: %4d/%d%!" n t + + (* init: create a tree with [t.depth] levels and each levels has + [t.tree_add] files + one directory going to the next levele. *) + let init t config = + let tree = Store.Tree.empty () in + let* v = Store.Repo.v config >>= Store.main in + let* tree = + times ~n:t.depth ~init:tree (fun depth tree -> + let paths = Array.init (t.tree_add + 1) (path ~depth) in + times ~n:t.tree_add ~init:tree (fun n tree -> + Store.Tree.add tree paths.(n) "init")) + in + Store.set_tree_exn v ~info [] tree >|= fun () -> Fmt.epr "[init done]\n%!" + + let run t config size = + let* r = Store.Repo.v config in + let* v = Store.main r in + Store.Tree.reset_counters (); + let paths = Array.init (t.tree_add + 1) (path ~depth:t.depth) in + let* () = + times ~n:t.ncommits ~init:() (fun i () -> + let* tree = Store.get_tree v [] in + if i mod t.gc = 0 then Gc.full_major (); + if i mod t.display = 0 then ( + plot_progress i t.ncommits; + print_stats ~size ~commits:i); + let* tree = + times ~n:t.tree_add ~init:tree (fun n tree -> + Store.Tree.add tree paths.(n) (string_of_int i)) + in + Store.set_tree_exn v ~info [] tree >|= fun () -> + if t.clear then Store.Tree.clear tree) + in + Store.Repo.close r >|= fun () -> Fmt.epr "\n[run done]\n%!" + + let main t config size = + let root = "_build/_bench" in + let config = config ~root in + let size () = size ~root in + let t = { t with root } in + Lwt_main.run (init t config >>= fun () -> run t config size) + + let main_term config size = Term.(const main $ t $ const config $ const size) + + let () = + at_exit (fun () -> + Fmt.epr "tree counters:\n%a\n%!" Store.Tree.dump_counters ()) + + let run ~config ~size = + let info = deprecated_info "Simple benchmark for trees" in + deprecated_exit @@ deprecated_eval (main_term config size, info) +end + +let () = + Metrics.enable_all (); + Metrics_gnuplot.set_reporter () diff --git a/vendors/irmin/src/irmin-test/irmin_bench.mli b/vendors/irmin/src/irmin-test/irmin_bench.mli new file mode 100644 index 000000000000..ab6fd6441092 --- /dev/null +++ b/vendors/irmin/src/irmin-test/irmin_bench.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2019 Etienne Millon + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (S : Irmin.Generic_key.KV with type Schema.Contents.t = string) : sig + val run : + config:(root:string -> Irmin.config) -> size:(root:string -> int) -> unit +end diff --git a/vendors/irmin/src/irmin-test/irmin_test.ml b/vendors/irmin/src/irmin-test/irmin_test.ml new file mode 100644 index 000000000000..cac12cf3c4db --- /dev/null +++ b/vendors/irmin/src/irmin-test/irmin_test.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Common +module Store = Store +module Common = Common +module Node = Node diff --git a/vendors/irmin/src/irmin-test/irmin_test.mli b/vendors/irmin/src/irmin-test/irmin_test.mli new file mode 100644 index 000000000000..52fa646d486b --- /dev/null +++ b/vendors/irmin/src/irmin-test/irmin_test.mli @@ -0,0 +1,74 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = Common.S +module type Generic_key = Common.Generic_key + +val reporter : ?prefix:string -> unit -> Logs.reporter + +module Suite : sig + type t + + val create : + name:string -> + ?init:(config:Irmin.config -> unit Lwt.t) -> + ?clean:(config:Irmin.config -> unit Lwt.t) -> + config:Irmin.config -> + store:(module S) -> + ?stats:(unit -> int * int) -> + ?import_supported:bool -> + unit -> + t + + val create_generic_key : + name:string -> + ?init:(config:Irmin.config -> unit Lwt.t) -> + ?clean:(config:Irmin.config -> unit Lwt.t) -> + config:Irmin.config -> + store:(module Generic_key) -> + ?stats:(unit -> int * int) -> + ?import_supported:bool -> + unit -> + t + + val name : t -> string + val config : t -> Irmin.config + val store : t -> (module S) option + val init : t -> config:Irmin.config -> unit Lwt.t + val clean : t -> config:Irmin.config -> unit Lwt.t +end + +val line : string -> unit + +module Schema = Common.Schema + +val store : (module Irmin.Maker) -> (module Irmin.Metadata.S) -> (module S) +val testable : 'a Irmin.Type.t -> 'a Alcotest.testable +val check : 'a Irmin.Type.t -> string -> 'a -> 'a -> unit +val checks : 'a Irmin.Type.t -> string -> 'a list -> 'a list -> unit + +module Store : sig + val run : + string -> + ?slow:bool -> + ?random_seed:int -> + sleep:(float -> unit Lwt.t) -> + misc:unit Alcotest_lwt.test list -> + (Alcotest.speed_level * Suite.t) list -> + unit Lwt.t +end + +module Node = Node diff --git a/vendors/irmin/src/irmin-test/node.ml b/vendors/irmin/src/irmin-test/node.ml new file mode 100644 index 000000000000..545f01f089bd --- /dev/null +++ b/vendors/irmin/src/irmin-test/node.ml @@ -0,0 +1,150 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let check pos typ ~expected actual = + let typ = + Alcotest.testable Irmin.Type.(pp_dump typ) Irmin.Type.(unstage (equal typ)) + in + Alcotest.(check ~pos typ) "" expected actual + +module type Map = sig + type t [@@deriving irmin] + type data [@@deriving irmin] + type key := string + + val empty : unit -> t + val is_empty : t -> bool + val length : t -> int + val list : ?offset:int -> ?length:int -> ?cache:bool -> t -> (key * data) list + val find : ?cache:bool -> t -> key -> data option + val add : t -> key -> data -> t + val remove : t -> key -> t + + (* Generators for use by the tests: *) + val random_data : unit -> data +end + +module Suite (Map : Map) = struct + type key = string [@@deriving irmin] + + let random_bindings n = + List.init n (fun i -> (string_of_int i, Map.random_data ())) + + let map_of_bindings kvs = + List.fold_left (fun t (k, v) -> Map.add t k v) (Map.empty ()) kvs + + let test_empty () = + check __POS__ [%typ: bool] ~expected:true Map.(is_empty (empty ())); + check __POS__ [%typ: int] ~expected:0 Map.(length (empty ())); + check __POS__ [%typ: (key * Map.data) list] ~expected:[] + Map.(list (empty ())) + + let test_add () = + let with_binding k v t = Map.add t k v in + let d1 = Map.random_data () and d2 = Map.random_data () in + let a = Map.empty () |> with_binding "1" d1 |> with_binding "2" d2 in + check __POS__ [%typ: int] ~expected:2 (Map.length a) + + let test_remove () = + (* Remove is a no-op on an empty node *) + check __POS__ [%typ: Map.t] ~expected:(Map.empty ()) + Map.(remove (empty ()) "foo") + + let test_find () = + let bindings = random_bindings 256 in + let node = map_of_bindings bindings in + bindings + |> List.iter (fun (k, v) -> + check __POS__ [%typ: Map.data option] ~expected:(Some v) + (Map.find node k)) + + let test_equal () = + let module Map = struct + include Map + + type nonrec t = t [@@deriving irmin ~equal ~to_bin_string ~of_bin_string] + end in + let bindings = random_bindings 256 in + let m = map_of_bindings bindings in + + let m_rev = map_of_bindings (List.rev bindings) in + check __POS__ [%typ: bool] ~expected:true (Map.equal m m_rev); + + let m_subset = map_of_bindings (List.tl bindings) in + check __POS__ [%typ: bool] ~expected:false (Map.equal m m_subset); + + let m_serialised = + m |> Map.to_bin_string |> Map.of_bin_string |> Result.get_ok + in + check __POS__ [%typ: bool] ~expected:true (Map.equal m m_serialised) + + let suite = + [ + ("empty", test_empty); + ("add", test_add); + ("remove", test_remove); + ("find", test_find); + ("equal", test_equal); + ] +end + +module Make (Make_node : Irmin.Node.Generic_key.Maker) : sig + val suite : unit Alcotest.test_case list +end = struct + (* For each [Node] maker, we can instantiate the test suite above twice: once + for regular nodes, and once for portable nodes. *) + + module Schema = Irmin.Schema.KV (Irmin.Contents.String) + module Hash = Schema.Hash + module Key = Irmin.Key.Of_hash (Hash) + module Node = Make_node (Hash) (Schema.Path) (Schema.Metadata) (Key) (Key) + + type key = Key.t [@@deriving irmin] + + module Extras = struct + type data = [ `Node of Key.t | `Contents of Key.t * unit ] + [@@deriving irmin] + + let random_data = + let hash_of_string = Irmin.Type.(unstage (of_bin_string Hash.t)) in + let random_string = + Irmin.Type.(unstage (random (string_of (`Fixed Hash.hash_size)))) + in + fun () -> + match hash_of_string (random_string ()) with + | Error _ -> assert false + | Ok x -> ( + match Random.int 2 with + | 0 -> `Node x + | 1 -> `Contents (x, ()) + | _ -> assert false) + end + + let suite = + let tc (name, f) = Alcotest.test_case name `Quick f in + let module Suite_node = Suite (struct + include Node + include Extras + end) in + let module Suite_node_portable = Suite (struct + include Node.Portable + include Extras + end) in + List.map tc Suite_node.suite + @ List.map + (fun (name, f) -> tc ("Portable." ^ name, f)) + Suite_node_portable.suite +end diff --git a/vendors/irmin/src/irmin-test/rusage.ml b/vendors/irmin/src/irmin-test/rusage.ml new file mode 100644 index 000000000000..98ac843ba087 --- /dev/null +++ b/vendors/irmin/src/irmin-test/rusage.ml @@ -0,0 +1,38 @@ +(* + * Copyright (c) 2019-2022 Zach Shipko + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type t = { + utime : float; + stime : float; + maxrss : int64; + ixrss : int64; + idrss : int64; + isrss : int64; + minflt : int64; + majflt : int64; + nswap : int64; + inblock : int64; + oublock : int64; + msgsnd : int64; + msgrcv : int64; + nsignals : int64; + nvcsw : int64; + nivcsw : int64; +} + +type who = SELF | CHILDREN + +external get : who -> t = "unix_getrusage" diff --git a/vendors/irmin/src/irmin-test/rusage_stubs.c b/vendors/irmin/src/irmin-test/rusage_stubs.c new file mode 100644 index 000000000000..98399707271d --- /dev/null +++ b/vendors/irmin/src/irmin-test/rusage_stubs.c @@ -0,0 +1,57 @@ +/* Copyright (c) 2019 Zach Shipko + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include + +#include +#include + +#define Nothing Val_int(0) + +CAMLprim value unix_getrusage(value v_who) { + CAMLparam1(v_who); + CAMLlocal1(v_usage); + int who = (Int_val(v_who) == 0) ? RUSAGE_SELF : RUSAGE_CHILDREN; + struct rusage ru; + if (getrusage(who, &ru)) { + caml_invalid_argument("getrusage"); + } + v_usage = caml_alloc(16, 0); + Store_field(v_usage, 0, + caml_copy_double((double)ru.ru_utime.tv_sec + + (double)ru.ru_utime.tv_usec / 1e6)); + Store_field(v_usage, 1, + caml_copy_double((double)ru.ru_stime.tv_sec + + (double)ru.ru_stime.tv_usec / 1e6)); + Store_field(v_usage, 2, caml_copy_int64(ru.ru_maxrss)); + Store_field(v_usage, 3, caml_copy_int64(ru.ru_ixrss)); + Store_field(v_usage, 4, caml_copy_int64(ru.ru_idrss)); + Store_field(v_usage, 5, caml_copy_int64(ru.ru_isrss)); + Store_field(v_usage, 6, caml_copy_int64(ru.ru_minflt)); + Store_field(v_usage, 7, caml_copy_int64(ru.ru_majflt)); + Store_field(v_usage, 8, caml_copy_int64(ru.ru_nswap)); + Store_field(v_usage, 9, caml_copy_int64(ru.ru_inblock)); + Store_field(v_usage, 10, caml_copy_int64(ru.ru_oublock)); + Store_field(v_usage, 11, caml_copy_int64(ru.ru_msgsnd)); + Store_field(v_usage, 12, caml_copy_int64(ru.ru_msgrcv)); + Store_field(v_usage, 13, caml_copy_int64(ru.ru_nsignals)); + Store_field(v_usage, 14, caml_copy_int64(ru.ru_nvcsw)); + Store_field(v_usage, 15, caml_copy_int64(ru.ru_nivcsw)); + CAMLreturn(v_usage); +} diff --git a/vendors/irmin/src/irmin-test/store.ml b/vendors/irmin/src/irmin-test/store.ml new file mode 100644 index 000000000000..f0b644a6af74 --- /dev/null +++ b/vendors/irmin/src/irmin-test/store.ml @@ -0,0 +1,2549 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let src = Logs.Src.create "test" ~doc:"Irmin tests" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Make (S : Generic_key) = struct + include Common.Make_helpers (S) + module History = Irmin.Commit.History (B.Commit) + + let with_binding k v t = S.Tree.add t k v + let random_value value = random_string value + + let random_path ~label ~path = + let short () = random_ascii_string label in + let rec aux = function 0 -> [] | n -> short () :: aux (n - 1) in + aux path + + let random_node ~label ~path ~value = + (random_path ~label ~path, random_value value) + + let random_nodes ?(label = 8) ?(path = 5) ?(value = 1024) n = + let rec aux acc = function + | 0 -> acc + | n -> aux (random_node ~label ~path ~value :: acc) (n - 1) + in + aux [] n + + let old k () = Lwt.return_ok (Some k) + + let may repo commits = function + | None -> Lwt.return_unit + | Some f -> f repo commits + + let may_get_keys repo keys = function + | None -> Lwt.return_unit + | Some f -> + let* commits = + Lwt_list.map_p + (fun key -> + S.Commit.of_key repo key >|= function + | None -> Alcotest.fail "Cannot read commit hash" + | Some c -> c) + keys + in + f repo commits + + let may_with_branch branches repo hook = + let* heads = + Lwt_list.map_p + (fun branch -> + let+ h = S.Head.find branch in + match h with + | None -> Alcotest.fail "Cannot read head" + | Some head -> head) + branches + in + may repo heads hook + + let contents c = S.Tree.v (`Contents (c, S.Metadata.default)) + + let test_contents x () = + let test repo = + let t = B.Repo.contents_t repo in + let check_key = check B.Contents.Key.t in + let check_val = check (T.option S.contents_t) in + let* kv2 = kv2 ~repo in + let* k2' = with_contents repo (fun t -> B.Contents.add t v2) in + check_key "kv2" kv2 k2'; + let* v2' = B.Contents.find t k2' in + check_val "v2" (Some v2) v2'; + let* k2'' = with_contents repo (fun t -> B.Contents.add t v2) in + check_key "kv2" kv2 k2''; + let* kv1 = kv1 ~repo in + let* k1' = with_contents repo (fun t -> B.Contents.add t v1) in + check_key "kv1" kv1 k1'; + let* k1'' = with_contents repo (fun t -> B.Contents.add t v1) in + check_key "kv1" kv1 k1''; + let* v1' = B.Contents.find t kv1 in + check_val "v1" (Some v1) v1'; + let* v2' = B.Contents.find t kv2 in + check_val "v2" (Some v2) v2'; + B.Repo.close repo >>= fun () -> + Lwt.catch + (fun () -> + let+ _ = with_contents repo (fun t -> B.Contents.add t v2) in + Alcotest.fail "Add after close should not be allowed") + (function Irmin.Closed -> Lwt.return_unit | exn -> Lwt.fail exn) + in + run x test + + let get = function None -> Alcotest.fail "get" | Some v -> v + + let test_nodes x () = + let test repo = + let g = g repo and n = n repo in + let* k = + with_contents repo (fun c -> B.Contents.add c "foo") >|= normal + in + let check_hash = check B.Hash.t in + let check_key = check B.Node.Key.t in + let check_val = check [%typ: Graph.value option] in + let check_list = checks [%typ: S.step * B.Node.Val.value] in + let check_node msg v = + let h' = B.Node.Hash.hash v in + let+ key = with_node repo (fun n -> B.Node.add n v) in + check_hash (msg ^ ": hash(v) = add(v)") (B.Node.Key.to_hash key) h' + in + let v = B.Node.Val.empty () in + check_node "empty node" v >>= fun () -> + let v1 = B.Node.Val.add v "x" k in + check_node "node: x" v1 >>= fun () -> + let v2 = B.Node.Val.add v "x" k in + check_node "node: x (bis)" v2 >>= fun () -> + check B.Node.Val.t "add x" v1 v2; + let v0 = B.Node.Val.remove v1 "x" in + check B.Node.Val.t "remove x" v v0; + let v3 = B.Node.Val.add v1 "x" k in + Alcotest.(check bool) "same same" true (v1 == v3); + let u = B.Node.Val.add v3 "y" k in + check_node "node: x+y" v3 >>= fun () -> + let u = B.Node.Val.add u "z" k in + check_node "node: x+y+z" u >>= fun () -> + let check_values u = + check_val "find x" (Some k) (B.Node.Val.find u "x"); + check_val "find y" (Some k) (B.Node.Val.find u "y"); + check_val "find z" (Some k) (B.Node.Val.find u "x"); + check_val "find xx" None (B.Node.Val.find u "xx") + in + check_values u; + let () = + let _w = B.Node.Val.of_list [ ("y", k); ("z", k); ("x", k) ] in + (* XXX: this isn't a valid check. [u] is not concrete, and [w] is. *) + (* check B.Node.Val.t "v" u w; *) + () + in + let all = B.Node.Val.list u in + check_list "list all" [ ("x", k); ("y", k); ("z", k) ] all; + let l = B.Node.Val.list ~length:1 u in + check_list "list length=1" [ ("x", k) ] l; + let l = B.Node.Val.list ~offset:1 u in + check_list "list offset=1" [ ("y", k); ("z", k) ] l; + let l = B.Node.Val.list ~offset:1 ~length:1 u in + check_list "list offset=1 length=1" [ List.nth all 1 ] l; + let u = B.Node.Val.add u "a" k in + check_node "node: x+y+z+a" u >>= fun () -> + let u = B.Node.Val.add u "b" k in + check_node "node: x+y+z+a+b" u >>= fun () -> + let h = B.Node.Hash.hash u in + let* k = with_node repo (fun n -> B.Node.add n u) in + check_hash "hash(v) = add(v)" h (B.Node.Key.to_hash k); + let* w = B.Node.find n k in + check_values (get w); + let* kv1 = kv1 ~repo in + let* k1 = with_node repo (fun g -> Graph.v g [ ("x", normal kv1) ]) in + let* k1' = with_node repo (fun g -> Graph.v g [ ("x", normal kv1) ]) in + check_key "k1.1" k1 k1'; + let* t1 = B.Node.find n k1 in + let k' = B.Node.Val.find (get t1) "x" in + check + (Irmin.Type.option B.Node.Val.value_t) + "find x" + (Some (normal kv1)) + k'; + let* k1'' = with_node repo (fun n -> B.Node.add n (get t1)) in + check_key "k1.2" k1 k1''; + let* k2 = with_node repo (fun g -> Graph.v g [ ("b", `Node k1) ]) in + let* k2' = with_node repo (fun g -> Graph.v g [ ("b", `Node k1) ]) in + check_key "k2.1" k2 k2'; + let* t2 = B.Node.find n k2 in + let* k2'' = with_node repo (fun n -> B.Node.add n (get t2)) in + check_key "k2.2" k2 k2''; + let* k1''' = Graph.find g k2 [ "b" ] in + check_val "k1.3" (Some (`Node k1)) k1'''; + let* k3 = with_node repo (fun g -> Graph.v g [ ("a", `Node k2) ]) in + let* k3' = with_node repo (fun g -> Graph.v g [ ("a", `Node k2) ]) in + check_key "k3.1" k3 k3'; + let* t3 = B.Node.find n k3 in + let* k3'' = with_node repo (fun n -> B.Node.add n (get t3)) in + check_key "k3.2" k3 k3''; + let* k2'' = Graph.find g k3 [ "a" ] in + check_val "k2.3" (Some (`Node k2)) k2''; + let* k1'''' = Graph.find g k2' [ "b" ] in + check_val "t1.2" (Some (`Node k1)) k1''''; + let* k1''''' = Graph.find g k3 [ "a"; "b" ] in + check_val "t1.3" (Some (`Node k1)) k1'''''; + let* kv11 = Graph.find g k1 [ "x" ] in + check_val "v1.1" (Some (normal kv1)) kv11; + let* kv12 = Graph.find g k2 [ "b"; "x" ] in + check_val "v1.2" (Some (normal kv1)) kv12; + let* kv13 = Graph.find g k3 [ "a"; "b"; "x" ] in + check_val "v1" (Some (normal kv1)) kv13; + let* kv2 = kv2 ~repo in + let* k4 = with_node repo (fun g -> Graph.v g [ ("x", normal kv2) ]) in + let* k5 = + with_node repo (fun g -> Graph.v g [ ("b", `Node k1); ("c", `Node k4) ]) + in + let* k6 = with_node repo (fun g -> Graph.v g [ ("a", `Node k5) ]) in + let* k6' = + with_node repo (fun g -> Graph.add g k3 [ "a"; "c"; "x" ] (normal kv2)) + in + check_key "node k6" k6 k6'; + let* n6' = B.Node.find n k6' in + let* n6 = B.Node.find n k6 in + check T.(option B.Node.Val.t) "node n6" n6 n6'; + let assert_no_duplicates n node = + let names = ref [] in + let+ all = Graph.list g node in + List.iter + (fun (s, _) -> + if List.mem ~equal:String.equal s !names then + Alcotest.failf "%s: duplicate!" n + else names := s :: !names) + all + in + let* n0 = with_node repo (fun g -> Graph.v g []) in + let* n1 = with_node repo (fun g -> Graph.add g n0 [ "b" ] (`Node n0)) in + let* n2 = with_node repo (fun g -> Graph.add g n1 [ "a" ] (`Node n0)) in + let* n3 = with_node repo (fun g -> Graph.add g n2 [ "a" ] (`Node n0)) in + assert_no_duplicates "1" n3 >>= fun () -> + let* n1 = with_node repo (fun g -> Graph.add g n0 [ "a" ] (`Node n0)) in + let* n2 = with_node repo (fun g -> Graph.add g n1 [ "b" ] (`Node n0)) in + let* n3 = with_node repo (fun g -> Graph.add g n2 [ "a" ] (`Node n0)) in + assert_no_duplicates "2" n3 >>= fun () -> + let* n1 = with_node repo (fun g -> Graph.add g n0 [ "b" ] (normal kv1)) in + let* n2 = with_node repo (fun g -> Graph.add g n1 [ "a" ] (normal kv1)) in + let* n3 = with_node repo (fun g -> Graph.add g n2 [ "a" ] (normal kv1)) in + assert_no_duplicates "3" n3 >>= fun () -> + let* n1 = with_node repo (fun g -> Graph.add g n0 [ "a" ] (normal kv1)) in + let* n2 = with_node repo (fun g -> Graph.add g n1 [ "b" ] (normal kv1)) in + let* n3 = with_node repo (fun g -> Graph.add g n2 [ "b" ] (normal kv1)) in + assert_no_duplicates "4" n3 >>= fun () -> + S.Repo.close repo >>= fun () -> + Lwt.catch + (fun () -> + let* n0 = with_node repo (fun g -> Graph.v g []) in + let* _ = + with_node repo (fun g -> Graph.add g n0 [ "b" ] (`Node n0)) + in + Alcotest.fail "Add after close should not be allowed") + (function Irmin.Closed -> Lwt.return_unit | exn -> Lwt.fail exn) + in + run x test + + let test_commits x () = + let test repo = + let info date = + let message = Fmt.str "Test commit: %d" date in + S.Info.v ~author:"test" ~message (Int64.of_int date) + in + let* kv1 = kv1 ~repo in + let h = h repo and c = B.Repo.commit_t repo in + let check_val = check (T.option B.Commit.Val.t) in + let check_key = check B.Commit.Key.t in + let check_keys = checks B.Commit.Key.t in + (* t3 -a-> t2 -b-> t1 -x-> (v1) *) + let* kt1 = with_node repo (fun g -> Graph.v g [ ("x", normal kv1) ]) in + let* kt2 = with_node repo (fun g -> Graph.v g [ ("a", `Node kt1) ]) in + let* kt3 = with_node repo (fun g -> Graph.v g [ ("b", `Node kt2) ]) in + (* r1 : t2 *) + let with_info n fn = with_commit repo (fun h -> fn h ~info:(info n)) in + let* kr1, _ = with_info 3 (History.v ~node:kt2 ~parents:[]) in + let* kr1', _ = with_info 3 (History.v ~node:kt2 ~parents:[]) in + let* t1 = B.Commit.find c kr1 in + let* t1' = B.Commit.find c kr1' in + check_val "t1" t1 t1'; + check_key "kr1" kr1 kr1'; + + (* r1 -> r2 : t3 *) + let* kr2, _ = with_info 4 (History.v ~node:kt3 ~parents:[ kr1 ]) in + let* kr2', _ = with_info 4 (History.v ~node:kt3 ~parents:[ kr1 ]) in + check_key "kr2" kr2 kr2'; + let* kr1s = History.closure h ~min:[] ~max:[ kr1 ] in + check_keys "g1" [ kr1 ] kr1s; + let* kr2s = History.closure h ~min:[] ~max:[ kr2 ] in + check_keys "g2" [ kr1; kr2 ] kr2s; + let* () = + S.Commit.of_key repo kr1 >|= function + | None -> Alcotest.fail "Cannot read commit hash" + | Some c -> + Alcotest.(check string) + "author" "test" + (S.Info.author (S.Commit.info c)) + in + S.Repo.close repo >>= fun () -> + Lwt.catch + (fun () -> + let+ _ = with_info 3 (History.v ~node:kt1 ~parents:[]) in + Alcotest.fail "Add after close should not be allowed") + (function Irmin.Closed -> Lwt.return_unit | exn -> Lwt.fail exn) + in + run x test + + let test_closure x () = + let test repo = + let info date = + let message = Fmt.str "Test commit: %d" date in + S.Info.v ~author:"test" ~message (Int64.of_int date) + in + let check_keys = checks B.Commit.Key.t in + let equal_key = Irmin.Type.(unstage (equal B.Commit.Key.t)) in + let h = h repo in + let initialise_nodes = + Lwt_list.map_p + (fun i -> + let* kv = + with_contents repo (fun t -> B.Contents.add t (string_of_int i)) + in + with_node repo (fun g -> Graph.v g [ (string_of_int i, normal kv) ])) + [ 0; 1; 2; 3; 4; 5; 6; 7; 8 ] + in + let with_info n fn = with_commit repo (fun h -> fn h ~info:(info n)) in + let initialise_graph nodes = + match nodes with + | [] -> assert false + | node :: rest -> + let* kr0, _ = with_info 0 (History.v ~node ~parents:[]) in + let commits = Array.make 9 kr0 in + let commit ~node ~parents i = + let+ kr1, _ = with_info i (History.v ~node ~parents) in + commits.(i) <- kr1; + i + 1 + in + let+ _ = + Lwt_list.fold_left_s + (fun i node -> + match i with + | 1 -> commit ~node ~parents:[ commits.(0) ] 1 + | 2 -> commit ~node ~parents:[] 2 + | 3 -> commit ~node ~parents:[ commits.(1) ] 3 + | 4 -> commit ~node ~parents:[ commits.(1); commits.(2) ] 4 + | 5 -> commit ~node ~parents:[ commits.(3); commits.(4) ] 5 + | 6 -> commit ~node ~parents:[ commits.(4) ] 6 + | 7 -> commit ~node ~parents:[] 7 + | 8 -> commit ~node ~parents:[ commits.(7) ] 8 + | _ -> assert false) + 1 rest + in + commits + in + (* initialise_graph creates the following graph of commits: + 0 <- 1 <- 3 <- 5 and 7 <- 8 + \ / + 2 <-- 4 <- 6 *) + let* commits = initialise_nodes >>= initialise_graph in + let* krs = History.closure h ~min:[ commits.(1) ] ~max:[ commits.(5) ] in + check_keys "commits between 1 and 5" + [ commits.(1); commits.(2); commits.(3); commits.(4); commits.(5) ] + krs; + let* krs = History.closure h ~min:[] ~max:[ commits.(5) ] in + check_keys "all commits under 5" + [ + commits.(0); + commits.(1); + commits.(2); + commits.(3); + commits.(4); + commits.(5); + ] + krs; + let* krs = + History.closure h + ~min:[ commits.(1); commits.(2) ] + ~max:[ commits.(5); commits.(6) ] + in + check_keys "disconnected max and min returns a connected graph" + [ + commits.(1); + commits.(2); + commits.(3); + commits.(4); + commits.(5); + commits.(6); + ] + krs; + let* krs = + History.closure h + ~min:[ commits.(1); commits.(7) ] + ~max:[ commits.(4); commits.(8) ] + in + check_keys "disconnected min and max returns a disconnected graph" + [ commits.(1); commits.(2); commits.(7); commits.(4); commits.(8) ] + krs; + let* () = + History.closure h ~min:[ commits.(7) ] ~max:[] >|= function + | [] -> () + | _ -> Alcotest.fail "expected empty list" + in + let* () = + let+ ls = History.closure h ~min:[ commits.(7) ] ~max:[ commits.(6) ] in + if List.mem ~equal:equal_key commits.(7) ls then + Alcotest.fail "disconnected node should not be in closure" + in + let* krs = + History.closure h ~min:[ commits.(4) ] ~max:[ commits.(4); commits.(6) ] + in + check_keys "min and max have the same commit" + [ commits.(6); commits.(4) ] + krs; + let* () = + let+ ls = + History.closure h + ~min:[ commits.(4); commits.(0) ] + ~max:[ commits.(4); commits.(6) ] + in + if List.mem ~equal:equal_key commits.(0) ls then + Alcotest.fail "disconnected node should not be in closure" + in + S.Repo.close repo + in + run x test + + let test_branches ?hook x () = + let test repo = + let check_keys = checks S.Branch.t in + let check_val = check (T.option @@ S.commit_t repo) in + let* kv1 = r1 ~repo in + let* kv2 = r2 ~repo in + line "pre-update"; + S.Branch.set repo b1 kv1 >>= fun () -> + may repo [ kv2 ] hook >>= fun () -> + line "post-update"; + let* k1' = S.Branch.find repo b1 in + check_val "r1" (Some kv1) k1'; + S.Branch.set repo b2 kv2 >>= fun () -> + let* k2' = S.Branch.find repo b2 in + check_val "r2" (Some kv2) k2'; + S.Branch.set repo b1 kv2 >>= fun () -> + let* k2'' = S.Branch.find repo b1 in + check_val "r1-after-update" (Some kv2) k2''; + let* bs = S.Branch.list repo in + check_keys "list" [ b1; b2 ] bs; + S.Branch.remove repo b1 >>= fun () -> + let* empty = S.Branch.find repo b1 in + check_val "empty" None empty; + let* b2' = S.Branch.list repo in + check_keys "all-after-remove" [ b2 ] b2'; + S.Repo.close repo >>= fun () -> + Lwt.catch + (fun () -> + let+ _ = S.Branch.set repo b1 kv1 in + Alcotest.fail "Add after close should not be allowed") + (function Irmin.Closed -> Lwt.return_unit | exn -> Lwt.fail exn) + in + run x test + + let test_tree_hashes x () = + let test repo = + let node bindings = + with_node repo (fun g -> + let* empty = Graph.empty g in + Lwt_list.fold_left_s + (fun t (k, v) -> + let* v = with_contents repo (fun t -> B.Contents.add t v) in + Graph.add g t k (`Contents (v, S.Metadata.default))) + empty bindings) + in + let tree bindings = + Lwt_list.fold_left_s + (fun t (k, v) -> S.Tree.add t k v) + (S.Tree.empty ()) bindings + in + let check_hash msg bindings = + let* node = node bindings in + let+ tree = tree bindings in + check B.Hash.t msg (B.Node.Key.to_hash node) (S.Tree.hash tree) + in + check_hash "empty" [] >>= fun () -> + let bindings1 = [ ([ "a" ], "x"); ([ "b" ], "y") ] in + check_hash "1 level" bindings1 >>= fun () -> + let bindings2 = [ ([ "a"; "b" ], "x"); ([ "a"; "c" ], "y") ] in + check_hash "2 levels" bindings2 >>= fun () -> S.Repo.close repo + in + run x test + + let test_simple_merges ?hook x () = + (* simple merges *) + let check_merge () = + let ok = Irmin.Merge.ok in + let dt = [%typ: int64 option] in + let dx = [%typ: (string * int64) list] in + let merge_skip ~old:_ _ _ = ok None in + let merge_left ~old:_ x _ = ok x in + let merge_right ~old:_ _ y = ok y in + let merge_default = Irmin.Merge.default dt in + let merge = function + | "left" -> Irmin.Merge.v dt merge_left + | "right" -> Irmin.Merge.v dt merge_right + | "skip" -> Irmin.Merge.v dt merge_skip + | _ -> merge_default + in + let merge_x = Irmin.Merge.alist T.string T.int64 merge in + let old () = ok (Some [ ("left", 1L); ("foo", 2L) ]) in + let x = [ ("left", 2L); ("right", 0L) ] in + let y = [ ("left", 1L); ("bar", 3L); ("skip", 0L) ] in + let m = [ ("left", 2L); ("bar", 3L) ] in + Irmin.Merge.(f merge_x) ~old x y >>= function + | Error (`Conflict c) -> Alcotest.failf "conflict %s" c + | Ok m' -> + check dx "compound merge" m m'; + Lwt.return_unit + in + let test repo = + check_merge () >>= fun () -> + let* kv1 = kv1 ~repo in + let* kv2 = kv2 ~repo in + let result = + T.(result (option B.Contents.Key.t) Irmin.Merge.conflict_t) + in + (* merge contents *) + let* kv1' = + with_contents repo (fun v -> + Irmin.Merge.f (B.Contents.merge v) ~old:(old (Some kv1)) (Some kv1) + (Some kv1)) + in + check result "merge kv1" (Ok (Some kv1)) kv1'; + let* kv2' = + with_contents repo (fun v -> + Irmin.Merge.f (B.Contents.merge v) ~old:(old (Some kv1)) (Some kv1) + (Some kv2)) + in + check result "merge kv2" (Ok (Some kv2)) kv2'; + + (* merge nodes *) + let g = g repo in + (* The empty node *) + let* k0 = with_node repo (fun g -> Graph.v g []) in + (* Create the node t1 -x-> (v1) *) + let* k1 = with_node repo (fun g -> Graph.v g [ ("x", normal kv1) ]) in + (* Create the node t2 -b-> t1 -x-> (v1) *) + let* k2 = with_node repo (fun g -> Graph.v g [ ("b", `Node k1) ]) in + (* Create the node t3 -c-> t1 -x-> (v1) *) + let* k3 = with_node repo (fun g -> Graph.v g [ ("c", `Node k1) ]) in + (* Should create the node: + t4 -b-> t1 -x-> (v1) + \c/ *) + let* k4 = + with_node repo (fun g -> + Irmin.Merge.(f @@ B.Node.merge g) + ~old:(old (Some k0)) (Some k2) (Some k3)) + in + let* k4 = merge_exn "k4" k4 in + let k4 = match k4 with Some k -> k | None -> failwith "k4" in + let _ = k4 in + let succ_t = [%typ: string * Graph.value] in + let* succ = Graph.list g k4 in + checks succ_t "k4" [ ("b", `Node k1); ("c", `Node k1) ] succ; + let info date = + let i = Int64.of_int date in + S.Info.v ~author:"test" ~message:"Test commit" i + in + let c = B.Repo.commit_t repo in + let with_info n fn = with_commit repo (fun h -> fn h ~info:(info n)) in + let* kr0, _ = with_info 0 (History.v ~node:k0 ~parents:[]) in + let* kr1, _ = with_info 1 (History.v ~node:k2 ~parents:[ kr0 ]) in + let* kr2, _ = with_info 2 (History.v ~node:k3 ~parents:[ kr0 ]) in + may_get_keys repo [ kr1; kr2 ] hook >>= fun () -> + let* kr3 = + with_info 3 (fun h ~info -> + Irmin.Merge.f + (History.merge h ~info:(fun () -> info)) + ~old:(old kr0) kr1 kr2) + in + let* kr3 = merge_exn "kr3" kr3 in + may_get_keys repo [ kr3 ] hook >>= fun () -> + let* kr3_key' = + with_info 4 (fun h ~info -> + Irmin.Merge.f + (History.merge h ~info:(fun () -> info)) + ~old:(old kr2) kr2 kr3) + in + let* kr3_key' = merge_exn "kr3_key'" kr3_key' in + let check_key = check B.Commit.Key.t in + check_key "kr3 id with immediate parent'" kr3 kr3_key'; + let* kr3_key = + with_info 5 (fun h ~info -> + Irmin.Merge.f + (History.merge h ~info:(fun () -> info)) + ~old:(old kr0) kr0 kr3) + in + let* kr3_key = merge_exn "kr3_key" kr3_key in + check_key "kr3 key with old parent" kr3 kr3_key; + let* kr3', _ = with_info 3 @@ History.v ~node:k4 ~parents:[ kr1; kr2 ] in + let* r3 = B.Commit.find c kr3 in + let* r3' = B.Commit.find c kr3' in + check T.(option B.Commit.Val.t) "r3" r3 r3'; + check_key "kr3" kr3 kr3'; + B.Repo.close repo + in + run x test + + let test_history ?hook x () = + let test repo = + let info date = + let i = Int64.of_int date in + S.Info.v ~author:"test" ~message:"Test commit" i + in + let assert_lcas_err msg err l2 = + let err_str = function + | `Too_many_lcas -> "Too_many_lcas" + | `Max_depth_reached -> "Max_depth_reached" + in + let pp_commits = Fmt.Dump.(list S.Commit.pp_hash) in + let l2 = + match l2 with + | Ok x -> Alcotest.failf "%s: %a" msg pp_commits x + | Error e -> err_str e + in + Alcotest.(check string) msg (err_str err) l2 + in + let assert_lcas msg l1 l2 = + let l2 = + match l2 with + | Ok x -> x + | Error `Too_many_lcas -> Alcotest.failf "%s: Too many LCAs" msg + | Error `Max_depth_reached -> + Alcotest.failf "%s: max depth reached" msg + in + checks (S.commit_t repo) msg l1 l2 + in + let assert_lcas msg ~max_depth n a b expected = + let* a = S.of_commit a in + let* b = S.of_commit b in + let* lcas = S.lcas ~max_depth ~n a b in + assert_lcas msg expected lcas; + let* lcas = S.lcas ~max_depth:(max_depth - 1) ~n a b in + let msg = Printf.sprintf "%s [max-depth=%d]" msg (max_depth - 1) in + assert_lcas_err msg `Max_depth_reached lcas; + Lwt.return_unit + in + let assert_last_modified msg ?depth ~n t key expected = + let+ last = S.last_modified ?depth ~n t key in + S.repo t |> fun repo -> + let msg = Printf.sprintf "%s [n=%d]" msg n in + checks (S.commit_t repo) msg expected last + in + let assert_history_empty msg c expected = + let* t = S.of_commit c in + S.history t + >|= S.History.is_empty + >|= Alcotest.(check bool) msg expected + in + let tree = S.Tree.empty () in + let k0 = random_path ~label:8 ~path:5 in + let k1 = random_path ~label:8 ~path:4 in + let k2 = random_path ~label:8 ~path:6 in + + (* test that we don't compute too many lcas + + 0(k0, k1) -> 1(k1) -> 2(k0) -> 3(k1, k0) -> 4(k1) + *) + let* tree = S.Tree.add tree k0 (random_value 1024) in + let* tree = S.Tree.add tree k1 (random_value 1024) in + let* c0 = S.Commit.v repo ~info:(info 0) ~parents:[] tree in + may repo [ c0 ] hook >>= fun () -> + assert_history_empty "nonempty 1 commit" c0 false >>= fun () -> + let* tree = S.Tree.add tree k1 (random_value 1024) in + let* c1 = + S.Commit.v repo ~info:(info 1) ~parents:[ S.Commit.key c0 ] tree + in + assert_history_empty "nonempty 2 commits" c0 false >>= fun () -> + let* tree = S.Tree.add tree k0 (random_value 1024) in + let* c2 = + S.Commit.v repo ~info:(info 2) ~parents:[ S.Commit.key c1 ] tree + in + let* tree = S.Tree.add tree k0 (random_value 1024) in + let* tree = S.Tree.add tree k1 (random_value 1024) in + let* c3 = + S.Commit.v repo ~info:(info 3) ~parents:[ S.Commit.key c2 ] tree + in + may repo [ c3 ] hook >>= fun () -> + let* tree = S.Tree.add tree k1 (random_value 1024) in + let* c4 = + S.Commit.v repo ~info:(info 4) ~parents:[ S.Commit.key c3 ] tree + in + assert_lcas "line lcas 1" ~max_depth:0 3 c3 c4 [ c3 ] >>= fun () -> + assert_lcas "line lcas 2" ~max_depth:1 3 c2 c4 [ c2 ] >>= fun () -> + assert_lcas "line lcas 3" ~max_depth:2 3 c1 c4 [ c1 ] >>= fun () -> + let* store = S.of_commit c4 in + let* () = + assert_last_modified "line last_modified 1" ~n:1 store k0 [ c3 ] + in + let* () = + assert_last_modified "line last_modified 2" ~n:2 store k0 [ c2; c3 ] + in + let* () = + assert_last_modified "line last_modified 3" ~n:3 store k0 [ c0; c2; c3 ] + in + let* () = + assert_last_modified "line last_modified 4" ~depth:1 ~n:3 store k0 + [ c3 ] + in + assert_last_modified "line last_modified 5" ~n:1 store k2 [] >>= fun () -> + let* () = + assert_last_modified "line last_modified 5" ~depth:0 ~n:2 store k0 [] + in + (* test for multiple lca + + 4(k1) -> 10 (k2) ---> 11(k0, k2) --> 13(k1) --> 15(k1, k2) + | \_______________________/____ + | _____________________/ \ + | / \ + \---> 12 (k0, k1) --> 14 (k2) --> 16 (k2) --> 17 (k0) + *) + let* tree = S.Tree.add tree k2 (random_value 1024) in + let* c10 = + S.Commit.v repo ~info:(info 10) ~parents:[ S.Commit.key c4 ] tree + in + let* tree_up = S.Tree.add tree k0 (random_value 1024) in + let* tree_up = S.Tree.add tree_up k2 (random_value 1024) in + let* c11 = + S.Commit.v repo ~info:(info 11) ~parents:[ S.Commit.key c10 ] tree_up + in + let* tree_down = S.Tree.add tree k0 (random_value 1024) in + let* tree_12 = S.Tree.add tree_down k1 (random_value 1024) in + let* c12 = + S.Commit.v repo ~info:(info 12) ~parents:[ S.Commit.key c10 ] tree_12 + in + let* tree_up = S.Tree.add tree_up k1 (random_value 1024) in + let* c13 = + S.Commit.v repo ~info:(info 13) ~parents:[ S.Commit.key c11 ] tree_up + in + let* tree_down = S.Tree.add tree_12 k2 (random_value 1024) in + let* c14 = + S.Commit.v repo ~info:(info 14) ~parents:[ S.Commit.key c12 ] tree_down + in + let* tree_up = S.Tree.add tree_12 k1 (random_value 1024) in + let* tree_up = S.Tree.add tree_up k2 (random_value 1024) in + let* c15 = + S.Commit.v repo ~info:(info 15) + ~parents:[ S.Commit.key c12; S.Commit.key c13 ] + tree_up + in + let* tree_down = S.Tree.add tree_down k2 (random_value 1024) in + let* c16 = + S.Commit.v repo ~info:(info 16) ~parents:[ S.Commit.key c14 ] tree_down + in + let* tree_down = S.Tree.add tree_down k0 (random_value 1024) in + let* c17 = + S.Commit.v repo ~info:(info 17) + ~parents:[ S.Commit.key c11; S.Commit.key c16 ] + tree_down + in + assert_lcas "x lcas 0" ~max_depth:0 5 c10 c10 [ c10 ] >>= fun () -> + assert_lcas "x lcas 1" ~max_depth:0 5 c14 c14 [ c14 ] >>= fun () -> + assert_lcas "x lcas 2" ~max_depth:0 5 c10 c11 [ c10 ] >>= fun () -> + assert_lcas "x lcas 3" ~max_depth:1 5 c12 c16 [ c12 ] >>= fun () -> + assert_lcas "x lcas 4" ~max_depth:1 5 c10 c13 [ c10 ] >>= fun () -> + assert_lcas "x lcas 5" ~max_depth:2 5 c13 c14 [ c10 ] >>= fun () -> + assert_lcas "x lcas 6" ~max_depth:3 5 c15 c16 [ c12 ] >>= fun () -> + assert_lcas "x lcas 7" ~max_depth:3 5 c15 c17 [ c11; c12 ] >>= fun () -> + let* store = S.of_commit c17 in + let* () = + assert_last_modified "x last_modified 1" ~n:3 store k0 [ c11; c12; c17 ] + in + let* () = + assert_last_modified "x last_modified 2" ~n:1 store k2 [ c16 ] + in + let* () = + assert_last_modified "x last_modified 3" ~n:2 store k1 [ c4; c12 ] + in + let* () = + assert_last_modified "x last_modified 4" ~depth:3 ~n:5 store k1 + [ c4; c12 ] + in + let* () = + assert_last_modified "x last_modified 5" ~depth:2 ~n:3 store k0 + [ c11; c17 ] + in + (* lcas on non transitive reduced graphs + + /->16 + | + 4->10->11->12->13->14->15 + | \--|--/ + \-----------/ + *) + let* c10 = + S.Commit.v repo ~info:(info 10) ~parents:[ S.Commit.key c4 ] tree + in + let* c11 = + S.Commit.v repo ~info:(info 11) ~parents:[ S.Commit.key c10 ] tree + in + let* c12 = + S.Commit.v repo ~info:(info 12) ~parents:[ S.Commit.key c11 ] tree + in + let* c13 = + S.Commit.v repo ~info:(info 13) ~parents:[ S.Commit.key c12 ] tree + in + let* c14 = + S.Commit.v repo ~info:(info 14) + ~parents:[ S.Commit.key c11; S.Commit.key c13 ] + tree + in + let* c15 = + S.Commit.v repo ~info:(info 15) + ~parents:[ S.Commit.key c13; S.Commit.key c14 ] + tree + in + let* c16 = + S.Commit.v repo ~info:(info 16) ~parents:[ S.Commit.key c11 ] tree + in + assert_lcas "weird lcas 1" ~max_depth:0 3 c14 c15 [ c14 ] >>= fun () -> + assert_lcas "weird lcas 2" ~max_depth:0 3 c13 c15 [ c13 ] >>= fun () -> + assert_lcas "weird lcas 3" ~max_depth:1 3 c12 c15 [ c12 ] >>= fun () -> + assert_lcas "weird lcas 4" ~max_depth:1 3 c11 c15 [ c11 ] >>= fun () -> + assert_lcas "weird lcas 4" ~max_depth:3 3 c15 c16 [ c11 ] >>= fun () -> + (* fast-forward *) + let ff = testable Irmin.Type.(result unit S.ff_error_t) in + let* t12 = S.of_commit c12 in + let* b1 = S.Head.fast_forward t12 c16 in + Alcotest.(check ff) "ff 1.1" (Error `Rejected) b1; + let* k12' = S.Head.get t12 in + check (S.commit_t repo) "ff 1.2" c12 k12'; + let* b2 = S.Head.fast_forward t12 ~n:1 c14 in + Alcotest.(check ff) "ff 2.1" (Error `Rejected) b2; + let* k12'' = S.Head.get t12 in + check (S.commit_t repo) "ff 2.2" c12 k12''; + let* b3 = S.Head.fast_forward t12 c14 in + Alcotest.(check ff) "ff 2.2" (Ok ()) b3; + let* c14' = S.Head.get t12 in + check (S.commit_t repo) "ff 2.3" c14 c14'; + B.Repo.close repo + in + run x test + + let test_empty ?hook x () = + let test repo = + let* t = S.empty repo in + let* h = S.Head.find t in + check T.(option @@ S.commit_t repo) "empty" None h; + let* r1 = r1 ~repo in + may repo [ r1 ] hook >>= fun () -> + S.set_exn t ~info:S.Info.none [ "b"; "x" ] v1 >>= fun () -> + let* h = S.Head.find t in + check T.(option @@ S.commit_t repo) "not empty" (Some r1) h; + B.Repo.close repo + in + run x test + + let test_slice ?hook x () = + let test repo = + let* t = S.main repo in + let a = "" in + let b = "haha" in + S.set_exn t ~info:(infof "slice") [ "x"; "a" ] a >>= fun () -> + S.set_exn t ~info:(infof "slice") [ "x"; "b" ] b >>= fun () -> + may_with_branch [ t ] repo hook >>= fun () -> + let* slice = S.Repo.export repo in + let str = T.to_json_string B.Slice.t slice in + let slice' = + match T.decode_json B.Slice.t (Jsonm.decoder (`String str)) with + | Ok t -> t + | Error (`Msg e) -> Alcotest.failf "decoding error: %s" e + in + check B.Slice.t "slices" slice slice'; + B.Repo.close repo + in + run x test + + let test_backend_nodes ?hook x () = + let test repo = + let check_val = check [%typ: S.contents option] in + let vx = "VX" in + let vy = "VY" in + let* t = S.main repo in + S.set_exn t ~info:(infof "add x/y/z") [ "x"; "y"; "z" ] vx >>= fun () -> + let* tree = S.get_tree t [ "x" ] in + S.set_tree_exn t ~info:(infof "update") [ "u" ] tree >>= fun () -> + let* vx' = S.find t [ "u"; "y"; "z" ] in + check_val "vx" (Some vx) vx'; + let* tree1 = S.get_tree t [ "u" ] in + S.set_exn t ~info:(infof "add u/x/y") [ "u"; "x"; "y" ] vy >>= fun () -> + may_with_branch [ t ] repo hook >>= fun () -> + let* tree2 = S.get_tree t [ "u" ] in + let* tree3 = S.Tree.add tree [ "x"; "z" ] vx in + let* v' = + Irmin.Merge.f S.Tree.merge ~old:(Irmin.Merge.promise tree1) tree2 tree3 + >>= merge_exn "tree" + in + S.set_tree_exn t ~info:(infof "merge") [ "u" ] v' >>= fun () -> + let* vy' = S.find t [ "u"; "x"; "y" ] in + check_val "vy after merge" (Some vy) vy'; + let* vx' = S.find t [ "u"; "x"; "z" ] in + check_val "vx after merge" (Some vx) vx'; + B.Repo.close repo + in + run x test + + let test_stores x () = + let test repo = + let check_val = check [%typ: S.contents option] in + let check_list = checks [%typ: S.Path.step * S.tree] in + let* t = S.main repo in + S.set_exn t ~info:(infof "init") [ "a"; "b" ] v1 >>= fun () -> + let* b0 = S.mem t [ "a"; "b" ] in + Alcotest.(check bool) "mem0" true b0; + let* t = S.clone ~src:t ~dst:"test" in + let* b1 = S.mem t [ "a"; "b" ] in + Alcotest.(check bool) "mem1" true b1; + let* b2 = S.mem t [ "a" ] in + Alcotest.(check bool) "mem2" false b2; + let* v1' = S.find t [ "a"; "b" ] in + check_val "v1.1" (Some v1) v1'; + let* r1 = S.Head.get t in + let* t = S.clone ~src:t ~dst:"test" in + S.set_exn t ~info:(infof "update") [ "a"; "c" ] v2 >>= fun () -> + let* b1 = S.mem t [ "a"; "b" ] in + Alcotest.(check bool) "mem3" true b1; + let* b2 = S.mem t [ "a" ] in + Alcotest.(check bool) "mem4" false b2; + let* v1' = S.find t [ "a"; "b" ] in + check_val "v1.1" (Some v1) v1'; + let* b1 = S.mem t [ "a"; "c" ] in + Alcotest.(check bool) "mem5" true b1; + let* v2' = S.find t [ "a"; "c" ] in + check_val "v1.1" (Some v2) v2'; + S.remove_exn t ~info:(infof "remove") [ "a"; "b" ] >>= fun () -> + let* v1'' = S.find t [ "a"; "b" ] in + check_val "v1.2" None v1''; + S.Head.set t r1 >>= fun () -> + let* v1'' = S.find t [ "a"; "b" ] in + check_val "v1.3" (Some v1) v1''; + let* ks = S.list t [ "a" ] in + check_list "path" [ ("b", contents v1) ] ks; + let* () = + S.set_exn t ~info:(infof "update2") [ "a"; long_random_ascii_string ] v1 + in + S.remove_exn t ~info:(infof "remove rec") [ "a" ] >>= fun () -> + let* dirs = S.list t [] in + check_list "remove rec" [] dirs; + let* () = + Lwt.catch + (fun () -> + S.set_exn t ~info:(infof "update root") [] v1 >>= fun () -> + Alcotest.fail "update root") + (function + | Invalid_argument _ -> Lwt.return_unit + | e -> Alcotest.fail ("update root: " ^ Printexc.to_string e)) + in + let* none = S.find t [] in + check_val "read root" none None; + S.set_exn t ~info:(infof "update") [ "a" ] v1 >>= fun () -> + S.remove_exn t ~info:(infof "remove rec --all") [] >>= fun () -> + let* dirs = S.list t [] in + check_list "remove rec root" [] dirs; + let a = "ok" in + let b = "maybe?" in + S.set_exn t ~info:(infof "fst one") [ "fst" ] a >>= fun () -> + S.set_exn t ~info:(infof "snd one") [ "fst"; "snd" ] b >>= fun () -> + let* fst = S.find t [ "fst" ] in + check_val "data model 1" None fst; + let* snd = S.find t [ "fst"; "snd" ] in + check_val "data model 2" (Some b) snd; + S.set_exn t ~info:(infof "fst one") [ "fst" ] a >>= fun () -> + let* fst = S.find t [ "fst" ] in + check_val "data model 3" (Some a) fst; + let* snd = S.find t [ "fst"; "snd" ] in + check_val "data model 4" None snd; + let tagx = "x" in + let tagy = "y" in + let xy = [ "x"; "y" ] in + let vx = "VX" in + let* tx = S.of_branch repo tagx in + S.Branch.remove repo tagx >>= fun () -> + S.Branch.remove repo tagy >>= fun () -> + S.set_exn tx ~info:(infof "update") xy vx >>= fun () -> + let* ty = S.clone ~src:tx ~dst:tagy in + let* vx' = S.find ty xy in + check_val "update tag" (Some vx) vx'; + S.status tx |> fun tagx' -> + S.status ty |> fun tagy' -> + check (S.Status.t repo) "tagx" (`Branch tagx) tagx'; + check (S.Status.t repo) "tagy" (`Branch tagy) tagy'; + let* t = S.main repo in + S.Repo.close repo >>= fun () -> + Lwt.catch + (fun () -> + let+ _ = S.set_exn t ~info:(infof "add after close") [ "a" ] "bar" in + Alcotest.fail "Add after close should not be allowed") + (function Irmin.Closed -> Lwt.return_unit | exn -> Lwt.fail exn) + in + run x test + + let test_atomic x () = + let test repo = + let check_commit = check T.(option (S.commit_t repo)) in + let* t = S.main repo in + let* _c_empty = + S.test_set_and_get_exn t ~info:(infof "init") [ "a"; "b" ] ~test:None + ~set:(Some v1) + in + let* c_none = + S.test_set_and_get_exn t ~info:(infof "init") [ "a"; "b" ] + ~test:(Some v1) ~set:(Some v1) + in + check_commit "No commit" None c_none; + let message0 = "first" in + let message1 = "second" in + let v3 = "v3" in + let* c0 = + S.test_set_and_get_exn t ~info:(infof "%s" message0) [ "a"; "b" ] + ~test:(Some v1) ~set:(Some v2) + in + let c0 = Option.get c0 in + let c0_message = S.Commit.info c0 |> S.Info.message in + Alcotest.(check string) "commit0" message0 c0_message; + let* c1 = + S.test_set_and_get_exn t ~info:(infof "%s" message1) [ "a"; "b" ] + ~test:(Some v2) ~set:(Some v3) + in + let* c0_store = S.of_commit c0 in + let* v2' = S.get c0_store [ "a"; "b" ] in + Alcotest.(check string) "commit0 value" v2 v2'; + let* c1_store = S.of_commit (Option.get c1) in + let* v3' = S.get c1_store [ "a"; "b" ] in + Alcotest.(check string) "commit1 value" v3 v3'; + S.Repo.close repo + in + run x test + + let stats_t = Alcotest.testable (Irmin.Type.pp_dump S.Tree.stats_t) ( = ) + + let empty_stats = + { S.Tree.nodes = 0; leafs = 0; skips = 0; depth = 0; width = 0 } + + let inspect = + Alcotest.testable + (fun ppf -> function + | `Contents -> Fmt.string ppf "contents" + | `Node `Key -> Fmt.string ppf "key" + | `Node `Map -> Fmt.string ppf "map" + | `Node `Value -> Fmt.string ppf "value" + | `Node `Portable_dirty -> Fmt.string ppf "portable_dirty" + | `Node `Pruned -> Fmt.string ppf "pruned") + ( = ) + + let test_tree_caches x () = + let test repo = + let info = S.Info.none in + let* t1 = S.main repo in + S.set_exn t1 ~info [ "a"; "b" ] "foo" >>= fun () -> + (* Testing cache *) + S.Tree.reset_counters (); + let* v = S.get_tree t1 [] in + Alcotest.(check inspect) "inspect" (`Node `Key) (S.Tree.inspect v); + let* v = S.Tree.add v [ "foo" ] "foo" in + Alcotest.(check inspect) "inspect:0" (`Node `Value) (S.Tree.inspect v); + Alcotest.(check int) "val-v:0" 0 (S.Tree.counters ()).node_val_v; + let* v = S.Tree.add v [ "bar"; "foo" ] "bar" in + Alcotest.(check inspect) "inspect:1" (`Node `Value) (S.Tree.inspect v); + Alcotest.(check int) "val-v:1" 0 (S.Tree.counters ()).node_val_v; + Alcotest.(check int) "val-list:1" 0 (S.Tree.counters ()).node_val_list; + let _ = S.Tree.hash v in + Alcotest.(check inspect) "inspect:2" (`Node `Value) (S.Tree.inspect v); + Alcotest.(check int) "val-v:2" 1 (S.Tree.counters ()).node_val_v; + Alcotest.(check int) "val-list:2" 0 (S.Tree.counters ()).node_val_list; + S.set_tree_exn t1 ~info [] v >>= fun () -> + Alcotest.(check inspect) "inspect:3" (`Node `Key) (S.Tree.inspect v); + Alcotest.(check int) "val-v:3" 2 (S.Tree.counters ()).node_val_v; + Alcotest.(check int) "val-list:3" 0 (S.Tree.counters ()).node_val_list; + B.Repo.close repo + in + run x test + + let pp_depth = Irmin.Type.pp S.Tree.depth_t + let pp_key = Irmin.Type.pp S.Path.t + let contents_t = T.pair S.contents_t S.metadata_t + let diff_t = T.(pair S.path_t (Irmin.Diff.t contents_t)) + let check_diffs = checks diff_t + let check_ls = checks T.(pair S.step_t S.tree_t) + + let test_trees x () = + let test repo = + let* t = S.main repo in + let nodes = random_nodes 100 in + let foo1 = random_value 10 in + let foo2 = random_value 10 in + let* v1 = + S.Tree.singleton [ "foo"; "bar"; "toto" ] foo2 + |> with_binding [ "foo"; "toto" ] foo1 + in + S.Tree.clear v1; + let* () = + let dont_skip k = + Alcotest.failf "should not have skipped: '%a'" pp_key k + in + S.Tree.fold ~depth:(`Eq 1) ~force:(`False dont_skip) v1 () + in + let* () = + S.Tree.fold ~depth:(`Eq 1) ~force:`True (S.Tree.empty ()) () + ~contents:(fun k _ -> + assert (List.length k = 1); + Alcotest.fail "contents") + ~node:(fun k _ -> + assert (List.length k = 1); + Alcotest.fail "node") + in + let fold depth ecs ens = + let* cs, ns = + S.Tree.fold v1 ?depth ~force:`True ~cache:false + ~contents:(fun path _ (cs, ns) -> Lwt.return (path :: cs, ns)) + ~node:(fun path _ (cs, ns) -> Lwt.return (cs, path :: ns)) + ([], []) + in + let paths = Alcotest.slist (testable S.Path.t) compare in + Alcotest.(check paths) + (Fmt.str "contents depth=%a" Fmt.(Dump.option pp_depth) depth) + ecs cs; + Alcotest.(check paths) + (Fmt.str "nodes depth=%a" Fmt.(Dump.option pp_depth) depth) + ens ns; + Lwt.return () + in + let* () = + fold None + [ [ "foo"; "bar"; "toto" ]; [ "foo"; "toto" ] ] + [ []; [ "foo" ]; [ "foo"; "bar" ] ] + in + fold (Some (`Eq 0)) [] [ [] ] >>= fun () -> + fold (Some (`Eq 1)) [] [ [ "foo" ] ] >>= fun () -> + let* () = + fold (Some (`Eq 2)) [ [ "foo"; "toto" ] ] [ [ "foo"; "bar" ] ] + in + fold (Some (`Lt 2)) [] [ []; [ "foo" ] ] >>= fun () -> + let* () = + fold + (Some (`Le 2)) + [ [ "foo"; "toto" ] ] + [ []; [ "foo" ]; [ "foo"; "bar" ] ] + in + let* () = + fold + (Some (`Ge 2)) + [ [ "foo"; "toto" ]; [ "foo"; "bar"; "toto" ] ] + [ [ "foo"; "bar" ] ] + in + fold (Some (`Gt 2)) [ [ "foo"; "bar"; "toto" ] ] [] >>= fun () -> + let* v1 = S.Tree.remove v1 [ "foo"; "bar"; "toto" ] in + let* v = S.Tree.find v1 [ "foo"; "toto" ] in + Alcotest.(check (option string)) "remove" (Some foo1) v; + let v1 = S.Tree.empty () in + let* s = S.Tree.stats v1 in + Alcotest.(check stats_t) "empty stats" empty_stats s; + let* v1 = S.Tree.add v1 [ "foo"; "1" ] foo1 in + let* v1 = S.Tree.add v1 [ "foo"; "2" ] foo2 in + let* s = S.Tree.stats v1 in + Alcotest.(check stats_t) + "stats 1" + { S.Tree.nodes = 2; leafs = 2; skips = 0; depth = 2; width = 2 } + s; + let* v1 = S.Tree.remove v1 [ "foo"; "1" ] in + let* v1 = S.Tree.remove v1 [ "foo"; "2" ] in + let* s = S.Tree.stats v1 in + Alcotest.(check stats_t) "empty stats" empty_stats s; + S.set_tree_exn t ~info:(infof "empty tree") [] v1 >>= fun () -> + let* head = S.Head.get t in + S.Commit.key head |> fun head -> + let* commit = B.Commit.find (ct repo) head in + let node = B.Commit.Val.node (get commit) in + let* node = B.Node.find (n repo) node in + check + T.(option B.Node.Val.t) + "empty tree" + (Some (B.Node.Val.empty ())) + node; + + (* Testing [Tree.diff] *) + let contents_t = T.pair S.contents_t S.metadata_t in + let diff = T.(pair S.path_t (Irmin.Diff.t contents_t)) in + let check_diffs = checks diff in + let check_val = check T.(option contents_t) in + let check_ls = checks T.(pair S.step_t S.tree_t) in + let normal c = Some (c, S.Metadata.default) in + let d0 = S.Metadata.default in + let v0 = S.Tree.empty () in + let v1 = S.Tree.empty () in + let v2 = S.Tree.empty () in + let* v1 = S.Tree.add v1 [ "foo"; "1" ] foo1 in + let* f = S.Tree.find_all v1 [ "foo"; "1" ] in + check_val "tree update" (normal foo1) f; + let* v1' = S.Tree.add v1 [ "foo"; "1" ] foo1 in + Alcotest.(check bool) "Tree.add keeps sharing" true (v1 == v1'); + let* v1' = S.Tree.remove v1 [ "foo"; "2" ] in + Alcotest.(check bool) "Tree.remove keeps sharing" true (v1 == v1'); + let* v1' = S.Tree.add_tree v1 [] v1 in + Alcotest.(check bool) "Tree.add_tree keeps sharing" true (v1 == v1'); + let* v2 = S.Tree.add v2 [ "foo"; "1" ] foo2 in + let* v2 = S.Tree.add v2 [ "foo"; "2" ] foo1 in + let* d1 = S.Tree.diff v0 v1 in + check_diffs "diff 1" [ ([ "foo"; "1" ], `Added (foo1, d0)) ] d1; + let* d2 = S.Tree.diff v1 v0 in + check_diffs "diff 2" [ ([ "foo"; "1" ], `Removed (foo1, d0)) ] d2; + let* d3 = S.Tree.diff v1 v2 in + check_diffs "diff 3" + [ + ([ "foo"; "1" ], `Updated ((foo1, d0), (foo2, d0))); + ([ "foo"; "2" ], `Added (foo1, d0)); + ] + d3; + let* v3 = S.Tree.add v2 [ "foo"; "bar"; "1" ] foo1 in + let* d4 = S.Tree.diff v2 v3 in + check_diffs "diff 4" [ ([ "foo"; "bar"; "1" ], `Added (foo1, d0)) ] d4; + let* d5 = S.Tree.diff v3 v2 in + check_diffs "diff 4" [ ([ "foo"; "bar"; "1" ], `Removed (foo1, d0)) ] d5; + + (* Testing length *) + let check_length msg t = + let* n = S.Tree.length t [] in + let+ l = S.Tree.list t [] in + Alcotest.(check int) msg n (List.length l) + in + let* () = check_length "bindings1 length" v2 in + let* () = + let t = contents "foo" in + check_length "contents length" t + in + + (* Testing paginated lists *) + let tree = + let c ?(info = S.Metadata.default) blob = `Contents (blob, info) in + S.Tree.of_concrete + (`Tree + [ + ("aa", c "0"); + ("a", c "1"); + ("bbb", c "3"); + ("b", c "3"); + ("aaa", c "1"); + ]) + in + let* _ = S.set_tree_exn t ~info:(infof "add tree") [] tree in + let* e = S.Tree.get_tree tree [ "a" ] in + let ls = + [ + ("aa", contents "0"); + ("a", e); + ("bbb", contents "3"); + ("b", contents "3"); + ("aaa", e); + ] + in + let* () = + let* l1 = S.Tree.list ~offset:0 ~length:2 tree [] in + let* l2 = S.Tree.list ~offset:2 ~length:2 tree [] in + let+ l3 = S.Tree.list ~offset:4 ~length:2 tree [] in + Alcotest.(check int) "size l1" 2 (List.length l1); + Alcotest.(check int) "size l2" 2 (List.length l2); + Alcotest.(check int) "size l3" 1 (List.length l3); + check_ls "2 paginated list" ls (l1 @ l2 @ l3) + in + let* () = + let* l1 = S.Tree.list ~offset:0 ~length:3 tree [] in + let+ l2 = S.Tree.list ~offset:3 ~length:6 tree [] in + Alcotest.(check int) "size l1" 3 (List.length l1); + Alcotest.(check int) "size l2" 2 (List.length l2); + check_ls "3 paginated list" ls (l1 @ l2) + in + let* () = + let* l1 = S.Tree.list ~offset:0 ~length:4 tree [] in + let+ l2 = S.Tree.list ~offset:4 ~length:4 tree [] in + Alcotest.(check int) "size l1" 4 (List.length l1); + Alcotest.(check int) "size l2" 1 (List.length l2); + check_ls "4 paginated list" ls (l1 @ l2) + in + let* () = + let* l1 = S.Tree.list ~offset:0 ~length:5 tree [] in + let+ l2 = S.Tree.list ~offset:5 ~length:5 tree [] in + Alcotest.(check int) "size l1" 5 (List.length l1); + Alcotest.(check int) "size l2" 0 (List.length l2); + check_ls "5 paginated list" ls (l1 @ l2) + in + let* c0 = + S.Tree.singleton [ "foo"; "a" ] "1" + |> with_binding [ "foo"; "b"; "c" ] "2" + >>= with_binding [ "foo"; "c" ] "3" + >>= with_binding [ "foo"; "d" ] "4" + in + let* b = S.Tree.get_tree c0 [ "foo"; "b" ] in + let* ls = S.Tree.list c0 [ "foo" ] in + check_ls "list all" + [ + ("a", contents "1"); ("b", b); ("c", contents "3"); ("d", contents "4"); + ] + ls; + let* ls = S.Tree.list ~offset:2 c0 [ "foo" ] in + check_ls "list offset=2" [ ("c", contents "3"); ("d", contents "4") ] ls; + let* ls = S.Tree.list ~offset:2 ~length:1 c0 [ "foo" ] in + check_ls "list offset=2 length=1" [ ("c", contents "3") ] ls; + let* ls = S.Tree.list ~length:1 c0 [ "foo" ] in + check_ls "list length=1" [ ("a", contents "1") ] ls; + + (* Testing concrete representation *) + let* c0 = + Lwt.return (S.Tree.empty ()) + >>= with_binding [ "foo"; "a" ] "1" + >>= with_binding [ "foo"; "b"; "c" ] "2" + >>= with_binding [ "bar"; "d" ] "3" + >>= with_binding [ "e" ] "4" + in + let* t0 = c0 |> S.Tree.to_concrete >|= S.Tree.of_concrete in + let* () = + let+ d0 = S.Tree.diff c0 t0 in + check_diffs "concrete roundtrip" [] d0 + in + let* () = + let* c0' = S.Tree.list c0 [] in + let+ t0' = S.Tree.list t0 [] in + check_ls "concrete list /" c0' t0' + in + let* () = + let* c0' = S.Tree.list c0 [ "foo" ] in + let+ t0' = S.Tree.list t0 [ "foo" ] in + check_ls "concrete tree list /foo" c0' t0' + in + let* () = + let* c0' = S.Tree.list c0 [ "bar"; "d" ] in + let+ t0' = S.Tree.list t0 [ "bar"; "d" ] in + check_ls "concrete tree list /bar/d" c0' t0' + in + + (* Testing other tree operations. *) + let v0 = S.Tree.empty () in + let* c = S.Tree.to_concrete v0 in + (match c with + | `Tree [] -> () + | _ -> Alcotest.fail "Excpected empty tree"); + let* v0 = S.Tree.add v0 [] foo1 in + let* foo1' = S.Tree.find_all v0 [] in + check_val "read /" (normal foo1) foo1'; + let* v0 = S.Tree.add v0 [ "foo"; "1" ] foo1 in + let* foo1' = S.Tree.find_all v0 [ "foo"; "1" ] in + check_val "read foo/1" (normal foo1) foo1'; + let* v0 = S.Tree.add v0 [ "foo"; "2" ] foo2 in + let* foo2' = S.Tree.find_all v0 [ "foo"; "2" ] in + check_val "read foo/2" (normal foo2) foo2'; + let check_tree v = + let* ls = S.Tree.list v [ "foo" ] in + check_ls "path1" [ ("1", contents foo1); ("2", contents foo2) ] ls; + let* foo1' = S.Tree.find_all v [ "foo"; "1" ] in + check_val "foo1" (normal foo1) foo1'; + let* foo2' = S.Tree.find_all v [ "foo"; "2" ] in + check_val "foo2" (normal foo2) foo2'; + Lwt.return_unit + in + let* v0 = + Lwt_list.fold_left_s (fun v0 (k, v) -> S.Tree.add v0 k v) v0 nodes + in + check_tree v0 >>= fun () -> + S.set_tree_exn t ~info:(infof "update_path b/") [ "b" ] v0 >>= fun () -> + S.set_tree_exn t ~info:(infof "update_path a/") [ "a" ] v0 >>= fun () -> + let* ls = S.list t [ "b"; "foo" ] in + check_ls "path2" [ ("1", contents foo1); ("2", contents foo2) ] ls; + let* foo1' = S.find_all t [ "b"; "foo"; "1" ] in + check_val "foo1" (normal foo1) foo1'; + let* foo2' = S.find_all t [ "a"; "foo"; "2" ] in + check_val "foo2" (normal foo2) foo2'; + let* v0 = S.get_tree t [ "b" ] in + check_tree v0 >>= fun () -> + S.set_exn t ~info:(infof "update b/x") [ "b"; "x" ] foo1 >>= fun () -> + let* v2 = S.get_tree t [ "b" ] in + let* v1 = S.Tree.add v0 [ "y" ] foo2 in + let* v' = + Irmin.Merge.(f S.Tree.merge ~old:(promise v0) v1 v2) + >>= merge_exn "merge trees" + in + S.set_tree_exn t ~info:(infof "merge_path") [ "b" ] v' >>= fun () -> + let* foo1' = S.find_all t [ "b"; "x" ] in + let* foo2' = S.find_all t [ "b"; "y" ] in + check_val "merge: b/x" (normal foo1) foo1'; + check_val "merge: b/y" (normal foo2) foo2'; + let* () = + Lwt_list.iteri_s + (fun i (k, v) -> + let* v' = S.find_all t ("a" :: k) in + check_val ("a" ^ string_of_int i) (normal v) v'; + let* v' = S.find_all t ("b" :: k) in + check_val ("b" ^ string_of_int i) (normal v) v'; + Lwt.return_unit) + nodes + in + let* v2 = S.get_tree t [ "b" ] in + let* _ = S.Tree.find_all v2 [ "foo"; "1" ] in + let* v2 = S.Tree.add v2 [ "foo"; "1" ] foo2 in + S.set_tree_exn t ~info:(infof "v2") [ "b" ] v2 >>= fun () -> + let* foo2' = S.find_all t [ "b"; "foo"; "1" ] in + check_val "update tree" (normal foo2) foo2'; + let* v3 = S.get_tree t [ "b" ] in + let* _ = S.Tree.find_all v3 [ "foo"; "1" ] in + let* v3 = S.Tree.remove v3 [ "foo"; "1" ] in + S.set_tree_exn t ~info:(infof "v3") [ "b" ] v3 >>= fun () -> + let* foo2' = S.find_all t [ "b"; "foo"; "1" ] in + check_val "remove tree" None foo2'; + let* r1 = r1 ~repo in + let* r2 = r2 ~repo in + let i0 = S.Info.empty in + let* c = + S.Commit.v repo ~info:S.Info.empty + ~parents:[ S.Commit.key r1; S.Commit.key r2 ] + v3 + in + S.Head.set t c >>= fun () -> + let* h = S.Head.get t in + S.Commit.info h |> fun i -> + check S.Info.t "commit info" i0 i; + let* tt = S.of_commit h in + let* g = S.history tt in + let pred = S.History.pred g h in + checks (S.commit_t repo) "head" [ r1; r2 ] pred; + let* foo2'' = S.find_all tt [ "b"; "foo"; "1" ] in + check_val "remove tt" None foo2''; + let vx = "VX" in + let px = [ "x"; "y"; "z" ] in + S.set_exn tt ~info:(infof "update") px vx >>= fun () -> + let* tree = S.get_tree tt [] in + S.Tree.clear tree; + let* s = S.Tree.stats tree in + Alcotest.(check stats_t) + "lazy stats" + { S.Tree.nodes = 0; leafs = 0; skips = 1; depth = 0; width = 0 } + s; + S.Tree.clear tree; + let* s = S.Tree.stats ~force:true tree in + Alcotest.(check stats_t) + "forced stats" + { S.Tree.nodes = 404; leafs = 103; skips = 0; depth = 5; width = 103 } + s; + let* vx' = S.Tree.find_all tree px in + check_val "updates" (normal vx) vx'; + let v = S.Tree.singleton [] vx in + let* () = + S.set_tree_exn t ~info:(infof "update file as tree") [ "a" ] v + in + let* vx' = S.find_all t [ "a" ] in + check_val "update file as tree" (normal vx) vx'; + B.Repo.close repo + in + run x test + + let pp_proof = Irmin.Type.pp (S.Tree.Proof.t S.Tree.Proof.tree_t) + let pp_stream = Irmin.Type.pp (S.Tree.Proof.t S.Tree.Proof.stream_t) + + let test_proofs x () = + let test repo = + (* Testing Merkle proof *) + let large_dir = + List.init 1000 (fun i -> + let v = string_of_int i in + ([ "dir"; v ], "BLOB:" ^ v)) + in + let* c0 = + Lwt.return (S.Tree.empty ()) + >>= with_binding [ "foo"; "a" ] "1" + >>= with_binding [ "foo"; "b"; "c" ] "2" + >>= with_binding [ "bar"; "d" ] "3" + >>= with_binding [ "e" ] "4" + >>= fun t -> + Lwt_list.fold_left_s (fun acc (k, v) -> S.Tree.add acc k v) t large_dir + in + let to_proof t = + let* store = S.empty repo in + let* () = S.set_tree_exn ~info:(infof "to_proof") store [] t in + let key = + match S.Tree.key t with None -> assert false | Some k -> k + in + let rec aux p t = + let* bindings = + Lwt.catch + (fun () -> S.Tree.list t []) + (function + | S.Tree.Pruned_hash _ -> Lwt.return [] | e -> Lwt.fail e) + in + Lwt_list.iter_s (fun (s, v) -> aux (p @ [ s ]) v) bindings + in + S.Tree.produce_proof repo key (fun t -> + let+ () = aux [] t in + (t, ())) + in + let* p0, () = to_proof c0 in + [%log.debug "p0=%a" pp_proof p0]; + let t0 = S.Tree.Proof.to_tree p0 in + let* () = + let+ d0 = S.Tree.diff c0 t0 in + check_diffs "proof roundtrip" [] d0 + in + let* () = + let* c0' = S.Tree.list c0 [] in + let+ t0' = S.Tree.list t0 [] in + check_ls "proof list /" c0' t0' + in + let* () = + let* c0' = S.Tree.list c0 [ "foo" ] in + let+ t0' = S.Tree.list t0 [ "foo" ] in + check_ls "proof tree list /foo" c0' t0' + in + let* () = + let* c0' = S.Tree.list c0 [ "bar"; "d" ] in + let+ t0' = S.Tree.list t0 [ "bar"; "d" ] in + check_ls "proof tree list /bar/d" c0' t0' + in + let* () = + let* c0' = S.Tree.list c0 [ "dir" ] in + let+ t0' = S.Tree.list t0 [ "dir" ] in + check_ls "proof tree list /dir" c0' t0' + in + let add_noise n prefix = + List.map (fun k -> (prefix @ [ k ], k)) (List.init n string_of_int) + in + let bindings = + [ + ([ "foo"; "age" ], "0"); + ([ "foo"; "version" ], "1"); + ([ "bar"; "age" ], "2"); + ([ "bar"; "version" ], "3"); + ] + @ add_noise 100 [ "foo" ] + @ add_noise 10 [ "hey" ] + @ add_noise 50 [ "bar" ] + in + let increment = function + | None -> assert false + | Some i -> Some (int_of_string i + 1 |> string_of_int) + in + let check_proof_f0 p = + let t = S.Tree.Proof.to_tree p in + let* i = S.Tree.find t [ "bar"; "age" ] in + Alcotest.(check (option string)) + "inside: find bar/age in proof" (Some "2") i; + let* i = S.Tree.find t [ "bar"; "version" ] in + Alcotest.(check (option string)) + "inside: find bar/version in proof" (Some "3") i; + let* i = S.Tree.find t [ "hello"; "there" ] in + Alcotest.(check (option string)) + "inside: do not find hello/there in proof" None i; + let+ () = + Lwt.catch + (fun () -> + let+ _ = S.Tree.find t [ "foo"; "version" ] in + Alcotest.fail "inside: should have raise: pruned_hash exn") + (function + | S.Tree.Pruned_hash _ | B.Node.Val.Dangling_hash _ -> + Lwt.return () + | e -> Lwt.fail e) + in + () + in + + let check_proof_f1 p = + let t = S.Tree.Proof.to_tree p in + let+ i = S.Tree.find t [ "foo"; "version" ] in + Alcotest.(check (option string)) + "outside: find foo/version" (Some "1") i + in + + let init_tree bindings = + let tree = S.Tree.empty () in + let* tree = + Lwt_list.fold_left_s + (fun tree (k, v) -> S.Tree.add tree k v) + tree bindings + in + let* store = S.empty repo in + let* () = S.set_tree_exn ~info:(infof "init_tree") store [] tree in + S.tree store + in + let* tree = init_tree bindings in + let key = + match S.Tree.key tree with None -> assert false | Some k -> k + in + + let f0 t0 = + let* t1 = S.Tree.update t0 [ "foo"; "age" ] increment in + let* t2 = S.Tree.update t1 [ "bar"; "age" ] increment in + let* t3 = S.Tree.get_tree t2 [ "bar" ] in + let* t4 = S.Tree.add_tree t2 [ "hello"; "there" ] t3 in + let* v = S.Tree.get t4 [ "hello"; "there"; "version" ] in + Alcotest.(check string) "hello/there/version" "3" v; + let t = S.Tree.empty () in + let* t5 = S.Tree.add_tree t [ "dir1"; "dir2" ] t4 in + let* v = S.Tree.get t5 [ "dir1"; "dir2"; "bar"; "age" ] in + Alcotest.(check string) "dir1/dir2/bar/age" "3" v; + let* t = S.Tree.remove t4 [ "bar" ] in + + (* Trigger certain paths in [S.Tree] during "verify" *) + let portable = + (* During "verify" [portable] is [Pruned] with [portable] in env *) + t0 + in + let portable_dirty = t in + let trigger_node_to_map t = + S.Tree.fold ~depth:(`Eq 1) ~order:`Sorted ~force:`True t () + in + let* () = trigger_node_to_map portable in + let* () = trigger_node_to_map portable_dirty in + let trigger_node_length t = + let+ (_ : int) = S.Tree.length t [] in + () + in + let* () = trigger_node_length portable in + let* () = trigger_node_length portable_dirty in + let trigger_node_fold_undefined t = + S.Tree.fold ~depth:(`Eq 1) ~order:`Undefined ~force:`True t () + in + let* () = trigger_node_fold_undefined portable in + let* () = trigger_node_fold_undefined portable_dirty in + let (_ : bool) = S.Tree.is_empty portable in + let trigger_node_to_backend_portable t = + match S.Tree.destruct t with + | `Contents _ -> assert false + | `Node n -> + let+ _ = S.to_backend_portable_node n in + () + in + let* () = trigger_node_to_backend_portable portable_dirty in + + Lwt.return (t, ()) + in + let f1 t0 = + let* p0, () = S.Tree.produce_proof repo key f0 in + let* () = check_proof_f0 p0 in + let+ v = S.Tree.get t0 [ "foo"; "version" ] in + Alcotest.(check string) "foo/version" "1" v; + (t0, ()) + in + let* p, () = S.Tree.produce_proof repo key f1 in + + let* () = check_proof_f1 p in + + let check_proof f = + let* p, () = S.Tree.produce_proof repo key f in + [%log.debug "Verifying proof %a" pp_proof p]; + let+ r = S.Tree.verify_proof p f in + match r with + | Ok (_, ()) -> () + | Error e -> + Alcotest.failf "check_proof: %a" + (Irmin.Type.pp S.Tree.verifier_error_t) + e + in + let* () = Lwt_list.iter_s check_proof [ f0; f1 ] in + + let check_stream f = + let* p, () = S.Tree.produce_stream repo key f in + [%log.debug "Verifying stream %a" pp_stream p]; + let+ r = S.Tree.verify_stream p f in + match r with + | Ok (_, ()) -> () + | Error e -> + Alcotest.failf "check_stream: %a" + (Irmin.Type.pp S.Tree.verifier_error_t) + e + in + let* () = Lwt_list.iter_s check_stream [ f0; f1 ] in + + (* check env sharing *) + let tree () = + S.Tree.of_concrete + (`Tree [ ("foo", `Contents ("bar", S.Metadata.default)) ]) + in + let contents () = + S.Tree.of_concrete (`Contents ("bar", S.Metadata.default)) + in + let check_env_empty msg t b = + let env = S.Tree.Private.get_env t in + Alcotest.(check bool) msg b (S.Tree.Private.Env.is_empty env) + in + let check_env msg t t' = + let env = S.Tree.Private.get_env t in + let env' = S.Tree.Private.get_env t' in + check S.Tree.Private.Env.t msg env env' + in + let x = ref None in + let* _ = + S.Tree.produce_proof repo key (fun t -> + check_env_empty "env should be set inside the proof" t false; + x := Some t; + + let t0 = tree () in + check_env_empty "env should not be set for fresh trees" t0 true; + + (* test changing subtress: check that envirnoment is + attached only the tree roots *) + let* t1 = S.Tree.add_tree t [ "foo" ] t0 in + check_env_empty "1: t's env should not change" t false; + check_env_empty "1: t0's env should not change" t0 true; + check_env "1: t1's env should be the same as t's" t1 t; + + let t0 = contents () in + let* t1 = S.Tree.add_tree t [ "foo" ] t0 in + check_env_empty "2: t's env should not change" t false; + check_env_empty "2: t0's env should not change" t0 true; + check_env "2: t1's env should be the same as t's" t1 t; + + (* test changing roots *) + let t0 = tree () in + let* t1 = S.Tree.add_tree t [] t0 in + check_env_empty "3: t's env should not change" t false; + check_env_empty "3: t0's env should not change" t0 true; + check_env "3: t1's env should be the same as t0's" t1 t0; + + let t0 = contents () in + let* t1 = S.Tree.add_tree t [] t0 in + check_env_empty "4: t's env should not change" t false; + check_env_empty "4: t0's env should not change" t0 true; + check_env "4: t1's env should be the same as t0's" t1 t0; + + (* check subtrees *) + let* t2 = S.Tree.get_tree t [ "foo" ] in + check_env "5: t2's env should be the same as t's" t2 t; + let* t3 = S.Tree.get_tree t [ "foo"; "age" ] in + check_env "5: t3's env should be the same as t's" t3 t; + + Lwt.return (t, ())) + in + let t = match !x with Some t -> t | None -> assert false in + check_env_empty "env is unset outside of the proof)" t true; + + (* test negative proofs *) + let check_bad_proof p = + let+ r = S.Tree.verify_proof p f0 in + match r with + | Ok _ -> Alcotest.fail "verify should have failed" + | Error _ -> () + in + + let* p0, () = S.Tree.produce_proof repo key f0 in + let proof ?(before = S.Tree.Proof.before p0) + ?(after = S.Tree.Proof.after p0) ?(state = S.Tree.Proof.state p0) () = + S.Tree.Proof.v ~before ~after state + in + let wrong_hash = B.Contents.Hash.hash "not the right hash!" in + let wrong_kinded_hash = `Node wrong_hash in + let* () = check_bad_proof (proof ~before:wrong_kinded_hash ()) in + let* () = check_bad_proof (proof ~after:wrong_kinded_hash ()) in + let* _ = S.Tree.verify_proof (proof ()) f0 in + let some_contents : S.Tree.Proof.tree list = + [ + Blinded_node wrong_hash; + Node []; + Inode { length = 1024; proofs = [] }; + Blinded_contents (wrong_hash, S.Metadata.default); + Contents ("yo", S.Metadata.default); + ] + in + let* () = + Lwt_list.iter_s + (fun c -> check_bad_proof (proof ~state:c ())) + some_contents + in + + (* test negative streams *) + let check_bad_stream p = + let+ r = S.Tree.verify_stream p f0 in + match r with + | Ok _ -> + Alcotest.failf "verify_stream should have failed %a" pp_stream p + | Error _ -> () + in + + let* p0, () = S.Tree.produce_stream repo key f0 in + let proof ?(before = S.Tree.Proof.before p0) + ?(after = S.Tree.Proof.after p0) ?(contents = S.Tree.Proof.state p0) + () = + S.Tree.Proof.v ~before ~after contents + in + let wrong_hash = B.Contents.Hash.hash "not the right hash!" in + let wrong_kinded_hash = `Node wrong_hash in + let* () = check_bad_stream (proof ~before:wrong_kinded_hash ()) in + let* () = check_bad_stream (proof ~after:wrong_kinded_hash ()) in + let* _ = S.Tree.verify_stream (proof ()) f0 in + let some_contents : S.Tree.Proof.stream list = + let s : S.Tree.Proof.elt list -> S.Tree.Proof.stream = List.to_seq in + let ok = List.of_seq (S.Tree.Proof.state p0) in + [ + s []; + s [ Node [] ]; + s [ Inode { length = 1024; proofs = [] } ]; + s [ Contents "yo" ]; + s (ok @ [ Node [] ]); + ] + in + let* () = + let x = ref 1 in + Lwt_list.iter_s + (fun c -> + incr x; + check_bad_stream (proof ~contents:c ())) + some_contents + in + + B.Repo.close repo + in + run x test + + let test_wide_nodes x () = + let test repo = + let size = 500_000 in + let c0 = S.Tree.empty () in + let rec wide_node i c = + if i >= size then Lwt.return c + else + S.Tree.add c [ "foo"; string_of_int i ] (string_of_int i) >>= fun c -> + wide_node (i + 1) c + in + wide_node 0 c0 >>= fun c -> + S.Tree.list c [ "foo" ] >>= fun ls -> + Alcotest.(check int) "list wide dir" size (List.length ls); + S.Tree.fold ~force:`True c ~uniq:`False + ~contents:(fun k _ i -> + Alcotest.(check int) "contents at [foo; i]" (List.length k) 2; + Lwt.return (i + 1)) + ~node:(fun k _ i -> + if not (List.length k = 0 || List.length k = 1) then + Alcotest.failf "nodes should be at [] and [foo], got %a" + (Irmin.Type.pp S.path_t) k; + Lwt.return i) + 0 + >>= fun nb_contents -> + Alcotest.(check int) "nb of contents folded over" size nb_contents; + S.Tree.remove c [ "foo"; "499999" ] >>= fun c1 -> + S.Tree.add c0 [] "499999" >>= fun c2 -> + S.Tree.add_tree c1 [ "foo"; "499999" ] c2 >>= fun c' -> + let h' = S.Tree.hash c' in + let h = S.Tree.hash c in + check S.Hash.t "same tree" h h'; + let* c1 = S.Tree.get_tree c [ "foo" ] in + let* _ = + S.Backend.Repo.batch repo (fun c n _ -> S.save_tree repo c n c1) + in + (match S.Tree.destruct c1 with + | `Contents _ -> Alcotest.fail "got `Contents, expected `Node" + | `Node node -> ( + let* v = S.to_backend_node node in + let () = + let ls = B.Node.Val.list v in + Alcotest.(check int) "list wide node" size (List.length ls) + in + let* bar_key = with_contents repo (fun t -> B.Contents.add t "bar") in + let k = normal bar_key in + let v1 = B.Node.Val.add v "x" k in + let* () = + let h' = B.Node.Hash.hash v1 in + let+ h = with_node repo (fun n -> B.Node.add n v1) in + check B.Node.Hash.t "wide node + x: hash(v) = add(v)" + (B.Node.Key.to_hash h) h' + in + let () = + let v2 = B.Node.Val.add v "x" k in + check B.Node.Val.t "add x" v1 v2 + in + let () = + let v0 = B.Node.Val.remove v1 "x" in + check B.Node.Val.t "remove x" v v0 + in + let* () = + let v3 = B.Node.Val.remove v "1" in + let h' = B.Node.Hash.hash v3 in + with_node repo (fun n -> B.Node.add n v3) >|= fun h -> + check B.Node.Hash.t "wide node - 1 : hash(v) = add(v)" + (B.Node.Key.to_hash h) h' + in + (match B.Node.Val.find v "499999" with + | None | Some (`Node _) -> Alcotest.fail "value 499999 not found" + | Some (`Contents (x, _)) -> + let x = B.Contents.Key.to_hash x in + let x' = B.Contents.Hash.hash "499999" in + check B.Contents.Hash.t "find 499999" x x'); + match B.Node.Val.find v "500000" with + | None -> Lwt.return_unit + | Some _ -> Alcotest.fail "value 500000 should not be found")) + >>= fun () -> B.Repo.close repo + in + run x test + + let test_commit_wide_node x () = + let test repo = + let size = 500_000 in + let c0 = S.Tree.empty () in + let rec wide_node i c = + if i >= size then Lwt.return c + else + S.Tree.add c [ "foo"; string_of_int i ] (string_of_int i) >>= fun c -> + wide_node (i + 1) c + in + wide_node 0 c0 >>= fun c -> + S.main repo >>= fun t -> + S.set_tree_exn t [ "wide" ] ~info:(infof "commit_wide_nodes") c + >>= fun () -> + S.list t [ "wide"; "foo" ] >>= fun ls -> + Alcotest.(check int) "commit wide node list" size (List.length ls); + B.Repo.close repo + in + run x test + + module Sync = Irmin.Sync.Make (S) + + let test_sync x () = + let test repo = + let* t1 = S.main repo in + S.set_exn t1 ~info:(infof "update a/b") [ "a"; "b" ] v1 >>= fun () -> + let* h = S.Head.get t1 in + let* _r1 = S.Head.get t1 in + S.set_exn t1 ~info:(infof "update a/c") [ "a"; "c" ] v2 >>= fun () -> + let* r2 = S.Head.get t1 in + S.set_exn t1 ~info:(infof "update a/d") [ "a"; "d" ] v1 >>= fun () -> + let* _r3 = S.Head.get t1 in + let* h = S.history t1 ~min:[ h ] in + Alcotest.(check int) "history-v" 3 (S.History.nb_vertex h); + Alcotest.(check int) "history-e" 2 (S.History.nb_edges h); + let remote = Irmin.remote_store (module S) t1 in + let* partial = Sync.fetch_exn t1 ~depth:0 remote in + let partial = + match partial with + | `Head x -> x + | `Empty -> failwith "no head: partial" + in + let* full = Sync.fetch_exn t1 remote in + let full = + match full with `Head x -> x | `Empty -> failwith "no head: full" + in + (* Restart a fresh store and import everything in there. *) + let tag = "export" in + let* t2 = S.of_branch repo tag in + S.Head.set t2 partial >>= fun () -> + let* b1 = S.mem t2 [ "a"; "b" ] in + Alcotest.(check bool) "mem-ab" true b1; + let* b2 = S.mem t2 [ "a"; "c" ] in + Alcotest.(check bool) "mem-ac" true b2; + let* b3 = S.mem t2 [ "a"; "d" ] in + Alcotest.(check bool) "mem-ad" true b3; + let* v1' = S.get t2 [ "a"; "d" ] in + check S.contents_t "v1" v1 v1'; + S.Head.set t2 r2 >>= fun () -> + let* b4 = S.mem t2 [ "a"; "d" ] in + Alcotest.(check bool) "mem-ab" false b4; + S.Head.set t2 full >>= fun () -> + S.Head.set t2 r2 >>= fun () -> + let* b4 = S.mem t2 [ "a"; "d" ] in + Alcotest.(check bool) "mem-ad" false b4; + B.Repo.close repo + in + run x test + + module Dot = Irmin.Dot (S) + + let output_file x t file = + let buf = Buffer.create 1024 in + let date d = + let tm = Unix.localtime (Int64.to_float d) in + Fmt.str "%2d:%2d:%2d" tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec + in + Dot.output_buffer t ~date buf >>= fun () -> + let oc = + open_out_bin + (Filename.get_temp_dir_name () / Fmt.str "%s-%s.dot" x.name file) + in + output_string oc (Buffer.contents buf); + close_out oc; + Lwt.return_unit + + let test_merge ?hook x () = + let test repo = + let v1 = "X1" in + let v2 = "X2" in + let v3 = "X3" in + let* t1 = S.main repo in + let* () = + S.set_exn t1 ~info:(infof "update a/b/a") [ "a"; "b"; "a" ] v1 + in + let* () = + S.set_exn t1 ~info:(infof "update a/b/b") [ "a"; "b"; "b" ] v2 + in + let* () = + S.set_exn t1 ~info:(infof "update a/b/c") [ "a"; "b"; "c" ] v3 + in + let test = "test" in + let* t2 = S.clone ~src:t1 ~dst:test in + let* () = + S.set_exn t1 ~info:(infof "update main:a/b/b") [ "a"; "b"; "b" ] v1 + in + let* () = + S.set_exn t1 ~info:(infof "update main:a/b/b") [ "a"; "b"; "b" ] v3 + in + let* () = + S.set_exn t2 ~info:(infof "update test:a/b/c") [ "a"; "b"; "c" ] v1 + in + output_file x t1 "before" >>= fun () -> + let* m = S.merge_into ~info:(infof "merge test into main") t2 ~into:t1 in + merge_exn "m" m >>= fun () -> + may_with_branch [ t1 ] repo hook >>= fun () -> + output_file x t1 "after" >>= fun () -> + let* v1' = S.get t1 [ "a"; "b"; "c" ] in + let* v2' = S.get t2 [ "a"; "b"; "b" ] in + let* v3' = S.get t1 [ "a"; "b"; "b" ] in + check S.contents_t "v1" v1 v1'; + check S.contents_t "v2" v2 v2'; + check S.contents_t "v3" v3 v3'; + B.Repo.close repo + in + run x test + + (* in this test an outdated reference to a tree is used by a commit: [tree] is + the tree with root [x] created by [c1] and modified by [c2]. [c3] reuse [tree] + which implicitly deletes the changes of [c2]. *) + let test_merge_outdated_tree x () = + let check_val = check T.(option S.contents_t) in + let none_fail f msg = + f >>= function None -> Alcotest.fail msg | Some c -> Lwt.return c + in + let test repo = + let vx = "VX" in + let vy = "VY" in + let old () = Lwt.return (Ok None) in + let* t = S.main repo in + S.set_exn t ~info:(infof "add x/y/z") [ "x"; "y"; "z" ] vx >>= fun () -> + let* _c1 = none_fail (S.Head.find t) "head not found" in + let* tree = S.get_tree t [ "x" ] in + S.set_exn t ~info:(infof "add u/x/y") [ "u"; "x"; "y" ] vy >>= fun () -> + let* c2 = none_fail (S.Head.find t) "head not found" in + let* tree3 = S.Tree.add tree [ "x"; "z" ] vx in + S.set_tree_exn t ~info:(infof "update") [ "u" ] tree3 >>= fun () -> + let* c3 = none_fail (S.Head.find t) "head not found" in + let info () = S.Commit.info c3 in + with_commit repo (fun commit_t -> + Irmin.Merge.f + (B.Commit.merge commit_t ~info) + ~old + (Some (S.Commit.key c3)) + (Some (S.Commit.key c2))) + >>= merge_exn "commit" + >>= function + | None -> Lwt.return_unit + | Some c4 -> + let* k = none_fail (S.Commit.of_key repo c4) "of hash" in + S.Branch.set repo "foo" k >>= fun () -> + let* t = S.of_branch repo "foo" in + let* vy' = S.find t [ "u"; "x"; "y" ] in + check_val "vy after merge" None vy'; + B.Repo.close repo + in + run x test + + let test_merge_unrelated ?hook x () = + run x @@ fun repo -> + let v1 = "X1" in + let* foo = S.of_branch repo "foo" in + let* bar = S.of_branch repo "bar" in + S.set_exn foo ~info:(infof "update foo:a") [ "a" ] v1 >>= fun () -> + S.set_exn bar ~info:(infof "update bar:b") [ "b" ] v1 >>= fun () -> + may_with_branch [ foo; bar ] repo hook >>= fun () -> + let* _ = + S.merge_into ~info:(infof "merge bar into foo") bar ~into:foo + >>= merge_exn "merge unrelated" + in + B.Repo.close repo + + let rec write fn = function + | 0 -> [] + | i -> (fun () -> fn i >>= Lwt.pause) :: write fn (i - 1) + + let perform l = Lwt_list.iter_p (fun f -> f ()) l + + let rec read fn check = function + | 0 -> [] + | i -> (fun () -> fn i >|= fun v -> check i v) :: read fn check (i - 1) + + let test_concurrent_low x () = + let test_branches repo = + let k = b1 in + let* v = r1 ~repo in + let write = write (fun _i -> S.Branch.set repo k v) in + let read = + read + (fun _i -> S.Branch.find repo k >|= get) + (fun i -> check (S.commit_t repo) (Fmt.str "tag %d" i) v) + in + perform (write 1) >>= fun () -> + perform (write 10 @ read 10 @ write 10 @ read 10) + in + let test_contents repo = + let* k = kv2 ~repo in + let v = v2 in + let t = B.Repo.contents_t repo in + let write = + write (fun _i -> + let* _ = with_contents repo (fun t -> B.Contents.add t v) in + Lwt.return_unit) + in + let read = + read + (fun _i -> B.Contents.find t k >|= get) + (fun i -> check S.contents_t (Fmt.str "contents %d" i) v) + in + perform (write 1) >>= fun () -> + perform (write 10 @ read 10 @ write 10 @ read 10) + in + run x (fun repo -> + Lwt.choose [ test_branches repo; test_contents repo ] >>= fun () -> + B.Repo.close repo) + + let test_concurrent_updates x () = + let test_one repo = + let k = [ "a"; "b"; "d" ] in + let v = "X1" in + let* t1 = S.main repo in + let* t2 = S.main repo in + let write t = + write (fun i -> S.set_exn t ~info:(infof "update: one %d" i) k v) + in + let read t = + read + (fun _ -> S.get t k) + (fun i -> check S.contents_t (Fmt.str "update: one %d" i) v) + in + perform (write t1 10 @ write t2 10) >>= fun () -> perform (read t1 10) + in + let test_multi repo = + let k i = [ "a"; "b"; "c"; string_of_int i ] in + let v i = Fmt.str "X%d" i in + let* t1 = S.main repo in + let* t2 = S.main repo in + let write t = + write (fun i -> + S.set_exn t ~info:(infof "update: multi %d" i) (k i) (v i)) + in + let read t = + read + (fun i -> S.get t (k i)) + (fun i -> check S.contents_t (Fmt.str "update: multi %d" i) (v i)) + in + perform (write t1 10 @ write t2 10) >>= fun () -> perform (read t1 10) + in + run x (fun repo -> + test_one repo >>= fun () -> + test_multi repo >>= fun () -> B.Repo.close repo) + + let test_concurrent_merges x () = + let test repo = + let k i = [ "a"; "b"; "c"; string_of_int i ] in + let v i = Fmt.str "X%d" i in + let* t1 = S.main repo in + let* t2 = S.main repo in + let write t n = + write (fun i -> + let tag = Fmt.str "tmp-%d-%d" n i in + let* m = S.clone ~src:t ~dst:tag in + S.set_exn m ~info:(infof "update") (k i) (v i) >>= fun () -> + Lwt.pause () >>= fun () -> + S.merge_into ~info:(infof "update: multi %d" i) m ~into:t + >>= merge_exn "update: multi") + in + let read t = + read + (fun i -> S.get t (k i)) + (fun i -> check S.contents_t (Fmt.str "update: multi %d" i) (v i)) + in + S.set_exn t1 ~info:(infof "update") (k 0) (v 0) >>= fun () -> + perform (write t1 1 10 @ write t2 2 10) >>= fun () -> + perform (read t1 10) >>= fun () -> B.Repo.close repo + in + run x test + + let pp_write_error = Irmin.Type.pp S.write_error_t + let tree_t = testable S.tree_t + + let test_with_tree x () = + let test repo = + let* t = S.main repo in + let update ?retries key strategy r w = + S.with_tree t ?retries ~info:(infof "with-tree") ~strategy key (fun _ -> + let+ v = Lwt_mvar.take r in + Some (S.Tree.of_contents v)) + >>= Lwt_mvar.put w + in + let check_ok = function + | Ok () -> () + | Error e -> Alcotest.failf "%a" pp_write_error e + in + let check_test e = function + | Error (`Test_was e') -> + Alcotest.(check (option tree_t)) "test-was" e e' + | Ok () -> Alcotest.fail "error expected" + | Error e -> + Alcotest.failf "an other error was expected: %a" pp_write_error e + in + let check_conflict = function + | Error (`Conflict _) -> () + | Ok () -> Alcotest.fail "error expected" + | Error e -> + Alcotest.failf "an other error was expected: %a" pp_write_error e + in + let set () = + let rx = Lwt_mvar.create_empty () in + let wx = Lwt_mvar.create_empty () in + let ry = Lwt_mvar.create_empty () in + let wy = Lwt_mvar.create_empty () in + S.set_exn t ~info:(infof "init") [ "a" ] "0" >>= fun () -> + Lwt.join + [ + update [ "a" ] ~retries:0 `Set rx wx; + update [ "a" ] ~retries:0 `Set ry wy; + ( Lwt_mvar.put rx "1" >>= fun () -> + Lwt_mvar.take wx >|= check_ok >>= fun () -> + let* a = S.get t [ "a" ] in + Alcotest.(check string) "set x" "1" a; + Lwt_mvar.put ry "2" >>= fun () -> + Lwt_mvar.take wy >|= check_ok >>= fun () -> + let+ a = S.get t [ "a" ] in + Alcotest.(check string) "set y" "2" a ); + ] + in + let test_and_set () = + let rx = Lwt_mvar.create_empty () in + let wx = Lwt_mvar.create_empty () in + let ry = Lwt_mvar.create_empty () in + let wy = Lwt_mvar.create_empty () in + let rz = Lwt_mvar.create_empty () in + let wz = Lwt_mvar.create_empty () in + S.set_exn t ~info:(infof "init") [ "a" ] "0" >>= fun () -> + Lwt.join + [ + update [ "a" ] ~retries:0 `Test_and_set rx wx; + update [ "a" ] ~retries:0 `Test_and_set ry wy; + update [ "a" ] ~retries:1 `Test_and_set rz wz; + ( Lwt_mvar.put rx "1" >>= fun () -> + Lwt_mvar.take wx >|= check_ok >>= fun () -> + let* a = S.get t [ "a" ] in + Alcotest.(check string) "test-and-set x" "1" a; + Lwt_mvar.put ry "2" >>= fun () -> + let* e = Lwt_mvar.take wy in + check_test (Some (S.Tree.of_contents "1")) e; + let* a = S.get t [ "a" ] in + Alcotest.(check string) "test-and-set y" "1" a; + Lwt_mvar.put rz "3" >>= fun () -> + (* there's a conflict, the transaction is restarted so need to feed a + new value *) + Lwt_mvar.put rz "4" >>= fun () -> + Lwt_mvar.take wz >|= check_ok >>= fun () -> + let+ a = S.get t [ "a" ] in + Alcotest.(check string) "test-and-set z" "4" a ); + ] + in + let merge () = + let rx = Lwt_mvar.create_empty () in + let wx = Lwt_mvar.create_empty () in + let ry = Lwt_mvar.create_empty () in + let wy = Lwt_mvar.create_empty () in + let rz = Lwt_mvar.create_empty () in + let wz = Lwt_mvar.create_empty () in + S.set_exn t ~info:(infof "init") [ "a" ] "0" >>= fun () -> + Lwt.join + [ + update [ "a" ] ~retries:0 `Merge rx wx; + update [ "a" ] ~retries:0 `Merge ry wy; + update [ "a" ] ~retries:1 `Merge rz wz; + ( Lwt_mvar.put rx "1" >>= fun () -> + Lwt_mvar.take wx >|= check_ok >>= fun () -> + let* a = S.get t [ "a" ] in + Alcotest.(check string) "merge x" "1" a; + Lwt_mvar.put ry "2" >>= fun () -> + Lwt_mvar.take wy >|= check_conflict >>= fun () -> + let* a = S.get t [ "a" ] in + Alcotest.(check string) "merge y" a "1"; + Lwt_mvar.put rz "3" >>= fun () -> + (* there's a conflict, the transaction is restarted so need to feed a + new value *) + Lwt_mvar.put rz "4" >>= fun () -> + Lwt_mvar.take wz >|= check_ok >>= fun () -> + let+ a = S.get t [ "a" ] in + Alcotest.(check string) "merge z" a "4" ); + ] + in + set () >>= test_and_set >>= merge >>= fun () -> B.Repo.close repo + in + run x test + + let test_concurrent_head_updates x () = + let test repo = + let k i = [ "a"; "b"; "c"; string_of_int i ] in + let v i = Fmt.str "X%d" i in + let* t1 = S.main repo in + let* t2 = S.main repo in + let retry d fn = + let rec aux i = + fn () >>= function + | true -> + [%log.debug "%d: ok!" d]; + Lwt.return_unit + | false -> + [%log.debug "%d: conflict, retrying (%d)." d i]; + aux (i + 1) + in + aux 1 + in + let write t n = + write (fun i -> + retry i (fun () -> + let* test = S.Head.find t in + let tag = Fmt.str "tmp-%d-%d" n i in + let* m = S.clone ~src:t ~dst:tag in + S.set_exn m ~info:(infof "update") (k i) (v i) >>= fun () -> + let* set = S.Head.find m in + Lwt.pause () >>= fun () -> S.Head.test_and_set t ~test ~set)) + in + let read t = + read + (fun i -> S.get t (k i)) + (fun i -> check S.contents_t (Fmt.str "update: multi %d" i) (v i)) + in + S.set_exn t1 ~info:(infof "update") (k 0) (v 0) >>= fun () -> + perform (write t1 1 5 @ write t2 2 5) >>= fun () -> + perform (read t1 5) >>= fun () -> B.Repo.close repo + in + run x test + + let test_shallow_objects x () = + let test repo = + (* NOTE: A store of type `Irmin.Generic_key.S` does not currently expose + functions for building nodes / commits with non-existent children, due to + the need to have _keys_ for all store pointers. + + A future version of this API may support such operations (e.g. for + constructing Merkle proofs), but until then we must synthesise test keys + by adding test values to the correponding backend stores directly. *) + let contents (s : string) : S.contents_key Lwt.t = + with_contents repo (fun c -> B.Contents.add c s) + in + let node (s : string) : S.node_key Lwt.t = + with_node repo (fun n -> + let* contents = contents s in + let node = B.Node.Val.(add (empty ())) s (normal contents) in + B.Node.add n node) + in + let commit (s : string) : S.commit_key Lwt.t = + with_commit repo (fun c -> + let* node = node s in + let commit = B.Commit.Val.v ~info:(info "") ~node ~parents:[] in + B.Commit.add c commit) + in + let* foo_k = node "foo" in + let* bar_k = node "bar" in + let tree_1 = S.Tree.shallow repo (`Node foo_k) in + let tree_2 = S.Tree.shallow repo (`Node bar_k) in + let* node_3 = + let+ contents_foo = contents "foo" in + S.Backend.Node.Val.of_list + [ + ("foo", `Contents (contents_foo, S.Metadata.default)); + ("bar", `Node bar_k); + ] + in + let tree_3 = S.Tree.of_node (S.of_backend_node repo node_3) in + let* _ = + S.Backend.Repo.batch repo (fun c n _ -> S.save_tree repo c n tree_3) + in + let key_3 = get_node_key (Option.get (S.Tree.key tree_3)) in + let info () = info "shallow" in + let* t = S.main repo in + S.set_tree_exn t [ "1" ] tree_1 ~info >>= fun () -> + S.set_tree_exn t [ "2" ] tree_2 ~info >>= fun () -> + let* h = S.Head.get t in + let* commit_v = + let+ commit_foo = commit "foo" in + S.Backend.Commit.Val.v ~info:(info ()) ~node:key_3 + ~parents:[ S.Commit.key h; commit_foo ] + in + let* commit_key = with_commit repo (fun c -> B.Commit.add c commit_v) in + let commit = S.of_backend_commit repo commit_key commit_v in + S.set_tree_exn t [ "3" ] ~parents:[ commit ] tree_3 ~info >>= fun () -> + let* t1 = S.find_tree t [ "1" ] in + Alcotest.(check (option tree_t)) "shallow tree" (Some tree_1) t1; + B.Repo.close repo + in + run x test + + let test_pre_hash_collisions x () = + let pre_hash_of ty = + let f = Irmin.Type.(pre_hash ty |> unstage) in + fun x -> + let buf = Buffer.create 0 in + f x (Buffer.add_string buf); + Buffer.contents buf + in + let rec add_entries acc = function + | 0 -> Lwt.return acc + | i -> + let s = string_of_int i in + let* acc = S.Tree.add acc [ s ] s in + add_entries acc (i - 1) + in + let equal_hash = Irmin.Type.(equal S.Hash.t |> unstage) in + let test create_tree repo = + let* tree = create_tree () in + let* c = S.Commit.v repo ~info:S.Info.empty ~parents:[] tree in + + let* node_b = + S.Tree.destruct tree + |> (function `Contents _ -> assert false | `Node n -> n) + |> S.to_backend_node + in + let node_ph = pre_hash_of S.Backend.Node.Val.t node_b in + let node_h = S.Backend.Node.Hash.hash node_b in + + let commit_b = S.to_backend_commit c in + let commit_ph = pre_hash_of S.Backend.Commit.Val.t commit_b in + let commit_h = S.Backend.Commit.Hash.hash commit_b in + + let* blob_k = + with_contents repo (fun t -> S.Backend.Contents.add t node_ph) + in + let blob_h = S.Backend.Contents.Key.to_hash blob_k in + if equal_hash node_h blob_h then + Alcotest.failf + "node pre-hash attack succeeded. pre-hash is \"%s\". backend node is \ + %a." + (String.escaped node_ph) + (Irmin.Type.pp S.Backend.Node.Val.t) + node_b; + + let* blob_k = + with_contents repo (fun t -> S.Backend.Contents.add t commit_ph) + in + let blob_h = S.Backend.Contents.Key.to_hash blob_k in + if equal_hash commit_h blob_h then + Alcotest.failf + "commit pre-hash attack succeeded. pre-hash is \"%s\". backend \ + commit is %a." + (String.escaped commit_ph) + (Irmin.Type.pp S.Backend.Commit.Val.t) + commit_b; + + S.Backend.Repo.close repo + in + (* Test collisions with the empty node (and its commit), *) + let* () = run x (test @@ fun () -> S.Tree.empty () |> Lwt.return) in + (* with a length one node, *) + run x (test @@ fun () -> add_entries (S.Tree.empty ()) 1) >>= fun () -> + (* and with a length >256 node (which is the threshold for unstable inodes + in irmin pack). *) + run x (test @@ fun () -> add_entries (S.Tree.empty ()) 260) +end + +let suite' l ?(prefix = "") (_, x) = + let (module S) = Suite.store_generic_key x in + let module T = Make (S) in + (prefix ^ x.name, l) + +let when_ b x = if b then x else [] + +let suite sleep (speed, x) = + let (module S) = Suite.store_generic_key x in + let module Zzz = struct + let sleep = sleep + end in + let module T = Make (S) in + let module T_graph = Store_graph.Make (S) in + let module T_watch = Store_watch.Make (Log) (Zzz) (S) in + let with_tree_enabled = + (* Disabled for flakiness. See https://github.com/mirage/irmin/issues/1090. *) + not + (List.mem ~equal:String.equal (Suite.name x) + [ + "FS"; + "FS.UNIX"; + "GIT"; + "GIT.UNIX"; + "HTTP.FS"; + "HTTP.FS.UNIX"; + "HTTP.GIT"; + "HTTP.GIT.UNIX"; + ]) + in + suite' + ([ + ("High-level operations on trees", speed, T.test_trees x); + ("Basic operations on contents", speed, T.test_contents x); + ("Basic operations on nodes", speed, T.test_nodes x); + ("Basic operations on commits", speed, T.test_commits x); + ("Basic operations on branches", speed, T.test_branches x); + ("Hash operations on trees", speed, T.test_tree_hashes x); + ("Basic merge operations", speed, T.test_simple_merges x); + ("Test merges on tree updates", speed, T.test_merge_outdated_tree x); + ("Tree caches and hashconsing", speed, T.test_tree_caches x); + ("Tree proofs", speed, T.test_proofs x); + ("Complex histories", speed, T.test_history x); + ("Empty stores", speed, T.test_empty x); + ("Backend node manipulation", speed, T.test_backend_nodes x); + ("High-level store operations", speed, T.test_stores x); + ("High-level atomic store operations", speed, T.test_atomic x); + ("High-level store merges", speed, T.test_merge x); + ("Unrelated merges", speed, T.test_merge_unrelated x); + ("Low-level concurrency", speed, T.test_concurrent_low x); + ("Concurrent updates", speed, T.test_concurrent_updates x); + ("Concurrent head updates", speed, T.test_concurrent_head_updates x); + ("Concurrent merges", speed, T.test_concurrent_merges x); + ("Shallow objects", speed, T.test_shallow_objects x); + ("Closure with disconnected commits", speed, T.test_closure x); + ("Prehash collisions", speed, T.test_pre_hash_collisions x); + ] + @ when_ x.import_supported + [ + ("Basic operations on slices", speed, T.test_slice x); + ("High-level store synchronisation", speed, T.test_sync x); + ] + @ when_ with_tree_enabled + [ ("with_tree strategies", speed, T.test_with_tree x) ] + @ List.map (fun (n, test) -> ("Graph." ^ n, speed, test x)) T_graph.tests + @ List.map (fun (n, test) -> ("Watch." ^ n, speed, test x)) T_watch.tests) + (speed, x) + +let slow_suite (speed, x) = + let (module S) = Suite.store_generic_key x in + let module T = Make (S) in + suite' ~prefix:"SLOW_" + [ + ("Commit wide node", speed, T.test_commit_wide_node x); + ("Wide nodes", `Slow, T.test_wide_nodes x); + ] + (speed, x) + +let run name ?(slow = false) ?random_seed ~sleep ~misc tl = + let () = + match random_seed with + | Some x -> Random.init x + | None -> Random.self_init () + in + Printexc.record_backtrace true; + (* Ensure that failures occuring in async lwt threads are raised. *) + (Lwt.async_exception_hook := fun exn -> raise exn); + let tl1 = List.map (suite sleep) tl in + let tl1 = if slow then tl1 @ List.map slow_suite tl else tl1 in + Alcotest_lwt.run name (misc @ tl1) diff --git a/vendors/irmin/src/irmin-test/store.mli b/vendors/irmin/src/irmin-test/store.mli new file mode 100644 index 000000000000..57aeeb89dc4b --- /dev/null +++ b/vendors/irmin/src/irmin-test/store.mli @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val run : + string -> + ?slow:bool -> + ?random_seed:int -> + sleep:(float -> unit Lwt.t) -> + misc:unit Alcotest_lwt.test list -> + (Alcotest.speed_level * Common.t) list -> + unit Lwt.t diff --git a/vendors/irmin/src/irmin-test/store_graph.ml b/vendors/irmin/src/irmin-test/store_graph.ml new file mode 100644 index 000000000000..2d576ea5d666 --- /dev/null +++ b/vendors/irmin/src/irmin-test/store_graph.ml @@ -0,0 +1,209 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +module Make (S : Generic_key) = struct + include Common.Make_helpers (S) + + let test_iter x () = + let test repo = + let pp_id = Irmin.Type.pp S.Tree.kinded_key_t in + let eq_id = Irmin.Type.(unstage (equal S.Tree.kinded_key_t)) in + let mem k ls = List.exists (fun k' -> eq_id k k') ls in + let visited = ref [] in + let skipped = ref [] in + let rev_order oldest k = + if !visited = [] && not (eq_id k oldest) then + Alcotest.fail "traversal should start with oldest node" + in + let in_order oldest k = + if !visited = [] && eq_id k oldest then + Alcotest.fail "traversal shouldn't start with oldest node" + in + let node k = + if mem (`Node k) !visited then + Alcotest.failf "node %a visited twice" (Irmin.Type.pp B.Node.Key.t) k; + visited := `Node k :: !visited; + Lwt.return_unit + in + let contents ?order k = + let e = `Contents (k, S.Metadata.default) in + if mem e !visited then + Alcotest.failf "contents %a visited twice" + (Irmin.Type.pp B.Contents.Key.t) + k; + (match order with None -> () | Some f -> f e); + visited := e :: !visited; + Lwt.return_unit + in + let test_rev_order ~nodes ~max = + let oldest = List.hd nodes in + let contents = contents ~order:(rev_order oldest) in + let+ () = + Graph.iter (g repo) ~min:[] ~max ~node ~contents ~rev:true () + in + List.iter + (fun k -> + if not (mem k !visited) then + Alcotest.failf "%a should be visited" + (Irmin.Type.pp S.Tree.kinded_key_t) + k) + nodes + in + let test_in_order ~nodes ~max = + let oldest = List.hd nodes in + let contents = contents ~order:(in_order oldest) in + let+ () = + Graph.iter (g repo) ~min:[] ~max ~node ~contents ~rev:false () + in + List.iter + (fun k -> + if not (mem k !visited) then + Alcotest.failf "%a should be visited" pp_id k) + nodes + in + let test_skip ~max ~to_skip ~not_visited = + let skip_node k = + if mem (`Node k) to_skip then ( + skipped := `Node k :: !skipped; + Lwt.return_true) + else Lwt.return_false + in + let+ () = + Graph.iter (g repo) ~min:[] ~max ~node ~contents ~skip_node ~rev:false + () + in + List.iter + (fun k -> + if mem k !visited || not (mem k !skipped) then + Alcotest.failf "%a should be skipped" pp_id k) + to_skip; + List.iter + (fun k -> + if mem k !visited || mem k !skipped then + Alcotest.failf "%a should not be skipped nor visited" pp_id k) + not_visited + in + let test_min_max ~nodes ~min ~max ~not_visited = + Graph.iter (g repo) ~min ~max ~node ~contents ~rev:false () + >|= fun () -> + List.iter + (fun k -> + if mem k not_visited && mem k !visited then + Alcotest.failf "%a should not be visited" pp_id k; + if (not (mem k not_visited)) && not (mem k !visited) then + Alcotest.failf "%a should not be visited" pp_id k) + nodes + in + let test1 () = + let* foo = with_contents repo (fun c -> B.Contents.add c "foo") in + let foo_k = (foo, S.Metadata.default) in + let* k1 = with_node repo (fun g -> Graph.v g [ ("b", normal foo) ]) in + let* k2 = with_node repo (fun g -> Graph.v g [ ("a", `Node k1) ]) in + let* k3 = with_node repo (fun g -> Graph.v g [ ("c", `Node k1) ]) in + let nodes = [ `Contents foo_k; `Node k1; `Node k2; `Node k3 ] in + visited := []; + test_rev_order ~nodes ~max:[ k2; k3 ] >>= fun () -> + visited := []; + test_in_order ~nodes ~max:[ k2; k3 ] >>= fun () -> + visited := []; + skipped := []; + test_skip ~max:[ k2; k3 ] ~to_skip:[ `Node k1 ] ~not_visited:[] + >>= fun () -> + visited := []; + let* () = + test_min_max ~nodes ~min:[ k1 ] ~max:[ k2 ] + ~not_visited:[ `Contents foo_k; `Node k3 ] + in + visited := []; + test_min_max ~nodes ~min:[ k2; k3 ] ~max:[ k2; k3 ] + ~not_visited:[ `Contents foo_k; `Node k1 ] + in + let test2 () = + (* Graph.iter requires a node as max, we cannot test a graph with only + contents. *) + let* foo = with_contents repo (fun c -> B.Contents.add c "foo") in + let foo_k = (foo, S.Metadata.default) in + let* k1 = with_node repo (fun g -> Graph.v g [ ("b", normal foo) ]) in + visited := []; + test_rev_order ~nodes:[ `Contents foo_k; `Node k1 ] ~max:[ k1 ] + >>= fun () -> + visited := []; + skipped := []; + test_skip ~max:[ k1 ] + ~to_skip:[ `Node k1 ] + ~not_visited:[ `Contents foo_k ] + in + let test3 () = + let* foo = with_contents repo (fun c -> B.Contents.add c "foo") in + let foo_k = (foo, S.Metadata.default) in + let* kb1 = with_node repo (fun g -> Graph.v g [ ("b1", normal foo) ]) in + let* ka1 = with_node repo (fun g -> Graph.v g [ ("a1", `Node kb1) ]) in + let* ka2 = with_node repo (fun g -> Graph.v g [ ("a2", `Node kb1) ]) in + let* kb2 = with_node repo (fun g -> Graph.v g [ ("b2", normal foo) ]) in + let* kc = + with_node repo (fun g -> + Graph.v g + [ ("c1", `Node ka1); ("c2", `Node ka2); ("c3", `Node kb2) ]) + in + let nodes = + [ + `Contents foo_k; + `Node kb1; + `Node ka1; + `Node ka2; + `Node kb2; + `Node kc; + ] + in + visited := []; + test_rev_order ~nodes ~max:[ kc ] >>= fun () -> + visited := []; + test_in_order ~nodes ~max:[ kc ] >>= fun () -> + visited := []; + skipped := []; + let* () = + test_skip ~max:[ kc ] + ~to_skip:[ `Node ka1; `Node ka2 ] + ~not_visited:[ `Node kb1 ] + in + visited := []; + skipped := []; + let* () = + test_skip ~max:[ kc ] + ~to_skip:[ `Node ka1; `Node ka2; `Node kb2 ] + ~not_visited:[ `Node kb1; `Contents foo_k ] + in + visited := []; + let* () = + test_min_max ~nodes ~min:[ kb1 ] ~max:[ ka1 ] + ~not_visited:[ `Contents foo_k; `Node ka2; `Node kb2; `Node kc ] + in + visited := []; + test_min_max ~nodes ~min:[ kc ] ~max:[ kc ] + ~not_visited: + [ `Contents foo_k; `Node kb1; `Node ka1; `Node ka2; `Node kb2 ] + in + test1 () >>= fun () -> + test2 () >>= fun () -> + test3 () >>= fun () -> B.Repo.close repo + in + run x test + + let tests = [ ("Iter", test_iter) ] +end diff --git a/vendors/irmin/src/irmin-test/store_graph.mli b/vendors/irmin/src/irmin-test/store_graph.mli new file mode 100644 index 000000000000..5e5cf9415ee4 --- /dev/null +++ b/vendors/irmin/src/irmin-test/store_graph.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make : Common.Store_tests diff --git a/vendors/irmin/src/irmin-test/store_watch.ml b/vendors/irmin/src/irmin-test/store_watch.ml new file mode 100644 index 000000000000..eb14afc329d4 --- /dev/null +++ b/vendors/irmin/src/irmin-test/store_watch.ml @@ -0,0 +1,379 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +module type Sleep = sig + val sleep : float -> unit Lwt.t +end + +module Make (Log : Logs.LOG) (Zzz : Sleep) (S : Generic_key) = struct + include Common.Make_helpers (S) + + let sleep ?(sleep_t = 0.01) () = + let sleep_t = min sleep_t 1. in + Lwt.pause () >>= fun () -> Zzz.sleep sleep_t + + let now_s () = Mtime.Span.to_s (Mtime_clock.elapsed ()) + + (* Re-apply [f] at intervals of [sleep_t] while [f] raises exceptions and + [while_ ()] holds. *) + let retry ?(timeout = 15.) ?(sleep_t = 0.) ~while_ fn = + let sleep_t = max sleep_t 0.001 in + let t = now_s () in + let str i = Fmt.str "%d, %.3fs" i (now_s () -. t) in + let rec aux i = + if now_s () -. t > timeout || not (while_ ()) then fn (str i); + try + fn (str i); + Lwt.return_unit + with ex -> + [%log.debug "retry ex: %s" (Printexc.to_string ex)]; + let sleep_t = sleep_t *. (1. +. (float i ** 2.)) in + sleep ~sleep_t () >>= fun () -> + [%log.debug "Test.retry %s" (str i)]; + aux (i + 1) + in + aux 0 + + let test_watch_exn x () = + let test repo = + let* t = S.main repo in + let* h = S.Head.find t in + let key = [ "a" ] in + let v1 = "bar" in + let v2 = "foo" in + let r = ref 0 in + let eq = Irmin.Type.(unstage (equal (Irmin.Diff.t (S.commit_t repo)))) in + let old_head = ref h in + let check x = + let+ h2 = S.Head.get t in + match !old_head with + | None -> if eq (`Added h2) x then incr r + | Some h -> if eq (`Updated (h, h2)) x then incr r + in + let* u = + S.watch ?init:h t (fun v -> check v >|= fun () -> failwith "test") + in + let* v = + S.watch ?init:h t (fun v -> check v >>= fun () -> Lwt.fail_with "test") + in + let* w = S.watch ?init:h t (fun v -> check v) in + S.set_exn t ~info:(infof "update") key v1 >>= fun () -> + let* () = + retry + ~while_:(fun () -> !r < 3) + (fun n -> Alcotest.(check int) ("watch 1 " ^ n) 3 !r) + in + let* h = S.Head.find t in + old_head := h; + S.set_exn t ~info:(infof "update") key v2 >>= fun () -> + let* () = + retry + ~while_:(fun () -> !r < 6) + (fun n -> Alcotest.(check int) ("watch 2 " ^ n) 6 !r) + in + S.unwatch u >>= fun () -> + S.unwatch v >>= fun () -> + S.unwatch w >>= fun () -> + let* h = S.Head.get t in + old_head := Some h; + let* u = + S.watch_key ~init:h t key (fun _ -> + incr r; + failwith "test") + in + let* v = + S.watch_key ~init:h t key (fun _ -> + incr r; + Lwt.fail_with "test") + in + let* w = + S.watch_key ~init:h t key (fun _ -> + incr r; + Lwt.return_unit) + in + S.set_exn t ~info:(infof "update") key v1 >>= fun () -> + let* () = + retry + ~while_:(fun () -> !r < 9) + (fun n -> Alcotest.(check int) ("watch 3 " ^ n) 9 !r) + in + S.set_exn t ~info:(infof "update") key v2 >>= fun () -> + let* () = + retry + ~while_:(fun () -> !r < 12) + (fun n -> Alcotest.(check int) ("watch 4 " ^ n) 12 !r) + in + S.unwatch u >>= fun () -> + S.unwatch v >>= fun () -> + S.unwatch w >>= fun () -> + Alcotest.(check unit) "ok!" () (); + B.Repo.close repo + in + run x test + + let test_watches x () = + let pp_w ppf (p, w) = Fmt.pf ppf "%d/%d" p w in + let pp_s ppf = function + | None -> Fmt.string ppf "*" + | Some w -> pp_w ppf (w ()) + in + let check_workers msg p w = + match x.stats with + | None -> Lwt.return_unit + | Some stats -> + retry + ~while_:(fun _ -> true) + (fun s -> + let got = stats () in + let exp = (p, w) in + let msg = Fmt.str "workers: %s %a (%s)" msg pp_w got s in + if got = exp then line msg + else ( + [%log.debug + "check-worker: expected %a, got %a" pp_w exp pp_w got]; + Alcotest.failf "%s: %a / %a" msg pp_w got pp_w exp)) + in + let module State = struct + type t = { + mutable adds : int; + mutable updates : int; + mutable removes : int; + } + + let pp ppf { adds; updates; removes } = + Fmt.pf ppf "{ adds=%d; updates=%d; removes=%d }" adds updates removes + + let empty () = { adds = 0; updates = 0; removes = 0 } + + let add t = + [%log.debug "add %a" pp t]; + t.adds <- t.adds + 1 + + let update t = + [%log.debug "update %a" pp t]; + t.updates <- t.updates + 1 + + let remove t = + [%log.debug "remove %a" pp t]; + t.removes <- t.removes + 1 + + let pretty ppf t = Fmt.pf ppf "%d/%d/%d" t.adds t.updates t.removes + let xpp ppf (a, u, r) = Fmt.pf ppf "%d/%d/%d" a u r + let xadd (a, u, r) = (a + 1, u, r) + let xupdate (a, u, r) = (a, u + 1, r) + let xremove (a, u, r) = (a, u, r + 1) + + let less_than a b = + a.adds <= b.adds + && a.updates <= b.updates + && a.removes <= b.removes + && not (a = b) + + let check ?sleep_t msg (p, w) (a_adds, a_updates, a_removes) b = + let a = { adds = a_adds; updates = a_updates; removes = a_removes } in + check_workers msg p w >>= fun () -> + retry ?sleep_t + ~while_:(fun () -> less_than b a (* While [b] converges toward [a] *)) + (fun s -> + let msg = Fmt.str "state: %s (%s)" msg s in + if a = b then line msg + else Alcotest.failf "%s: %a / %a" msg pp a pp b) + + let process ?sleep_t t head = + let* () = + match sleep_t with None -> Lwt.return_unit | Some s -> Zzz.sleep s + in + let () = + match head with + | `Added _ -> add t + | `Updated _ -> update t + | `Removed _ -> remove t + in + Lwt.return_unit + + let apply msg state kind fn ?(first = false) on s n = + let msg mode n w s = + let kind = + match kind with + | `Add -> "add" + | `Update -> "update" + | `Remove -> "remove" + in + let mode = + match mode with `Pre -> "[pre-condition]" | `Post -> "" + in + Fmt.str "%s %s %s %d on=%b expected=%a:%a current=%a:%a" mode msg kind + n on xpp s pp_w w pretty state pp_s x.stats + in + let check mode n w s = check (msg mode n w s) w s state in + let incr = + match kind with + | `Add -> xadd + | `Update -> xupdate + | `Remove -> xremove + in + let rec aux pre = function + | 0 -> Lwt.return_unit + | i -> + let pre_w = + if on then (1, if i = n && first then 0 else 1) else (0, 0) + in + let post_w = if on then (1, 1) else (0, 0) in + let post = if on then incr pre else pre in + (* check pre-condition *) + check `Pre (n - i) pre_w pre >>= fun () -> + [%log.debug "[waiting for] %s" (msg `Post (n - i) post_w post)]; + fn (n - i) >>= fun () -> + (* check post-condition *) + check `Post (n - i) post_w post >>= fun () -> aux post (i - 1) + in + aux s n + end in + let test repo1 = + let* t1 = S.main repo1 in + let* repo = S.Repo.v x.config in + let* t2 = S.main repo in + [%log.debug "WATCH"]; + let state = State.empty () in + let sleep_t = 0.02 in + let process = State.process ~sleep_t state in + let stops_0 = ref [] in + let stops_1 = ref [] in + let rec watch = function + | 0 -> Lwt.return_unit + | n -> + let t = if n mod 2 = 0 then t1 else t2 in + let* s = S.watch t process in + if n mod 2 = 0 then stops_0 := s :: !stops_0 + else stops_1 := s :: !stops_1; + watch (n - 1) + in + let v1 = "X1" in + let v2 = "X2" in + S.set_exn t1 ~info:(infof "update") [ "a"; "b" ] v1 >>= fun () -> + S.Branch.remove repo1 S.Branch.main >>= fun () -> + State.check "init" (0, 0) (0, 0, 0) state >>= fun () -> + watch 100 >>= fun () -> + State.check "watches on" (1, 0) (0, 0, 0) state >>= fun () -> + S.set_exn t1 ~info:(infof "update") [ "a"; "b" ] v1 >>= fun () -> + State.check "watches adds" (1, 1) (100, 0, 0) state >>= fun () -> + S.set_exn t2 ~info:(infof "update") [ "a"; "c" ] v1 >>= fun () -> + State.check "watches updates" (1, 1) (100, 100, 0) state >>= fun () -> + S.Branch.remove repo S.Branch.main >>= fun () -> + State.check "watches removes" (1, 1) (100, 100, 100) state >>= fun () -> + Lwt_list.iter_s (fun f -> S.unwatch f) !stops_0 >>= fun () -> + S.set_exn t2 ~info:(infof "update") [ "a" ] v1 >>= fun () -> + State.check "watches half off" (1, 1) (150, 100, 100) state >>= fun () -> + Lwt_list.iter_s (fun f -> S.unwatch f) !stops_1 >>= fun () -> + S.set_exn t1 ~info:(infof "update") [ "a" ] v2 >>= fun () -> + State.check "watches off" (0, 0) (150, 100, 100) state >>= fun () -> + [%log.debug "WATCH-ALL"]; + let state = State.empty () in + let* head = r1 ~repo in + let add = + State.apply "branch-watch-all" state `Add (fun n -> + let tag = Fmt.str "t%d" n in + S.Branch.set repo tag head) + in + let remove = + State.apply "branch-watch-all" state `Remove (fun n -> + let tag = Fmt.str "t%d" n in + S.Branch.remove repo tag) + in + let* main = S.Branch.get repo "main" in + let* u = + S.Branch.watch_all + ~init:[ ("main", main) ] + repo + (fun _ -> State.process state) + in + add true (0, 0, 0) 10 ~first:true >>= fun () -> + remove true (10, 0, 0) 5 >>= fun () -> + S.unwatch u >>= fun () -> + add false (10, 0, 5) 4 >>= fun () -> + remove false (10, 0, 5) 4 >>= fun () -> + [%log.debug "WATCH-KEY"]; + let state = State.empty () in + let path1 = [ "a"; "b"; "c" ] in + let path2 = [ "a"; "d" ] in + let path3 = [ "a"; "b"; "d" ] in + let add = + State.apply "branch-key" state `Add (fun _ -> + let v = "" in + S.set_exn t1 ~info:(infof "set1") path1 v >>= fun () -> + S.set_exn t1 ~info:(infof "set2") path2 v >>= fun () -> + S.set_exn t1 ~info:(infof "set3") path3 v >>= fun () -> + Lwt.return_unit) + in + let update = + State.apply "branch-key" state `Update (fun n -> + let v = string_of_int n in + S.set_exn t2 ~info:(infof "update1") path1 v >>= fun () -> + S.set_exn t2 ~info:(infof "update2") path2 v >>= fun () -> + S.set_exn t2 ~info:(infof "update3") path3 v >>= fun () -> + Lwt.return_unit) + in + let remove = + State.apply "branch-key" state `Remove (fun _ -> + S.remove_exn t1 ~info:(infof "remove1") path1 >>= fun () -> + S.remove_exn t1 ~info:(infof "remove2") path2 >>= fun () -> + S.remove_exn t1 ~info:(infof "remove3") path3 >>= fun () -> + Lwt.return_unit) + in + S.remove_exn t1 ~info:(infof "clean") [] >>= fun () -> + let* init = S.Head.get t1 in + let* u = S.watch_key t1 ~init path1 (State.process state) in + add true (0, 0, 0) 1 ~first:true >>= fun () -> + update true (1, 0, 0) 10 >>= fun () -> + remove true (1, 10, 0) 1 >>= fun () -> + S.unwatch u >>= fun () -> + add false (1, 10, 1) 3 >>= fun () -> + update false (1, 10, 1) 5 >>= fun () -> + remove false (1, 10, 1) 4 >>= fun () -> + [%log.debug "WATCH-MORE"]; + let state = State.empty () in + let update = + State.apply "watch-more" state `Update (fun n -> + let v = string_of_int n in + let path1 = [ "a"; "b"; "c"; string_of_int n; "1" ] in + let path2 = [ "a"; "x"; "c"; string_of_int n; "1" ] in + let path3 = [ "a"; "y"; "c"; string_of_int n; "1" ] in + S.set_exn t2 ~info:(infof "update1") path1 v >>= fun () -> + S.set_exn t2 ~info:(infof "update2") path2 v >>= fun () -> + S.set_exn t2 ~info:(infof "update3") path3 v >>= fun () -> + Lwt.return_unit) + in + S.remove_exn t1 ~info:(infof "remove") [ "a" ] >>= fun () -> + S.set_exn t1 ~info:(infof "prepare") [ "a"; "b"; "c" ] "" >>= fun () -> + let* h = S.Head.get t1 in + let* u = S.watch_key t2 ~init:h [ "a"; "b" ] (State.process state) in + update true (0, 0, 0) 10 ~first:true >>= fun () -> + S.unwatch u >>= fun () -> + update false (0, 10, 0) 10 >>= fun () -> + B.Repo.close repo >>= fun () -> B.Repo.close repo1 + in + run x test + + let tests = + (* [test_watches] has been disabled for being flaky. + TODO: work out why, fix it, and re-enable it. + See https://github.com/mirage/irmin/issues/1447. *) + let _ = ("Basic operations", test_watches) in + [ ("Callbacks and exceptions", test_watch_exn) ] +end diff --git a/vendors/irmin/src/irmin-test/store_watch.mli b/vendors/irmin/src/irmin-test/store_watch.mli new file mode 100644 index 000000000000..52f253c7bb3c --- /dev/null +++ b/vendors/irmin/src/irmin-test/store_watch.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (_ : Logs.LOG) (_ : Common.Sleep) : Common.Store_tests diff --git a/vendors/irmin/src/irmin-tezos/dune b/vendors/irmin/src/irmin-tezos/dune new file mode 100644 index 000000000000..93d3e85228c8 --- /dev/null +++ b/vendors/irmin/src/irmin-tezos/dune @@ -0,0 +1,6 @@ +(library + (name irmin_tezos) + (public_name irmin-tezos) + (libraries tezos-base58 digestif fmt irmin irmin-pack irmin-pack.unix) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin-tezos/irmin_tezos.ml b/vendors/irmin/src/irmin-tezos/irmin_tezos.ml new file mode 100644 index 000000000000..2b52362bdfad --- /dev/null +++ b/vendors/irmin/src/irmin-tezos/irmin_tezos.ml @@ -0,0 +1,28 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Schema = Schema + +module Conf = struct + let entries = 32 + let stable_hash = 256 + let contents_length_header = Some `Varint + let inode_child_order = `Seeded_hash + let forbid_empty_dir_persistence = true +end + +module Maker = Irmin_pack_unix.Maker (Conf) +module Store = Maker.Make (Schema) diff --git a/vendors/irmin/src/irmin-tezos/irmin_tezos.mli b/vendors/irmin/src/irmin-tezos/irmin_tezos.mli new file mode 100644 index 000000000000..0dfc883f0e01 --- /dev/null +++ b/vendors/irmin/src/irmin-tezos/irmin_tezos.mli @@ -0,0 +1,31 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Schema = Schema +module Conf : Irmin_pack.Conf.S + +module Store : + Irmin_pack_unix.S + with type Schema.Hash.t = Schema.Hash.t + and type Schema.Branch.t = Schema.Branch.t + and type Schema.Metadata.t = Schema.Metadata.t + and type Schema.Path.t = Schema.Path.t + and type Schema.Path.step = Schema.Path.step + and type Schema.Contents.t = Schema.Contents.t + and type Backend.Remote.endpoint = unit + and type contents_key = Schema.Hash.t Irmin_pack_unix.Pack_key.t + and type node_key = Schema.Hash.t Irmin_pack_unix.Pack_key.t + and type commit_key = Schema.Hash.t Irmin_pack_unix.Pack_key.t diff --git a/vendors/irmin/src/irmin-tezos/schema.ml b/vendors/irmin/src/irmin-tezos/schema.ml new file mode 100644 index 000000000000..0ecb2b424988 --- /dev/null +++ b/vendors/irmin/src/irmin-tezos/schema.ml @@ -0,0 +1,151 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Path = Irmin.Path.String_list +module Metadata = Irmin.Metadata.None +module Branch = Irmin.Branch.String + +module Hash : Irmin.Hash.S = struct + module H = Digestif.Make_BLAKE2B (struct + let digest_size = 32 + end) + + type t = H.t + + let prefix = "\079\199" (* Co(52) *) + + let pp ppf t = + let s = H.to_raw_string t in + Tezos_base58.pp ppf (Tezos_base58.encode ~prefix s) + + let of_b58 : string -> (t, [ `Msg of string ]) result = + fun x -> + match Tezos_base58.decode ~prefix (Base58 x) with + | Some x -> Ok (H.of_raw_string x) + | None -> Error (`Msg "Failed to read b58check_encoding data") + + let short_hash_string = Repr.(unstage (short_hash string)) + let short_hash ?seed t = short_hash_string ?seed (H.to_raw_string t) + + let t : t Repr.t = + Repr.map ~pp ~of_string:of_b58 + Repr.(string_of (`Fixed H.digest_size)) + ~short_hash H.of_raw_string H.to_raw_string + + let short_hash_string = short_hash_string ?seed:None + let short_hash t = short_hash_string (H.to_raw_string t) + let hash_size = H.digest_size + + let short_hash_substring t ~off = + short_hash_string (Bigstringaf.substring t ~off ~len:hash_size) + + let hash = H.digesti_string + let to_raw_string = H.to_raw_string + let unsafe_of_raw_string = H.of_raw_string +end + +module Info = Irmin.Info.Default + +module Node + (Contents_key : Irmin.Key.S with type hash = Hash.t) + (Node_key : Irmin.Key.S with type hash = Hash.t) = +struct + module M = + Irmin.Node.Generic_key.Make (Hash) (Path) (Metadata) (Contents_key) + (Node_key) + + (* [V1] is only used to compute preimage hashes. [assert false] + statements should be unreachable.*) + module V1 : sig + val pre_hash : M.t -> (string -> unit) -> unit + end = struct + module Hash = Irmin.Hash.V1 (Hash) + + type entry = string * M.value + + (* Irmin 1.4 uses int8 to store filename lengths. + + Irmin 2 use a variable-size encoding for strings; this is using int8 + for strings of size stricly less than 128 (e.g. 2^7) which happen to + be the case for all filenames ever produced by Irmin 1.4. *) + let step_t = Irmin.Type.string + + let metadata_t = + let some = "\255\000\000\000\000\000\000\000" in + let none = "\000\000\000\000\000\000\000\000" in + Irmin.Type.(map (string_of (`Fixed 8))) + (fun _ -> assert false) + (function Some _ -> some | None -> none) + + let metadata_of_entry (_, t) = + match t with `Node _ -> None | `Contents (_, m) -> Some m + + let hash_of_entry (_, t) = + match t with + | `Node h -> Node_key.to_hash h + | `Contents (h, _) -> Contents_key.to_hash h + + (* Irmin 1.4 uses int64 to store list lengths *) + let entry_t : entry Irmin.Type.t = + let open Irmin.Type in + record "Tree.entry" (fun _ _ _ -> assert false) + |+ field "kind" metadata_t metadata_of_entry + |+ field "name" step_t fst + |+ field "hash" Hash.t hash_of_entry + |> sealr + + let entries_t : entry list Irmin.Type.t = + Irmin.Type.(list ~len:`Int64 entry_t) + + let pre_hash_entries = Irmin.Type.(unstage (pre_hash entries_t)) + let compare_entry (x, _) (y, _) = String.compare x y + let step_to_string = Irmin.Type.(unstage (to_bin_string Path.step_t)) + let str_key (k, v) = (step_to_string k, v) + + let pre_hash t = + M.list t + |> List.map str_key + |> List.fast_sort compare_entry + |> pre_hash_entries + end + + include M + + let t = Irmin.Type.(like t ~pre_hash:V1.pre_hash) +end + +module Commit + (Node_key : Irmin.Key.S with type hash = Hash.t) + (Commit_key : Irmin.Key.S with type hash = Hash.t) = +struct + module M = Irmin.Commit.Generic_key.Make (Hash) (Node_key) (Commit_key) + module V1 = Irmin.Commit.V1.Make (Hash) (M) + include M + + let pre_hash_v1_t = Irmin.Type.(unstage (pre_hash V1.t)) + let pre_hash_v1 t = pre_hash_v1_t (V1.import t) + let t = Irmin.Type.(like t ~pre_hash:pre_hash_v1) +end + +module Contents = struct + type t = bytes + + let ty = Irmin.Type.(pair (bytes_of `Int64) unit) + let pre_hash_ty = Irmin.Type.(unstage (pre_hash ty)) + let pre_hash_v1 x = pre_hash_ty (x, ()) + let t = Irmin.Type.(like bytes ~pre_hash:pre_hash_v1) + let merge = Irmin.Merge.(idempotent (Irmin.Type.option t)) +end diff --git a/vendors/irmin/src/irmin-tezos/schema.mli b/vendors/irmin/src/irmin-tezos/schema.mli new file mode 100644 index 000000000000..b1d7246cb95f --- /dev/null +++ b/vendors/irmin/src/irmin-tezos/schema.mli @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include + Irmin.Schema.Extended + with type Contents.t = bytes + and type Metadata.t = unit + and type Path.t = string list + and type Path.step = string + and type Branch.t = string + and module Info = Irmin.Info.Default diff --git a/vendors/irmin/src/irmin/append_only.ml b/vendors/irmin/src/irmin/append_only.ml new file mode 100644 index 000000000000..2075b21c1c46 --- /dev/null +++ b/vendors/irmin/src/irmin/append_only.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Append_only_intf diff --git a/vendors/irmin/src/irmin/append_only.mli b/vendors/irmin/src/irmin/append_only.mli new file mode 100644 index 000000000000..0356a7e81971 --- /dev/null +++ b/vendors/irmin/src/irmin/append_only.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Append_only_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/append_only_intf.ml b/vendors/irmin/src/irmin/append_only_intf.ml new file mode 100644 index 000000000000..b5d318d4aae5 --- /dev/null +++ b/vendors/irmin/src/irmin/append_only_intf.ml @@ -0,0 +1,51 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +open Store_properties + +module type S = sig + (** {1 Append-only stores} + + Append-only stores are store where it is possible to read and add new + values. *) + + include Read_only.S + (** @inline *) + + val add : [> write ] t -> key -> value -> unit Lwt.t + (** Write the contents of a value to the store. *) + + include Closeable with type 'a t := 'a t + (** @inline *) + + include Batch with type 'a t := 'a t + (** @inline *) +end + +module Append_only_is_a_read_only (X : S) : Read_only.S = X + +module type Maker = functor (K : Type.S) (V : Type.S) -> sig + include S with type key = K.t and type value = V.t + + include Of_config with type 'a t := 'a t + (** @inline *) +end + +module type Sigs = sig + module type S = S + module type Maker = Maker +end diff --git a/vendors/irmin/src/irmin/atomic_write.ml b/vendors/irmin/src/irmin/atomic_write.ml new file mode 100644 index 000000000000..7bf9b0db100e --- /dev/null +++ b/vendors/irmin/src/irmin/atomic_write.ml @@ -0,0 +1,61 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Atomic_write_intf + +module Check_closed_store (AW : S) = struct + type t = { closed : bool ref; t : AW.t } + type key = AW.key + type value = AW.value + type watch = AW.watch + + let make_closeable t = { closed = ref false; t } + + let get_if_open_exn t = + if !(t.closed) then raise Store_properties.Closed else t.t + + let mem t k = (get_if_open_exn t |> AW.mem) k + let find t k = (get_if_open_exn t |> AW.find) k + let set t k v = (get_if_open_exn t |> AW.set) k v + + let test_and_set t k ~test ~set = + (get_if_open_exn t |> AW.test_and_set) k ~test ~set + + let remove t k = (get_if_open_exn t |> AW.remove) k + let list t = get_if_open_exn t |> AW.list + let watch t ?init f = (get_if_open_exn t |> AW.watch) ?init f + let watch_key t k ?init f = (get_if_open_exn t |> AW.watch_key) k ?init f + let unwatch t w = (get_if_open_exn t |> AW.unwatch) w + + let close t = + if !(t.closed) then Lwt.return_unit + else ( + t.closed := true; + AW.close t.t) + + let clear t = get_if_open_exn t |> AW.clear +end + +module Check_closed (Make_atomic_write : Maker) (K : Type.S) (V : Type.S) = +struct + module AW = Make_atomic_write (K) (V) + include Check_closed_store (AW) + + let v conf = + let+ t = AW.v conf in + { closed = ref false; t } +end diff --git a/vendors/irmin/src/irmin/atomic_write.mli b/vendors/irmin/src/irmin/atomic_write.mli new file mode 100644 index 000000000000..f42c7e8c8f5b --- /dev/null +++ b/vendors/irmin/src/irmin/atomic_write.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Atomic_write_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/atomic_write_intf.ml b/vendors/irmin/src/irmin/atomic_write_intf.ml new file mode 100644 index 000000000000..15f506c225d2 --- /dev/null +++ b/vendors/irmin/src/irmin/atomic_write_intf.ml @@ -0,0 +1,110 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Store_properties + +type 'a diff = 'a Diff.t + +module type S = sig + (** {1 Atomic write stores} + + Atomic-write stores are stores where it is possible to read, update and + remove elements, with atomically guarantees. *) + + type t + (** The type for atomic-write backend stores. *) + + include Read_only.S with type _ t := t + (** @inline *) + + val set : t -> key -> value -> unit Lwt.t + (** [set t k v] replaces the contents of [k] by [v] in [t]. If [k] is not + already defined in [t], create a fresh binding. Raise [Invalid_argument] + if [k] is the {{!Irmin.Path.S.empty} empty path}. *) + + val test_and_set : + t -> key -> test:value option -> set:value option -> bool Lwt.t + (** [test_and_set t key ~test ~set] sets [key] to [set] only if the current + value of [key] is [test] and in that case returns [true]. If the current + value of [key] is different, it returns [false]. [None] means that the + value does not have to exist or is removed. + + {b Note:} The operation is guaranteed to be atomic. *) + + val remove : t -> key -> unit Lwt.t + (** [remove t k] remove the key [k] in [t]. *) + + val list : t -> key list Lwt.t + (** [list t] it the list of keys in [t]. *) + + type watch + (** The type of watch handlers. *) + + val watch : + t -> + ?init:(key * value) list -> + (key -> value diff -> unit Lwt.t) -> + watch Lwt.t + (** [watch t ?init f] adds [f] to the list of [t]'s watch handlers and returns + the watch handler to be used with {!unwatch}. [init] is the optional + initial values. It is more efficient to use {!watch_key} to watch only a + single given key.*) + + val watch_key : + t -> key -> ?init:value -> (value diff -> unit Lwt.t) -> watch Lwt.t + (** [watch_key t k ?init f] adds [f] to the list of [t]'s watch handlers for + the key [k] and returns the watch handler to be used with {!unwatch}. + [init] is the optional initial value of the key. *) + + val unwatch : t -> watch -> unit Lwt.t + (** [unwatch t w] removes [w] from [t]'s watch handlers. *) + + include Clearable with type _ t := t + (** @inline *) + + include Closeable with type _ t := t + (** @inline *) +end + +module type Maker = functor (K : Type.S) (V : Type.S) -> sig + include S with type key = K.t and type value = V.t + + include Of_config with type _ t := t + (** @inline *) +end + +module type Sigs = sig + module type S = S + module type Maker = Maker + + module Check_closed_store (AW : S) : sig + include + S + with type key = AW.key + and type value = AW.value + and type watch = AW.watch + + val make_closeable : AW.t -> t + (** [make_closeable t] returns a version of [t] that raises {!Irmin.Closed} + if an operation is performed when it is already closed. *) + + val get_if_open_exn : t -> AW.t + (** [get_if_open_exn t] returns the store (without close checks) if it is + open; otherwise raises {!Irmin.Closed} *) + end + + module Check_closed (M : Maker) : Maker +end diff --git a/vendors/irmin/src/irmin/backend.ml b/vendors/irmin/src/irmin/backend.ml new file mode 100644 index 000000000000..4b9f981b7f90 --- /dev/null +++ b/vendors/irmin/src/irmin/backend.ml @@ -0,0 +1,119 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Store_properties + +open struct + module type Node_portable = Node.Portable.S + module type Commit_portable = Commit.Portable.S +end + +(** [S] is what a backend must define in order to be made an irmin store. *) +module type S = sig + module Schema : Schema.S + (** A store schema, meant to be provided by the user. *) + + module Hash : Hash.S with type t = Schema.Hash.t + (** Hashing implementation. *) + + (** A contents store. *) + module Contents : + Contents.Store with type hash = Hash.t and type value = Schema.Contents.t + + (** A node store. *) + module Node : + Node.Store + with type hash = Hash.t + and type Val.contents_key = Contents.key + and module Path = Schema.Path + and module Metadata = Schema.Metadata + + (** A node abstraction that is portable from different repos. Similar to + [Node.Val]. *) + module Node_portable : + Node_portable + with type node := Node.value + and type hash := Hash.t + and type metadata := Schema.Metadata.t + and type step := Schema.Path.step + + (** A commit store. *) + module Commit : + Commit.Store + with type hash = Hash.t + and type Val.node_key = Node.key + and module Info = Schema.Info + + (** A commit abstraction that is portable from different repos. Similar to + [Commit.Val]. *) + module Commit_portable : + Commit_portable + with type commit := Commit.value + and type hash := Hash.t + and module Info = Schema.Info + + (** A branch store. *) + module Branch : + Branch.Store with type key = Schema.Branch.t and type value = Commit.key + + (** A slice abstraction. *) + module Slice : + Slice.S + with type contents = Contents.hash * Contents.value + and type node = Node.hash * Node.value + and type commit = Commit.hash * Commit.value + + (** A repo abstraction. *) + module Repo : sig + type t + + (** Repo opening and closing functions *) + + include Of_config with type _ t := t + (** @inline *) + + include Closeable with type _ t := t + (** @inline *) + + (** Getters from repo to backend store in ro mode *) + + val contents_t : t -> read Contents.t + val node_t : t -> read Node.t + val commit_t : t -> read Commit.t + val config : t -> Conf.t + + val batch : + t -> + (read_write Contents.t -> + read_write Node.t -> + read_write Commit.t -> + 'a Lwt.t) -> + 'a Lwt.t + (** A getter from repo to backend stores in rw mode. *) + + val branch_t : t -> Branch.t + (** A branch store getter from repo *) + end + + (** URI-based low-level remote synchronisation. *) + module Remote : sig + include Remote.S with type commit = Commit.key and type branch = Branch.key + + val v : Repo.t -> t Lwt.t + end +end diff --git a/vendors/irmin/src/irmin/branch.ml b/vendors/irmin/src/irmin/branch.ml new file mode 100644 index 000000000000..9380ad2576ec --- /dev/null +++ b/vendors/irmin/src/irmin/branch.ml @@ -0,0 +1,36 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Branch_intf + +module String = struct + type t = string + + let t = Type.string + let main = "main" + + let is_valid s = + let ok = ref true in + let n = String.length s in + let i = ref 0 in + while !i < n do + (match s.[!i] with + | 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '-' | '_' | '.' -> () + | _ -> ok := false); + incr i + done; + !ok +end diff --git a/vendors/irmin/src/irmin/branch.mli b/vendors/irmin/src/irmin/branch.mli new file mode 100644 index 000000000000..cb6bbce14402 --- /dev/null +++ b/vendors/irmin/src/irmin/branch.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** User-defined branches. *) + +include Branch_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/branch_intf.ml b/vendors/irmin/src/irmin/branch_intf.ml new file mode 100644 index 000000000000..a34a4c28f81a --- /dev/null +++ b/vendors/irmin/src/irmin/branch_intf.ml @@ -0,0 +1,62 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** {1 Signature for Branches} *) + + type t [@@deriving irmin] + (** The type for branches. *) + + val main : t + (** The name of the main branch. *) + + val is_valid : t -> bool + (** Check if the branch is valid. *) +end + +module Irmin_key = Key + +module type Store = sig + (** {1 Branch Store} *) + + include Atomic_write.S + + module Key : S with type t = key + (** Base functions on keys. *) + + module Val : Irmin_key.S with type t = value + (** Base functions on values. *) +end + +module type Sigs = sig + (** {1 Branches} *) + + module type S = S + (** The signature for branches. Irmin branches are similar to Git branches: + they are used to associated user-defined names to head commits. Branches + have a default value: the {{!Branch.S.main} main} branch. *) + + module String : S with type t = string + (** [String] is an implementation of {{!Branch.S} S} where branches are + strings. The [main] branch is ["main"]. Valid branch names contain only + alpha-numeric characters, [-], [_], [.], and [/]. *) + + module type Store = Store + (** [Store] specifies the signature for branch stores. + + A {i branch store} is a mutable and reactive key / value store, where keys + are branch names created by users and values are keys are head commmits. *) +end diff --git a/vendors/irmin/src/irmin/commit.ml b/vendors/irmin/src/irmin/commit.ml new file mode 100644 index 000000000000..da05c481734a --- /dev/null +++ b/vendors/irmin/src/irmin/commit.ml @@ -0,0 +1,699 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Commit_intf +open Merge.Infix + +let src = Logs.Src.create "irmin.commit" ~doc:"Irmin commits" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Maker_generic_key (I : Info.S) = struct + module Info = I + + module Make + (H : Type.S) + (N : Key.S with type hash = H.t) + (C : Key.S with type hash = H.t) = + struct + module Info = I + + type hash = H.t [@@deriving irmin ~compare] + type node_key = N.t [@@deriving irmin ~compare] + type commit_key = C.t [@@deriving irmin] + + type t = { node : node_key; parents : commit_key list; info : Info.t } + [@@deriving irmin] + + type t_not_prefixed = t [@@deriving irmin] + + let pre_hash = Type.(unstage (pre_hash t)) + + (* Manually add a prefix to default commits, in order to prevent hash + collision between contents and commits (see + https://github.com/mirage/irmin/issues/1304). + If we only prefix the prehash of contents, (suppose the prefix is "B"), + then we can have a collision with the prehash of a commit (the prehash of + a commit starts with the hash of the root and can start with a "B" - the + prefix of the contents is not enough to prevent the collision). *) + let pre_hash_prefixed x f = + f "C"; + pre_hash x f + + let t = Type.(like t ~pre_hash:pre_hash_prefixed) + let parents t = t.parents + let node t = t.node + let info t = t.info + let compare_commit_key x y = compare_hash (C.to_hash x) (C.to_hash y) + + let v ~info ~node ~parents = + let parents = List.fast_sort compare_commit_key parents in + { node; parents; info } + + module Portable = struct + module Info = I + + type commit = t + + type t = { node : hash; parents : hash list; info : Info.t } + [@@deriving irmin] + + type t_not_prefixed = t [@@deriving irmin] + + let pre_hash = Type.(unstage (pre_hash t)) + + let pre_hash_prefixed x f = + f "C"; + pre_hash x f + + let t = Type.(like t ~pre_hash:pre_hash_prefixed) + + type commit_key = H.t [@@deriving irmin] + type node_key = H.t [@@deriving irmin] + type hash = H.t [@@deriving irmin] + + let parents t = t.parents + let node t = t.node + let info t = t.info + + let v ~info ~node ~parents = + let parents = List.fast_sort compare_hash parents in + { node; parents; info } + + let of_commit : commit -> t = + fun { node; parents; info } -> + let node = N.to_hash node in + let parents = List.map C.to_hash parents in + { node; parents; info } + end + end + + module Make_v2 + (H : Type.S) + (N : Key.S with type hash = H.t) + (C : Key.S with type hash = H.t) = + struct + include Make (H) (N) (C) + + let t = t_not_prefixed_t + + module Portable = struct + include Portable + + let t = t_not_prefixed_t + end + end +end + +module Maker (Info : Info.S) = struct + include Maker_generic_key (Info) + + module Make (H : Type.S) = struct + module Key = Key.Of_hash (H) + include Make (H) (Key) (Key) + end +end + +module Store_generic_key + (I : Info.S) + (N : Node.Store) + (S : Indexable.S) + (H : Hash.S with type t = S.hash) + (V : S_generic_key + with type node_key = N.Key.t + and type commit_key = S.Key.t + and type t = S.value + and module Info := I) = +struct + module Node = N + module Val = V + module Key = S.Key + module Hash = Hash.Typed (H) (V) + module Info = I + + type 'a t = 'a N.t * 'a S.t + type key = Key.t [@@deriving irmin ~equal] + type value = S.value + type hash = S.hash + + let add (_, t) = S.add t + let unsafe_add (_, t) = S.unsafe_add t + let mem (_, t) = S.mem t + let index (_, t) = S.index t + let find (_, t) = S.find t + let batch (n, s) f = N.batch n (fun n -> S.batch s (fun s -> f (n, s))) + + let close (n, s) = + let* () = N.close n in + let+ () = S.close s in + () + + let merge_node (t, _) = Merge.f (N.merge t) + let pp_key = Type.pp Key.t + let err_not_found k = Fmt.kstr invalid_arg "Commit.get: %a not found" pp_key k + + let get (_, t) k = + S.find t k >>= function None -> err_not_found k | Some v -> Lwt.return v + + let empty_if_none (n, _) = function + | None -> N.add n (N.Val.empty ()) + | Some node -> Lwt.return node + + let equal_key = Type.(unstage (equal Key.t)) + let equal_opt_keys = Type.(unstage (equal (option Key.t))) + + let merge_commit info t ~old k1 k2 = + [%log.debug "Commit.merge %a %a" pp_key k1 pp_key k2]; + let* v1 = get t k1 in + let* v2 = get t k2 in + if List.mem ~equal:equal_key k1 (Val.parents v2) then Merge.ok k2 + else if List.mem ~equal:equal_key k2 (Val.parents v1) then Merge.ok k1 + else + (* If we get an error while looking the the lca, then we + assume that there is no common ancestor. Maybe we want to + expose this to the user in a more structured way. But maybe + that's too much low-level details. *) + let* old = + old () >>= function + | Error (`Conflict msg) -> + [%log.debug "old: conflict %s" msg]; + Lwt.return_none + | Ok o -> Lwt.return o + in + if equal_opt_keys old (Some k1) then Merge.ok k2 + else if equal_opt_keys old (Some k2) then Merge.ok k1 + else + let old () = + match old with + | None -> Merge.ok None + | Some old -> + let* vold = get t old in + Merge.ok (Some (Some (Val.node vold))) + in + merge_node t ~old (Some (Val.node v1)) (Some (Val.node v2)) + >>=* fun node -> + let* node = empty_if_none t node in + let parents = [ k1; k2 ] in + let commit = Val.v ~node ~parents ~info:(info ()) in + let* key = add t commit in + Merge.ok key + + let merge t ~info = Merge.(option (v Key.t (merge_commit info t))) +end + +module Generic_key = struct + module type S = S_generic_key + module type Maker = Maker_generic_key + + module Maker = Maker_generic_key + module Store = Store_generic_key + include Maker (Info.Default) +end + +module Portable = struct + module Of_commit (X : S) = struct + include X + + let of_commit t = t + end + + module type S = Portable +end + +module Store + (I : Info.S) + (N : Node.Store) + (S : Content_addressable.S with type key = N.key) + (H : Hash.S with type t = S.key) + (V : S with type hash = S.key and type t = S.value and module Info := I) = +struct + include + Store_generic_key (I) (N) (Indexable.Of_content_addressable (H) (S)) (H) (V) + + module Val = struct + include Val + + type hash = H.t [@@deriving irmin] + end +end + +module History (S : Store) = struct + type commit_key = S.Key.t [@@deriving irmin] + type node_key = S.Val.node_key [@@deriving irmin] + type v = S.Val.t [@@deriving irmin] + type info = S.Info.t [@@deriving irmin] + type 'a t = 'a S.t + + let merge t ~info = + let f ~old c1 c2 = + let somify = Merge.map_promise (fun x -> Some x) in + let merge = S.merge t ~info in + Merge.f merge ~old:(somify old) (Some c1) (Some c2) >>=* function + | None -> Merge.conflict "History.merge" + | Some x -> Merge.ok x + in + Merge.v S.Key.t f + + let v t ~node ~parents ~info = + let commit = S.Val.v ~node ~parents ~info in + let+ hash = S.add t commit in + (hash, commit) + + let pp_key = Type.pp S.Key.t + + let parents t c = + [%log.debug "parents %a" pp_key c]; + S.find t c >|= function None -> [] | Some c -> S.Val.parents c + + module U = struct + type t = unit [@@deriving irmin] + end + + module Graph = Object_graph.Make (U) (S.Node.Key) (S.Key) (U) + + let edges t = + [%log.debug "edges"]; + [ `Node (S.Val.node t) ] @ List.map (fun k -> `Commit k) (S.Val.parents t) + + let closure t ~min ~max = + [%log.debug "closure"]; + let pred = function + | `Commit k -> ( S.find t k >|= function Some r -> edges r | None -> []) + | _ -> Lwt.return_nil + in + let min = List.map (fun k -> `Commit k) min in + let max = List.map (fun k -> `Commit k) max in + let+ g = Graph.closure ~pred ~min ~max () in + List.fold_left + (fun acc -> function `Commit k -> k :: acc | _ -> acc) + [] (Graph.vertex g) + + let ignore_lwt _ = Lwt.return_unit + + let iter t ~min ~max ?(commit = ignore_lwt) ?edge + ?(skip = fun _ -> Lwt.return_false) ?(rev = true) () = + let max = List.map (fun x -> `Commit x) max in + let min = List.map (fun x -> `Commit x) min in + let node = function `Commit x -> commit x | _ -> assert false in + let skip = function `Commit x -> skip x | _ -> assert false in + let pred = function + | `Commit k -> parents t k >|= List.map (fun x -> `Commit x) + | _ -> assert false + in + let edge = + Option.map + (fun edge n pred -> + match (n, pred) with + | `Commit src, `Commit dst -> edge src dst + | _ -> assert false) + edge + in + Graph.iter ~pred ~min ~max ~node ?edge ~skip ~rev () + + module K = struct + type t = S.Key.t + + let compare = Type.(unstage (compare S.Key.t)) + let hash k = S.Hash.short_hash (S.Key.to_hash k) + let equal = Type.(unstage (equal S.Key.t)) + end + + module KSet = Set.Make (K) + module KHashtbl = Hashtbl.Make (K) + + let read_parents t commit = + S.find t commit >|= function + | None -> KSet.empty + | Some c -> KSet.of_list (S.Val.parents c) + + let equal_keys = Type.(unstage (equal S.Key.t)) + let str_key k = String.sub (Type.to_string S.Key.t k) 0 4 + let pp_key = Fmt.of_to_string str_key + + let pp_keys ppf keys = + let keys = KSet.elements keys in + Fmt.pf ppf "[%a]" Fmt.(list ~sep:(any " ") pp_key) keys + + let str_keys = Fmt.to_to_string pp_keys + let lca_calls = ref 0 + + let rec unqueue todo seen = + if Queue.is_empty todo then None + else + let ((_, commit) as pop) = Queue.pop todo in + if KSet.mem commit seen then unqueue todo seen else Some pop + + (* Traverse the graph of commits using a breadth first search + strategy. Start by visiting the commits in [init] and stops + either when [check] returns [`Stop] or when all the ancestors of + [init] have been visited. *) + let traverse_bfs t ~f ~pp:_ ~check ~init ~return = + let todo = Queue.create () in + let add_todo d x = Queue.add (d, x) todo in + KSet.iter (add_todo 0) init; + let rec aux seen = + match check () with + | (`Too_many_lcas | `Max_depth_reached) as x -> Lwt.return (Error x) + | `Stop -> return () + | `Continue -> ( + match unqueue todo seen with + | None -> return () + | Some (depth, commit) -> + (* Log.debug "lca %d: %s.%d %a" + !lca_calls (pp_key commit) depth force (pp ()); *) + let seen = KSet.add commit seen in + let* parents = read_parents t commit in + let () = f depth commit parents in + let parents = KSet.diff parents seen in + KSet.iter (add_todo (depth + 1)) parents; + aux seen) + in + aux KSet.empty + + (* Initially the first node is marked as [Seen1] and the second as [Seen2]. + Marks are updated as the search progresses, and may change. *) + type mark = + | Seen1 (* reachable from the first commit *) + | Seen2 (* reachable from the second commit *) + | SeenBoth (* reachable from both, but below an LCA *) + | LCA + + (* reachable from both; candidate for the answer set *) + + let _pp_mark = function + | Seen1 -> "seen1" + | Seen2 -> "seen2" + | SeenBoth -> "seenBoth" + | LCA -> "LCA" + + (* Exploration state *) + type state = { + marks : mark KHashtbl.t; + (* marks of commits already explored *) + parents : KSet.t KHashtbl.t; + (* parents of commits already explored *) + layers : (int, KSet.t) Hashtbl.t; + (* layers of commit, sorted by depth *) + c1 : S.key; + (* initial state 1 *) + c2 : S.key; + (* initial state 2 *) + mutable depth : int; + (* the current exploration depth *) + mutable lcas : int; + (* number of commit marked with LCA *) + mutable complete : bool; (* is the exploration complete? *) + } + + let pp_state t = + lazy + (let pp m = + KHashtbl.fold + (fun k v acc -> if v = m then str_key k :: acc else acc) + t.marks [] + |> String.concat " " + in + Fmt.str "d: %d, seen1: %s, seen2: %s, seenboth: %s, lcas: %s (%d) %s" + t.depth (pp Seen1) (pp Seen2) (pp SeenBoth) (pp LCA) t.lcas + (String.concat " | " + (Hashtbl.fold + (fun d ks acc -> Fmt.str "(%d: %s)" d (str_keys ks) :: acc) + t.layers []))) + + let get_mark_exn t elt = KHashtbl.find t.marks elt + let get_mark t elt = try Some (get_mark_exn t elt) with Not_found -> None + let set_mark t elt mark = KHashtbl.replace t.marks elt mark + let get_layer t d = try Hashtbl.find t.layers d with Not_found -> KSet.empty + + let add_to_layer t d k = + Hashtbl.replace t.layers d (KSet.add k (get_layer t d)) + + let add_parent t c p = KHashtbl.add t.parents c p + + let get_parent t c = + try KHashtbl.find t.parents c with Not_found -> KSet.empty + + let incr_lcas t = t.lcas <- t.lcas + 1 + let decr_lcas t = t.lcas <- t.lcas - 1 + + let both_seen t k = + match get_mark t k with + | None | Some Seen1 | Some Seen2 -> false + | _ -> true + + let empty_state c1 c2 = + let t = + { + marks = KHashtbl.create 10; + parents = KHashtbl.create 10; + layers = Hashtbl.create 10; + c1; + c2; + depth = 0; + lcas = 0; + complete = false; + } + in + set_mark t c1 Seen1; + set_mark t c2 Seen2; + t + + (* update the parent mark and keep the number of lcas up-to-date. *) + let update_mark t mark commit = + let new_mark = + match (mark, get_mark t commit) with + | Seen1, Some Seen1 | Seen1, None -> Seen1 + | Seen2, Some Seen2 | Seen2, None -> Seen2 + | SeenBoth, Some LCA -> + decr_lcas t; + SeenBoth + | SeenBoth, _ -> SeenBoth + | Seen1, Some Seen2 | Seen2, Some Seen1 -> + incr_lcas t; + LCA + | _, Some LCA -> LCA + | _ -> SeenBoth + in + (* check for fast-forwards *) + let is_init () = equal_keys commit t.c1 || equal_keys commit t.c2 in + let is_shared () = new_mark = SeenBoth || new_mark = LCA in + if is_shared () && is_init () then ( + [%log.debug "fast-forward"]; + t.complete <- true); + set_mark t commit new_mark; + new_mark + + (* update the ancestors which have already been visisted. *) + let update_ancestors_marks t mark commit = + let todo = Queue.create () in + Queue.add commit todo; + let rec loop mark = + if Queue.is_empty todo then () + else + let a = Queue.pop todo in + let old_mark = get_mark t a in + let mark = update_mark t mark a in + let () = + match old_mark with + | Some (SeenBoth | LCA) -> () (* Can't be an LCA lower down *) + | Some old when old = mark -> () (* No change *) + | _ -> KSet.iter (fun x -> Queue.push x todo) (get_parent t a) + in + loop (if mark = LCA then SeenBoth else mark) + in + loop mark + + (* We are looking for LCAs, doing a breadth-first-search from the two starting commits. + This is called each time we visit a new commit. *) + let update_parents t depth commit parents = + add_parent t commit parents; + add_to_layer t depth commit; + if depth <> t.depth then ( + assert (depth = t.depth + 1); + + (* before starting to explore a new layer, check if we really + have some work to do, ie. do we still have a commit seen only + by one node? *) + let layer = get_layer t t.depth in + let complete = KSet.for_all (both_seen t) layer in + if complete then t.complete <- true else t.depth <- depth); + let mark = get_mark_exn t commit in + KSet.iter (update_ancestors_marks t mark) parents + + let lcas t = + KHashtbl.fold (fun k v acc -> if v = LCA then k :: acc else acc) t.marks [] + + let check ~max_depth ~n t = + if t.depth > max_depth then `Max_depth_reached + else if t.lcas > n then `Too_many_lcas + else if t.lcas = n || t.complete then `Stop + else `Continue + + let lcas t ?(max_depth = max_int) ?(n = max_int) c1 c2 = + incr lca_calls; + if max_depth < 0 then Lwt.return (Error `Max_depth_reached) + else if n <= 0 then Lwt.return (Error `Too_many_lcas) + else if equal_keys c1 c2 then Lwt.return (Ok [ c1 ]) + else + let init = KSet.of_list [ c1; c2 ] in + let s = empty_state c1 c2 in + let check () = check ~max_depth ~n s in + let pp () = pp_state s in + let return () = Lwt.return (Ok (lcas s)) in + let t0 = Sys.time () in + Lwt.finalize + (fun () -> + traverse_bfs t ~f:(update_parents s) ~pp ~check ~init ~return) + (fun () -> + let t1 = Sys.time () -. t0 in + [%log.debug "lcas %d: depth=%d time=%.4fs" !lca_calls s.depth t1]; + Lwt.return_unit) + + let rec three_way_merge t ~info ?max_depth ?n c1 c2 = + [%log.debug "3-way merge between %a and %a" pp_key c1 pp_key c2]; + if equal_keys c1 c2 then Merge.ok c1 + else + let* lcas = lcas t ?max_depth ?n c1 c2 in + let old () = + match lcas with + | Error `Too_many_lcas -> Merge.conflict "Too many lcas" + | Error `Max_depth_reached -> Merge.conflict "Max depth reached" + | Ok [] -> Merge.ok None (* no common ancestor *) + | Ok (old :: olds) -> + let rec aux acc = function + | [] -> Merge.ok (Some acc) + | old :: olds -> + three_way_merge t ~info acc old >>=* fun acc -> aux acc olds + in + aux old olds + in + let merge = + merge t ~info + |> Merge.with_conflict (fun msg -> + Fmt.str "Recursive merging of common ancestors: %s" msg) + |> Merge.f + in + merge ~old c1 c2 + + let lca_aux t ~info ?max_depth ?n c1 c2 = + if equal_keys c1 c2 then Merge.ok (Some c1) + else + lcas t ?max_depth ?n c1 c2 >>= function + | Error `Too_many_lcas -> Merge.conflict "Too many lcas" + | Error `Max_depth_reached -> Merge.conflict "Max depth reached" + | Ok [] -> Merge.ok None (* no common ancestor *) + | Ok [ x ] -> Merge.ok (Some x) + | Ok (c :: cs) -> + let rec aux acc = function + | [] -> Merge.ok (Some acc) + | c :: cs -> ( + three_way_merge t ~info ?max_depth ?n acc c >>= function + | Error (`Conflict _) -> Merge.ok None + | Ok acc -> aux acc cs) + in + aux c cs + + let rec lca t ~info ?max_depth ?n = function + | [] -> Merge.conflict "History.lca: empty" + | [ c ] -> Merge.ok (Some c) + | c1 :: c2 :: cs -> ( + lca_aux t ~info ?max_depth ?n c1 c2 >>=* function + | None -> Merge.ok None + | Some c -> lca t ~info ?max_depth ?n (c :: cs)) +end + +module V1 = struct + module Info = struct + include Info.Default + + let t : t Type.t = + let open Type in + record "info" (fun date author message -> v ~author ~message date) + |+ field "date" int64 (fun t -> date t) + |+ field "author" (string_of `Int64) (fun t -> author t) + |+ field "message" (string_of `Int64) (fun t -> message t) + |> sealr + end + + module Make (Hash : Hash.S) (C : Generic_key.S with module Info := Info) = + struct + module K (K : Type.S) = struct + let h = Type.string_of `Int64 + + type t = K.t [@@deriving irmin ~pre_hash ~to_bin_string ~of_bin_string] + + let size_of = Type.Size.using to_bin_string (Type.Size.t h) + + let encode_bin = + let encode_bin = Type.(unstage (encode_bin h)) in + fun e k -> encode_bin (to_bin_string e) k + + let decode_bin = + let decode_bin = Type.(unstage (decode_bin h)) in + fun buf pos_ref -> + let v = decode_bin buf pos_ref in + match of_bin_string v with + | Ok v -> v + | Error (`Msg e) -> Fmt.failwith "decode_bin: %s" e + + (* Manually box hashes in V1 commits with length headers: *) + let pre_hash = + let hash_length_header : string = + let b = Bytes.create 8 in + Bytes.set_int64_be b 0 (Int64.of_int Hash.hash_size); + Bytes.unsafe_to_string b + in + fun x f -> + f hash_length_header; + pre_hash x f + + let t = Type.like K.t ~bin:(encode_bin, decode_bin, size_of) ~pre_hash + end + + module Node_key = K (struct + type t = C.node_key [@@deriving irmin] + end) + + module Commit_key = K (struct + type t = C.commit_key [@@deriving irmin] + end) + + type node_key = Node_key.t [@@deriving irmin] + type commit_key = Commit_key.t [@@deriving irmin] + type t = { parents : commit_key list; c : C.t } + + module Info = Info + + let import c = { c; parents = C.parents c } + let export t = t.c + let node t = C.node t.c + let parents t = t.parents + let info t = C.info t.c + let v ~info ~node ~parents = { parents; c = C.v ~node ~parents ~info } + let make = v + + let t : t Type.t = + let open Type in + record "commit" (fun node parents info -> make ~info ~node ~parents) + |+ field "node" Node_key.t node + |+ field "parents" (list ~len:`Int64 Commit_key.t) parents + |+ field "info" Info.t info + |> sealr + end +end + +include Maker (Info.Default) diff --git a/vendors/irmin/src/irmin/commit.mli b/vendors/irmin/src/irmin/commit.mli new file mode 100644 index 000000000000..0bd9361dc315 --- /dev/null +++ b/vendors/irmin/src/irmin/commit.mli @@ -0,0 +1,27 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Commit values represent the store history. + + Every commit contains a list of predecessor commits, and the collection of + commits form an acyclic directed graph. + + Every commit also can contain an optional key, pointing to a + {{!Backend.Commit.Store} node} value. See the {{!Backend.Node.Store} Node} + signature for more details on node values. *) + +include Commit_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/commit_intf.ml b/vendors/irmin/src/irmin/commit_intf.ml new file mode 100644 index 000000000000..51de11896625 --- /dev/null +++ b/vendors/irmin/src/irmin/commit_intf.ml @@ -0,0 +1,330 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S_generic_key = sig + (** {1 Commit values} *) + + type t [@@deriving irmin] + (** The type for commit values. *) + + type node_key [@@deriving irmin] + (** Type for node keys. *) + + type commit_key [@@deriving irmin] + (** Type for commit keys. *) + + module Info : Info.S + (** The type for commit info. *) + + val v : info:Info.t -> node:node_key -> parents:commit_key list -> t + (** Create a commit. *) + + val node : t -> node_key + (** The underlying node key. *) + + val parents : t -> commit_key list + (** The commit parents. *) + + val info : t -> Info.t + (** The commit info. *) +end + +module type S = sig + type hash [@@deriving irmin] + + (** @inline *) + include S_generic_key with type node_key = hash and type commit_key = hash +end + +module type Portable = sig + include S + + type commit + + val of_commit : commit -> t +end + +open struct + module S_is_a_generic_key (X : S) : S_generic_key = X +end + +module type Maker_generic_key = sig + module Info : Info.S + + module Make + (H : Type.S) + (N : Key.S with type hash = H.t) + (C : Key.S with type hash = H.t) : sig + include + S_generic_key + with type node_key = N.t + and type commit_key = C.t + and module Info = Info + + module Portable : + Portable with type commit := t and type hash := H.t and module Info = Info + end + + module Make_v2 + (H : Type.S) + (N : Key.S with type hash = H.t) + (C : Key.S with type hash = H.t) : sig + include + S_generic_key + with type node_key = N.t + and type commit_key = C.t + and module Info = Info + + module Portable : + Portable with type commit := t and type hash := H.t and module Info = Info + end +end + +module type Maker = sig + module Info : Info.S + module Make (H : Type.S) : S with type hash = H.t and module Info = Info +end + +module type Store = sig + (** {1 Commit Store} *) + + include Indexable.S + + module Info : Info.S + (** Commit info. *) + + (** [Val] provides functions for commit values. *) + module Val : + S_generic_key + with type t = value + and type commit_key = key + and module Info := Info + + module Hash : Hash.Typed with type t = hash and type value = value + + module Node : Node.Store with type key = Val.node_key + (** [Node] is the underlying node store. *) + + val merge : [> read_write ] t -> info:Info.f -> key option Merge.t + (** [merge] is the 3-way merge function for commit keys. *) +end + +module type History = sig + (** {1 Commit History} *) + + type 'a t + (** The type for store handles. *) + + type node_key [@@deriving irmin] + (** The type for node keys. *) + + type commit_key [@@deriving irmin] + (** The type for commit keys. *) + + type v [@@deriving irmin] + (** The type for commit objects. *) + + type info [@@deriving irmin] + (** The type for commit info. *) + + val v : + [> write ] t -> + node:node_key -> + parents:commit_key list -> + info:info -> + (commit_key * v) Lwt.t + (** Create a new commit. *) + + val parents : [> read ] t -> commit_key -> commit_key list Lwt.t + (** Get the commit parents. + + Commits form a append-only, fully functional, partial-order + data-structure: every commit carries the list of its immediate + predecessors. *) + + val merge : [> read_write ] t -> info:(unit -> info) -> commit_key Merge.t + (** [merge t] is the 3-way merge function for commit. *) + + val lcas : + [> read ] t -> + ?max_depth:int -> + ?n:int -> + commit_key -> + commit_key -> + (commit_key list, [ `Max_depth_reached | `Too_many_lcas ]) result Lwt.t + (** Find the lowest common ancestors + {{:http://en.wikipedia.org/wiki/Lowest_common_ancestor} lca} between two + commits. *) + + val lca : + [> read_write ] t -> + info:(unit -> info) -> + ?max_depth:int -> + ?n:int -> + commit_key list -> + (commit_key option, Merge.conflict) result Lwt.t + (** Compute the lowest common ancestors ancestor of a list of commits by + recursively calling {!lcas} and merging the results. + + If one of the merges results in a conflict, or if a call to {!lcas} + returns either [Error `Max_depth_reached] or [Error `Too_many_lcas] then + the function returns the same error. *) + + val three_way_merge : + [> read_write ] t -> + info:(unit -> info) -> + ?max_depth:int -> + ?n:int -> + commit_key -> + commit_key -> + (commit_key, Merge.conflict) result Lwt.t + (** Compute the {!lcas} of the two commit and 3-way merge the result. *) + + val closure : + [> read ] t -> + min:commit_key list -> + max:commit_key list -> + commit_key list Lwt.t + (** Same as {{!Node.Graph.closure} Node.Graph.closure} but for the history + graph. *) + + val iter : + [> read ] t -> + min:commit_key list -> + max:commit_key list -> + ?commit:(commit_key -> unit Lwt.t) -> + ?edge:(commit_key -> commit_key -> unit Lwt.t) -> + ?skip:(commit_key -> bool Lwt.t) -> + ?rev:bool -> + unit -> + unit Lwt.t + (** Same as {{!Node.Graph.iter} Node.Graph.iter} but for traversing the + history graph. *) +end + +module type Sigs = sig + module type S = S + module type Maker = Maker + + (** [Maker] provides a simple implementation of commit values, parameterized + by commit info. *) + module Maker (I : Info.S) : Maker with module Info = I + + (** [Generic_key] generalises the concept of "commit" to one that supports + object keys that are not strictly equal to hashes. *) + module Generic_key : sig + module type S = S_generic_key + module type Maker = Maker_generic_key + + module Maker (I : Info.S) : Maker with module Info = I + + module Store + (I : Info.S) + (N : Node.Store) + (S : Indexable.S) + (H : Hash.S with type t = S.hash) + (V : S + with type node_key = N.key + and type commit_key = S.key + and type t = S.value + and module Info := I) : + Store + with type 'a t = 'a N.t * 'a S.t + and type key = S.key + and type value = S.value + and module Info = I + and type hash = S.hash + and module Val = V + + include Maker with module Info = Info.Default + end + + (** V1 serialisation. *) + module V1 : sig + module Info : Info.S with type t = Info.Default.t + (** Serialisation format for V1 info. *) + + module Make (Hash : Hash.S) (C : Generic_key.S with module Info := Info) : sig + include + Generic_key.S + with module Info = Info + and type node_key = C.node_key + and type commit_key = C.commit_key + + val import : C.t -> t + val export : t -> C.t + end + end + + module Portable : sig + (** Portable form of a commit implementation that can be constructed from a + concrete representation and used in computing hashes. Conceptually, a + [Commit.Portable.t] is a [Commit.t] in which all internal keys have been + replaced with the hashes of the values they point to. + + As with {!Node.Portable}, computations over portable values must commute + with those over [t]s. *) + + (** A node implementation with hashes for keys is trivially portable: *) + module Of_commit (S : S) : + Portable + with type commit := S.t + and type t = S.t + and type hash = S.hash + and module Info = S.Info + + module type S = Portable + end + + module type Store = Store + (** [Store] specifies the signature for commit stores. *) + + (** [Store] creates a new commit store. *) + module Store + (I : Info.S) + (N : Node.Store) + (S : Content_addressable.S with type key = N.key) + (H : Hash.S with type t = S.key) + (V : S with type hash = S.key and type t = S.value and module Info := I) : + Store + with type 'a t = 'a N.t * 'a S.t + and type key = S.key + and type hash = S.key + and type value = S.value + and module Info = I + and module Val = V + + module type History = History + (** [History] specifies the signature for commit history. The history is + represented as a partial-order of commits and basic functions to search + through that history are provided. + + Every commit can point to an entry point in a node graph, where + user-defined contents are stored. *) + + (** Build a commit history. *) + module History (C : Store) : + History + with type 'a t = 'a C.t + and type v = C.Val.t + and type node_key = C.Node.key + and type commit_key = C.key + and type info = C.Info.t + + include Maker with module Info = Info.Default +end diff --git a/vendors/irmin/src/irmin/conf.ml b/vendors/irmin/src/irmin/conf.ml new file mode 100644 index 000000000000..4c3a69a59db4 --- /dev/null +++ b/vendors/irmin/src/irmin/conf.ml @@ -0,0 +1,175 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2017 Daniel C. Bünzli + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) +open! Import + +module Univ = struct + type t = exn + + let create (type s) () = + let module M = struct + exception E of s option + end in + ((fun x -> M.E (Some x)), function M.E x -> x | _ -> None) +end + +type 'a key = { + name : string; + doc : string option; + docv : string option; + docs : string option; + ty : 'a Type.t; + default : 'a; + to_univ : 'a -> Univ.t; + of_univ : Univ.t -> 'a option; +} + +type k = K : 'a key -> k + +module M = Map.Make (struct + type t = k + + let compare (K a) (K b) = String.compare a.name b.name +end) + +module Spec = struct + module M = Map.Make (String) + + type t = { name : string; mutable keys : k M.t } + + let all = Hashtbl.create 8 + + let v name = + let keys = M.empty in + if Hashtbl.mem all name then + Fmt.failwith "Config spec already exists: %s" name; + let x = { name; keys } in + Hashtbl.replace all name x; + x + + let name { name; _ } = name + let update spec name k = spec.keys <- M.add name k spec.keys + let list () = Hashtbl.to_seq_values all + let find name = Hashtbl.find_opt all name + let find_key spec name = M.find_opt name spec.keys + let keys spec = M.to_seq spec.keys |> Seq.map snd + let clone { name; keys } = { name; keys } + + let join dest src = + let dest = clone dest in + let name = ref dest.name in + let keys = + List.fold_left + (fun acc spec -> + if dest.name = spec.name then acc + else + let () = name := !name ^ "-" ^ spec.name in + M.add_seq (M.to_seq spec.keys) acc) + dest.keys src + in + { name = !name; keys } +end + +type t = Spec.t * Univ.t M.t + +let spec = fst + +let key ?docs ?docv ?doc ~spec name ty default = + let () = + String.iter + (function + | '-' | '_' | 'a' .. 'z' | '0' .. '9' -> () + | _ -> raise @@ Invalid_argument name) + name + in + let to_univ, of_univ = Univ.create () in + let k = { name; ty; default; to_univ; of_univ; doc; docv; docs } in + Spec.update spec name (K k); + k + +let name t = t.name +let doc t = t.doc +let docv t = t.docv +let docs t = t.docs +let ty t = t.ty +let default t = t.default +let empty spec = (spec, M.empty) +let singleton spec k v = (spec, M.singleton (K k) (k.to_univ v)) +let is_empty (_, t) = M.is_empty t +let mem (_, d) k = M.mem (K k) d + +let add (spec, d) k v = + if Spec.find_key spec k.name |> Option.is_none then + Fmt.invalid_arg "invalid config key: %s" k.name + else (spec, M.add (K k) (k.to_univ v) d) + +let verify (spec, d) = + M.iter + (fun (K k) _ -> + if Spec.find_key spec k.name |> Option.is_none then + Fmt.invalid_arg "invalid config key: %s" k.name) + d; + (spec, d) + +let union (rs, r) (ss, s) = + let spec = Spec.join rs [ ss ] in + (spec, M.fold M.add r s) + +let rem (s, d) k = (s, M.remove (K k) d) +let find (_, d) k = try k.of_univ (M.find (K k) d) with Not_found -> None +let uri = Type.(map string) Uri.of_string Uri.to_string + +let get (_, d) k = + try + match k.of_univ (M.find (K k) d) with + | Some v -> v + | None -> raise Not_found + with Not_found -> k.default + +let keys (_, conf) = M.to_seq conf |> Seq.map (fun (k, _) -> k) +let with_spec (_, conf) spec = (spec, conf) + +let to_strings (_, conf) = + conf + |> M.to_seq + |> Seq.map (fun (K k, v) -> + ( k.name, + match k.of_univ v with + | Some v -> Type.to_string k.ty v + | None -> assert false )) + +let pp ppf t = + t |> to_strings |> List.of_seq |> Fmt.Dump.(list (pair string string)) ppf + +let equal t1 t2 = + t1 == t2 + || Seq.for_all2 + (fun (k1, v1) (k2, v2) -> String.equal k1 k2 && String.equal v1 v2) + (to_strings t1) (to_strings t2) + +(* ~root *) +let root spec = + key ~spec ~docv:"ROOT" ~doc:"The location of the Irmin store on disk." + ~docs:"COMMON OPTIONS" "root" + Type.(string) + "." + +let find_root (spec, d) : string option = + match Spec.find_key spec "root" with + | None -> None + | Some (K k) -> ( + let v = find (spec, d) k in + match v with None -> None | Some v -> Some (Type.to_string k.ty v)) diff --git a/vendors/irmin/src/irmin/conf.mli b/vendors/irmin/src/irmin/conf.mli new file mode 100644 index 000000000000..1f08f95622bd --- /dev/null +++ b/vendors/irmin/src/irmin/conf.mli @@ -0,0 +1,167 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** {1 Configuration converters} + + A configuration converter transforms a string value to an OCaml value and + vice-versa. *) + +(** {1:keys Keys} *) + +type 'a key +(** The type for configuration keys whose lookup value is ['a]. *) + +type k = K : 'a key -> k + +module Spec : sig + type t + (** A configuration spec is used to group keys by backend *) + + val v : string -> t + (** [v name] is a new configuration specification named [name] *) + + val name : t -> string + (** [name spec] is the name associated with a config spec *) + + val list : unit -> t Seq.t + (** [list ()] is a sequence containing all available config specs *) + + val find : string -> t option + (** [find name] is the config spec associated with [name] if available *) + + val find_key : t -> string -> k option + (** [find_key spec k] is the key associated with the name [k] in [spec] *) + + val keys : t -> k Seq.t + (** [keys spec] is a sequence of keys available in [spec] *) + + val join : t -> t list -> t + (** [join a b] is a new [Spec.t] combining [a] and all specs present in [b] + + The name of the resulting spec will be the name of [a] and the names of + the specs in [b] joined by hyphens. *) +end + +val key : + ?docs:string -> + ?docv:string -> + ?doc:string -> + spec:Spec.t -> + string -> + 'a Type.t -> + 'a -> + 'a key +(** [key ~docs ~docv ~doc ~spec name conv default] is a configuration key named + [name] that maps to value [default] by default. It will be associated with + the config grouping [spec]. [conv] is used to convert key values provided by + end users. + + [docs] is the title of a documentation section under which the key is + documented. [doc] is a short documentation string for the key, this should + be a single sentence or paragraph starting with a capital letter and ending + with a dot. [docv] is a meta-variable for representing the values of the key + (e.g. ["BOOL"] for a boolean). + + @raise Invalid_argument + if the key name is not made of a sequence of ASCII lowercase letter, + digit, dash or underscore. + + {b Warning.} No two keys should share the same [name] as this may lead to + difficulties in the UI. *) + +val name : 'a key -> string +(** The key name. *) + +val ty : 'a key -> 'a Type.t +(** [tc k] is [k]'s converter. *) + +val default : 'a key -> 'a +(** [default k] is [k]'s default value. *) + +val doc : 'a key -> string option +(** [doc k] is [k]'s documentation string (if any). *) + +val docv : 'a key -> string option +(** [docv k] is [k]'s value documentation meta-variable (if any). *) + +val docs : 'a key -> string option +(** [docs k] is [k]'s documentation section (if any). *) + +val root : Spec.t -> string key +(** Default [--root=ROOT] argument. *) + +(** {1:conf Configurations} *) + +type t +(** The type for configurations. *) + +val pp : t Fmt.t +(** [pp] is the pretty printer for configuration values. *) + +val equal : t -> t -> bool +(** [equal] is the equality for configuration values. Two values are equal if + they have the same [pp] representation. *) + +val spec : t -> Spec.t +(** [spec c] is the specification associated with [c] *) + +val empty : Spec.t -> t +(** [empty spec] is an empty configuration. *) + +val singleton : Spec.t -> 'a key -> 'a -> t +(** [singleton spec k v] is the configuration where [k] maps to [v]. *) + +val is_empty : t -> bool +(** [is_empty c] is [true] iff [c] is empty. *) + +val mem : t -> 'a key -> bool +(** [mem c k] is [true] iff [k] has a mapping in [c]. *) + +val add : t -> 'a key -> 'a -> t +(** [add c k v] is [c] with [k] mapping to [v]. *) + +val rem : t -> 'a key -> t +(** [rem c k] is [c] with [k] unbound. *) + +val union : t -> t -> t +(** [union r s] is the union of the configurations [r] and [s]. *) + +val find : t -> 'a key -> 'a option +(** [find c k] is [k]'s mapping in [c], if any. *) + +val get : t -> 'a key -> 'a +(** [get c k] is [k]'s mapping in [c]. + + {b Raises.} [Not_found] if [k] is not bound in [d]. *) + +val keys : t -> k Seq.t +(** [keys c] is a sequence of all keys present in [c] *) + +val with_spec : t -> Spec.t -> t +(** [with_spec t s] is the config [t] with spec [s] *) + +val verify : t -> t +(** [verify t] is an identity function that ensures all keys match the spec + + {b Raises.} [Invalid_argument] if [t] contains invalid keys *) + +(** {1:builtin_converters Built-in value converters} *) + +val uri : Uri.t Type.t +(** [uri] converts values with {!Uri.of_string}. *) + +val find_root : t -> string option +(** [find_root c] is [root]'s mapping in [c], if any. *) diff --git a/vendors/irmin/src/irmin/content_addressable.ml b/vendors/irmin/src/irmin/content_addressable.ml new file mode 100644 index 000000000000..aa7b506b5cb0 --- /dev/null +++ b/vendors/irmin/src/irmin/content_addressable.ml @@ -0,0 +1,84 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Content_addressable_intf + +module Make (AO : Append_only.Maker) (K : Hash.S) (V : Type.S) = struct + include AO (K) (V) + open Lwt.Infix + module H = Hash.Typed (K) (V) + + let hash = H.hash + let pp_key = Type.pp K.t + let equal_hash = Type.(unstage (equal K.t)) + + let find t k = + find t k >>= function + | None -> Lwt.return_none + | Some v as r -> + let k' = hash v in + if equal_hash k k' then Lwt.return r + else + Fmt.kstr Lwt.fail_invalid_arg "corrupted value: got %a, expecting %a" + pp_key k' pp_key k + + let unsafe_add t k v = add t k v + + let add t v = + let k = hash v in + add t k v >|= fun () -> k +end + +module Check_closed (CA : Maker) (K : Hash.S) (V : Type.S) = struct + module S = CA (K) (V) + + type 'a t = { closed : bool ref; t : 'a S.t } + type key = S.key + type value = S.value + + let check_not_closed t = if !(t.closed) then raise Store_properties.Closed + + let mem t k = + check_not_closed t; + S.mem t.t k + + let find t k = + check_not_closed t; + S.find t.t k + + let add t v = + check_not_closed t; + S.add t.t v + + let unsafe_add t k v = + check_not_closed t; + S.unsafe_add t.t k v + + let batch t f = + check_not_closed t; + S.batch t.t (fun w -> f { t = w; closed = t.closed }) + + let v conf = + let+ t = S.v conf in + { closed = ref false; t } + + let close t = + if !(t.closed) then Lwt.return_unit + else ( + t.closed := true; + S.close t.t) +end diff --git a/vendors/irmin/src/irmin/content_addressable.mli b/vendors/irmin/src/irmin/content_addressable.mli new file mode 100644 index 000000000000..ed9b4cc43d03 --- /dev/null +++ b/vendors/irmin/src/irmin/content_addressable.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Content_addressable_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/content_addressable_intf.ml b/vendors/irmin/src/irmin/content_addressable_intf.ml new file mode 100644 index 000000000000..1c0fe4a1e497 --- /dev/null +++ b/vendors/irmin/src/irmin/content_addressable_intf.ml @@ -0,0 +1,69 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +open Store_properties + +module type S = sig + (** A {i content-addressable} store is an indexed read-write store in which + values are keyed directly by their hashes. *) + + include Read_only.S + (** @inline *) + + val add : [> write ] t -> value -> key Lwt.t + (** Write the contents of a value to the store. It's the responsibility of the + content-addressable store to generate a consistent key. *) + + val unsafe_add : [> write ] t -> key -> value -> unit Lwt.t + (** Same as {!add} but allows specifying the key directly. The backend might + choose to discard that key and/or can be corrupt if the key scheme is not + consistent. *) + + include Closeable with type 'a t := 'a t + (** @inline *) + + include Batch with type 'a t := 'a t + (** @inline *) +end + +module type Maker = functor (Hash : Hash.S) (Value : Type.S) -> sig + include S with type value = Value.t and type key = Hash.t + + include Of_config with type 'a t := 'a t + (** @inline *) +end + +module type Sigs = sig + module type S = S + module type Maker = Maker + + module Make + (Append_only_maker : Append_only.Maker) + (Hash : Hash.S) + (Value : Type.S) : sig + include + S + with type 'a t = 'a Append_only_maker(Hash)(Value).t + and type value = Value.t + and type key = Hash.t + + include Of_config with type 'a t := 'a t + (** @inline *) + end + + module Check_closed (M : Maker) : Maker +end diff --git a/vendors/irmin/src/irmin/contents.ml b/vendors/irmin/src/irmin/contents.ml new file mode 100644 index 000000000000..9cc3126f996e --- /dev/null +++ b/vendors/irmin/src/irmin/contents.ml @@ -0,0 +1,251 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Contents_intf + +let lexeme e x = ignore (Jsonm.encode e (`Lexeme x)) + +let rec encode_json e = function + | `Null -> lexeme e `Null + | `Bool b -> lexeme e (`Bool b) + | `String s -> lexeme e (`String s) + | `Float f -> lexeme e (`Float f) + | `A a -> + lexeme e `As; + List.iter (encode_json e) a; + lexeme e `Ae + | `O o -> + lexeme e `Os; + List.iter + (fun (k, v) -> + lexeme e (`Name k); + encode_json e v) + o; + lexeme e `Oe + +let decode_json d = + let decode d = + match Jsonm.decode d with + | `Lexeme l -> l + | `Error e -> failwith (Fmt.str "%a" Jsonm.pp_error e) + | _ -> failwith "invalid JSON encoding" + in + let rec unwrap v d = + match v with + | `Os -> obj [] d + | `As -> arr [] d + | (`Null | `Bool _ | `String _ | `Float _) as v -> v + | _ -> failwith "invalid JSON value" + and arr vs d = + match decode d with + | `Ae -> `A (List.rev vs) + | v -> + let v = unwrap v d in + arr (v :: vs) d + and obj ms d = + match decode d with + | `Oe -> `O (List.rev ms) + | `Name k -> + let v = unwrap (decode d) d in + obj ((k, v) :: ms) d + | _ -> failwith "invalid JSON object" + in + try Ok (unwrap (decode d) d) with Failure msg -> Error (`Msg msg) + +type json = + [ `Null + | `Bool of bool + | `String of string + | `Float of float + | `O of (string * json) list + | `A of json list ] +[@@deriving irmin] + +module Json_value = struct + type t = json [@@deriving irmin] + + let pp fmt x = + let buffer = Buffer.create 32 in + let encoder = Jsonm.encoder (`Buffer buffer) in + encode_json encoder x; + ignore @@ Jsonm.encode encoder `End; + let s = Buffer.contents buffer in + Fmt.pf fmt "%s" s + + let of_string s = + let decoder = Jsonm.decoder (`String s) in + match decode_json decoder with Ok obj -> Ok obj | Error _ as err -> err + + let equal_bool = Type.(unstage (equal bool)) + let equal_float = Type.(unstage (equal float)) + + let rec equal a b = + match (a, b) with + | `Null, `Null -> true + | `Bool a, `Bool b -> equal_bool a b + | `String a, `String b -> String.equal a b + | `Float a, `Float b -> equal_float a b + | `A a, `A b -> ( + try List.for_all2 (fun a' b' -> equal a' b') a b + with Invalid_argument _ -> false) + | `O a, `O b -> ( + let compare_fst (a, _) (b, _) = compare a b in + try + List.for_all2 + (fun (k, v) (k', v') -> k = k' && equal v v') + (List.sort compare_fst a) (List.sort compare_fst b) + with Invalid_argument _ -> false) + | _, _ -> false + + let t = Type.like ~equal ~pp ~of_string t + + let rec merge_object ~old x y = + let open Merge.Infix in + let m = + Merge.(alist Type.string t (fun _key -> option (v t merge_value))) + in + Merge.(f m ~old x y) >>=* fun x -> Merge.ok (`O x) + + and merge_float ~old x y = + let open Merge.Infix in + Merge.(f float ~old x y) >>=* fun f -> Merge.ok (`Float f) + + and merge_string ~old x y = + let open Merge.Infix in + Merge.(f string ~old x y) >>=* fun s -> Merge.ok (`String s) + + and merge_bool ~old x y = + let open Merge.Infix in + Merge.(f bool ~old x y) >>=* fun b -> Merge.ok (`Bool b) + + and merge_array ~old x y = + let open Merge.Infix in + Merge.(f (Merge.idempotent (Type.list t)) ~old x y) >>=* fun x -> + Merge.ok (`A x) + + and merge_value ~old x y = + let open Merge.Infix in + old () >>=* fun old -> + match (old, x, y) with + | Some `Null, _, _ -> merge_value ~old:(fun () -> Merge.ok None) x y + | None, `Null, `Null -> Merge.ok `Null + | Some (`Float old), `Float a, `Float b -> + merge_float ~old:(fun () -> Merge.ok (Some old)) a b + | None, `Float a, `Float b -> merge_float ~old:(fun () -> Merge.ok None) a b + | Some (`String old), `String a, `String b -> + merge_string ~old:(fun () -> Merge.ok (Some old)) a b + | None, `String a, `String b -> + merge_string ~old:(fun () -> Merge.ok None) a b + | Some (`Bool old), `Bool a, `Bool b -> + merge_bool ~old:(fun () -> Merge.ok (Some old)) a b + | None, `Bool a, `Bool b -> merge_bool ~old:(fun () -> Merge.ok None) a b + | Some (`A old), `A a, `A b -> + merge_array ~old:(fun () -> Merge.ok (Some old)) a b + | None, `A a, `A b -> merge_array ~old:(fun () -> Merge.ok None) a b + | Some (`O old), `O a, `O b -> + merge_object ~old:(fun () -> Merge.ok (Some old)) a b + | None, `O a, `O b -> merge_object ~old:(fun () -> Merge.ok None) a b + | _, _, _ -> Merge.conflict "Conflicting JSON datatypes" + + let merge_json = Merge.(v t merge_value) + let merge = Merge.(option merge_json) +end + +module Json = struct + type t = (string * json) list [@@deriving irmin] + + let pp fmt x = + let buffer = Buffer.create 32 in + let encoder = Jsonm.encoder (`Buffer buffer) in + encode_json encoder (`O x); + ignore @@ Jsonm.encode encoder `End; + let s = Buffer.contents buffer in + Fmt.pf fmt "%s" s + + let of_string s = + let decoder = Jsonm.decoder (`String s) in + match decode_json decoder with + | Ok (`O obj) -> Ok obj + | Ok _ -> Error (`Msg "Irmin JSON values must be objects") + | Error _ as err -> err + + let equal a b = Json_value.equal (`O a) (`O b) + let t = Type.like ~equal ~pp ~of_string t + + let merge = + Merge.(option (alist Type.string Json_value.t (fun _ -> Json_value.merge))) +end + +module String_v2 = struct + type t = string [@@deriving irmin] + + let merge = Merge.idempotent Type.(option string) +end + +module String = struct + type t = string [@@deriving irmin] + + let pre_hash = Type.(unstage (pre_hash t)) + + (* Manually add a prefix to default contents, in order to prevent hash + collision between contents and nodes or commits (see + https://github.com/mirage/irmin/issues/1304). *) + let pre_hash_prefixed x f = + f "B"; + pre_hash x f + + let t = Type.(like t ~pre_hash:pre_hash_prefixed) + let merge = Merge.idempotent Type.(option string) +end + +module Store_indexable + (S : Indexable.S) + (H : Hash.S with type t = S.hash) + (C : S with type t = S.value) = +struct + module Val = C + module Hash = Hash.Typed (H) (C) + include S + + let read_opt t = function None -> Lwt.return_none | Some k -> find t k + + let add_opt t = function + | None -> Lwt.return_none + | Some v -> add t v >>= Lwt.return_some + + let merge t = + Merge.like_lwt Type.(option Key.t) Val.merge (read_opt t) (add_opt t) +end + +module Store + (S : Content_addressable.S) + (H : Hash.S with type t = S.key) + (C : S with type t = S.value) = + Store_indexable (Indexable.Of_content_addressable (H) (S)) (H) (C) + +module V1 = struct + module String = struct + include String + + let t = Type.(boxed (string_of `Int64)) + + type nonrec t = t [@@deriving irmin ~encode_bin ~decode_bin ~pre_hash] + + let size_of = Type.Size.t t + let t = Type.like t ~bin:(encode_bin, decode_bin, size_of) ~pre_hash + end +end diff --git a/vendors/irmin/src/irmin/contents.mli b/vendors/irmin/src/irmin/contents.mli new file mode 100644 index 000000000000..286391727339 --- /dev/null +++ b/vendors/irmin/src/irmin/contents.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Values. *) + +include Contents_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/contents_intf.ml b/vendors/irmin/src/irmin/contents_intf.ml new file mode 100644 index 000000000000..64c0811f8476 --- /dev/null +++ b/vendors/irmin/src/irmin/contents_intf.ml @@ -0,0 +1,107 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + (** {1 Signature for store contents} *) + + type t [@@deriving irmin] + (** The type for user-defined contents. *) + + val merge : t option Merge.t + (** Merge function. Evaluates to [`Conflict msg] if the values cannot be + merged properly. The arguments of the merge function can take [None] to + mean that the key does not exists for either the least-common ancestor or + one of the two merging points. The merge function returns [None] when the + key's value should be deleted. *) +end + +module type Store = sig + include Indexable.S + + val merge : [> read_write ] t -> key option Merge.t + (** [merge t] lifts the merge functions defined on contents values to contents + key. The merge function will: {e (i)} read the values associated with the + given keys, {e (ii)} use the merge function defined on values and + {e (iii)} write the resulting values into the store to get the resulting + key. See {!val-S.merge}. + + If any of these operations fail, return [`Conflict]. *) + + module Val : S with type t = value + module Hash : Hash.Typed with type t = hash and type value = value +end + +module type Sigs = sig + module type S = S + + module String : S with type t = string + (** Contents of type [string], with the {{!Irmin.Merge.default} default} 3-way + merge strategy: assume that update operations are idempotent and conflict + iff values are modified concurrently. *) + + module String_v2 : S with type t = string + (** Similar to [String] above, but the hash computation is compatible with + versions older than irmin.3.0 *) + + type json = + [ `Null + | `Bool of bool + | `String of string + | `Float of float + | `O of (string * json) list + | `A of json list ] + + module Json : S with type t = (string * json) list + (** [Json] contents are associations from strings to [json] values stored as + JSON encoded strings. If the same JSON key has been modified concurrently + with different values then the [merge] function conflicts. *) + + module Json_value : S with type t = json + (** [Json_value] allows any kind of json value to be stored, not only objects. *) + + module V1 : sig + module String : S with type t = string + (** Same as {!String} but use v1 serialisation format. *) + end + + module type Store = Store + (** Contents store. *) + + (** [Store] creates a contents store. *) + module Store + (S : Content_addressable.S) + (H : Hash.S with type t = S.key) + (C : S with type t = S.value) : + Store + with type 'a t = 'a S.t + and type key = H.t + and type hash = H.t + and type value = C.t + + (** [Store_indexable] is like {!Store} but uses an indexable store as a + backend (rather than a content-addressable one). *) + module Store_indexable + (S : Indexable.S) + (H : Hash.S with type t = S.hash) + (C : S with type t = S.value) : + Store + with type 'a t = 'a S.t + and type key = S.key + and type value = S.value + and type hash = S.hash +end diff --git a/vendors/irmin/src/irmin/data/dune b/vendors/irmin/src/irmin/data/dune new file mode 100644 index 000000000000..d0ddd5ce62d8 --- /dev/null +++ b/vendors/irmin/src/irmin/data/dune @@ -0,0 +1,6 @@ +(library + (name irmin_data) + (public_name irmin.data) + (libraries bigstringaf fmt) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin/data/fixed_size_string_set.ml b/vendors/irmin/src/irmin/data/fixed_size_string_set.ml new file mode 100644 index 000000000000..4979a36100bc --- /dev/null +++ b/vendors/irmin/src/irmin/data/fixed_size_string_set.ml @@ -0,0 +1,237 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type elt = string + +type t = { + elt_length : int; + hash_elt : elt -> int; + hash_elt_substring : Bigstringaf.t -> off:int -> len:int -> int; + empty_slot : elt; + mutable data : Bigstringaf.t; + mutable data_length : int; + mutable slot_count : int; + mutable cardinal : int; +} + +type hashset = t + +module Slot : sig + type t + + val of_elt : hashset -> elt -> t + val of_elt_substring : hashset -> src:Bigstringaf.t -> src_off:int -> t + val contains : hashset -> t -> elt -> bool + + val contains_substring : + hashset -> t -> src:Bigstringaf.t -> src_off:int -> bool + + val is_empty : hashset -> t -> bool + val get : hashset -> t -> elt + val set : hashset -> t -> elt -> unit + val set_substring : hashset -> t -> src:Bigstringaf.t -> src_off:int -> unit + val next : hashset -> t -> t + val iter_all : hashset -> f:(t -> unit) -> unit + val to_offset : t -> int +end = struct + type t = Offset of int [@@ocaml.unboxed] + + let offset_of_hash h hash = + let index = abs hash mod h.slot_count in + Offset (index * h.elt_length) + + let of_elt h elt = offset_of_hash h (h.hash_elt elt) + + let of_elt_substring h ~src ~src_off = + offset_of_hash h (h.hash_elt_substring src ~off:src_off ~len:h.elt_length) + + let contains h (Offset offset) string = + Bigstringaf.memcmp_string h.data offset string 0 h.elt_length = 0 + + let contains_substring h (Offset offset) ~src ~src_off = + Bigstringaf.memcmp h.data offset src src_off h.elt_length = 0 + + let is_empty h t = contains h t h.empty_slot + + let get h (Offset offset) = + Bigstringaf.substring h.data ~off:offset ~len:h.elt_length + + let set h (Offset offset) elt = + Bigstringaf.blit_from_string elt ~src_off:0 h.data ~dst_off:offset + ~len:h.elt_length + + let set_substring h (Offset offset) ~src ~src_off = + Bigstringaf.blit src ~src_off h.data ~dst_off:offset ~len:h.elt_length + + let next h (Offset offset) = Offset ((offset + h.elt_length) mod h.data_length) + + let iter_all hashset ~f = + assert (hashset.data_length <> 0); + f (Offset 0); + let rec aux = function + | Offset 0 -> () + | offset -> + f offset; + aux (next hashset offset) + in + aux (next hashset (Offset 0)) + + let to_offset (Offset n) = n +end + +let empty_all_slots t = + Slot.iter_all t ~f:(fun slot -> Slot.set t slot t.empty_slot) + +module Default = struct + let hash : string -> int = Hashtbl.hash + let hash_substring t ~off ~len = hash (Bigstringaf.substring t ~off ~len) + let null ~elt_length = String.make elt_length '\000' +end + +let create ~elt_length ?(initial_slots = 0) ?hash ?hash_substring ?null () = + if elt_length <= 0 then + Fmt.invalid_arg "%s.create: element length must be strictly positive" + __MODULE__; + let empty_slot = + match null with Some x -> x | None -> Default.null ~elt_length + in + let hash_elt, hash_elt_substring = + match (hash, hash_substring) with + | Some h, Some h' -> (h, h') + | None, None -> (Default.hash, Default.hash_substring) + | Some _, None | None, Some _ -> + Fmt.invalid_arg + "%s.create: must pass either both [hash] and [hash_substring] or \ + neither" + __MODULE__ + in + let slot_count = + let rec aux n = + if n >= initial_slots then n + else if n * 2 > Sys.max_array_length then n + else aux (n * 2) + in + aux 2 + in + let data_length = slot_count * elt_length in + let data = Bigstringaf.create data_length in + let t = + { + data; + data_length; + hash_elt; + hash_elt_substring; + elt_length; + empty_slot; + slot_count; + cardinal = 0; + } + in + empty_all_slots t; + t + +let load_factor t = + let slots_available = Bigstringaf.length t.data / t.elt_length in + Float.of_int t.cardinal /. Float.of_int slots_available + +type ok_or_duplicate = [ `Ok | `Duplicate ] + +let rec unguarded_add t slot elt : ok_or_duplicate = + if Slot.is_empty t slot then ( + (* Write the element to this slot *) + Slot.set t slot elt; + `Ok) + else if Slot.contains t slot elt then `Duplicate + else unguarded_add t (Slot.next t slot) elt + +let rec unguarded_add_substring t slot ~src ~src_off : ok_or_duplicate = + if Slot.is_empty t slot then ( + (* Write the element to this slot *) + Slot.set_substring t slot ~src ~src_off; + `Ok) + else if Slot.contains_substring t slot ~src ~src_off then `Duplicate + else unguarded_add_substring t (Slot.next t slot) ~src ~src_off + +let resize t = + let old_len = Bigstringaf.length t.data in + let old_data = t.data in + let new_len = old_len + (t.slot_count / 2 * t.elt_length) in + let new_data = Bigstringaf.create new_len in + let old_t = { t with data = old_data; data_length = old_len } in + t.data <- new_data; + t.data_length <- new_len; + t.slot_count <- new_len / t.elt_length; + empty_all_slots t; + Slot.iter_all old_t ~f:(fun old_slot -> + if not (Slot.is_empty old_t old_slot) then + let src_off = Slot.to_offset old_slot in + let new_slot = Slot.of_elt_substring t ~src:old_t.data ~src_off in + let result = + unguarded_add_substring t new_slot ~src:old_t.data ~src_off + in + assert (result = `Ok)) + +(* Resize when the hashset is more than 90% full: *) +let max_load_factor = 0.9 + +let add t elt = + if String.length elt <> t.elt_length then + Fmt.invalid_arg "%s.add: cannot write string of incorrect size to hashset" + __MODULE__; + if String.equal elt t.empty_slot then + Fmt.invalid_arg "%s.add: cannot write null value to hashset" __MODULE__; + + if Float.compare (load_factor t) max_load_factor >= 0 then resize t; + let slot = Slot.of_elt t elt in + let result = unguarded_add t slot elt in + if result = `Ok then t.cardinal <- t.cardinal + 1; + result + +let add_exn t elt = + match add t elt with + | `Ok -> () + | `Duplicate -> + Fmt.invalid_arg "%s.add_exn: element '%S' already present" __MODULE__ elt + +let mem t elt = + if String.length elt <> t.elt_length then + Fmt.invalid_arg "%s.mem: cannot read string of incorrect size from hashset" + __MODULE__; + if String.equal elt t.empty_slot then + Fmt.failwith "%s.mem: cannot read null value from hashset" __MODULE__; + + let rec probe_loop slot = + if Slot.contains t slot elt then true + else if Slot.is_empty t slot then false + else probe_loop (Slot.next t slot) + in + probe_loop (Slot.of_elt t elt) + +let invariant invariant_elt t = + let element_count = ref 0 in + Slot.iter_all t ~f:(fun slot -> + if not (Slot.is_empty t slot) then ( + incr element_count; + invariant_elt (Slot.get t slot))); + assert (t.cardinal = !element_count) + +(* Using [Obj.reachable_words] directly on values of type [t] will give + inaccurate results since bigstrings are allocated on the C heap. As a + workaround, we provide a dedicated [reachable_words] function for use in + benchmarking this implementation. *) +let reachable_words t = + let bytes_per_word = Sys.word_size / 8 in + (t.data_length / bytes_per_word) + Obj.reachable_words (Obj.repr t) diff --git a/vendors/irmin/src/irmin/data/fixed_size_string_set.mli b/vendors/irmin/src/irmin/data/fixed_size_string_set.mli new file mode 100644 index 000000000000..7633c6cca225 --- /dev/null +++ b/vendors/irmin/src/irmin/data/fixed_size_string_set.mli @@ -0,0 +1,60 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type t +(** The type of mutable sets of fixed-length strings. *) + +type elt := string + +val create : + elt_length:int -> + ?initial_slots:int -> + ?hash:(elt -> int) -> + ?hash_substring:(Bigstringaf.t -> off:int -> len:int -> int) -> + ?null:string -> + unit -> + t +(** [create] builds an empty set of fixed-length strings. The parameters are as + follows: + + - [elt_length]: the length of each element string in bytes; + + - [initial_slots]: the minimum number of slots contained in the initial + internal buffer (NOTE: the actual number of slots will be the least power + of two greater than or equal to [initial_buffer]. This is not the same as + the number of elements that can fit inside the buffer, which also depends + on the maximum load factor); + + - [hash] / [hash_substring]: functions to use for placing elements inside + the internal buffer (given that the element is contained in a string or a + bigstring respectively). The stored elements must have uniformly + distributed [hash] results for good performance, and the two hash + functions must be equivalent. Defaults to [Hashtbl.hash] (and an + equivalent function on substrings). + + - [null]: a string of size [elt_length] that is guaranteed to never be added + to the hashset. Passing this string to {!add} or {!mem} after creating the + hashset will result in an exception being raised. *) + +include Hashset.S with type t := t and type elt := elt + +val invariant : (elt -> unit) -> t -> unit +(** [invariant f t] checks the internal invariants of [t] and calls [f] on every + element contained within. Exposed for testing. *) + +val reachable_words : t -> int +(** [reachable_words t] is the total number of words of data kept alive by [t] + (on both the C and OCaml heaps). *) diff --git a/vendors/irmin/src/irmin/data/hashset.ml b/vendors/irmin/src/irmin/data/hashset.ml new file mode 100644 index 000000000000..d161f46203a3 --- /dev/null +++ b/vendors/irmin/src/irmin/data/hashset.ml @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + type t + type elt + + val add : t -> elt -> [ `Ok | `Duplicate ] + (** [add t elt] adds [elt] to the set [t] and returns [`Ok] if [elt] is not + already a member of [t], otherwise returns [`Duplicate] and leaves the + hashset unchanged. *) + + val add_exn : t -> elt -> unit + (** [add_exn t elt] adds [elt] to the set [t]. + + @raise Invalid_argument if [elt] is already a member of [t]. *) + + val mem : t -> elt -> bool + (** [mem t elt] is [true] iff [elt] has been added to the hashset. *) +end diff --git a/vendors/irmin/src/irmin/data/irmin_data.ml b/vendors/irmin/src/irmin/data/irmin_data.ml new file mode 100644 index 000000000000..c5eb9283fb33 --- /dev/null +++ b/vendors/irmin/src/irmin/data/irmin_data.ml @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** This module contains data structure implementations used in the + implementation of Irmin. It is exposed only for internal use, and does not + provide a stable API. *) + +module Fixed_size_string_set = Fixed_size_string_set +(** Mutable sets of strings with a common length. *) diff --git a/vendors/irmin/src/irmin/diff.ml b/vendors/irmin/src/irmin/diff.ml new file mode 100644 index 000000000000..8e0e4d27735c --- /dev/null +++ b/vendors/irmin/src/irmin/diff.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type 'a t = [ `Updated of 'a * 'a | `Removed of 'a | `Added of 'a ] +[@@deriving irmin] diff --git a/vendors/irmin/src/irmin/diff.mli b/vendors/irmin/src/irmin/diff.mli new file mode 100644 index 000000000000..e9b36e6d9a2c --- /dev/null +++ b/vendors/irmin/src/irmin/diff.mli @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type 'a t = [ `Updated of 'a * 'a | `Removed of 'a | `Added of 'a ] +[@@deriving irmin] +(** The type for representing differences betwen values. *) diff --git a/vendors/irmin/src/irmin/dot.ml b/vendors/irmin/src/irmin/dot.ml new file mode 100644 index 000000000000..957f0cf508d1 --- /dev/null +++ b/vendors/irmin/src/irmin/dot.ml @@ -0,0 +1,226 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Printf +open Astring + +let src = Logs.Src.create "irmin.dot" ~doc:"Irmin dot graph output" + +module Log = (val Logs.src_log src : Logs.LOG) + +module type S = sig + type db + + val output_buffer : + db -> + ?html:bool -> + ?depth:int -> + ?full:bool -> + date:(int64 -> string) -> + Buffer.t -> + unit Lwt.t +end + +exception Utf8_failure + +let is_valid_utf8 str = + try + Uutf.String.fold_utf_8 + (fun _ _ -> function `Malformed _ -> raise Utf8_failure | _ -> ()) + () str; + true + with Utf8_failure -> false + +module Make (S : Store.Generic_key.S) = struct + type db = S.t + + module Branch = S.Backend.Branch + module Contents = S.Backend.Contents + module Node = S.Backend.Node + module Commit = S.Backend.Commit + module Slice = S.Backend.Slice + + module Graph = + Object_graph.Make (Contents.Hash) (Node.Hash) (Commit.Hash) (Branch.Key) + + module Info = S.Info + + let pp_author = Type.pp Info.author_t + let pp_message = Type.pp Info.message_t + + let fprintf (t : db) ?depth ?(html = false) ?full ~date name = + [%log.debug + "depth=%s html=%b full=%s" + (match depth with None -> "" | Some d -> string_of_int d) + html + (match full with None -> "" | Some b -> string_of_bool b)]; + let* slice = S.Repo.export ?full ?depth (S.repo t) in + let vertex = Hashtbl.create 102 in + let add_vertex v l = Hashtbl.add vertex v l in + let mem_vertex v = Hashtbl.mem vertex v in + let edges = ref [] in + let add_edge v1 l v2 = + if mem_vertex v1 && mem_vertex v2 then edges := (v1, l, v2) :: !edges + in + let string_of_hash t k = + let s = Type.to_string t k in + if String.length s <= 8 then s else String.with_range s ~len:8 + in + let string_of_contents s = + let s = + if String.length s <= 10 then s else String.with_range s ~len:10 + in + let s = if is_valid_utf8 s then s else "" in + s + in + let label_of_node k _ = + let s = + (if html then + sprintf "

" + else fun x -> x) + (string_of_hash Node.Hash.t k) + in + `Label s + in + let label_of_step l = + let l = Type.to_string S.Path.step_t l in + let s = + (if html then sprintf "
%s
" else fun x -> x) + (string_of_contents l) + in + `Label s + in + let label_of_commit k c = + let k = string_of_hash Commit.Hash.t k in + let o = Commit.Val.info c in + let s = + if html then + let message = Fmt.to_to_string pp_message (Info.message o) in + Fmt.str + "
\n\ + \
%s
\n\ + \
%a
\n\ + \
%s
\n\ + \
%s
\n\ + \
 
\n\ +
" + k pp_author (Info.author o) + (date (Info.date o)) + (String.Ascii.escape message) + else sprintf "%s" k + in + `Label s + in + let label_of_contents k v = + let k = string_of_hash Contents.Hash.t k in + let s = + if html then + sprintf + "
\n\ + \
%s
\n\ + \
 
\n\ +
" + k + else + let v = string_of_contents (Type.to_string Contents.Val.t v) in + sprintf "%s (%s)" k (String.Ascii.escape_string v) + in + `Label s + in + let label_of_tag t = + let s = + if html then + sprintf "
%s
" (Type.to_string Branch.Key.t t) + else Type.to_string Branch.Key.t t + in + `Label s + in + let contents = ref [] in + let nodes = ref [] in + let commits = ref [] in + let* () = + Slice.iter slice (function + | `Contents c -> + contents := c :: !contents; + Lwt.return_unit + | `Node n -> + nodes := n :: !nodes; + Lwt.return_unit + | `Commit c -> + commits := c :: !commits; + Lwt.return_unit) + in + List.iter + (fun (k, c) -> + add_vertex (`Contents k) [ `Shape `Box; label_of_contents k c ]) + !contents; + List.iter + (fun (k, t) -> + add_vertex (`Node k) [ `Shape `Box; `Style `Dotted; label_of_node k t ]) + !nodes; + List.iter + (fun (k, r) -> + add_vertex (`Commit k) + [ `Shape `Box; `Style `Bold; label_of_commit k r ]) + !commits; + List.iter + (fun (k, t) -> + List.iter + (fun (l, v) -> + match v with + | `Contents (v, _meta) -> + let v = Contents.Key.to_hash v in + add_edge (`Node k) + [ `Style `Dotted; label_of_step l ] + (`Contents v) + | `Node n -> + let n = Node.Key.to_hash n in + add_edge (`Node k) [ `Style `Solid; label_of_step l ] (`Node n)) + (Node.Val.list t)) + !nodes; + List.iter + (fun (k, r) -> + List.iter + (fun c -> + let c = Commit.Key.to_hash c in + add_edge (`Commit k) [ `Style `Bold ] (`Commit c)) + (Commit.Val.parents r); + let node_hash = Commit.Val.node r |> Node.Key.to_hash in + add_edge (`Commit k) [ `Style `Dashed ] (`Node node_hash)) + !commits; + let branch_t = S.Backend.Repo.branch_t (S.repo t) in + let* bs = Branch.list branch_t in + let+ () = + Lwt_list.iter_s + (fun r -> + Branch.find branch_t r >|= function + | None -> () + | Some k -> + let k = Commit.Key.to_hash k in + add_vertex (`Branch r) + [ `Shape `Plaintext; label_of_tag r; `Style `Filled ]; + add_edge (`Branch r) [ `Style `Bold ] (`Commit k)) + bs + in + let vertex = Hashtbl.fold (fun k v acc -> (k, v) :: acc) vertex [] in + fun ppf -> Graph.output ppf vertex !edges name + + let output_buffer t ?html ?depth ?full ~date buf = + let+ fprintf = fprintf t ?depth ?full ?html ~date "graph" in + let ppf = Format.formatter_of_buffer buf in + fprintf ppf +end diff --git a/vendors/irmin/src/irmin/dot.mli b/vendors/irmin/src/irmin/dot.mli new file mode 100644 index 000000000000..aa8f90346151 --- /dev/null +++ b/vendors/irmin/src/irmin/dot.mli @@ -0,0 +1,45 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Store dumps. *) + +module type S = sig + (** {1 Dot Export} *) + + type db + + val output_buffer : + db -> + ?html:bool -> + ?depth:int -> + ?full:bool -> + date:(int64 -> string) -> + Buffer.t -> + unit Lwt.t + (** [output_buffer t ?html ?depth ?full buf] outputs the Graphviz + representation of [t] in the buffer [buf]. + + [html] (default is false) enables HTML labels. + + [depth] is used to limit the depth of the commit history. [None] here + means no limitation. + + If [full] is set (default is not) the full graph, including the commits, + nodes and contents, is exported, otherwise it is the commit history graph + only. *) +end + +module Make (S : Store.Generic_key.S) : S with type db = S.t diff --git a/vendors/irmin/src/irmin/dune b/vendors/irmin/src/irmin/dune new file mode 100644 index 000000000000..938a2ff5ecd6 --- /dev/null +++ b/vendors/irmin/src/irmin/dune @@ -0,0 +1,22 @@ +(library + (name irmin) + (public_name irmin) + (libraries + irmin.data + astring + bheap + digestif + fmt + jsonm + logs + logs.fmt + lwt + mtime + ocamlgraph + uri + uutf + (re_export repr)) + (preprocess + (pps ppx_irmin.internal -- --lib "Type")) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin/export_for_backends.ml b/vendors/irmin/src/irmin/export_for_backends.ml new file mode 100644 index 000000000000..507a4913b68c --- /dev/null +++ b/vendors/irmin/src/irmin/export_for_backends.ml @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Store_properties = Store_properties +module Logging = Logging +module Reversed_list = Reversed_list +include Import diff --git a/vendors/irmin/src/irmin/hash.ml b/vendors/irmin/src/irmin/hash.ml new file mode 100644 index 000000000000..c99a0a620d6a --- /dev/null +++ b/vendors/irmin/src/irmin/hash.ml @@ -0,0 +1,118 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Hash_intf + +module Make (H : Digestif.S) = struct + type t = H.t + + external get_64 : string -> int -> int64 = "%caml_string_get64u" + external swap64 : int64 -> int64 = "%bswap_int64" + + let get_64_little_endian str idx = + if Sys.big_endian then swap64 (get_64 str idx) else get_64 str idx + + let short_hash c = Int64.to_int (get_64_little_endian (H.to_raw_string c) 0) + + let short_hash_substring bigstring ~off = + Int64.to_int (Bigstringaf.get_int64_le bigstring off) + + let hash_size = H.digest_size + + let of_hex s = + match H.consistent_of_hex s with + | x -> Ok x + | exception Invalid_argument e -> Error (`Msg e) + + let pp_hex ppf x = Fmt.string ppf (H.to_hex x) + + let t = + Type.map ~pp:pp_hex ~of_string:of_hex + Type.(string_of (`Fixed hash_size)) + H.of_raw_string H.to_raw_string + + let hash s = H.digesti_string s + let to_raw_string s = H.to_raw_string s + let unsafe_of_raw_string s = H.of_raw_string s +end + +module Make_BLAKE2B (D : sig + val digest_size : int +end) = + Make (Digestif.Make_BLAKE2B (D)) + +module Make_BLAKE2S (D : sig + val digest_size : int +end) = + Make (Digestif.Make_BLAKE2S (D)) + +module SHA1 = Make (Digestif.SHA1) +module RMD160 = Make (Digestif.RMD160) +module SHA224 = Make (Digestif.SHA224) +module SHA256 = Make (Digestif.SHA256) +module SHA384 = Make (Digestif.SHA384) +module SHA512 = Make (Digestif.SHA512) +module BLAKE2B = Make (Digestif.BLAKE2B) +module BLAKE2S = Make (Digestif.BLAKE2S) + +module Typed (K : S) (V : Type.S) = struct + include K + + type value = V.t [@@deriving irmin ~pre_hash] + + let hash v = K.hash (pre_hash_value v) +end + +module V1 (K : S) : S with type t = K.t = struct + type t = K.t [@@deriving irmin ~encode_bin ~decode_bin] + + let hash = K.hash + let short_hash = K.short_hash + let short_hash_substring = K.short_hash_substring + let hash_size = K.hash_size + let int64_to_bin_string = Type.(unstage (to_bin_string int64)) + let hash_size_str = int64_to_bin_string (Int64.of_int K.hash_size) + let to_raw_string = K.to_raw_string + let unsafe_of_raw_string = K.unsafe_of_raw_string + + let encode_bin e f = + f hash_size_str; + encode_bin e f + + let decode_bin buf pos_ref = + pos_ref := !pos_ref + 8; + decode_bin buf pos_ref + + let size_of = Type.Size.custom_static (8 + hash_size) + let t = Type.like K.t ~bin:(encode_bin, decode_bin, size_of) +end + +module Set = struct + module Make (Hash : S) = struct + include Irmin_data.Fixed_size_string_set + + let create ?(initial_slots = 0) () = + let elt_length = Hash.hash_size + and hash s = Hash.(short_hash (unsafe_of_raw_string s)) + and hash_substring t ~off ~len:_ = Hash.short_hash_substring t ~off in + create ~elt_length ~initial_slots ~hash ~hash_substring () + + let add t h = add t (Hash.to_raw_string h) + let mem t h = mem t (Hash.to_raw_string h) + end + + module type S = Set +end diff --git a/vendors/irmin/src/irmin/hash.mli b/vendors/irmin/src/irmin/hash.mli new file mode 100644 index 000000000000..f9d039dfaac7 --- /dev/null +++ b/vendors/irmin/src/irmin/hash.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Hash_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/hash_intf.ml b/vendors/irmin/src/irmin/hash_intf.ml new file mode 100644 index 000000000000..9091fb4ef9db --- /dev/null +++ b/vendors/irmin/src/irmin/hash_intf.ml @@ -0,0 +1,133 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** Signature for digest hashes, inspired by Digestif. *) + + type t + (** The type for digest hashes. *) + + val hash : ((string -> unit) -> unit) -> t + (** Compute a deterministic store key from a sequence of strings. *) + + val short_hash : t -> int + (** [short_hash h] is a small hash of [h], to be used for instance as the + `hash` function of an OCaml [Hashtbl]. *) + + val hash_size : int + (** [hash_size] is the size of hash results, in bytes. *) + + val to_raw_string : t -> string + (** [to_raw_string t] is the raw sequence of bytes in [t] (of length + {!hash_size}). *) + + val unsafe_of_raw_string : string -> t + (** [unsafe_of_raw_string b] is the hash consisting of the raw sequence of + bytes [b]. + + {b Warning}: this function cannot guarantee that the supplied byte string + is a valid output of the hash process, so should only be used on strings + that are known to have been built with {!to_raw_string}. *) + + val short_hash_substring : Bigstringaf.t -> off:int -> int + (** [short_hash_substring t off] computes the short-hash of the raw hash data + contained in [t] at offset [off]. It has behaviour equivalent to: + + {[ + Bigstringaf.substring t ~off ~len:hash_size + |> unsafe_of_raw_string + |> short_hash + ]} + + but may be more efficient due to not needing to allocate an intermediate + [string]. *) + + (** {1 Value Types} *) + + val t : t Type.t + (** [t] is the value type for {!type-t}. *) +end + +module type Typed = sig + type t + type value + + val hash : value -> t + (** Compute a deterministic store key from a string. *) + + val short_hash : t -> int + (** [short_hash h] is a small hash of [h], to be used for instance as the + `hash` function of an OCaml [Hashtbl]. *) + + val hash_size : int + (** [hash_size] is the size of hash results, in bytes. *) + + (** {1 Value Types} *) + + val t : t Type.t + (** [t] is the value type for {!type-t}. *) +end + +module type Set = sig + type t + type hash + + val create : ?initial_slots:int -> unit -> t + val add : t -> hash -> [ `Ok | `Duplicate ] + val mem : t -> hash -> bool +end + +module type Sigs = sig + module type S = S + (** Signature for hash values. *) + + module type Typed = Typed + (** Signature for typed hashes, where [hash] directly takes a value as + argument and incremental hashing is not possible. *) + + (** Digestif hashes. *) + module Make (H : Digestif.S) : S with type t = H.t + + module Make_BLAKE2B (D : sig + val digest_size : int + end) : S + + module Make_BLAKE2S (D : sig + val digest_size : int + end) : S + + module SHA1 : S + module RMD160 : S + module SHA224 : S + module SHA256 : S + module SHA384 : S + module SHA512 : S + module BLAKE2B : S + module BLAKE2S : S + + (** v1 serialisation *) + module V1 (H : S) : S with type t = H.t + + (** Typed hashes. *) + module Typed (K : S) (V : Type.S) : + Typed with type t = K.t and type value = V.t + + module Set : sig + module Make (Hash : S) : Set with type hash := Hash.t + + module type S = Set + end +end diff --git a/vendors/irmin/src/irmin/import.ml b/vendors/irmin/src/irmin/import.ml new file mode 100644 index 000000000000..6fe68be9472f --- /dev/null +++ b/vendors/irmin/src/irmin/import.ml @@ -0,0 +1,157 @@ +(* + * Copyright (c) 2019-2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* Extensions to the default namespace, opened throughout the Irmin codebase. *) + +type read = Perms.read +type write = Perms.write +type read_write = Perms.read_write + +(** {2 Lwt syntax} *) + +include Lwt.Syntax + +let ( >>= ) = Lwt.Infix.( >>= ) +let ( >|= ) = Lwt.Infix.( >|= ) + +(** {2 Dependency extensions} *) + +module Option = struct + include Option + (** @closed *) + + let of_result = function Ok x -> Some x | Error _ -> None + let might f = function Some x -> f x | None -> Ok () +end + +module List = struct + include List + (** @closed *) + + let rec is_longer_than : type a. int -> a list -> bool = + fun len l -> + if len < 0 then true + else match l with [] -> false | _ :: tl -> is_longer_than (len - 1) tl + + let map f l = + let rec aux acc = function + | [] -> acc [] + | h :: t -> (aux [@tailcall]) (fun t' -> acc (f h :: t')) t + in + aux (fun x -> x) l + + let concat l = + let rec aux acc curr l = + match (curr, l) with + | [], [] -> List.rev acc + | [], [ l ] -> List.rev_append acc l + | [], h :: t -> (aux [@tailcall]) acc h t + | h :: t, l -> (aux [@tailcall]) (h :: acc) t l + in + aux [] [] l + + (* For compatibility with versions older than ocaml.4.11.0 *) + let concat_map f l = + let rec aux f acc = function + | [] -> rev acc + | x :: l -> + let xs = f x in + aux f (rev_append xs acc) l + in + aux f [] l + + let rec mem : type a. equal:(a -> a -> bool) -> a -> a t -> bool = + fun ~equal y -> function + | [] -> false + | x :: xs -> equal x y || mem ~equal y xs + + let rec rev_append_map : type a b. (a -> b) -> a list -> b list -> b list = + fun f xs ys -> + match xs with [] -> ys | x :: xs -> rev_append_map f xs (f x :: ys) + + let insert_exn : type a. a list -> int -> a -> a list = + fun l idx v -> + (* [list_insert l 0 v] is [v :: l] *) + assert (idx >= 0); + let rec aux l i acc = + if i = 0 then List.rev_append acc (v :: l) + else + match l with + | [] -> failwith "list_insert: input list too short" + | hd :: tl -> aux tl (i - 1) (hd :: acc) + in + aux l idx [] +end + +module Seq = struct + include Seq + (** @closed *) + + let rec drop : type a. int -> a t -> a t = + fun n l () -> + match l () with + | l' when n = 0 -> l' + | Nil -> Nil + | Cons (_, l') -> drop (n - 1) l' () + + let exists : type a. (a -> bool) -> a Seq.t -> bool = + fun f s -> + let rec aux s = + match s () with Seq.Nil -> false | Seq.Cons (v, s) -> f v || aux s + in + aux s + + let rec take : type a. int -> a t -> a t = + fun n l () -> + if n = 0 then Nil + else match l () with Nil -> Nil | Cons (x, l') -> Cons (x, take (n - 1) l') + + let for_all : type a. (a -> bool) -> a Seq.t -> bool = + fun f s -> + let rec aux s = + match s () with Seq.Nil -> true | Seq.Cons (v, s) -> f v && aux s + in + aux s + + (* For compatibility with versions older than ocaml.4.11.0 *) + let rec append seq1 seq2 () = + match seq1 () with + | Nil -> seq2 () + | Cons (x, next) -> Cons (x, append next seq2) + + (* Since 4.14 *) + let rec for_all2 f xs ys = + match xs () with + | Nil -> true + | Cons (x, xs) -> ( + match ys () with + | Nil -> true + | Cons (y, ys) -> f x y && for_all2 f xs ys) +end + +let shuffle state arr = + let rec aux n = + if n > 1 then ( + let k = Random.State.int state (n + 1) in + let temp = arr.(n) in + arr.(n) <- arr.(k); + arr.(k) <- temp; + aux (n - 1)) + in + let len = Array.length arr in + aux (len - 1); + () diff --git a/vendors/irmin/src/irmin/indexable.ml b/vendors/irmin/src/irmin/indexable.ml new file mode 100644 index 000000000000..5f833bea856e --- /dev/null +++ b/vendors/irmin/src/irmin/indexable.ml @@ -0,0 +1,83 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Indexable_intf + +module Maker_concrete_key2_of_1 (X : Maker_concrete_key1) = struct + type ('h, _) key = 'h X.key + + module Key (H : Hash.S) (_ : Type.S) = X.Key (H) + module Make = X.Make +end + +module Of_content_addressable (Key : Type.S) (S : Content_addressable.S) = +struct + include S + + type hash = key + type key = Key.t + + module Key = struct + include Key + + type nonrec hash = hash + + let to_hash x = x + end + + let index _ h = Lwt.return_some h + let unsafe_add t h v = unsafe_add t h v >|= fun () -> h +end + +module Check_closed_store (CA : S) = struct + module Key = CA.Key + + type 'a t = { closed : bool ref; t : 'a CA.t } + type value = CA.value + type key = CA.key + type hash = CA.hash + + let make_closeable t = { closed = ref false; t } + + let get_if_open_exn t = + if !(t.closed) then raise Store_properties.Closed else t.t + + let mem t k = (get_if_open_exn t |> CA.mem) k + let index t h = (get_if_open_exn t |> CA.index) h + let find t k = (get_if_open_exn t |> CA.find) k + let add t v = (get_if_open_exn t |> CA.add) v + let unsafe_add t k v = (get_if_open_exn t |> CA.unsafe_add) k v + + let batch t f = + (get_if_open_exn t |> CA.batch) (fun w -> f { t = w; closed = t.closed }) + + let close t = + if !(t.closed) then Lwt.return_unit + else ( + t.closed := true; + CA.close t.t) +end + +module Check_closed (M : Maker) (Hash : Hash.S) (Value : Type.S) = struct + module CA = M (Hash) (Value) + include Check_closed_store (CA) + + let v conf = + let+ t = CA.v conf in + { closed = ref false; t } +end diff --git a/vendors/irmin/src/irmin/indexable.mli b/vendors/irmin/src/irmin/indexable.mli new file mode 100644 index 000000000000..df5168c32aca --- /dev/null +++ b/vendors/irmin/src/irmin/indexable.mli @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Indexable_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/indexable_intf.ml b/vendors/irmin/src/irmin/indexable_intf.ml new file mode 100644 index 000000000000..e7c084e8a232 --- /dev/null +++ b/vendors/irmin/src/irmin/indexable_intf.ml @@ -0,0 +1,149 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Store_properties + +module type S_without_key_impl = sig + include Read_only.S + (** @inline *) + + type hash + (** The type of hashes of [value]. *) + + val add : [> write ] t -> value -> key Lwt.t + (** Write the contents of a value to the store, and obtain its key. *) + + val unsafe_add : [> write ] t -> hash -> value -> key Lwt.t + (** Same as {!add} but allows specifying the value's hash directly. The + backend might choose to discard that hash and/or can be corrupt if the + hash is not consistent. *) + + val index : [> read ] t -> hash -> key option Lwt.t + (** Indexing maps the hash of a value to a corresponding key of that value in + the store. For stores that are addressed by hashes directly, this is + typically [fun _t h -> Lwt.return (Key.of_hash h)]; for stores with more + complex addressing schemes, [index] may attempt a lookup operation in the + store. + + In general, indexing is best-effort and reveals no information about the + membership of the value in the store. In particular: + + - [index t hash = Some key] doesn't guarantee [mem t key]: the value with + hash [hash] may still be absent from the store; + + - [index t hash = None] doesn't guarantee that there is no [key] such that + [mem t key] and [Key.to_hash key = hash]: the value may still be present + in the store under a key that is not indexed. *) + + include Batch with type 'a t := 'a t + (** @inline *) +end + +module type S = sig + (** An {i indexable} store is a read-write store in which values can be added + and later found via their keys. + + Keys are not necessarily portable between different stores, so each store + provides an {!val-index} mechanism to find keys by the hashes of the + values they reference. *) + + include S_without_key_impl (* @inline *) + module Key : Key.S with type t = key and type hash = hash +end + +module type Maker = functor (Hash : Hash.S) (Value : Type.S) -> sig + include S with type value = Value.t and type hash = Hash.t + + include Of_config with type 'a t := 'a t + (** @inline *) +end + +(** A {!Maker_concrete_key} is an indexable store in which the key type is + uniquely determined by the hash type and is stated up-front. *) +module type Maker_concrete_key1 = sig + type 'h key + + module Key : functor (Hash : Hash.S) -> + Key.S with type t = Hash.t key and type hash = Hash.t + + module Make : functor (Hash : Hash.S) (Value : Type.S) -> sig + include + S + with type value = Value.t + and type hash = Hash.t + and type key = Hash.t key + + include Of_config with type 'a t := 'a t + (** @inline *) + end +end + +(** Like {!Maker_concrete_key1}, but the key type may also depend on type of the + value that it references. *) +module type Maker_concrete_key2 = sig + type ('h, 'v) key + + module Key : functor (Hash : Hash.S) (Value : Type.S) -> + Key.S with type t = (Hash.t, Value.t) key and type hash = Hash.t + + module Make : functor (Hash : Hash.S) (Value : Type.S) -> sig + include + S + with type value = Value.t + and type hash = Hash.t + and type key = (Hash.t, Value.t) key + + include Of_config with type 'a t := 'a t + (** @inline *) + end +end + +module type Sigs = sig + module type S = S + module type S_without_key_impl = S_without_key_impl + module type Maker = Maker + module type Maker_concrete_key1 = Maker_concrete_key1 + module type Maker_concrete_key2 = Maker_concrete_key2 + + module Maker_concrete_key2_of_1 (X : Maker_concrete_key1) : + Maker_concrete_key2 with type ('h, _) key = 'h X.key + + module Of_content_addressable + (Key : Type.S) + (S : Content_addressable.S with type key = Key.t) : + S + with type 'a t = 'a S.t + and type key = Key.t + and type hash = Key.t + and type value = S.value + + module Check_closed_store (CA : S) : sig + include + S with type key = CA.key and type hash = CA.hash and type value = CA.value + + val make_closeable : 'a CA.t -> 'a t + (** [make_closeable t] returns a version of [t] that raises {!Irmin.Closed} + if an operation is performed when it is already closed. *) + + val get_if_open_exn : 'a t -> 'a CA.t + (** [get_if_open_exn t] returns the store (without close checks) if it is + open; otherwise raises {!Irmin.Closed} *) + end + + module Check_closed (M : Maker) : Maker +end diff --git a/vendors/irmin/src/irmin/info.ml b/vendors/irmin/src/irmin/info.ml new file mode 100644 index 000000000000..9cf6d3404283 --- /dev/null +++ b/vendors/irmin/src/irmin/info.ml @@ -0,0 +1,41 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Info_intf + +module Default = struct + type author = string [@@deriving irmin] + type message = string [@@deriving irmin] + + type t = { date : int64; author : author; message : message } + [@@deriving irmin ~equal] + + type f = unit -> t + + let empty = { date = 0L; author = ""; message = "" } + let is_empty = equal empty + + let v ?(author = "") ?(message = "") date = + let r = { date; message; author } in + if is_empty r then empty else r + + let date t = t.date + let author t = t.author + let message t = t.message + let none () = empty +end + +type default = Default.t diff --git a/vendors/irmin/src/irmin/info.mli b/vendors/irmin/src/irmin/info.mli new file mode 100644 index 000000000000..295eedba8339 --- /dev/null +++ b/vendors/irmin/src/irmin/info.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Info_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/info_intf.ml b/vendors/irmin/src/irmin/info_intf.ml new file mode 100644 index 000000000000..2b0dfbf1092d --- /dev/null +++ b/vendors/irmin/src/irmin/info_intf.ml @@ -0,0 +1,67 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** {1 Commit Info} *) + +module type S = sig + type author = string [@@deriving irmin] + type message = string [@@deriving irmin] + + type t [@@deriving irmin] + (** The type for commit info. *) + + val v : ?author:author -> ?message:message -> int64 -> t + (** Create a new commit info. *) + + val date : t -> int64 + (** [date t] is [t]'s commit date. + + The date provided by the user when calling the {!v} function. Rounding + [Unix.gettimeofday ()] (when available) is a good value for such date. On + more esoteric platforms, any monotonic counter is a fine value as well. On + the Git backend, the date is translated into the commit {e Date} field and + is expected to be the number of POSIX seconds (thus not counting leap + seconds) since the Epoch. *) + + val author : t -> author + (** [author t] is [t]'s commit author. + + The author identifies the entity (human, unikernel, process, thread, etc) + performing an operation. For the Git backend, this will be directly + translated into the {e Author} field. *) + + val message : t -> message + (** [message t] is [t]'s commit message. *) + + val empty : t + (** The empty commit info. *) + + (** {1 Info Functions} *) + + type f = unit -> t + (** Alias for functions which can build commit info. *) + + val none : f + (** The empty info function. [none ()] is [empty] *) +end + +module type Sigs = sig + module type S = S + + module Default : S + + type default = Default.t +end diff --git a/vendors/irmin/src/irmin/irmin.ml b/vendors/irmin/src/irmin/irmin.ml new file mode 100644 index 000000000000..5a3efa3e09ba --- /dev/null +++ b/vendors/irmin/src/irmin/irmin.ml @@ -0,0 +1,245 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Type = Repr +module Metrics = Metrics +module Diff = Diff +module Read_only = Read_only +module Append_only = Append_only +module Indexable = Indexable +module Content_addressable = Content_addressable +module Atomic_write = Atomic_write +module Contents = Contents +module Merge = Merge +module Branch = Branch +module Node = Node +module Commit = Commit +module Info = Info +module Schema = Schema +module Dot = Dot.Make +module Hash = Hash +module Path = Path +module Perms = Perms +module Key = Key +module Irmin_node = Node + +exception Closed = Store_properties.Closed + +module type Maker_generic_key_args = sig + module Contents_store : Indexable.Maker_concrete_key2 + module Node_store : Indexable.Maker_concrete_key1 + module Commit_store : Indexable.Maker_concrete_key1 + module Branch_store : Atomic_write.Maker +end + +module Maker_generic_key (Backend : Maker_generic_key_args) = struct + type endpoint = unit + type ('h, 'v) contents_key = ('h, 'v) Backend.Contents_store.key + type 'h node_key = 'h Backend.Node_store.key + type 'h commit_key = 'h Backend.Commit_store.key + + module Make (S : Schema.S) = struct + module X = struct + module Schema = S + module Hash = S.Hash + module Contents_key = Backend.Contents_store.Key (S.Hash) (S.Contents) + module Node_key = Backend.Node_store.Key (S.Hash) + module Commit_key = Backend.Commit_store.Key (S.Hash) + + module Contents = struct + module Backend = Backend.Contents_store.Make (S.Hash) (S.Contents) + include Contents.Store_indexable (Backend) (S.Hash) (S.Contents) + end + + module Node = struct + module Value = + Node.Generic_key.Make (S.Hash) (S.Path) (S.Metadata) (Contents_key) + (Node_key) + + module Backend = Backend.Node_store.Make (S.Hash) (Value) + + include + Node.Generic_key.Store (Contents) (Backend) (S.Hash) (Value) + (S.Metadata) + (S.Path) + end + + module Node_portable = Node.Value.Portable + + module Commit = struct + module Commit_maker = Commit.Generic_key.Maker (Schema.Info) + module Value = Commit_maker.Make (S.Hash) (Node_key) (Commit_key) + module Backend = Backend.Commit_store.Make (S.Hash) (Value) + + include + Commit.Generic_key.Store (S.Info) (Node) (Backend) (S.Hash) (Value) + end + + module Commit_portable = Commit.Value.Portable + + module Branch = struct + module Val = Commit.Key + include Backend.Branch_store (S.Branch) (Val) + module Key = S.Branch + end + + module Slice = Slice.Make (Contents) (Node) (Commit) + module Remote = Remote.None (Commit_key) (S.Branch) + + module Repo = struct + type t = { + config : Conf.t; + contents : read Contents.t; + nodes : read Node.t; + commits : read Commit.t; + branch : Branch.t; + } + + let contents_t t = t.contents + let node_t t = t.nodes + let commit_t t = t.commits + let branch_t t = t.branch + let config t = t.config + + let batch t f = + Contents.Backend.batch t.contents @@ fun c -> + Node.Backend.batch (snd t.nodes) @@ fun n -> + Commit.Backend.batch (snd t.commits) @@ fun ct -> + let contents_t = c in + let node_t = (contents_t, n) in + let commit_t = (node_t, ct) in + f contents_t node_t commit_t + + let v config = + let* contents = Contents.Backend.v config in + let* nodes = Node.Backend.v config in + let* commits = Commit.Backend.v config in + let nodes = (contents, nodes) in + let commits = (nodes, commits) in + let+ branch = Branch.v config in + { contents; nodes; commits; branch; config } + + let close t = + Contents.Backend.close t.contents >>= fun () -> + Node.Backend.close (snd t.nodes) >>= fun () -> + Commit.Backend.close (snd t.commits) >>= fun () -> + Branch.close t.branch + end + end + + include Store.Make (X) + end +end + +module Maker (CA : Content_addressable.Maker) (AW : Atomic_write.Maker) = struct + module Indexable_store = struct + type 'h key = 'h + + module Key = Key.Of_hash + + module Make (Hash : Hash.S) (Value : Type.S) = struct + module CA = Content_addressable.Check_closed (CA) (Hash) (Value) + include Indexable.Of_content_addressable (Hash) (CA) + + let v = CA.v + end + end + + module Maker_args = struct + module Contents_store = Indexable.Maker_concrete_key2_of_1 (Indexable_store) + module Node_store = Indexable_store + module Commit_store = Indexable_store + module Branch_store = Atomic_write.Check_closed (AW) + end + + include Maker_generic_key (Maker_args) +end + +module KV_maker (CA : Content_addressable.Maker) (AW : Atomic_write.Maker) = +struct + type metadata = unit + type hash = Schema.default_hash + type info = Info.default + + module Maker = Maker (CA) (AW) + include Maker + module Make (C : Contents.S) = Maker.Make (Schema.KV (C)) +end + +module Of_backend = Store.Make + +module type Tree = Tree.S +module type S = Store.S + +type config = Conf.t +type 'a diff = 'a Diff.t + +module type Maker = Store.Maker +module type KV = Store.KV +module type KV_maker = Store.KV_maker + +module Generic_key = struct + include Store.Generic_key + + module type Maker_args = Maker_generic_key_args + + module Maker = Maker_generic_key +end + +module Backend = struct + module Conf = Conf + module Slice = Slice + module Remote = Remote + + module type S = Backend.S + + module Watch = Watch + module Lock = Lock + module Lru = Lru +end + +let version = Version.current + +module Sync = Sync + +type remote = Remote.t = .. + +let remote_store (type t) (module M : Generic_key.S with type t = t) (t : t) = + let module X : Store.Generic_key.S with type t = t = M in + Sync.remote_store (module X) t + +module Metadata = Metadata +module Json_tree = Store.Json_tree +module Export_for_backends = Export_for_backends +module Storage = Storage + +module Of_storage (M : Storage.Make) (H : Hash.S) (V : Contents.S) = struct + module CA = Storage.Content_addressable (M) + module AW = Storage.Atomic_write (M) + module Maker = Maker (CA) (AW) + + include Maker.Make (struct + module Hash = H + module Contents = V + module Info = Info.Default + module Metadata = Metadata.None + module Path = Path.String_list + module Branch = Branch.String + module Node = Node.Make (Hash) (Path) (Metadata) + module Commit = Commit.Make (Hash) + end) +end diff --git a/vendors/irmin/src/irmin/irmin.mli b/vendors/irmin/src/irmin/irmin.mli new file mode 100644 index 000000000000..97b23fb0e292 --- /dev/null +++ b/vendors/irmin/src/irmin/irmin.mli @@ -0,0 +1,504 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** The {!Irmin} module provides a common interface and types used by all + backends. + + The prinicipal concept is the {i store} (see {!S}), which provides access to + persistently stored values, commits and branches. *) + +val version : string +(** The version of the library. *) + +(** {1:stores Stores} + + An Irmin store is a branch-consistent store where keys are lists of steps. + + An example is a Git repository where keys are filenames, {e i.e.} lists of + ['/']-separated strings. More complex examples are structured values, where + steps might contain first-class field accessors and array offsets. + + Irmin provides the following features: + + - Support for fast clones, branches and merges, in a fashion very similar to + Git. + - Efficient staging areas for fast, transient, in-memory operations. + - Fast {{!Sync} synchronization} primitives between remote stores, using + native backend protocols (as the Git protocol) when available. *) + +exception Closed +(** The exception raised when any operation is attempted on a closed store, + except for {!S.close}, which is idempotent. *) + +(** Irmin stores. *) +module type S = sig + include Store.S + (** @inline *) +end + +(** {2 Schema} *) + +module Type = Repr +(** Dynamic types for Irmin values, supplied by + {{:https://github.com/mirage/repr} [Repr]}. These values can be derived from + type definitions via [\[@@deriving irmin\]] (see the + {{:https://github.com/mirage/irmin/blob/main/README_PPX.md} documentation + for [ppx_irmin]})*) + +module Hash = Hash +(** Hashing functions. + + [Hash] provides user-defined hash functions to digest serialized contents. + Some {{!backend} backends} might be parameterized by such hash functions, + others might work with a fixed one (for instance, the Git format uses only + {{!Hash.SHA1} SHA1}). + + A {{!Hash.SHA1} SHA1} implementation is available to pass to the backends. *) + +module Branch = Branch + +module Info = Info +(** Commit info are used to keep track of the origin of write operations in the + stores. [Info] models the metadata associated with commit objects in Git. *) + +module Node = Node +module Commit = Commit + +module Metadata = Metadata +(** [Metadata] defines metadata that is attached to contents but stored in + nodes. For instance, the Git backend uses this to indicate the type of file + (normal, executable or symlink). *) + +module Path = Path +(** Store paths. + + An Irmin {{!Irmin.S} store} binds {{!Path.S.t} paths} to user-defined + {{!Contents.S} contents}. Paths are composed by basic elements, that we call + {{!Path.S.step} steps}. The following [Path] module provides functions to + manipulate steps and paths. *) + +module Contents = Contents +(** [Contents] specifies how user-defined contents need to be {e serializable} + and {e mergeable}. + + The user needs to provide: + + - a type [t] to be used as store contents. + - a value type for [t] (built using the {{!Irmin.Type} Irmin.Type} + combinators). + - a 3-way [merge] function, to handle conflicts between multiple versions of + the same contents. + + Default implementations for {{!Contents.String} idempotent string} and + {{!Contents.Json} JSON} contents are provided. *) + +module Schema = Schema +(** Store schemas *) + +(** {2 Common Stores} *) + +(** [KV] is similar to {!S} but chooses sensible implementations for path and + branch. *) +module type KV = sig + include Store.KV + (** @inline *) +end + +module Json_tree : Store.Json_tree + +(** {2 Creating Stores} *) + +(** [Maker] is the signature exposed by any backend providing {!S} + implementations. {!Maker.Make} is parameterised by {!Schema.S}. It does not + use any native synchronization primitives. *) +module type Maker = sig + include Store.Maker + (** @inline *) +end + +(** [KV_maker] is like {!Maker} but where everything except the contents is + replaced by sensible default implementations. {!KV_maker.Make} is + parameterised by {!Contents.S} *) +module type KV_maker = sig + include Store.KV_maker + (** @inline *) +end + +(** {2 Generic Key Stores} *) + +module Key = Key + +(** "Generic key" stores are Irmin stores in which the backend may not be keyed + directly by the hashes of stored values. See {!Key} for more details. *) +module Generic_key : sig + include module type of Store.Generic_key + (** @inline *) + + module type Maker_args = sig + module Contents_store : Indexable.Maker_concrete_key2 + module Node_store : Indexable.Maker_concrete_key1 + module Commit_store : Indexable.Maker_concrete_key1 + module Branch_store : Atomic_write.Maker + end + + module Maker (X : Maker_args) : + Maker + with type ('h, 'v) contents_key = ('h, 'v) X.Contents_store.key + and type 'h node_key = 'h X.Node_store.key + and type 'h commit_key = 'h X.Commit_store.key +end + +(** {1 Backends} + + A backend is an implementation exposing either a concrete implementation of + {!S} or a functor providing {!S} once applied. *) + +type config = Conf.t +(** The type for backend-specific configuration values. + + Every backend has different configuration options, which are kept abstract + to the user. *) + +(** {2 Low-level Stores} *) + +(** An Irmin backend is built from a number of lower-level stores, each + implementing fewer operations, such as {{!Content_addressable.Store} + content-addressable} and {{!Atomic_write.Store} atomic-write} stores. *) + +module Read_only = Read_only +(** Read-only backend backends. *) + +module Append_only = Append_only +(** Append-only backend backends. *) + +module Indexable = Indexable +(** Indexable backend backends. *) + +module Content_addressable = Content_addressable +(** Content-addressable backends. *) + +module Atomic_write = Atomic_write +(** Atomic-write stores. *) + +(** [Maker] uses the same type for all internal keys and store all the values in + the same store. *) +module Maker (CA : Content_addressable.Maker) (AW : Atomic_write.Maker) : + Maker with type endpoint = unit + +(** [KV_maker] is like {!module-Maker} but uses sensible default implementations + for everything except the contents type. *) +module KV_maker (CA : Content_addressable.Maker) (AW : Atomic_write.Maker) : + KV_maker + with type endpoint = unit + and type metadata = unit + and type info = Info.default + +(** {2 Backend} *) + +(** [Backend] defines functions only useful for creating new backends. If you + are just using the library (and not developing a new backend), you should + not use this module. *) +module Backend : sig + module Conf : module type of Conf + (** Backend configuration. + + A backend configuration is a set of {{!keys} keys} mapping to typed + values. Backends define their own keys. *) + + module Watch = Watch + module Lock = Lock + module Lru = Lru + module Slice = Slice + module Remote = Remote + + module type S = Backend.S + (** The modules that define a complete Irmin backend. Apply an implementation + to {!Of_backend} to create an Irmin store. *) +end + +(** [Of_backend] gives full control over store creation through definining a + {!Backend.S}. *) +module Of_backend (B : Backend.S) : + Generic_key.S + with module Schema = B.Schema + and type repo = B.Repo.t + and type slice = B.Slice.t + and type contents_key = B.Contents.Key.t + and type node_key = B.Node.Key.t + and type commit_key = B.Commit.Key.t + and module Backend = B + +(** {2 Storage} *) + +module Storage = Storage +(** [Storage] provides {!Storage.Make} for defining a custom storage layer that + can be used to create Irmin stores. Unlike {!Backend.S}, an implementation + of {!Storage.Make} is only concerned with storing and retrieving keys and + values. It can be used to create stores for {!Backend.S} through something + like {!Storage.Content_addressable} or, primarily, with {!Of_storage} to + automatically construct an Irmin store. *) + +(** [Of_storage] uses a custom storage layer and chosen hash and contents type + to create a key-value store. *) +module Of_storage (M : Storage.Make) (H : Hash.S) (V : Contents.S) : + KV with type hash = H.t and module Schema.Contents = V + +(** {2 Helpers} *) + +module Perms = Perms + +module Export_for_backends = Export_for_backends +(** Helper module containing useful top-level types for defining Irmin backends. + This module is relatively unstable. *) + +(** {1 Advanced} *) + +(** {2 Custom Merge Operators} *) + +module Merge = Merge +(** [Merge] provides functions to build custom 3-way merge operators for various + user-defined contents. *) + +module Diff = Diff +(** Differences between values. *) + +type 'a diff = 'a Diff.t +(** The type for representing differences betwen values. *) + +(** {3 Example} *) + +(** The complete code for the following can be found in + [examples/custom_merge.ml]. + + We will demonstrate the use of custom merge operators by defining mergeable + debug log files. We first define a log entry as a pair of a timestamp and a + message, using the combinator exposed by {!Irmin.Type}: + + {[ + open Lwt.Infix + open Astring + + let time = ref 0L + let failure fmt = Fmt.kstr failwith fmt + + (* A log entry *) + module Entry : sig + include Irmin.Type.S + + val v : string -> t + val timestamp : t -> int64 + end = struct + type t = { timestamp : int64; message : string } [@@deriving irmin] + + let compare x y = Int64.compare x.timestamp y.timestamp + + let v message = + time := Int64.add 1L !time; + { timestamp = !time; message } + + let timestamp t = t.timestamp + + let pp ppf { timestamp; message } = + Fmt.pf ppf "%04Ld: %s" timestamp message + + let of_string str = + match String.cut ~sep:": " str with + | None -> Error (`Msg ("invalid entry: " ^ str)) + | Some (x, message) -> ( + try Ok { timestamp = Int64.of_string x; message } + with Failure e -> Error (`Msg e)) + + let t = Irmin.Type.like ~pp ~of_string ~compare t + end + ]} + + A log file is a list of entries (one per line), ordered by decreasing order + of timestamps. The 3-way [merge] operator for log files concatenates and + sorts the new entries and prepend them to the common ancestor's ones. + + {[ + (* A log file *) + module Log : sig + include Irmin.Contents.S + + val add : t -> Entry.t -> t + val empty : t + end = struct + type t = Entry.t list [@@deriving irmin] + + let empty = [] + let pp_entry = Irmin.Type.pp Entry.t + let lines ppf l = List.iter (Fmt.pf ppf "%a\n" pp_entry) (List.rev l) + + let of_string str = + let lines = String.cuts ~empty:false ~sep:"\n" str in + try + List.fold_left + (fun acc l -> + match Irmin.Type.of_string Entry.t l with + | Ok x -> x :: acc + | Error (`Msg e) -> failwith e) + [] lines + |> fun l -> Ok l + with Failure e -> Error (`Msg e) + + let t = Irmin.Type.like ~pp:lines ~of_string t + let timestamp = function [] -> 0L | e :: _ -> Entry.timestamp e + + let newer_than timestamp file = + let rec aux acc = function + | [] -> List.rev acc + | h :: _ when Entry.timestamp h <= timestamp -> List.rev acc + | h :: t -> aux (h :: acc) t + in + aux [] file + + let merge ~old t1 t2 = + let open Irmin.Merge.Infix in + old () >>=* fun old -> + let old = match old with None -> [] | Some o -> o in + let ts = timestamp old in + let t1 = newer_than ts t1 in + let t2 = newer_than ts t2 in + let t3 = + List.sort (Irmin.Type.compare Entry.t) (List.rev_append t1 t2) + in + Irmin.Merge.ok (List.rev_append t3 old) + + let merge = Irmin.Merge.(option (v t merge)) + let add t e = e :: t + end + ]} + + {b Note:} The serialisation primitives used in that example are not very + efficient in this case as they parse the file every time. For real usage, + you would write buffered versions of [Log.pp] and [Log.of_string]. + + To persist the log file on disk, we need to choose a backend. We show here + how to use the on-disk [Git] backend on Unix. + + {[ + (* Build an Irmin store containing log files. *) + module Store = Irmin_unix.Git.FS.KV (Log) + + (* Set-up the local configuration of the Git repository. *) + let config = Irmin_git.config ~bare:true Config.root + + (* Convenient alias for the info function for commit messages *) + let info = Irmin_unix.info + ]} + + We can now define a toy example to use our mergeable log files. + + {[ + let log_file = [ "local"; "debug" ] + + let all_logs t = + Store.find t log_file >|= function None -> Log.empty | Some l -> l + + (** Persist a new entry in the log. Pretty inefficient as it reads/writes + the whole file every time. *) + let log t fmt = + Printf.ksprintf + (fun message -> + all_logs t >>= fun logs -> + let logs = Log.add logs (Entry.v message) in + Store.set_exn t ~info:(info "Adding a new entry") log_file logs) + fmt + + let print_logs name t = + all_logs t >|= fun logs -> + Fmt.pr "-----------\n%s:\n-----------\n%a%!" name (Irmin.Type.pp Log.t) + logs + + let main () = + Config.init (); + Store.Repo.v config >>= fun repo -> + Store.main repo >>= fun t -> + (* populate the log with some random messages *) + Lwt_list.iter_s + (fun msg -> log t "This is my %s " msg) + [ "first"; "second"; "third" ] + >>= fun () -> + Printf.printf "%s\n\n" what; + print_logs "lca" t >>= fun () -> + Store.clone ~src:t ~dst:"test" >>= fun x -> + log x "Adding new stuff to x" >>= fun () -> + log x "Adding more stuff to x" >>= fun () -> + log x "More. Stuff. To x." >>= fun () -> + print_logs "branch 1" x >>= fun () -> + log t "I can add stuff on t also" >>= fun () -> + log t "Yes. On t!" >>= fun () -> + print_logs "branch 2" t >>= fun () -> + Store.merge_into ~info:(info "Merging x into t") x ~into:t >>= function + | Ok () -> print_logs "merge" t + | Error _ -> failwith "conflict!" + + let () = Lwt_main.run (main ()) + ]} *) + +(** {2 Synchronization} *) + +type remote = Remote.t = .. +(** The type for remote stores. *) + +val remote_store : (module Generic_key.S with type t = 'a) -> 'a -> remote +(** [remote_store t] is the remote corresponding to the local store [t]. + Synchronization is done by importing and exporting store {{!BC.slice} + slices}, so this is usually much slower than native synchronization using + {!Store.remote} but it works for all backends. *) + +module Sync = Sync +(** Remote synchronisation. *) + +(** {3 Example} *) + +(** A simple synchronization example, using the {{!Irmin_unix.Git} Git} backend + and the {!Sync} helpers. The code clones a fresh repository if the + repository does not exist locally, otherwise it performs a fetch: in this + case, only the missing contents are downloaded. + + The complete code for the following can be found in [examples/sync.ml]. + + {[ + open Lwt.Infix + module S = Irmin_unix.Git.FS.KV (Irmin.Contents.String) + module Sync = Irmin.Sync (S) + + let config = Irmin_git.config "/tmp/test" + + let upstream = + if Array.length Sys.argv = 2 then + Uri.of_string (Store.remote Sys.argv.(1)) + else ( + Printf.eprintf "Usage: sync [uri]\n%!"; + exit 1) + + let test () = + S.Repo.v config >>= S.main >>= fun t -> + Sync.pull_exn t upstream `Set >>= fun () -> + S.get t [ "README.md" ] >|= fun r -> Printf.printf "%s\n%!" r + + let () = Lwt_main.run (test ()) + ]} *) + +(** {1 Helpers} *) + +(** [Dot] provides functions to export a store to the Graphviz `dot` format. *) +module Dot (S : Generic_key.S) : Dot.S with type db = S.t + +module Metrics = Metrics +(** Type agnostics mechanisms to manipulate metrics. *) diff --git a/vendors/irmin/src/irmin/key.ml b/vendors/irmin/src/irmin/key.ml new file mode 100644 index 000000000000..c7b86c388e3b --- /dev/null +++ b/vendors/irmin/src/irmin/key.ml @@ -0,0 +1,25 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Key_intf + +module Of_hash (Hash : Type.S) = struct + type t = Hash.t [@@deriving irmin] + type hash = Hash.t + + let to_hash x = x [@@inline] + let of_hash x = x [@@inline] +end diff --git a/vendors/irmin/src/irmin/key.mli b/vendors/irmin/src/irmin/key.mli new file mode 100644 index 000000000000..dc5b25d5470c --- /dev/null +++ b/vendors/irmin/src/irmin/key.mli @@ -0,0 +1,92 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Module types for {i keys} into an arbitrary store. + + {2 Choices of key representation} + + {3 Hash-like keys} + + Most Irmin stores are keyed directly by a {i hash} of the values that they + store. This results in a so-called "content-addressable" store, in which all + possible contents values have exactly one key. The key is derived from the + value via [hash] and, given a key, the corresponding value can be retrieved + from the store via [find]: + + {[ + ┌───────────────────────────────┐ + │ │ + ┌───────┐ v find ┌───────┐ hash ┌─────┐ + │ Store │ ──> (+) ──────> │ Value │ ──────> │ Key │ + └───────┘ └───────┘ └─────┘ + ]} + + Keys built this way – with a 1:1 correspondence between the key and the + hash, are known as {!Hash_like}. This class of key representation has some + important properties: + + - {b irredundant storage}: given that an object's key is derived directly + from its representation, there can be at most one copy of any content + value in the store at one time – the store is naturally free of + duplicates. + + - {b reproducibility}: again, because keys are derived directly from values, + multiple parties are guaranteed to compute the same store keys for a given + set of stored values. + + However, it also has some disadvantages. Implementing a hash-keyed store + requires some mechanism for mapping hashes to their physical location (e.g. + their offset on disk), called an "index". This auxiliary index occupies + space, and must be queried for each pointer in the store (even for internal + pointers between nodes along a path). + + {3 Non-hash-like keys} + + For this reason, Irmin allows backends to supply custom key representations + that do not satisfy the above properties (i.e. not irredundant, and not + reproducible). This leads to the following more complex set of relationships + between the values: + + {[ + ┌────────────────────────────────────────────────────────┐ + │ │ + ┌············┼··········································┐ │ + : │ : │ + ┌───────┐ v find ┌───────┐ hash ┌──────┐ v index ┌─────┐ + │ Store │ ──> (+) ──────> │ Value │ ──────> │ Hash │ ··> (+) ·······> │ Key │ + └───────┘ └───────┘ └──────┘ └─────┘ + │ v ∧ to_hash │ ^ + └───────────────────────> (+) └────────────────────────┘ │ + │ add │ + └────────────────────────────────────────────┘ + ]} + + In general, the key of a value isn't known until it has been added to a + particular store, and keys need not be portable between different stores. + It's still required that keys be convertible to hashes, as this ensures the + consistency of Irmin's Merkle tree structure. + + Stores that use non-hash-like keys are not content-addressable, since the + user can't compute the key of a value given the value itself (and perhaps a + value has more than one possible key). + + Implementer's note: all key implementations must have a pre-hash + implementation derived in terms of [Key.to_hash]. That is, for all keys [k], + given [h = Key.to_hash k] then [Irmin.Type.pre_hash key_t k] must equal + [Irmin.Type.pre_hash hash_t h]. *) + +include Key_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/key_intf.ml b/vendors/irmin/src/irmin/key_intf.ml new file mode 100644 index 000000000000..3a1539102b81 --- /dev/null +++ b/vendors/irmin/src/irmin/key_intf.ml @@ -0,0 +1,62 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + type t [@@deriving irmin] + (** The type for keys. *) + + type hash + + val to_hash : t -> hash +end + +module type Hash_like = sig + include S + + val of_hash : hash -> t +end + +module Store_spec = struct + module type S = sig + type ('h, 'v) contents_key + type 'h node_key + type 'h commit_key + end + + module type Hash_keyed = + S + with type ('h, _) contents_key = 'h + and type 'h node_key = 'h + and type 'h commit_key = 'h + + module rec Hash_keyed : Hash_keyed = Hash_keyed +end + +module type Sigs = sig + module type S = S + module type Hash_like = Hash_like + + (** The simplest possible [Key] implementation is just a hash of the + corresponding value, attaching no additional metadata about the value. *) + module Of_hash (H : Type.S) : Hash_like with type t = H.t and type hash = H.t + + module Store_spec : sig + module type S = Store_spec.S + module type Hash_keyed = Store_spec.Hash_keyed + + module Hash_keyed : Hash_keyed + end +end diff --git a/vendors/irmin/src/irmin/lock.ml b/vendors/irmin/src/irmin/lock.ml new file mode 100644 index 000000000000..6cd3f5a0abfb --- /dev/null +++ b/vendors/irmin/src/irmin/lock.ml @@ -0,0 +1,66 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + type key + type t + + val v : unit -> t + val with_lock : t -> key -> (unit -> 'a Lwt.t) -> 'a Lwt.t + val stats : t -> int +end + +module Make (K : Type.S) = struct + module K = struct + type t = K.t + + let hash = Hashtbl.hash + let equal = Type.(unstage (equal K.t)) + end + + module KHashtbl = Hashtbl.Make (K) + + type key = K.t + type t = { global : Lwt_mutex.t; locks : Lwt_mutex.t KHashtbl.t } + + let v () = { global = Lwt_mutex.create (); locks = KHashtbl.create 1024 } + let stats t = KHashtbl.length t.locks + + let lock t key () = + let lock = + try KHashtbl.find t.locks key + with Not_found -> + let lock = Lwt_mutex.create () in + KHashtbl.add t.locks key lock; + lock + in + Lwt.return lock + + let unlock t key () = + let () = + if KHashtbl.mem t.locks key then + let lock = KHashtbl.find t.locks key in + if Lwt_mutex.is_empty lock then KHashtbl.remove t.locks key + in + Lwt.return_unit + + let with_lock t k fn = + let* lock = Lwt_mutex.with_lock t.global (lock t k) in + let* r = Lwt_mutex.with_lock lock fn in + Lwt_mutex.with_lock t.global (unlock t k) >>= fun () -> Lwt.return r +end diff --git a/vendors/irmin/src/irmin/lock.mli b/vendors/irmin/src/irmin/lock.mli new file mode 100644 index 000000000000..718b6db22b29 --- /dev/null +++ b/vendors/irmin/src/irmin/lock.mli @@ -0,0 +1,37 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** {1 Process locking helpers} *) + +module type S = sig + type t + (** The type for lock manager. *) + + type key + (** The type for key to be locked. *) + + val v : unit -> t + (** Create a lock manager. *) + + val with_lock : t -> key -> (unit -> 'a Lwt.t) -> 'a Lwt.t + (** [with_lock t k f] executes [f ()] while holding the exclusive lock + associated to the key [k]. *) + + val stats : t -> int +end + +(** Create a lock manager implementation. *) +module Make (K : Type.S) : S with type key = K.t diff --git a/vendors/irmin/src/irmin/logging.ml b/vendors/irmin/src/irmin/logging.ml new file mode 100644 index 000000000000..f398ae412f5e --- /dev/null +++ b/vendors/irmin/src/irmin/logging.ml @@ -0,0 +1,61 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Logging_intf +module Source_code_position = Ppx_irmin_internal_lib.Source_code_position + +(** A logs reporter that is aware of the tags added by [ppx_irmin.internal]. *) +let reporter : + ?filter_src:(Logs.src -> bool) -> + ?prefix:string -> + (module Clock) -> + Logs.reporter = + fun ?(filter_src = Fun.const true) ?(prefix = "") (module Clock) -> + let pad n x = + if String.length x > n then x else x ^ String.make (n - String.length x) ' ' + in + let start_time = Clock.counter () in + let report src level ~over k msgf = + let k _ = + over (); + k () + in + let ppf = match level with Logs.App -> Fmt.stdout | _ -> Fmt.stderr in + let with_stamp h tags k fmt = + let dt = Mtime.Span.to_us (Clock.count start_time) in + let source_pos_text, source_pos_colour = + match tags with + | None -> (Logs.Src.name src, `Magenta) + | Some tags -> + let text = + Logs.Tag.find Source_code_position.tag tags + |> Option.fold ~none:"" ~some:(fun (fname, lnum, _, _) -> + Fmt.str "%s:%d" fname lnum) + in + (text, `Faint) + in + Fmt.kpf k ppf + ("%s%+04.0fus %a %a @[" ^^ fmt ^^ "@]@.") + prefix dt + Fmt.(styled source_pos_colour string) + (pad 35 source_pos_text) Logs_fmt.pp_header (level, h) + in + msgf @@ fun ?header ?tags fmt -> + if filter_src src then with_stamp header tags k fmt + else Format.ikfprintf k ppf fmt + in + { Logs.report } diff --git a/vendors/irmin/src/irmin/logging.mli b/vendors/irmin/src/irmin/logging.mli new file mode 100644 index 000000000000..b86bdac8c8b9 --- /dev/null +++ b/vendors/irmin/src/irmin/logging.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Logging_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/logging_intf.ml b/vendors/irmin/src/irmin/logging_intf.ml new file mode 100644 index 000000000000..703fde55cb5f --- /dev/null +++ b/vendors/irmin/src/irmin/logging_intf.ml @@ -0,0 +1,48 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type Clock = sig + (** A monotonic time source. See {!Mtime_clock} for an OS-dependent + implementation. *) + + type counter + + val counter : unit -> counter + val count : counter -> Mtime.span +end + +module type Sigs = sig + (** {!Logs} tags attached to the log entries emitted by Irmin: *) + + module Source_code_position : sig + type t = string * int * int * int + (** The type of iclusive ranges of source code positions, as generated by + the OCaml {!val-Stdlib.__POS__} macro. The 4-tuple components are 'file + name', 'line number', 'column start' and 'column end' respectively. *) + + val pp : t Fmt.t + val tag : t Logs.Tag.def + end + + module type Clock = Clock + + val reporter : + ?filter_src:(Logs.src -> bool) -> + ?prefix:string -> + (module Clock) -> + Logs.reporter + (** A default {!Logs} reporter that is sensitive to the logs tags above. *) +end diff --git a/vendors/irmin/src/irmin/lru.ml b/vendors/irmin/src/irmin/lru.ml new file mode 100644 index 000000000000..dffddcf0e306 --- /dev/null +++ b/vendors/irmin/src/irmin/lru.ml @@ -0,0 +1,147 @@ +(* + Copyright (c) 2016 David Kaloper Meršinjak + Copyright (c) 2013-2022 Thomas Gazagnaire + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) + +(* Extracted from https://github.com/pqwy/lru *) + +module Make (H : Hashtbl.HashedType) = struct + module HT = Hashtbl.Make (H) + + module Q = struct + type 'a node = { + value : 'a; + mutable next : 'a node option; + mutable prev : 'a node option; + } + + type 'a t = { + mutable first : 'a node option; + mutable last : 'a node option; + } + + let detach t n = + let np = n.prev and nn = n.next in + (match np with + | None -> t.first <- nn + | Some x -> + x.next <- nn; + n.prev <- None); + match nn with + | None -> t.last <- np + | Some x -> + x.prev <- np; + n.next <- None + + let append t n = + let on = Some n in + match t.last with + | Some x as l -> + x.next <- on; + t.last <- on; + n.prev <- l + | None -> + t.first <- on; + t.last <- on + + let node x = { value = x; prev = None; next = None } + let create () = { first = None; last = None } + + let iter t f = + let rec aux f = function + | Some n -> + let next = n.next in + f n.value; + aux f next + | _ -> () + in + aux f t.first + + let clear t = + t.first <- None; + t.last <- None + end + + type key = HT.key + + type 'a t = { + ht : (key * 'a) Q.node HT.t; + q : (key * 'a) Q.t; + mutable cap : int; + mutable w : int; + weight : 'a -> int; + } + + let create ?(weight = function _ -> 1) cap = + { cap; w = 0; ht = HT.create cap; q = Q.create (); weight } + + let drop_lru t = + match t.q.first with + | None -> () + | Some ({ Q.value = k, v; _ } as n) -> + t.w <- t.w - t.weight v; + HT.remove t.ht k; + Q.detach t.q n + + let remove t k = + try + let n = HT.find t.ht k in + t.w <- t.w - t.weight (snd n.value); + HT.remove t.ht k; + Q.detach t.q n + with Not_found -> () + + let add t k v = + if t.cap = 0 then () + else ( + remove t k; + let n = Q.node (k, v) in + let w = t.weight v in + if w > t.cap then + (* if [v] is bigger than the LRU capacity, just skip it *) () + else ( + t.w <- t.w + w; + while t.w > t.cap do + drop_lru t + done; + HT.add t.ht k n; + Q.append t.q n)) + + let promote t k = + try + let n = HT.find t.ht k in + Q.( + detach t.q n; + append t.q n) + with Not_found -> () + + let find t k = + let v = HT.find t.ht k in + promote t k; + snd v.value + + let mem t k = + match HT.mem t.ht k with + | false -> false + | true -> + promote t k; + true + + let iter t f = Q.iter t.q (fun (k, v) -> f k v) + + let clear t = + t.w <- 0; + HT.clear t.ht; + Q.clear t.q +end diff --git a/vendors/irmin/src/irmin/lru.mli b/vendors/irmin/src/irmin/lru.mli new file mode 100644 index 000000000000..871b9a10e005 --- /dev/null +++ b/vendors/irmin/src/irmin/lru.mli @@ -0,0 +1,27 @@ +(* + Copyright (c) 2016 David Kaloper Meršinjak + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) + +(* Extracted from https://github.com/pqwy/lru *) + +module Make (H : Hashtbl.HashedType) : sig + type 'a t + + val create : ?weight:('a -> int) -> int -> 'a t + val add : 'a t -> H.t -> 'a -> unit + val find : 'a t -> H.t -> 'a + val mem : 'a t -> H.t -> bool + val clear : 'a t -> unit + val iter : 'a t -> (H.t -> 'a -> unit) -> unit +end diff --git a/vendors/irmin/src/irmin/mem/dune b/vendors/irmin/src/irmin/mem/dune new file mode 100644 index 000000000000..e667c80c957c --- /dev/null +++ b/vendors/irmin/src/irmin/mem/dune @@ -0,0 +1,6 @@ +(library + (name irmin_mem) + (public_name irmin.mem) + (libraries irmin logs lwt) + (preprocess + (pps ppx_irmin.internal))) diff --git a/vendors/irmin/src/irmin/mem/import.ml b/vendors/irmin/src/irmin/mem/import.ml new file mode 100644 index 000000000000..71053e21ba54 --- /dev/null +++ b/vendors/irmin/src/irmin/mem/import.ml @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/src/irmin/mem/irmin_mem.ml b/vendors/irmin/src/irmin/mem/irmin_mem.ml new file mode 100644 index 000000000000..e69eefa1af17 --- /dev/null +++ b/vendors/irmin/src/irmin/mem/irmin_mem.ml @@ -0,0 +1,167 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +let src = Logs.Src.create "irmin.mem" ~doc:"Irmin in-memory store" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Conf = struct + include Irmin.Backend.Conf + + let spec = Spec.v "mem" + let root config = find_root config |> Option.value ~default:"." +end + +module Read_only (K : Irmin.Type.S) (V : Irmin.Type.S) = struct + module KMap = Map.Make (struct + type t = K.t + + let compare = Irmin.Type.(unstage (compare K.t)) + end) + + type key = K.t + type value = V.t + type 'a t = { mutable t : value KMap.t; root : string } + + let new_instance root = { t = KMap.empty; root } + + let v = + let cache : (string, 'a t) Hashtbl.t = Hashtbl.create 0 in + fun config -> + let root = Conf.root config in + let t = + match Hashtbl.find_opt cache root with + | None -> + let t = new_instance root in + Hashtbl.add cache root t; + t + | Some t -> t + in + Lwt.return t + + let clear t = + [%log.debug "clear"]; + t.t <- KMap.empty; + Lwt.return_unit + + let close _ = + [%log.debug "close"]; + Lwt.return_unit + + let cast t = (t :> read_write t) + let batch t f = f (cast t) + let pp_key = Irmin.Type.pp K.t + + let find { t; _ } key = + [%log.debug "find %a" pp_key key]; + try Lwt.return_some (KMap.find key t) with Not_found -> Lwt.return_none + + let mem { t; _ } key = + [%log.debug "mem %a" pp_key key]; + Lwt.return (KMap.mem key t) +end + +module Append_only (K : Irmin.Type.S) (V : Irmin.Type.S) = struct + include Read_only (K) (V) + + let add t key value = + [%log.debug "add -> %a" pp_key key]; + t.t <- KMap.add key value t.t; + Lwt.return_unit +end + +module Atomic_write (K : Irmin.Type.S) (V : Irmin.Type.S) = struct + module RO = Read_only (K) (V) + module W = Irmin.Backend.Watch.Make (K) (V) + module L = Irmin.Backend.Lock.Make (K) + + type t = { t : unit RO.t; w : W.t; lock : L.t } + type key = RO.key + type value = RO.value + type watch = W.watch + + let watches = W.v () + let lock = L.v () + + let v config = + let* t = RO.v config in + Lwt.return { t; w = watches; lock } + + let close t = W.clear t.w >>= fun () -> RO.close t.t + let find t = RO.find t.t + let mem t = RO.mem t.t + let watch_key t = W.watch_key t.w + let watch t = W.watch t.w + let unwatch t = W.unwatch t.w + + let list t = + [%log.debug "list"]; + RO.KMap.fold (fun k _ acc -> k :: acc) t.t.RO.t [] |> Lwt.return + + let set t key value = + [%log.debug "update"]; + let* () = + L.with_lock t.lock key (fun () -> + t.t.RO.t <- RO.KMap.add key value t.t.RO.t; + Lwt.return_unit) + in + W.notify t.w key (Some value) + + let remove t key = + [%log.debug "remove"]; + let* () = + L.with_lock t.lock key (fun () -> + t.t.RO.t <- RO.KMap.remove key t.t.RO.t; + Lwt.return_unit) + in + W.notify t.w key None + + let equal_v_opt = Irmin.Type.(unstage (equal (option V.t))) + + let test_and_set t key ~test ~set = + [%log.debug "test_and_set"]; + let* updated = + L.with_lock t.lock key (fun () -> + let+ v = find t key in + if equal_v_opt test v then + let () = + match set with + | None -> t.t.RO.t <- RO.KMap.remove key t.t.RO.t + | Some v -> t.t.RO.t <- RO.KMap.add key v t.t.RO.t + in + true + else false) + in + let+ () = if updated then W.notify t.w key set else Lwt.return_unit in + updated + + let clear t = W.clear t.w >>= fun () -> RO.clear t.t +end + +let config () = Conf.empty Conf.spec + +module Content_addressable = Irmin.Content_addressable.Make (Append_only) +module S = Irmin.Maker (Content_addressable) (Atomic_write) +module KV = Irmin.KV_maker (Content_addressable) (Atomic_write) +include S + +(* Enforce that {!S} is a sub-type of {!Irmin.Maker}. *) +module Maker_is_a_maker : Irmin.Maker = S + +(* Enforce that {!KV} is a sub-type of {!Irmin.KV_maker}. *) +module KV_is_a_KV : Irmin.KV_maker = KV diff --git a/vendors/irmin/src/irmin/mem/irmin_mem.mli b/vendors/irmin/src/irmin/mem/irmin_mem.mli new file mode 100644 index 000000000000..592e0a94e1d6 --- /dev/null +++ b/vendors/irmin/src/irmin/mem/irmin_mem.mli @@ -0,0 +1,47 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** In-memory store. + + A simple in-memory store, using hash tables. Once one of the functors below + is instantiated to a module [M], it has a unique shared hash-table: multiple + invocation of [M.create] will see and manipulate the same contents. *) + +module Conf : sig + val spec : Irmin.Backend.Conf.Spec.t +end + +val config : unit -> Irmin.config +(** Configuration values. *) + +module Append_only : Irmin.Append_only.Maker +(** An in-memory store for append-only values. *) + +module Content_addressable : Irmin.Content_addressable.Maker +(** An in-memory store for content-addressable values. *) + +module Atomic_write : Irmin.Atomic_write.Maker +(** An in-memory store with atomic-write guarantees. *) + +(** Constructor for in-memory KV stores. *) +module KV : + Irmin.KV_maker + with type endpoint = unit + and type metadata = unit + and type info = Irmin.Info.default + +include Irmin.Maker with type endpoint = unit +(** Constructor for in-memory Irmin store. *) diff --git a/vendors/irmin/src/irmin/merge.ml b/vendors/irmin/src/irmin/merge.ml new file mode 100644 index 000000000000..67435d80e95a --- /dev/null +++ b/vendors/irmin/src/irmin/merge.ml @@ -0,0 +1,421 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Printf + +let src = Logs.Src.create "irmin.merge" ~doc:"Irmin merging" + +module Log = (val Logs.src_log src : Logs.LOG) + +type conflict = [ `Conflict of string ] +type 'a promise = unit -> ('a option, conflict) result Lwt.t + +let promise t : 'a promise = fun () -> Lwt.return (Ok (Some t)) + +let memo fn = + let r = ref None in + fun () -> + match !r with + | Some x -> x + | None -> + let* x = fn () in + r := Some (Lwt.return x); + Lwt.return x + +type 'a f = old:'a promise -> 'a -> 'a -> ('a, conflict) result Lwt.t +type 'a t = 'a Type.t * 'a f + +let v t f = (t, f) +let f (x : 'a t) = snd x + +let conflict fmt = + ksprintf + (fun msg -> + [%log.debug "conflict: %s" msg]; + Lwt.return (Error (`Conflict msg))) + fmt + +let bind x f = x >>= function Error e -> Lwt.return (Error e) | Ok x -> f x +let map f x = x >|= function Error _ as x -> x | Ok x -> Ok (f x) + +let map_promise f t () = + t () >|= function + | Error _ as x -> x + | Ok None -> Ok None + | Ok (Some a) -> Ok (Some (f a)) + +let bind_promise t f () = + t () >>= function + | Error e -> Lwt.return (Error e) + | Ok None -> Lwt.return (Ok None) + | Ok (Some a) -> f a () + +let ok x = Lwt.return (Ok x) + +module Infix = struct + let ( >>=* ) = bind + let ( >|=* ) x f = map f x + let ( >>=? ) = bind_promise + let ( >|=? ) x f = map_promise f x +end + +open Infix + +let default (type a) (t : a Type.t) : a t = + let pp = Type.pp t and equal = Type.(unstage (equal t)) in + ( t, + fun ~old t1 t2 -> + let open Infix in + [%log.debug "default %a | %a" pp t1 pp t2]; + old () >>=* function + | None -> conflict "default: add/add and no common ancestor" + | Some old -> + [%log.debug "default old=%a" pp t1]; + if equal old t1 && equal t1 t2 then ok t1 + else if equal old t1 then ok t2 + else if equal old t2 then ok t1 + else conflict "default" ) + +let idempotent dt = + let equal = Type.(unstage (equal dt)) in + let default = default dt in + let f ~old x y = if equal x y then ok x else f default ~old x y in + v dt f + +let seq = function + | [] -> invalid_arg "nothing to merge" + | (t, _) :: _ as ts -> + ( t, + fun ~old v1 v2 -> + Lwt_list.fold_left_s + (fun acc (_, merge) -> + match acc with Ok x -> ok x | Error _ -> merge ~old v1 v2) + (Error (`Conflict "nothing to merge")) + ts ) + +let option (type a) ((a, t) : a t) : a option t = + let pp_a = Type.pp a and equal = Type.(unstage (equal a)) in + let dt = Type.option a in + let pp = Type.pp dt in + ( dt, + fun ~old t1 t2 -> + [%log.debug "some %a | %a" pp t1 pp t2]; + f (default Type.(option a)) ~old t1 t2 >>= function + | Ok x -> ok x + | Error _ -> ( + match (t1, t2) with + | None, None -> ok None + | Some v1, Some v2 -> + let open Infix in + let old () = + old () >>=* function + | None -> ok None + | Some o -> + [%log.debug "option old=%a" pp o]; + ok o + in + t ~old v1 v2 >|=* fun x -> Some x + | Some x, None | None, Some x -> ( + let open Infix in + old () >>=* function + | None | Some None -> ok (Some x) + | Some (Some o) -> + [%log.debug "option old=%a" pp_a o]; + if equal x o then ok (Some x) else conflict "option: add/del") + ) ) + +let pair (da, a) (db, b) = + let dt = Type.pair da db in + let pp = Type.pp dt in + ( dt, + fun ~old x y -> + [%log.debug "pair %a | %a" pp x pp y]; + (snd (default dt)) ~old x y >>= function + | Ok x -> ok x + | Error _ -> + let (a1, b1), (a2, b2) = (x, y) in + let o1 = map_promise fst old in + let o2 = map_promise snd old in + a ~old:o1 a1 a2 >>=* fun a3 -> + b ~old:o2 b1 b2 >|=* fun b3 -> (a3, b3) ) + +let triple (da, a) (db, b) (dc, c) = + let dt = Type.triple da db dc in + let pp = Type.pp dt in + ( dt, + fun ~old x y -> + [%log.debug "triple %a | %a" pp x pp y]; + (snd (default dt)) ~old x y >>= function + | Ok x -> ok x + | Error _ -> + let (a1, b1, c1), (a2, b2, c2) = (x, y) in + let o1 = map_promise (fun (x, _, _) -> x) old in + let o2 = map_promise (fun (_, x, _) -> x) old in + let o3 = map_promise (fun (_, _, x) -> x) old in + a ~old:o1 a1 a2 >>=* fun a3 -> + b ~old:o2 b1 b2 >>=* fun b3 -> + c ~old:o3 c1 c2 >|=* fun c3 -> (a3, b3, c3) ) + +exception C of string + +let merge_elt merge_v old key vs = + let v1, v2 = + match vs with + | `Left v -> (Some v, None) + | `Right v -> (None, Some v) + | `Both (v1, v2) -> (Some v1, Some v2) + in + let old () = old key in + merge_v key ~old v1 v2 >>= function + | Error (`Conflict msg) -> Lwt.fail (C msg) + | Ok x -> Lwt.return x + +(* assume l1 and l2 are key-sorted *) +let alist_iter2 compare_k f l1 l2 = + let rec aux l1 l2 = + match (l1, l2) with + | [], t -> List.iter (fun (key, v) -> f key (`Right v)) t + | t, [] -> List.iter (fun (key, v) -> f key (`Left v)) t + | (k1, v1) :: t1, (k2, v2) :: t2 -> ( + match compare_k k1 k2 with + | 0 -> + f k1 (`Both (v1, v2)); + aux t1 t2 + | x -> + if x < 0 then ( + f k1 (`Left v1); + aux t1 l2) + else ( + f k2 (`Right v2); + aux l1 t2)) + in + aux l1 l2 + +(* assume l1 and l2 are key-sorted *) +let alist_iter2_lwt compare_k f l1 l2 = + let l3 = ref [] in + alist_iter2 compare_k (fun left right -> l3 := f left right :: !l3) l1 l2; + Lwt_list.iter_p Fun.id (List.rev !l3) + +(* DO NOT assume l1 and l2 are key-sorted *) +let alist_merge_lwt compare_k f l1 l2 = + let open Lwt in + let l3 = ref [] in + let sort l = List.sort (fun (x, _) (y, _) -> compare_k x y) l in + let l1 = sort l1 in + let l2 = sort l2 in + let f key data = + f key data >>= function + | None -> return_unit + | Some v -> + l3 := (key, v) :: !l3; + return_unit + in + alist_iter2_lwt compare_k f l1 l2 >>= fun () -> return !l3 + +let alist dx dy merge_v = + let pair = Type.pair dx dy in + let compare_pair = Type.unstage (Type.compare pair) in + let compare_dx = Type.(unstage (compare dx)) in + let dt = Type.list pair in + ( dt, + fun ~old x y -> + let pp = Type.pp dt in + [%log.debug "alist %a | %a" pp x pp y]; + let sort = List.sort compare_pair in + let x = sort x in + let y = sort y in + let old k = + let open Infix in + old () >|=* function + | None -> Some None (* no parent = parent with empty value *) + | Some old -> + let old = try Some (List.assoc k old) with Not_found -> None in + Some old + in + let merge_v k = f (merge_v k) in + Lwt.catch + (fun () -> + alist_merge_lwt compare_dx (merge_elt merge_v old) x y >>= ok) + (function C msg -> conflict "%s" msg | e -> Lwt.fail e) ) + +module MultiSet (K : sig + include Set.OrderedType + + val t : t Type.t +end) = +struct + module M = Map.Make (K) + + let of_alist l = List.fold_left (fun map (k, v) -> M.add k v map) M.empty l + let t = Type.map Type.(list (pair K.t int64)) of_alist M.bindings + + let merge ~old m1 m2 = + let get k m = try M.find k m with Not_found -> 0L in + let set k v m = match v with 0L -> M.remove k m | _ -> M.add k v m in + let add k v m = set k (Int64.add v @@ get k m) m in + let keys = ref M.empty in + old () >|=* fun old -> + let old = + match old with + | None -> M.empty (* no parent = parent with empty value *) + | Some o -> o + in + M.iter (fun k v -> keys := add k (Int64.neg v) !keys) old; + M.iter (fun k v -> keys := add k v !keys) m1; + M.iter (fun k v -> keys := add k v !keys) m2; + !keys + + let merge = (t, merge) +end + +module Set (K : sig + include Set.OrderedType + + val t : t Type.t +end) = +struct + module S = Set.Make (K) + + let of_list l = List.fold_left (fun set elt -> S.add elt set) S.empty l + let t = Type.(map @@ list K.t) of_list S.elements + let pp = Type.pp t + + let merge ~old x y = + [%log.debug "merge %a %a" pp x pp y]; + old () >|=* fun old -> + let old = match old with None -> S.empty | Some o -> o in + let ( ++ ) = S.union and ( -- ) = S.diff in + let to_add = x -- old ++ (y -- old) in + let to_del = old -- x ++ (old -- y) in + old -- to_del ++ to_add + + let merge = (t, merge) +end + +module Map (K : sig + include Map.OrderedType + + val t : t Type.t +end) = +struct + module M = Map.Make (K) + + let of_alist l = List.fold_left (fun map (k, v) -> M.add k v map) M.empty l + let t x = Type.map Type.(list @@ pair K.t x) of_alist M.bindings + let iter2 f t1 t2 = alist_iter2 K.compare f (M.bindings t1) (M.bindings t2) + + let iter2 f m1 m2 = + let m3 = ref [] in + iter2 (fun key data -> m3 := f key data :: !m3) m1 m2; + Lwt_list.iter_p (fun b -> b >>= fun () -> Lwt.return_unit) (List.rev !m3) + + let merge_maps f m1 m2 = + let l3 = ref [] in + let f key data = + f key data >|= function None -> () | Some v -> l3 := (key, v) :: !l3 + in + iter2 f m1 m2 >>= fun () -> + let m3 = of_alist !l3 in + Lwt.return m3 + + let merge dv (merge_v : K.t -> 'a option t) = + let pp ppf m = Type.(pp (list (pair K.t dv))) ppf @@ M.bindings m in + let merge_v k = f (merge_v k) in + ( t dv, + fun ~old m1 m2 -> + [%log.debug "assoc %a | %a" pp m1 pp m2]; + Lwt.catch + (fun () -> + let old key = + old () >>=* function + | None -> ok None + | Some old -> + [%log.debug "assoc old=%a" pp old]; + let old = + try Some (M.find key old) with Not_found -> None + in + ok (Some old) + in + merge_maps (merge_elt merge_v old) m1 m2 >>= ok) + (function C msg -> conflict "%s" msg | e -> Lwt.fail e) ) +end + +let like da t a_to_b b_to_a = + let pp = Type.pp da in + let merge ~old a1 a2 = + [%log.debug "biject %a | %a" pp a1 pp a2]; + try + let b1 = a_to_b a1 in + let b2 = a_to_b a2 in + let old = memo (map_promise a_to_b old) in + (f t) ~old b1 b2 >|=* b_to_a + with Not_found -> conflict "biject" + in + seq [ default da; (da, merge) ] + +let like_lwt (type a b) da (t : b t) (a_to_b : a -> b Lwt.t) + (b_to_a : b -> a Lwt.t) : a t = + let pp = Type.pp da in + let merge ~old a1 a2 = + [%log.debug "biject' %a | %a" pp a1 pp a2]; + try + let* b1 = a_to_b a1 in + let* b2 = a_to_b a2 in + let old = + memo (fun () -> + bind (old ()) @@ function + | None -> ok None + | Some a -> + let+ b = a_to_b a in + Ok (Some b)) + in + bind ((f t) ~old b1 b2) @@ fun b3 -> b_to_a b3 >>= ok + with Not_found -> conflict "biject'" + in + seq [ default da; (da, merge) ] + +let unit = default Type.unit +let bool = default Type.bool +let char = default Type.char +let int32 = default Type.int32 +let int64 = default Type.int64 +let float = default Type.float +let string = default Type.string + +type counter = int64 + +let counter = + ( Type.int64, + fun ~old x y -> + old () >|=* fun old -> + let old = match old with None -> 0L | Some o -> o in + let ( + ) = Int64.add and ( - ) = Int64.sub in + x + y - old ) + +let with_conflict rewrite (d, f) = + let f ~old x y = + f ~old x y >>= function + | Error (`Conflict msg) -> conflict "%s" (rewrite msg) + | Ok x -> ok x + in + (d, f) + +let conflict_t = + Type.(map string) (fun x -> `Conflict x) (function `Conflict x -> x) + +type nonrec 'a result = ('a, conflict) result [@@deriving irmin] diff --git a/vendors/irmin/src/irmin/merge.mli b/vendors/irmin/src/irmin/merge.mli new file mode 100644 index 000000000000..2ec7b19f34f6 --- /dev/null +++ b/vendors/irmin/src/irmin/merge.mli @@ -0,0 +1,227 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Merge operators. *) + +type conflict = [ `Conflict of string ] [@@deriving irmin] +(** The type for merge errors. *) + +val ok : 'a -> ('a, conflict) result Lwt.t +(** Return [Ok x]. *) + +val conflict : ('a, unit, string, ('b, conflict) result Lwt.t) format4 -> 'a +(** Return [Error (Conflict str)]. *) + +val bind : + ('a, 'b) result Lwt.t -> + ('a -> ('c, 'b) result Lwt.t) -> + ('c, 'b) result Lwt.t +(** [bind r f] is the merge result which behaves as of the application of the + function [f] to the return value of [r]. If [r] fails, [bind r f] also + fails, with the same conflict. *) + +val map : ('a -> 'c) -> ('a, 'b) result Lwt.t -> ('c, 'b) result Lwt.t +(** [map f m] maps the result of a merge. This is the same as + [bind m (fun x -> ok (f x))]. *) + +(** {1 Merge Combinators} *) + +type 'a promise = unit -> ('a option, conflict) result Lwt.t +(** An ['a] promise is a function which, when called, will eventually return a + value type of ['a]. A promise is an optional, lazy and non-blocking value. *) + +val promise : 'a -> 'a promise +(** [promise a] is the promise containing [a]. *) + +val map_promise : ('a -> 'b) -> 'a promise -> 'b promise +(** [map_promise f a] is the promise containing [f] applied to what is promised + by [a]. *) + +val bind_promise : 'a promise -> ('a -> 'b promise) -> 'b promise +(** [bind_promise a f] is the promise returned by [f] applied to what is + promised by [a]. *) + +type 'a f = old:'a promise -> 'a -> 'a -> ('a, conflict) result Lwt.t +(** Signature of a merge function. [old] is the value of the least-common + ancestor. + + {v + /----> t1 ----\ + ----> old |--> result + \----> t2 ----/ + v} *) + +type 'a t +(** The type for merge combinators. *) + +val v : 'a Type.t -> 'a f -> 'a t +(** [v dt f] create a merge combinator. *) + +val f : 'a t -> 'a f +(** [f m] is [m]'s merge function. *) + +val seq : 'a t list -> 'a t +(** Call the merge functions in sequence. Stop as soon as one is {e not} + returning a conflict. *) + +val like : 'a Type.t -> 'b t -> ('a -> 'b) -> ('b -> 'a) -> 'a t +(** Use the merge function defined in another domain. If the converting + functions raise any exception the merge is a conflict. *) + +val with_conflict : (string -> string) -> 'a t -> 'a t +(** [with_conflict f m] is [m] with the conflict error message modified by [f]. *) + +val like_lwt : 'a Type.t -> 'b t -> ('a -> 'b Lwt.t) -> ('b -> 'a Lwt.t) -> 'a t +(** Same as {{!Merge.biject} biject} but with blocking domain converting + functions. *) + +(** {1 Basic Merges} *) + +val default : 'a Type.t -> 'a t +(** [default t] is the default merge function for values of type [t]. This is a + simple merge function which supports changes in one branch at a time: + + - if [t1=old] then the result of the merge is [OK t2]; + - if [t2=old] then return [OK t1]; + - otherwise the result is [Conflict]. *) + +val idempotent : 'a Type.t -> 'a t +(** [idempotent t] is the default merge function for values of type [t] using + idempotent operations. It follows the same rules as the {!default} merge + function but also adds: + + - if [t1=t2] then the result of the merge is [OK t1]. *) + +val unit : unit t +(** [unit] is the default merge function for unit values. *) + +val bool : bool t +(** [bool] is the default merge function for booleans. *) + +val char : char t +(** [char] is the default merge function for characters. *) + +val int32 : int32 t +(** [int32] is the default merge function for 32-bits integers. *) + +val int64 : int64 t +(** [int64] the default merge function for 64-bit integers. *) + +val float : float t +(** [float] is the default merge function for floating point numbers. *) + +val string : string t +(** The default string merge function. Do not do anything clever, just compare + the strings using the [default] merge function. *) + +val option : 'a t -> 'a option t +(** Lift a merge function to optional values of the same type. If all the + provided values are inhabited, then call the provided merge function, + otherwise use the same behavior as {!default}. *) + +val pair : 'a t -> 'b t -> ('a * 'b) t +(** Lift merge functions to pairs of elements. *) + +val triple : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t +(** Lift merge functions to triples of elements. *) + +(** {1 Counters and Multisets} *) + +type counter = int64 +(** The type for counter values. It is expected that the only valid operations + on counters are {e increment} and {e decrement}. The following merge + functions ensure that the counter semantics are preserved: {e i.e.} it + ensures that the number of increments and decrements is preserved. *) + +val counter : counter t +(** The merge function for mergeable counters. *) + +(** Multi-sets. *) +module MultiSet (K : sig + include Set.OrderedType + + val t : t Type.t +end) : sig + val merge : counter Map.Make(K).t t +end + +(** {1 Maps and Association Lists} *) + +(** We consider the only valid operations for maps and association lists to be: + + - Adding a new bindings to the map. + - Removing a binding from the map. + - Replacing an existing binding with a different value. + - {e Trying to add an already existing binding is a no-op}. + + We thus assume that no operation on maps is modifying the {e key} names. So + the following merge functions ensures that {e (i)} new bindings are + preserved {e (ii)} removed bindings stay removed and {e (iii)} modified + bindings are merged using the merge function of values. + + {b Note:} We only consider sets of bindings, instead of multisets. + Application developers should take care of concurrent addition and removal + of similar bindings themselves, by using the appropriate {{!Merge.MSet} + multi-sets}. *) + +(** Lift merge functions to sets. *) +module Set (E : sig + include Set.OrderedType + + val t : t Type.t +end) : sig + val merge : Set.Make(E).t t +end + +val alist : 'a Type.t -> 'b Type.t -> ('a -> 'b option t) -> ('a * 'b) list t +(** Lift the merge functions to association lists. *) + +(** Lift the merge functions to maps. *) + +module Map (K : sig + include Map.OrderedType + + val t : t Type.t +end) : sig + val merge : 'a Type.t -> (K.t -> 'a option t) -> 'a Map.Make(K).t t +end + +(** Infix operators for manipulating merge results and {!promise}s. + + [open Irmin.Merge.Infix] at the top of your file to use them. *) +module Infix : sig + (** {1 Merge Result Combinators} *) + + val ( >>=* ) : + ('a, conflict) result Lwt.t -> + ('a -> ('b, conflict) result Lwt.t) -> + ('b, conflict) result Lwt.t + (** [>>=*] is {!bind}. *) + + val ( >|=* ) : + ('a, conflict) result Lwt.t -> ('a -> 'b) -> ('b, conflict) result Lwt.t + (** [>|=*] is {!map}. *) + + (** {1 Promise Combinators} + + This is useful to manipulate lca results. *) + + val ( >>=? ) : 'a promise -> ('a -> 'b promise) -> 'b promise + (** [>>=?] is {!bind_promise}. *) + + val ( >|=? ) : 'a promise -> ('a -> 'b) -> 'b promise + (** [>|=?] is {!map_promise}. *) +end diff --git a/vendors/irmin/src/irmin/metadata.ml b/vendors/irmin/src/irmin/metadata.ml new file mode 100644 index 000000000000..a0a8c2505523 --- /dev/null +++ b/vendors/irmin/src/irmin/metadata.ml @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Metadata_intf + +module None = struct + type t = unit [@@deriving irmin] + + let default = () + let merge = Merge.v t (fun ~old:_ () () -> Merge.ok ()) +end diff --git a/vendors/irmin/src/irmin/metadata.mli b/vendors/irmin/src/irmin/metadata.mli new file mode 100644 index 000000000000..c8808836a354 --- /dev/null +++ b/vendors/irmin/src/irmin/metadata.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Metadata_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/metadata_intf.ml b/vendors/irmin/src/irmin/metadata_intf.ml new file mode 100644 index 000000000000..3ecacde227fe --- /dev/null +++ b/vendors/irmin/src/irmin/metadata_intf.ml @@ -0,0 +1,31 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Node metadata. *) + +module type S = sig + include Type.Defaultable + + val merge : t Merge.t + (** [merge] is the merge function for metadata. *) +end + +module type Sigs = sig + module type S = S + + module None : S with type t = unit + (** A metadata definition for systems that don't use metadata. *) +end diff --git a/vendors/irmin/src/irmin/metrics.ml b/vendors/irmin/src/irmin/metrics.ml new file mode 100644 index 000000000000..eb3422c4c171 --- /dev/null +++ b/vendors/irmin/src/irmin/metrics.ml @@ -0,0 +1,46 @@ +(* +* Copyright (c) 2022 - Étienne Marais +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*) + +let uid = + let id = ref (-1) in + fun () -> + incr id; + !id + +type origin = .. + +type 'a t = { + uid : int; + name : string; + origin : origin option; + repr : 'a Repr.ty; + mutable state : 'a; +} + +let state m = m.state +let set_state m v = m.state <- v + +type 'a update_mode = Mutate of ('a -> unit) | Replace of ('a -> 'a) + +let v : + type a. ?origin:origin -> name:string -> initial_state:a -> a Repr.ty -> a t + = + fun ?origin ~name ~initial_state repr -> + { uid = uid (); origin; name; repr; state = initial_state } + +let update : type a. a t -> a update_mode -> unit = + fun m kind -> + match kind with Mutate f -> f m.state | Replace f -> m.state <- f m.state diff --git a/vendors/irmin/src/irmin/metrics.mli b/vendors/irmin/src/irmin/metrics.mli new file mode 100644 index 000000000000..a8f4caf6c997 --- /dev/null +++ b/vendors/irmin/src/irmin/metrics.mli @@ -0,0 +1,54 @@ +(* + * Copyright (c) 2022 Etienne Marais + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Metrics] defines primitives to handle metrics inside of Irmin. Its purpose + is to decouple the metrics type definition from the data manipulation. + + A {!t} can be modified in different ways, depending on the {!update_mode}. *) + +type origin = .. +(** An extensible type to get the location of the definition. *) + +type 'a t +(** {!t} is the object that describes how a {!t} is gathered and store. The ['a] + parameter represents the type of the internal data. *) + +val state : 'a t -> 'a +(** The internal state extracted from a {!t}. *) + +val set_state : 'a t -> 'a -> unit +(** [set_state m v] updates the value in the {!t} object. *) + +(** {!update_mode} describes how the data will be handled by the {!update} + function. + + - Mutate: the value and the storage are not modified but the content of the + value can be mutate. + - Replace f: apply f to the value and updates its content. + + It gives the possibility to handle the same metric in different ways. *) +type 'a update_mode = Mutate of ('a -> unit) | Replace of ('a -> 'a) + +val v : ?origin:origin -> name:string -> initial_state:'a -> 'a Repr.ty -> 'a t +(** [v ~origin ~name ~initial_state repr ] create a new {!t}. The [origin] can + be set to give an hint about where the data are gathered. [name] is a name + to describe this metrics. [initial_state] is the first value to store in the + metric object. [repr] describes the type representation to allow + serialization. *) + +val update : 'a t -> 'a update_mode -> unit +(** [update metrics mode] updates the metric by taking in consideration [mode] + to define how it acts on [t] according to their specication. *) diff --git a/vendors/irmin/src/irmin/node.ml b/vendors/irmin/src/irmin/node.ml new file mode 100644 index 000000000000..72d3f008be8a --- /dev/null +++ b/vendors/irmin/src/irmin/node.ml @@ -0,0 +1,785 @@ +(* + * Copyright (c) 2013 Louis Gesbert + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Node_intf + +let src = Logs.Src.create "irmin.node" ~doc:"Irmin trees/nodes" + +module Log = (val Logs.src_log src : Logs.LOG) + +(* Add [merge] to a [Core] implementation. *) +module Of_core (S : Core) = struct + include S + (* Merges *) + + let all_contents t = + let kvs = S.list t in + List.fold_left + (fun acc -> function k, `Contents c -> (k, c) :: acc | _ -> acc) + [] kvs + + let all_succ t = + let kvs = S.list t in + List.fold_left + (fun acc -> function k, `Node n -> (k, n) :: acc | _ -> acc) + [] kvs + + (* [Merge.alist] expects us to return an option. [C.merge] does + that, but we need to consider the metadata too... *) + let merge_metadata merge_contents = + (* This gets us [C.t option, S.Val.Metadata.t]. We want [(C.t * + S.Val.Metadata.t) option]. *) + let explode = function + | None -> (None, S.Metadata.default) + | Some (c, m) -> (Some c, m) + in + let implode = function None, _ -> None | Some c, m -> Some (c, m) in + Merge.like [%typ: (S.contents_key * S.metadata) option] + (Merge.pair merge_contents S.Metadata.merge) + explode implode + + let merge_contents merge_key = + Merge.alist S.step_t (Type.pair S.contents_key_t S.metadata_t) (fun _step -> + merge_metadata merge_key) + + let merge_node merge_key = + Merge.alist S.step_t S.node_key_t (fun _step -> merge_key) + + (* FIXME: this is very broken; do the same thing as [Tree.merge] + instead. *) + let merge ~contents ~node = + let explode t = (all_contents t, all_succ t) in + let implode (contents, succ) = + let xs = List.rev_map (fun (s, c) -> (s, `Contents c)) contents in + let ys = List.rev_map (fun (s, n) -> (s, `Node n)) succ in + S.of_list (xs @ ys) + in + let merge = Merge.pair (merge_contents contents) (merge_node node) in + Merge.like S.t merge explode implode +end + +module Irmin_hash = Hash + +(* A [Make] implementation providing the subset of [S] that can be implemented + over abstract [key] types. *) +module Make_core + (Hash : Hash.S) (Path : sig + type step [@@deriving irmin] + end) + (Metadata : Metadata.S) + (Contents_key : Key.S with type hash = Hash.t) + (Node_key : Key.S with type hash = Hash.t) = +struct + module Metadata = Metadata + + type contents_key = Contents_key.t [@@deriving irmin] + type node_key = Node_key.t [@@deriving irmin] + type step = Path.step [@@deriving irmin] + type metadata = Metadata.t [@@deriving irmin ~equal] + type hash = Hash.t [@@deriving irmin] + + type 'key contents_entry = { name : Path.step; contents : 'key } + [@@deriving irmin] + + type 'key contents_m_entry = { + metadata : Metadata.t; + name : Path.step; + contents : 'key; + } + [@@deriving irmin] + + module StepMap = Map.Make (struct + type t = Path.step [@@deriving irmin ~compare] + end) + + type 'h node_entry = { name : Path.step; node : 'h } [@@deriving irmin] + + type entry = + | Node of node_key node_entry + | Contents of contents_key contents_entry + | Contents_m of contents_key contents_m_entry + (* Invariant: the [_hash] cases are only externally reachable via + [Portable.of_node]. *) + | Node_hash of Hash.t node_entry + | Contents_hash of Hash.t contents_entry + | Contents_m_hash of Hash.t contents_m_entry + [@@deriving irmin] + + type t = entry StepMap.t + type value = [ `Contents of contents_key * metadata | `Node of node_key ] + + type weak_value = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin] + + (* FIXME: special-case the default metadata in the default signature? *) + let value_t = + let open Type in + variant "value" (fun n c x -> function + | `Node h -> n h + | `Contents (h, m) -> + if equal_metadata m Metadata.default then c h else x (h, m)) + |~ case1 "node" node_key_t (fun k -> `Node k) + |~ case1 "contents" contents_key_t (fun h -> + `Contents (h, Metadata.default)) + |~ case1 "contents-x" (pair contents_key_t Metadata.t) (fun (h, m) -> + `Contents (h, m)) + |> sealv + + let to_entry (k, (v : value)) = + match v with + | `Node h -> Node { name = k; node = h } + | `Contents (h, m) -> + if equal_metadata m Metadata.default then + Contents { name = k; contents = h } + else Contents_m { metadata = m; name = k; contents = h } + + let inspect_nonportable_entry_exn : entry -> step * value = function + | Node n -> (n.name, `Node n.node) + | Contents c -> (c.name, `Contents (c.contents, Metadata.default)) + | Contents_m c -> (c.name, `Contents (c.contents, c.metadata)) + | Node_hash _ | Contents_hash _ | Contents_m_hash _ -> + (* Not reachable after [Portable.of_node]. See invariant on {!entry}. *) + assert false + + let step_of_entry : entry -> step = function + | Node { name; _ } + | Node_hash { name; _ } + | Contents { name; _ } + | Contents_m { name; _ } + | Contents_hash { name; _ } + | Contents_m_hash { name; _ } -> + name + + let weak_of_entry : entry -> step * weak_value = function + | Node n -> (n.name, `Node (Node_key.to_hash n.node)) + | Node_hash n -> (n.name, `Node n.node) + | Contents c -> + (c.name, `Contents (Contents_key.to_hash c.contents, Metadata.default)) + | Contents_m c -> + (c.name, `Contents (Contents_key.to_hash c.contents, c.metadata)) + | Contents_hash c -> (c.name, `Contents (c.contents, Metadata.default)) + | Contents_m_hash c -> (c.name, `Contents (c.contents, c.metadata)) + + let of_seq l = + Seq.fold_left + (fun acc x -> StepMap.add (fst x) (to_entry x) acc) + StepMap.empty l + + let of_list l = of_seq (List.to_seq l) + + let seq_entries ~offset ?length (t : t) = + let take seq = match length with None -> seq | Some n -> Seq.take n seq in + StepMap.to_seq t |> Seq.drop offset |> take + + let seq ?(offset = 0) ?length ?cache:_ (t : t) = + seq_entries ~offset ?length t + |> Seq.map (fun (_, e) -> inspect_nonportable_entry_exn e) + + let list ?offset ?length ?cache:_ t = List.of_seq (seq ?offset ?length t) + let find_entry ?cache:_ (t : t) s = StepMap.find_opt s t + + let find ?cache (t : t) s = + Option.map + (fun e -> snd (inspect_nonportable_entry_exn e)) + (find_entry ?cache t s) + + let empty = Fun.const StepMap.empty + let is_empty e = StepMap.is_empty e + let length e = StepMap.cardinal e + let clear _ = () + let equal_entry_opt = Type.(unstage (equal (option entry_t))) + + let add_entry t k e = + StepMap.update k + (fun e' -> if equal_entry_opt (Some e) e' then e' else Some e) + t + + let add t k v = + let e = to_entry (k, v) in + add_entry t k e + + let remove t k = StepMap.remove k t + + let of_entries es = + List.to_seq es |> Seq.map (fun e -> (step_of_entry e, e)) |> StepMap.of_seq + + let entries e = List.rev_map (fun (_, e) -> e) (StepMap.bindings e) + + module Hash_preimage = struct + type entry = + | Node_hash of Hash.t node_entry + | Contents_hash of Hash.t contents_entry + | Contents_m_hash of Hash.t contents_m_entry + [@@deriving irmin] + + type t = entry list [@@deriving irmin ~pre_hash] + type t_not_prefixed = t [@@deriving irmin ~pre_hash] + + let pre_hash = Type.(unstage (pre_hash t)) + + (* Manually add a prefix to default nodes, in order to prevent hash + collision between contents and nodes (see + https://github.com/mirage/irmin/issues/1304). + + Prefixing the contents is not enough to prevent the collision: the + prehash of a node starts with the number of its children, which can + coincide with the prefix of the content's prehash. *) + let pre_hash x f = + f "N"; + pre_hash x f + end + + let pre_hash pre_hash t f = + let entries : Hash_preimage.t = + StepMap.to_seq t + |> Seq.map (fun (_, v) -> + match v with + (* Weaken keys to hashes *) + | Node { name; node } -> + Hash_preimage.Node_hash { name; node = Node_key.to_hash node } + | Contents { name; contents } -> + Contents_hash + { name; contents = Contents_key.to_hash contents } + | Contents_m { metadata; name; contents } -> + Contents_m_hash + { metadata; name; contents = Contents_key.to_hash contents } + | Node_hash { name; node } -> Node_hash { name; node } + | Contents_hash { name; contents } -> + Contents_hash { name; contents } + | Contents_m_hash { metadata; name; contents } -> + Contents_m_hash { metadata; name; contents }) + |> Seq.fold_left (fun xs x -> x :: xs) [] + in + pre_hash entries f + + let t = + let pre_hash = pre_hash Hash_preimage.pre_hash in + Type.map ~pre_hash Type.(list entry_t) of_entries entries + + let t_not_prefixed = + let pre_hash = pre_hash Hash_preimage.pre_hash_t_not_prefixed in + Type.map ~pre_hash Type.(list entry_t) of_entries entries + + let with_handler _ t = t + + let head_entries t = + let l = seq_entries ~offset:0 t |> List.of_seq in + `Node l + + let head t = + let (`Node l) = head_entries t in + let l = List.map (fun (_, e) -> inspect_nonportable_entry_exn e) l in + `Node l + + module Ht = + Irmin_hash.Typed + (Hash) + (struct + type nonrec t = t [@@deriving irmin] + end) + + let hash_exn ?force:_ = Ht.hash +end + +module Portable = struct + module Of_core (X : sig + type hash + + include + Core + with type hash := hash + and type contents_key = hash + and type node_key = hash + end) = + struct + include X + + let of_node t = t + + type proof = + [ `Blinded of hash + | `Values of (step * value) list + | `Inode of int * (int * proof) list ] + [@@deriving irmin] + + let to_proof (t : t) : proof = `Values (seq t |> List.of_seq) + + let of_proof ~depth (t : proof) = + assert (depth = 0); + match t with + | `Blinded _ | `Inode _ -> None + | `Values e -> Some (of_list e) + end + + module Of_node (X : S) = struct + include Of_core (X) + include X + end + + module type S = Portable +end + +module Make_generic_key + (Hash : Hash.S) (Path : sig + type step [@@deriving irmin] + end) + (Metadata : Metadata.S) + (Contents_key : Key.S with type hash = Hash.t) + (Node_key : Key.S with type hash = Hash.t) = +struct + module Core = Make_core (Hash) (Path) (Metadata) (Contents_key) (Node_key) + include Core + include Of_core (Core) + + module Portable = struct + module Core = struct + include Core + + type contents_key = hash [@@deriving irmin] + type node_key = hash [@@deriving irmin] + type value = weak_value [@@deriving irmin] + + let to_entry name = function + | `Node node -> Node_hash { name; node } + | `Contents (contents, metadata) -> + if equal_metadata metadata Metadata.default then + Contents_hash { name; contents } + else Contents_m_hash { name; contents; metadata } + + let of_seq s = + Seq.fold_left + (fun acc (name, v) -> StepMap.add name (to_entry name v) acc) + StepMap.empty s + + let of_list s = of_seq (List.to_seq s) + + let add t name v = + let entry = to_entry name v in + add_entry t name entry + + let find ?cache t s = + Option.map (fun e -> snd (weak_of_entry e)) (find_entry ?cache t s) + + let seq ?(offset = 0) ?length ?cache:_ (t : t) = + seq_entries ~offset ?length t |> Seq.map (fun (_, e) -> weak_of_entry e) + + let list ?offset ?length ?cache t = + List.of_seq (seq ?offset ?length ?cache t) + + let head t = + let (`Node l) = head_entries t in + let l = List.map (fun (_, e) -> weak_of_entry e) l in + `Node l + end + + include Of_core (Core) + include Portable.Of_core (Core) + end + + exception Dangling_hash of { context : string; hash : hash } + + type nonrec hash = hash [@@deriving irmin ~pp] + + let () = + Printexc.register_printer (function + | Dangling_hash { context; hash } -> + Some (Fmt.str "%s: encountered dangling hash %a" context pp_hash hash) + | _ -> None) +end + +module Make_generic_key_v2 + (Hash : Hash.S) (Path : sig + type step [@@deriving irmin] + end) + (Metadata : Metadata.S) + (Contents_key : Key.S with type hash = Hash.t) + (Node_key : Key.S with type hash = Hash.t) = +struct + include Make_generic_key (Hash) (Path) (Metadata) (Contents_key) (Node_key) + + let t = t_not_prefixed + + module Portable = struct + include Portable + + let t = t_not_prefixed + end +end + +module Make + (Hash : Hash.S) (Path : sig + type step [@@deriving irmin] + end) + (Metadata : Metadata.S) = +struct + module Key = Key.Of_hash (Hash) + include Make_generic_key (Hash) (Path) (Metadata) (Key) (Key) +end + +module Store_generic_key + (C : Contents.Store) + (S : Indexable.S) + (H : Hash.S with type t = S.hash) + (V : S_generic_key + with type t = S.value + and type contents_key = C.Key.t + and type node_key = S.Key.t) + (M : Metadata.S with type t = V.metadata) + (P : Path.S with type step = V.step) = +struct + module Val = struct + include V + + type hash = H.t + end + + module Contents = C + module Key = S.Key + module Hash = Hash.Typed (H) (Val) + module Path = P + module Metadata = M + + type 'a t = 'a C.t * 'a S.t + type value = S.value + type key = Key.t + type hash = Hash.t + + let mem (_, t) = S.mem t + let find (_, t) = S.find t + let add (_, t) = S.add t + let unsafe_add (_, t) = S.unsafe_add t + let index (_, t) h = S.index t h + let batch (c, s) f = C.batch c (fun n -> S.batch s (fun s -> f (n, s))) + + let close (c, s) = + let* () = C.close c in + let+ () = S.close s in + () + + let rec merge t = + let merge_key = + Merge.v [%typ: Key.t option] (fun ~old x y -> + Merge.(f (merge t)) ~old x y) + in + let merge = Val.merge ~contents:C.(merge (fst t)) ~node:merge_key in + let read = function + | None -> Lwt.return (Val.empty ()) + | Some k -> ( find t k >|= function None -> Val.empty () | Some v -> v) + in + let add v = + if Val.is_empty v then Lwt.return_none else add t v >>= Lwt.return_some + in + Merge.like_lwt [%typ: Key.t option] merge read add +end + +module Generic_key = struct + module type S = S_generic_key + module type Maker = Maker_generic_key + module type Core = Core + + module Make = Make_generic_key + module Store = Store_generic_key + module Make_v2 = Make_generic_key_v2 +end + +module Store + (C : Contents.Store) + (S : Content_addressable.S with type key = C.key) + (H : Hash.S with type t = S.key) + (V : S with type t = S.value and type hash = S.key) + (M : Metadata.S with type t = V.metadata) + (P : Path.S with type step = V.step) = +struct + module S = Indexable.Of_content_addressable (H) (S) + include Store_generic_key (C) (S) (H) (V) (M) (P) +end + +module Graph (S : Store) = struct + module Path = S.Path + module Contents_key = S.Contents.Key + module Metadata = S.Metadata + + type step = Path.step [@@deriving irmin] + type metadata = Metadata.t [@@deriving irmin] + type contents_key = Contents_key.t [@@deriving irmin] + type node_key = S.Key.t [@@deriving irmin] + type path = Path.t [@@deriving irmin] + type 'a t = 'a S.t + type value = [ `Contents of contents_key * metadata | `Node of node_key ] + + let empty t = S.add t (S.Val.empty ()) + + let list t n = + [%log.debug "steps"]; + S.find t n >|= function None -> [] | Some n -> S.Val.list n + + module U = struct + type t = unit [@@deriving irmin] + end + + module Graph = Object_graph.Make (Contents_key) (S.Key) (U) (U) + + let edges t = + List.rev_map + (function _, `Node n -> `Node n | _, `Contents (c, _) -> `Contents c) + (S.Val.list t) + + let pp_key = Type.pp S.Key.t + let pp_keys = Fmt.(Dump.list pp_key) + let pp_path = Type.pp S.Path.t + let equal_val = Type.(unstage (equal S.Val.t)) + + let pred t = function + | `Node k -> ( S.find t k >|= function None -> [] | Some v -> edges v) + | _ -> Lwt.return_nil + + let closure t ~min ~max = + [%log.debug "closure min=%a max=%a" pp_keys min pp_keys max]; + let min = List.rev_map (fun x -> `Node x) min in + let max = List.rev_map (fun x -> `Node x) max in + let+ g = Graph.closure ~pred:(pred t) ~min ~max () in + List.fold_left + (fun acc -> function `Node x -> x :: acc | _ -> acc) + [] (Graph.vertex g) + + let ignore_lwt _ = Lwt.return_unit + + let iter t ~min ~max ?(node = ignore_lwt) ?(contents = ignore_lwt) ?edge + ?(skip_node = fun _ -> Lwt.return_false) + ?(skip_contents = fun _ -> Lwt.return_false) ?(rev = true) () = + let min = List.rev_map (fun x -> `Node x) min in + let max = List.rev_map (fun x -> `Node x) max in + let node = function + | `Node x -> node x + | `Contents c -> contents c + | `Branch _ | `Commit _ -> Lwt.return_unit + in + let edge = + Option.map + (fun edge n pred -> + match (n, pred) with + | `Node src, `Node dst -> edge src dst + | _ -> Lwt.return_unit) + edge + in + let skip = function + | `Node x -> skip_node x + | `Contents c -> skip_contents c + | _ -> Lwt.return_false + in + Graph.iter ~pred:(pred t) ~min ~max ~node ?edge ~skip ~rev () + + let v t xs = S.add t (S.Val.of_list xs) + + let find_step t node step = + [%log.debug "contents %a" pp_key node]; + S.find t node >|= function None -> None | Some n -> S.Val.find n step + + let find t node path = + [%log.debug "read_node_exn %a %a" pp_key node pp_path path]; + let rec aux node path = + match Path.decons path with + | None -> Lwt.return_some (`Node node) + | Some (h, tl) -> ( + find_step t node h >>= function + | (None | Some (`Contents _)) as x -> Lwt.return x + | Some (`Node node) -> aux node tl) + in + aux node path + + let err_empty_path () = invalid_arg "Irmin.node: empty path" + + let map_one t node f label = + [%log.debug "map_one %a" Type.(pp Path.step_t) label]; + let old_key = S.Val.find node label in + let* old_node = + match old_key with + | None | Some (`Contents _) -> Lwt.return (S.Val.empty ()) + | Some (`Node k) -> ( + S.find t k >|= function None -> S.Val.empty () | Some v -> v) + in + let* new_node = f old_node in + if equal_val old_node new_node then Lwt.return node + else if S.Val.is_empty new_node then + let node = S.Val.remove node label in + if S.Val.is_empty node then Lwt.return (S.Val.empty ()) + else Lwt.return node + else + let+ k = S.add t new_node in + S.Val.add node label (`Node k) + + let map t node path f = + [%log.debug "map %a %a" pp_key node pp_path path]; + let rec aux node path = + match Path.decons path with + | None -> Lwt.return (f node) + | Some (h, tl) -> map_one t node (fun node -> aux node tl) h + in + let* node = + S.find t node >|= function None -> S.Val.empty () | Some n -> n + in + aux node path >>= S.add t + + let add t node path n = + [%log.debug "add %a %a" pp_key node pp_path path]; + match Path.rdecons path with + | Some (path, file) -> map t node path (fun node -> S.Val.add node file n) + | None -> ( + match n with + | `Node n -> Lwt.return n + | `Contents _ -> failwith "TODO: Node.add") + + let rdecons_exn path = + match Path.rdecons path with + | Some (l, t) -> (l, t) + | None -> err_empty_path () + + let remove t node path = + let path, file = rdecons_exn path in + map t node path (fun node -> S.Val.remove node file) + + let value_t = S.Val.value_t +end + +module V1 (N : Generic_key.S with type step = string) = struct + module K (H : Type.S) = struct + let h = Type.string_of `Int64 + + type t = H.t [@@deriving irmin ~to_bin_string ~of_bin_string] + + let size_of = Type.Size.using to_bin_string (Type.Size.t h) + + let encode_bin = + let encode_bin = Type.(unstage (encode_bin h)) in + fun e k -> encode_bin (to_bin_string e) k + + let decode_bin = + let decode_bin = Type.(unstage (decode_bin h)) in + fun buf pos_ref -> + let v = decode_bin buf pos_ref in + match of_bin_string v with + | Ok v -> v + | Error (`Msg e) -> Fmt.failwith "decode_bin: %s" e + + let t = Type.like t ~bin:(encode_bin, decode_bin, size_of) + end + + module Node_key = K (struct + type t = N.node_key + + let t = N.node_key_t + end) + + module Contents_key = K (struct + type t = N.contents_key + + let t = N.contents_key_t + end) + + module Metadata = N.Metadata + + type step = N.step + type node_key = Node_key.t [@@deriving irmin] + type contents_key = Contents_key.t [@@deriving irmin] + type metadata = N.metadata [@@deriving irmin] + type hash = N.hash [@@deriving irmin] + type value = N.value + type t = { n : N.t; entries : (step * value) list } + + exception Dangling_hash = N.Dangling_hash + + let import n = { n; entries = N.list n } + let export t = t.n + let with_handler _ t = t + let hash_exn ?force t = N.hash_exn ?force t.n + let head t = N.head t.n + + let of_seq entries = + let n = N.of_seq entries in + let entries = List.of_seq entries in + { n; entries } + + let of_list entries = + let n = N.of_list entries in + { n; entries } + + let seq ?(offset = 0) ?length ?cache:_ t = + let take seq = match length with None -> seq | Some n -> Seq.take n seq in + List.to_seq t.entries |> Seq.drop offset |> take + + let list ?offset ?length ?cache t = List.of_seq (seq ?offset ?length ?cache t) + let empty () = { n = N.empty (); entries = [] } + let is_empty t = t.entries = [] + let length e = N.length e.n + let clear _ = () + let find ?cache t k = N.find ?cache t.n k + + let add t k v = + let n = N.add t.n k v in + if t.n == n then t else { n; entries = N.list n } + + let remove t k = + let n = N.remove t.n k in + if t.n == n then t else { n; entries = N.list n } + + let v1_step = Type.string_of `Int64 + let step_to_bin_string = Type.(unstage (to_bin_string v1_step)) + let step_of_bin_string = Type.(unstage (of_bin_string v1_step)) + + let step_t : step Type.t = + let to_string p = step_to_bin_string p in + let of_string s = + step_of_bin_string s |> function + | Ok x -> x + | Error (`Msg e) -> Fmt.failwith "Step.of_string: %s" e + in + Type.(map (string_of `Int64)) of_string to_string + + let is_default = Type.(unstage (equal N.metadata_t)) Metadata.default + + let value_t = + let open Type in + record "node" (fun contents metadata node -> + match (contents, metadata, node) with + | Some c, None, None -> `Contents (c, Metadata.default) + | Some c, Some m, None -> `Contents (c, m) + | None, None, Some n -> `Node n + | _ -> failwith "invalid node") + |+ field "contents" (option Contents_key.t) (function + | `Contents (x, _) -> Some x + | _ -> None) + |+ field "metadata" (option metadata_t) (function + | `Contents (_, x) when not (is_default x) -> Some x + | _ -> None) + |+ field "node" (option Node_key.t) (function + | `Node n -> Some n + | _ -> None) + |> sealr + + let t : t Type.t = + Type.map Type.(list ~len:`Int64 (pair step_t value_t)) of_list list + + let merge ~contents ~node = + let merge = N.merge ~contents ~node in + let f ~old x y = + let old = Merge.map_promise (fun old -> old.n) old in + let+ r = Merge.f merge ~old x.n y.n in + match r with Ok r -> Ok (import r) | Error e -> Error e + in + Merge.v t f +end diff --git a/vendors/irmin/src/irmin/node.mli b/vendors/irmin/src/irmin/node.mli new file mode 100644 index 000000000000..8cbe4350b16f --- /dev/null +++ b/vendors/irmin/src/irmin/node.mli @@ -0,0 +1,27 @@ +(* + * Copyright (c) 2013 Louis Gesbert + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Node] provides functions to describe the graph-like structured values. + + The node blocks form a labeled directed acyclic graph, labeled by + {{!Path.S.step} steps}: a list of steps defines a unique path from one node + to an other. + + Each node can point to user-defined {{!Contents.S} contents} values. *) + +include Node_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/node_intf.ml b/vendors/irmin/src/irmin/node_intf.ml new file mode 100644 index 000000000000..27f03fdcb357 --- /dev/null +++ b/vendors/irmin/src/irmin/node_intf.ml @@ -0,0 +1,476 @@ +(* + * Copyright (c) 2013 Louis Gesbert + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type Core = sig + (** {1 Node values} *) + + type t [@@deriving irmin] + (** The type for node values. *) + + type metadata [@@deriving irmin] + (** The type for node metadata. *) + + type contents_key [@@deriving irmin] + (** The type for contents keys. *) + + type node_key [@@deriving irmin] + (** The type for node keys. *) + + type step [@@deriving irmin] + (** The type for steps between nodes. *) + + type value = [ `Node of node_key | `Contents of contents_key * metadata ] + [@@deriving irmin] + (** The type for either (node) keys or (contents) keys combined with their + metadata. *) + + type hash [@@deriving irmin] + (** The type of hashes of values. *) + + val of_list : (step * value) list -> t + (** [of_list l] is the node [n] such that [list n = l]. *) + + val list : + ?offset:int -> ?length:int -> ?cache:bool -> t -> (step * value) list + (** [list t] is the contents of [t]. [offset] and [length] are used to + paginate results. *) + + val of_seq : (step * value) Seq.t -> t + (** [of_seq s] is the node [n] such that [seq n = s]. *) + + val seq : + ?offset:int -> ?length:int -> ?cache:bool -> t -> (step * value) Seq.t + (** [seq t] is the contents of [t]. [offset] and [length] are used to paginate + results. + + See {!caching} for an explanation of the [cache] parameter *) + + val empty : unit -> t + (** [empty ()] is the empty node. *) + + val is_empty : t -> bool + (** [is_empty t] is true iff [t] is {!empty}. *) + + val length : t -> int + (** [length t] is the number of entries in [t]. *) + + val hash_exn : ?force:bool -> t -> hash + (** [hash_exn t] is the hash of [t]. + + Another way of computing it is [Hash.Typed(Hash)(Node).hash t] which + computes the pre-hash of [t] before hashing it using [Hash]. [hash_exn] + might be faster because the it may be optimised (e.g. it may use caching). + + [hash_exn t] is [hash_exn ~force:true t] which is not expected to raise an + exception. [hash_exn ~force:false t] will raise [Not_found] if the hash + requires IOs to be computed. *) + + val clear : t -> unit + (** Cleanup internal caches. *) + + val find : ?cache:bool -> t -> step -> value option + (** [find t s] is the value associated with [s] in [t]. + + A node can point to user-defined {{!contents_key} contents}. The edge + between the node and the contents is labeled by a {!step}. + + See {!caching} for an explanation of the [cache] parameter *) + + val add : t -> step -> value -> t + (** [add t s v] is the node where [find t v] is [Some s] but is similar to [t] + otherwise. *) + + val remove : t -> step -> t + (** [remove t s] is the node where [find t s] is [None] but is similar to [t] + otherwise. *) + + module Metadata : Metadata.S with type t = metadata + (** Metadata functions. *) + + (** {2:caching caching} + + [cache] regulates the caching behaviour regarding the node's internal data + which may be lazily loaded from the backend, depending on the node + implementation. + + [cache] defaults to [true] which may greatly reduce the IOs and the + runtime but may also increase the memory consumption. + + [cache = false] doesn't replace a call to [clear], it only prevents the + storing of new data, it doesn't discard the existing one. *) + + (** {1 Recursive Nodes} *) + + (** Some [Node] implementations (like [irmin-pack]'s inodes) can represent a + node as a set of nodes. One operation on such "high-level" node + corresponds to a sequence of recursive calls to the underlying + "lower-level" nodes. Note: theses [effects] are not in the Lwt monad on + purpose (so [Tree.hash] and [Tree.equal] are not in the Lwt monad as + well). *) + + type effect := expected_depth:int -> node_key -> t option + (** The type for read effects. *) + + val with_handler : (effect -> effect) -> t -> t + (** [with_handler f] replace the current effect handler [h] by [f h]. [f h] + will be called for all the recursive read effects that are required by + recursive operations on nodes. .*) + + type head := + [ `Node of (step * value) list | `Inode of int * (int * hash) list ] + [@@deriving irmin] + + val head : t -> head + (** Reveal the shallow internal structure of the node. + + Only hashes and not keys are revealed in the [`Inode] case, this is + because these inodes might not be keyed yet. *) +end + +module type S_generic_key = sig + include Core + (** @inline *) + + (** {2 merging} *) + + val merge : + contents:contents_key option Merge.t -> + node:node_key option Merge.t -> + t Merge.t + (** [merge] is the merge function for nodes. *) + + exception Dangling_hash of { context : string; hash : hash } +end + +module type S = sig + type hash + + (** @inline *) + include + S_generic_key + with type hash := hash + and type contents_key = hash + and type node_key = hash +end + +module type Portable = sig + type hash + + (** @inline *) + include + Core + with type hash := hash + and type contents_key = hash + and type node_key = hash + + type node + + val of_node : node -> t + + (** {2 merging} *) + + val merge : + contents:contents_key option Merge.t -> + node:node_key option Merge.t -> + t Merge.t + (** [merge] is the merge function for nodes. *) + + (** {1 Proofs} *) + + type proof = + [ `Blinded of hash + | `Values of (step * value) list + | `Inode of int * (int * proof) list ] + [@@deriving irmin] + (** The type for proof trees. *) + + val to_proof : t -> proof + + val of_proof : depth:int -> proof -> t option + (** [of_proof ~depth p] is [None] if [p] is corrupted or incompatible with + [depth]. It is [Some t] when [t] is a node if the operation succeeded. + + [hash_exn t] never raises [Not_found] *) +end + +open struct + module S_is_a_generic_key (X : S) : S_generic_key = X +end + +module type Maker_generic_key = functor + (Hash : Hash.S) + (Path : sig + type step [@@deriving irmin] + end) + (Metadata : Metadata.S) + (Contents_key : Key.S with type hash = Hash.t) + (Node_key : Key.S with type hash = Hash.t) + -> sig + include + S_generic_key + with type metadata = Metadata.t + and type step = Path.step + and type hash = Hash.t + and type contents_key = Contents_key.t + and type node_key = Node_key.t + + module Portable : + Portable + with type node := t + and type step := step + and type metadata := metadata + and type hash := hash +end + +module type Store = sig + include Indexable.S + + module Path : Path.S + (** [Path] provides base functions on node paths. *) + + val merge : [> read_write ] t -> key option Merge.t + (** [merge] is the 3-way merge function for nodes keys. *) + + module Metadata : Metadata.S + (** [Metadata] provides base functions for node metadata. *) + + (** [Val] provides base functions for node values. *) + module Val : + S_generic_key + with type t = value + and type hash = hash + and type node_key = key + and type metadata = Metadata.t + and type step = Path.step + + module Hash : Hash.Typed with type t = hash and type value = value + + module Contents : Contents.Store with type key = Val.contents_key + (** [Contents] is the underlying contents store. *) +end + +module type Graph = sig + (** {1 Node Graphs} *) + + type 'a t + (** The type for store handles. *) + + type metadata [@@deriving irmin] + (** The type for node metadata. *) + + type contents_key [@@deriving irmin] + (** The type of user-defined contents. *) + + type node_key [@@deriving irmin] + (** The type for node values. *) + + type step [@@deriving irmin] + (** The type of steps. A step is used to pass from one node to another. *) + + type path [@@deriving irmin] + (** The type of store paths. A path is composed of {{!step} steps}. *) + + type value = [ `Node of node_key | `Contents of contents_key * metadata ] + [@@deriving irmin] + (** The type for store values. *) + + val empty : [> write ] t -> node_key Lwt.t + (** The empty node. *) + + val v : [> write ] t -> (step * value) list -> node_key Lwt.t + (** [v t n] is a new node containing [n]. *) + + val list : [> read ] t -> node_key -> (step * value) list Lwt.t + (** [list t n] is the contents of the node [n]. *) + + val find : [> read ] t -> node_key -> path -> value option Lwt.t + (** [find t n p] is the contents of the path [p] starting form [n]. *) + + val add : [> read_write ] t -> node_key -> path -> value -> node_key Lwt.t + (** [add t n p v] is the node [x] such that [find t x p] is [Some v] and it + behaves the same [n] for other operations. *) + + val remove : [> read_write ] t -> node_key -> path -> node_key Lwt.t + (** [remove t n path] is the node [x] such that [find t x] is [None] and it + behhaves then same as [n] for other operations. *) + + val closure : + [> read ] t -> min:node_key list -> max:node_key list -> node_key list Lwt.t + (** [closure t min max] is the unordered list of nodes [n] reachable from a + node of [max] along a path which: (i) either contains no [min] or (ii) it + ends with a [min]. + + {b Note:} Both [min] and [max] are subsets of [n]. *) + + val iter : + [> read ] t -> + min:node_key list -> + max:node_key list -> + ?node:(node_key -> unit Lwt.t) -> + ?contents:(contents_key -> unit Lwt.t) -> + ?edge:(node_key -> node_key -> unit Lwt.t) -> + ?skip_node:(node_key -> bool Lwt.t) -> + ?skip_contents:(contents_key -> bool Lwt.t) -> + ?rev:bool -> + unit -> + unit Lwt.t + (** [iter t min max node edge skip rev ()] iterates in topological order over + the closure of [t]. + + It applies the following functions while traversing the graph: [node] on + the nodes; [edge n predecessor_of_n] on the directed edges; [skip_node n] + to not include a node [n], its predecessors and the outgoing edges of [n] + and [skip_contents c] to not include content [c]. + + If [rev] is true (the default) then the graph is traversed in the reverse + order: [node n] is applied only after it was applied on all its + predecessors; [edge n p] is applied after [node n]. Note that [edge n p] + is applied even if [p] is skipped. *) +end + +module type Sigs = sig + module type S = S + + (** [Make] provides a simple node implementation, parameterized by hash, path + and metadata implementations. The contents and node values are addressed + directly by their hash. *) + module Make + (Hash : Hash.S) (Path : sig + type step [@@deriving irmin] + end) + (Metadata : Metadata.S) : + S + with type hash = Hash.t + and type metadata = Metadata.t + and type step = Path.step + + (** [Generic_key] generalises the concept of "node" to one that supports + object keys that are not strictly equal to hashes. *) + module Generic_key : sig + module type S = S_generic_key + module type Maker = Maker_generic_key + module type Core = Core + + module Make : Maker + + module Make_v2 : Maker + (** [Make_v2] provides a similar implementation as [Make] but the hash + computation is compatible with versions older than irmin.3.0 *) + + module Store + (C : Contents.Store) + (S : Indexable.S) + (H : Hash.S with type t = S.hash) + (V : S + with type t = S.value + and type hash = H.t + and type contents_key = C.key + and type node_key = S.key) + (M : Metadata.S with type t = V.metadata) + (P : Path.S with type step = V.step) : + Store + with type 'a t = 'a C.t * 'a S.t + and type key = S.key + and type hash = S.hash + and type value = S.value + and module Path = P + and module Metadata = M + and module Val = V + end + + (** v1 serialisation *) + module V1 (N : Generic_key.S with type step = string) : sig + include + Generic_key.S + with type contents_key = N.contents_key + and type node_key = N.node_key + and type step = N.step + and type metadata = N.metadata + + val import : N.t -> t + val export : t -> N.t + end + + module Portable : sig + (** Portable form of a node implementation that can be constructed from a + concrete representation and used in computing hashes. Conceptually, a + [Node.Portable.t] is a [Node.t] in which all internal keys have been + replaced with the hashes of the values they point to. + + Computations over [Portable.t] values must commute with those over [t]s, + as in the following diagram: + + {[ + ┌────────┐ ┌─────────┐ of_node ┌────────────────┐ + │ Key │ │ Node │ ─────────> │ Node.Portable │ + └────────┘ └─────────┘ └────────────────┘ + │ │ add/remove │ │ + to_hash └───────────> (+) add/remove │ + │ ┌──────────────┼──────────────────────> (+) + v │ v v + ┌────────┐ ┌─────────┐ ┌────────────────┐ + │ Hash │ │ Node' │ ─────────> │ Node.Portable' │ + └────────┘ └─────────┘ of_node └────────────────┘ + ]} *) + + (** A node implementation with hashes for keys is trivially portable: *) + module Of_node (S : S) : + Portable + with type node := S.t + and type t = S.t + and type step = S.step + and type metadata = S.metadata + and type hash = S.hash + + module type S = Portable + end + + module type Store = Store + (** [Store] specifies the signature for node stores. *) + + (** [Store] creates node stores. *) + module Store + (C : Contents.Store) + (S : Content_addressable.S with type key = C.key) + (H : Hash.S with type t = S.key) + (V : S with type t = S.value and type hash = S.key) + (M : Metadata.S with type t = V.metadata) + (P : Path.S with type step = V.step) : + Store + with type 'a t = 'a C.t * 'a S.t + and type key = S.key + and type value = S.value + and type hash = H.t + and module Path = P + and module Metadata = M + and module Val = V + + module type Graph = Graph + (** [Graph] specifies the signature for node graphs. A node graph is a + deterministic DAG, labeled by steps. *) + + module Graph (N : Store) : + Graph + with type 'a t = 'a N.t + and type contents_key = N.Contents.key + and type node_key = N.key + and type metadata = N.Metadata.t + and type step = N.Path.step + and type path = N.Path.t +end diff --git a/vendors/irmin/src/irmin/object_graph.ml b/vendors/irmin/src/irmin/object_graph.ml new file mode 100644 index 000000000000..bb47a16371d5 --- /dev/null +++ b/vendors/irmin/src/irmin/object_graph.ml @@ -0,0 +1,291 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Object_graph_intf + +let src = Logs.Src.create "irmin.graph" ~doc:"Irmin graph support" + +module Log = (val Logs.src_log src : Logs.LOG) + +let list_partition_map f t = + let rec aux fst snd = function + | [] -> (List.rev fst, List.rev snd) + | h :: t -> ( + match f h with + | `Fst x -> aux (x :: fst) snd t + | `Snd x -> aux fst (x :: snd) t) + in + aux [] [] t + +module Make + (Contents_key : Type.S) + (Node_key : Type.S) + (Commit_key : Type.S) + (Branch : Type.S) = +struct + module X = struct + type t = + [ `Contents of Contents_key.t + | `Node of Node_key.t + | `Commit of Commit_key.t + | `Branch of Branch.t ] + [@@deriving irmin] + + let equal = Type.(unstage (equal t)) + let compare = Type.(unstage (compare t)) + let hash_contents = Type.(unstage (short_hash Contents_key.t)) + let hash_commit = Type.(unstage (short_hash Commit_key.t)) + let hash_node = Type.(unstage (short_hash Node_key.t)) + let hash_branch = Type.(unstage (short_hash Branch.t)) + + (* we are using cryptographic hashes here, so the first bytes + are good enough to be used as short hashes. *) + let hash (t : t) : int = + match t with + | `Contents c -> hash_contents c + | `Node n -> hash_node n + | `Commit c -> hash_commit c + | `Branch b -> hash_branch b + end + + module G = Graph.Imperative.Digraph.ConcreteBidirectional (X) + module GO = Graph.Oper.I (G) + module Topological = Graph.Topological.Make (G) + + module Table : sig + type t + + val create : int option -> t + val add : t -> X.t -> int -> unit + val mem : t -> X.t -> bool + end = struct + module Lru = Lru.Make (X) + module Tbl = Hashtbl.Make (X) + + type t = L of int Lru.t | T of int Tbl.t + + let create = function + | None -> T (Tbl.create 1024) + | Some n -> L (Lru.create n) + + let add t k v = match t with L t -> Lru.add t k v | T t -> Tbl.add t k v + let mem t k = match t with L t -> Lru.mem t k | T t -> Tbl.mem t k + end + + module Set = Set.Make (X) + include G + include GO + + type dump = vertex list * (vertex * vertex) list + + (* XXX: for the binary format, we can use offsets in the vertex list + to save space. *) + module Dump = struct + type t = X.t list * (X.t * X.t) list [@@deriving irmin] + end + + let vertex g = G.fold_vertex (fun k set -> k :: set) g [] + let edges g = G.fold_edges (fun k1 k2 list -> (k1, k2) :: list) g [] + let pp_vertices = Fmt.Dump.list (Type.pp X.t) + let pp_depth ppf d = if d <> max_int then Fmt.pf ppf "depth=%d,@ " d + + type action = Visit of (X.t * int) | Treat of X.t + + let iter ?cache_size ?(depth = max_int) ~pred ~min ~max ~node ?edge ~skip ~rev + () = + [%log.debug + "@[<2>iter:@ %arev=%b,@ min=%a,@ max=%a@, cache=%a@]" pp_depth depth rev + pp_vertices min pp_vertices max + Fmt.(Dump.option int) + cache_size]; + let marks = Table.create cache_size in + let mark key level = Table.add marks key level in + let todo = Stack.create () in + (* if a branch is in [min], add the commit it is pointing to too. *) + let* min = + Lwt_list.fold_left_s + (fun acc -> function + | `Branch _ as x -> pred x >|= fun c -> (x :: c) @ acc + | x -> Lwt.return (x :: acc)) + [] min + in + let min = Set.of_list min in + let has_mark key = Table.mem marks key in + List.iter (fun k -> Stack.push (Visit (k, 0)) todo) max; + let treat key = + [%log.debug "TREAT %a" Type.(pp X.t) key]; + node key >>= fun () -> + if not (Set.mem key min) then + (* the edge function is optional to prevent an unnecessary computation + of the preds .*) + match edge with + | None -> Lwt.return_unit + | Some edge -> + let* keys = pred key in + Lwt_list.iter_p (fun k -> edge key k) keys + else Lwt.return_unit + in + let visit_predecessors ~filter_history key level = + let+ keys = pred key in + (*if a commit is in [min] cut the history but still visit + its nodes. *) + List.iter + (function + | `Commit _ when filter_history -> () + | k -> Stack.push (Visit (k, level + 1)) todo) + keys + in + let visit key level = + if level >= depth then Lwt.return_unit + else if has_mark key then Lwt.return_unit + else + skip key >>= function + | true -> Lwt.return_unit + | false -> + let+ () = + [%log.debug "VISIT %a %d" Type.(pp X.t) key level]; + mark key level; + if rev then Stack.push (Treat key) todo; + match key with + | `Commit _ -> + visit_predecessors ~filter_history:(Set.mem key min) key level + | _ -> + if Set.mem key min then Lwt.return_unit + else visit_predecessors ~filter_history:false key level + in + if not rev then Stack.push (Treat key) todo + in + let rec pop () = + match Stack.pop todo with + | exception Stack.Empty -> Lwt.return_unit + | Treat key -> treat key >>= pop + | Visit (key, level) -> visit key level >>= pop + in + pop () + + let breadth_first_traversal ?cache_size ~pred ~max ~node () = + let marks = Table.create cache_size in + let mark key level = Table.add marks key level in + let todo = Queue.create () in + let has_mark key = Table.mem marks key in + List.iter (fun k -> Queue.push (Visit (k, 0)) todo) max; + let treat key = + [%log.debug "TREAT %a" Type.(pp X.t) key]; + node key + in + let visit_predecessors key level = + let+ keys = pred key in + List.iter (fun k -> Queue.push (Visit (k, level + 1)) todo) keys + in + let visit key level = + if has_mark key then Lwt.return_unit + else ( + [%log.debug "VISIT %a" Type.(pp X.t) key]; + mark key level; + treat key >>= fun () -> visit_predecessors key level) + in + let rec pop () = + match Queue.pop todo with + | exception Queue.Empty -> Lwt.return_unit + | Treat _ -> + Fmt.failwith "in bfs always treat the node as soon as its visited" + | Visit (key, level) -> visit key level >>= pop + in + pop () + + let closure ?(depth = max_int) ~pred ~min ~max () = + let g = G.create ~size:1024 () in + List.iter (G.add_vertex g) max; + let node key = + if not (G.mem_vertex g key) then G.add_vertex g key else (); + Lwt.return_unit + in + let edge node pred = + G.add_edge g pred node; + Lwt.return_unit + in + let skip _ = Lwt.return_false in + iter ~depth ~pred ~min ~max ~node ~edge ~skip ~rev:false () >|= fun () -> g + + let min g = + G.fold_vertex + (fun v acc -> if G.in_degree g v = 0 then v :: acc else acc) + g [] + + let max g = + G.fold_vertex + (fun v acc -> if G.out_degree g v = 0 then v :: acc else acc) + g [] + + let vertex_attributes = ref (fun _ -> []) + let edge_attributes = ref (fun _ -> []) + let graph_name = ref None + + module Dot = Graph.Graphviz.Dot (struct + include G + + let edge_attributes k = !edge_attributes k + let default_edge_attributes _ = [] + + let vertex_name k = + let str t v = "\"" ^ Type.to_string t v ^ "\"" in + match k with + | `Node n -> str Node_key.t n + | `Commit c -> str Commit_key.t c + | `Contents c -> str Contents_key.t c + | `Branch b -> str Branch.t b + + let vertex_attributes k = !vertex_attributes k + let default_vertex_attributes _ = [] + let get_subgraph _ = None + + let graph_attributes _ = + match !graph_name with None -> [] | Some n -> [ `Label n ] + end) + + let export t = (vertex t, edges t) + + let import (vs, es) = + let g = G.create ~size:(List.length vs) () in + List.iter (G.add_vertex g) vs; + List.iter (fun (v1, v2) -> G.add_edge g v1 v2) es; + g + + let output ppf vertex edges name = + [%log.debug "output %s" name]; + let g = G.create ~size:(List.length vertex) () in + List.iter (fun (v, _) -> G.add_vertex g v) vertex; + List.iter (fun (v1, _, v2) -> G.add_edge g v1 v2) edges; + let eattrs (v1, v2) = + try + let l = List.filter (fun (x, _, y) -> x = v1 && y = v2) edges in + let l = List.fold_left (fun acc (_, l, _) -> l @ acc) [] l in + let labels, others = + list_partition_map (function `Label l -> `Fst l | x -> `Snd x) l + in + match labels with + | [] -> others + | [ l ] -> `Label l :: others + | _ -> `Label (String.concat "," labels) :: others + with Not_found -> [] + in + let vattrs v = try List.assoc v vertex with Not_found -> [] in + vertex_attributes := vattrs; + edge_attributes := eattrs; + graph_name := Some name; + Dot.fprint_graph ppf g +end diff --git a/vendors/irmin/src/irmin/object_graph.mli b/vendors/irmin/src/irmin/object_graph.mli new file mode 100644 index 000000000000..a16412aaa267 --- /dev/null +++ b/vendors/irmin/src/irmin/object_graph.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Graphs. *) + +include Object_graph_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/object_graph_intf.ml b/vendors/irmin/src/irmin/object_graph_intf.ml new file mode 100644 index 000000000000..063c3bbe0b38 --- /dev/null +++ b/vendors/irmin/src/irmin/object_graph_intf.ml @@ -0,0 +1,139 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + include Graph.Sig.I + (** Directed graph *) + + include Graph.Oper.S with type g := t + (** Basic operations. *) + + (** Topological traversal *) + module Topological : sig + val fold : (vertex -> 'a -> 'a) -> t -> 'a -> 'a + end + + val vertex : t -> vertex list + (** Get all the vertices. *) + + val edges : t -> (vertex * vertex) list + (** Get all the relations. *) + + val closure : + ?depth:int -> + pred:(vertex -> vertex list Lwt.t) -> + min:vertex list -> + max:vertex list -> + unit -> + t Lwt.t + (** [closure depth pred min max ()] creates the transitive closure graph of + [max] using the predecessor relation [pred]. The graph is bounded by the + [min] nodes and by [depth]. + + {b Note:} Both [min] and [max] are subsets of [n]. *) + + val iter : + ?cache_size:int -> + ?depth:int -> + pred:(vertex -> vertex list Lwt.t) -> + min:vertex list -> + max:vertex list -> + node:(vertex -> unit Lwt.t) -> + ?edge:(vertex -> vertex -> unit Lwt.t) -> + skip:(vertex -> bool Lwt.t) -> + rev:bool -> + unit -> + unit Lwt.t + (** [iter depth min max node edge skip rev ()] iterates in topological order + over the closure graph starting with the [max] nodes and bounded by the + [min] nodes and by [depth]. + + It applies three functions while traversing the graph: [node] on the + nodes; [edge n predecessor_of_n] on the directed edges and [skip n] to not + include a node [n], its predecessors and the outgoing edges of [n]. + + If [rev] is true (the default) then the graph is traversed in the reverse + order: [node n] is applied only after it was applied on all its + predecessors; [edge n p] is applied after [node n]. Note that [edge n p] + is applied even if [p] is skipped. + + [cache_size] is the size of the LRU cache used to store nodes already + seen. If [None] (by default) every traversed nodes is stored (and thus no + entries are never removed from the LRU). *) + + val breadth_first_traversal : + ?cache_size:int -> + pred:(vertex -> vertex list Lwt.t) -> + max:vertex list -> + node:(vertex -> unit Lwt.t) -> + unit -> + unit Lwt.t + (** [breadth_first_traversal ?cache_size pred max node ()] traverses the + closure graph in breadth-first order starting with the [max] nodes. It + applies [node] on the nodes of the graph while traversing it. *) + + val output : + Format.formatter -> + (vertex * Graph.Graphviz.DotAttributes.vertex list) list -> + (vertex * Graph.Graphviz.DotAttributes.edge list * vertex) list -> + string -> + unit + (** [output ppf vertex edges name] create aand dumps the graph contents on + [ppf]. The graph is defined by its [vertex] and [edges]. [name] is the + name of the output graph.*) + + val min : t -> vertex list + (** Compute the minimum vertex. *) + + val max : t -> vertex list + (** Compute the maximun vertex. *) + + type dump = vertex list * (vertex * vertex) list + (** Expose the graph internals. *) + + val export : t -> dump + (** Expose the graph as a pair of vertices and edges. *) + + val import : dump -> t + (** Import a graph. *) + + module Dump : Type.S with type t = dump + (** The base functions over graph internals. *) +end + +module type HASH = sig + include Type.S + + val short_hash : t -> int +end + +module type Sigs = sig + module type S = S + module type HASH = HASH + + (** Build a graph. *) + module Make + (Contents_key : Type.S) + (Node_key : Type.S) + (Commit_key : Type.S) + (Branch : Type.S) : + S + with type V.t = + [ `Contents of Contents_key.t + | `Node of Node_key.t + | `Commit of Commit_key.t + | `Branch of Branch.t ] +end diff --git a/vendors/irmin/src/irmin/path.ml b/vendors/irmin/src/irmin/path.ml new file mode 100644 index 000000000000..95b73760b6d0 --- /dev/null +++ b/vendors/irmin/src/irmin/path.ml @@ -0,0 +1,48 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Astring +include Path_intf + +module String_list = struct + type step = string [@@deriving irmin] + type t = step list + + let empty = [] + let is_empty l = l = [] + let cons s t = s :: t + let rcons t s = t @ [ s ] + let decons = function [] -> None | h :: t -> Some (h, t) + + let rdecons l = + match List.rev l with [] -> None | h :: t -> Some (List.rev t, h) + + let map l f = List.map f l + let v x = x + + let pp ppf t = + let len = List.fold_left (fun acc s -> 1 + acc + String.length s) 1 t in + let buf = Buffer.create len in + List.iter + (fun s -> + Buffer.add_char buf '/'; + Buffer.add_string buf s) + t; + Fmt.string ppf (Buffer.contents buf) + + let of_string s = Ok (List.filter (( <> ) "") (String.cuts s ~sep:"/")) + let t = Type.like ~pp ~of_string Type.(list step_t) +end diff --git a/vendors/irmin/src/irmin/path.mli b/vendors/irmin/src/irmin/path.mli new file mode 100644 index 000000000000..32c9de496f5f --- /dev/null +++ b/vendors/irmin/src/irmin/path.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Tree path handling. *) + +include Path_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/path_intf.ml b/vendors/irmin/src/irmin/path_intf.ml new file mode 100644 index 000000000000..9ff994bff53f --- /dev/null +++ b/vendors/irmin/src/irmin/path_intf.ml @@ -0,0 +1,67 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** {1 Path} *) + + type t + (** The type for path values. *) + + type step + (** Type type for path's steps. *) + + val empty : t + (** The empty path. *) + + val v : step list -> t + (** Create a path from a list of steps. *) + + val is_empty : t -> bool + (** Check if the path is empty. *) + + val cons : step -> t -> t + (** Prepend a step to the path. *) + + val rcons : t -> step -> t + (** Append a step to the path. *) + + val decons : t -> (step * t) option + (** Deconstruct the first element of the path. Return [None] if the path is + empty. *) + + val rdecons : t -> (t * step) option + (** Deconstruct the last element of the path. Return [None] if the path is + empty. *) + + val map : t -> (step -> 'a) -> 'a list + (** [map t f] maps [f] over all steps of [t]. *) + + (** {1 Value Types} *) + + val t : t Type.t + (** [t] is the value type for {!type-t}. *) + + val step_t : step Type.t + (** [step_t] is the value type for {!step}. *) +end + +module type Sigs = sig + module type S = S + (** Signature for path implementations.*) + + (** An implementation of paths as string lists. *) + module String_list : S with type step = string and type t = string list +end diff --git a/vendors/irmin/src/irmin/perms.ml b/vendors/irmin/src/irmin/perms.ml new file mode 100644 index 000000000000..1d66477f05f9 --- /dev/null +++ b/vendors/irmin/src/irmin/perms.ml @@ -0,0 +1,66 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Types representing {i permissions} ['perms] for performing operations on a + certain type ['perms t]. + + They are intended to be used as phantom parameters of the types that they + control access to. As an example, consider the following type of references + with permissions: + + {[ + module Ref : sig + type (+'a, -'perms) t + + val create : 'a -> ('a, read_write) t + val get : ('a, [> read ]) t -> 'a + val set : ('a, [> write ]) t -> 'a -> unit + end + ]} + + This type allows references to be created with arbitrary read-write access. + One can then create weaker views onto the reference – with access to fewer + operations – by upcasting: + + {[ + let read_only t = (t :> (_, read) Ref.t) + let write_only t = (t :> (_, write) Ref.t) + ]} + + Note that the ['perms] phantom type parameter should be contravariant: it's + safe to discard permissions, but not to gain new ones. *) + +module Read = struct + type t = [ `Read ] +end + +module Write = struct + type t = [ `Write ] +end + +module Read_write = struct + type t = [ Read.t | Write.t ] +end + +type read = Read.t +(** The type parameter of a handle with [read] permissions. *) + +type write = Write.t +(** The type parameter of a handle with [write] permissions. *) + +type read_write = Read_write.t +(** The type parameter of a handle with both {!read} and {!write} permissions. *) diff --git a/vendors/irmin/src/irmin/proof.ml b/vendors/irmin/src/irmin/proof.ml new file mode 100644 index 000000000000..e72a3c5bec6d --- /dev/null +++ b/vendors/irmin/src/irmin/proof.ml @@ -0,0 +1,664 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Proof_intf + +module Make + (C : Type.S) + (H : Type.S) (S : sig + type step [@@deriving irmin] + end) + (M : Type.S) = +struct + type contents = C.t [@@deriving irmin] + type hash = H.t [@@deriving irmin] + type step = S.step [@@deriving irmin] + type metadata = M.t [@@deriving irmin] + + type kinded_hash = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin] + + type 'a inode = { length : int; proofs : (int * 'a) list } [@@deriving irmin] + + type 'a inode_extender = { length : int; segments : int list; proof : 'a } + [@@deriving irmin] + + type tree = + | Contents of contents * metadata + | Blinded_contents of hash * metadata + | Node of (step * tree) list + | Blinded_node of hash + | Inode of inode_tree inode + | Extender of inode_tree inode_extender + [@@deriving irmin] + + and inode_tree = + | Blinded_inode of hash + | Inode_values of (step * tree) list + | Inode_tree of inode_tree inode + | Inode_extender of inode_tree inode_extender + [@@deriving irmin] + + type elt = + | Contents of contents + | Node of (step * kinded_hash) list + | Inode of hash inode + | Inode_extender of hash inode_extender + [@@deriving irmin] + + type stream = elt Seq.t [@@deriving irmin] + + type 'a t = { before : kinded_hash; after : kinded_hash; state : 'a } + [@@deriving irmin] + + let before t = t.before + let after t = t.after + let state t = t.state + let v ~before ~after state = { after; before; state } +end + +type bad_stream_exn = + | Stream_too_long of { context : string; reason : string } + | Stream_too_short of { context : string; reason : string } + | Proof_mismatch of { context : string; reason : string } + +exception Bad_proof of { context : string } +exception Bad_stream of bad_stream_exn + +let bad_proof_exn context = raise (Bad_proof { context }) + +let bad_stream_too_long context reason = + raise (Bad_stream (Stream_too_long { context; reason })) + +let bad_stream_too_short context reason = + raise (Bad_stream (Stream_too_short { context; reason })) + +let bad_stream_exn context reason = + raise (Bad_stream (Proof_mismatch { context; reason })) + +let bad_stream_exn_fmt s fmt = Fmt.kstr (bad_stream_exn ("Proof.Env." ^ s)) fmt + +let bad_stream_too_short_fmt s fmt = + Fmt.kstr (bad_stream_too_short ("Proof.Env." ^ s)) fmt + +module Env + (B : Backend.S) + (P : S + with type contents := B.Contents.Val.t + and type hash := B.Hash.t + and type step := B.Node.Val.step + and type metadata := B.Node.Val.metadata) = +struct + module H = B.Hash + + module Hashes = struct + include Hashtbl.Make (struct + type t = H.t + + let hash = H.short_hash + let equal = Type.(unstage (equal H.t)) + end) + + let of_list l = of_seq (List.to_seq l) + let to_list t = List.of_seq (to_seq t) + let t elt_t = Type.map [%typ: (H.t * elt) list] of_list to_list + end + + type mode = Produce | Serialise | Deserialise | Consume [@@deriving irmin] + type kind = Set | Stream [@@deriving irmin] + + module Set = struct + type produce = { + nodes : B.Node.Val.t Hashes.t; + contents : B.Contents.Val.t Hashes.t; + } + [@@deriving irmin] + + type deserialise = { + nodes : B.Node_portable.t Hashes.t; + contents : B.Contents.Val.t Hashes.t; + } + [@@deriving irmin] + + type t = + | Produce of produce + | Serialise of produce + | Deserialise of deserialise + | Consume of deserialise + [@@deriving irmin] + + let producer () = + Produce { contents = Hashes.create 13; nodes = Hashes.create 13 } + + let deserialiser () = + Deserialise { contents = Hashes.create 13; nodes = Hashes.create 13 } + end + + module Stream = struct + let ref_t v = Type.map v ref ( ! ) + + type produce = { + set : unit Hashes.t; + singleton_inodes : (int * H.t) Hashes.t; + rev_elts : (H.t * P.elt) list ref; + rev_elts_size : int ref; + } + [@@deriving irmin] + + type consume = { + nodes : B.Node_portable.t Hashes.t; + contents : B.Contents.Val.t Hashes.t; + stream : P.elt Seq.t ref; + } + [@@deriving irmin] + + type t = Produce of produce | Consume of consume [@@deriving irmin] + + let producer () = + let set = Hashes.create 13 in + let singleton_inodes = Hashes.create 13 in + let rev_elts = ref [] in + let rev_elts_size = ref 0 in + Produce { set; singleton_inodes; rev_elts; rev_elts_size } + + let consumer stream = + let nodes = Hashes.create 13 in + let contents = Hashes.create 13 in + let stream = ref stream in + Consume { nodes; contents; stream } + + let push { rev_elts; rev_elts_size; _ } h_elt index = + incr rev_elts_size; + rev_elts := List.insert_exn !rev_elts index h_elt + end + + type v = Empty | Set of Set.t | Stream of Stream.t [@@deriving irmin] + type t = v ref + + let t = Type.map v_t ref ( ! ) + let empty () : t = ref Empty + let is_empty t = !t = Empty + let copy ~into t = into := !t + + type hash = H.t [@@deriving irmin ~equal ~pp] + + let rec forward_lookup h singleton_inodes : (int * hash) list option = + match Hashes.find_opt singleton_inodes h with + | None -> None + | Some (i', h') -> ( + match forward_lookup h' singleton_inodes with + | None -> Some [ (i', h') ] + | Some l -> Some ((i', h') :: l)) + + let apply_extenders ~length singleton_inodes skips proofs = + let rec accumulate_segments ~(acc : int Reversed_list.t) h = function + | [] -> (Reversed_list.rev acc, h) + | (i', h') :: rest -> accumulate_segments ~acc:(i' :: acc) h' rest + in + let inode = P.Inode { length; proofs } in + match proofs with + | [ (i, h) ] -> ( + match forward_lookup h singleton_inodes with + | None -> inode + | Some ls -> ( + let () = + (* Push all hashes except the last one into [skips] *) + match List.rev ((i, h) :: ls) with + | [] | [ _ ] -> failwith "idk" + | _ :: tl -> List.iter (fun (_, h) -> Hashes.add skips h ()) tl + in + let i, h = accumulate_segments ~acc:[ i ] h ls in + match i with + | [] | [ _ ] -> assert false + | segments -> P.Inode_extender { length; segments; proof = h })) + | _ -> inode + + let post_processing singleton_inodes (stream : (hash * P.elt) list) : + P.elt list = + let skips = Hashes.create 13 in + (* [skips] are the elements of the [stream] that are included in the + extenders, they will be removed from the final stream. *) + let rec aux rev_elts = function + | [] -> List.rev rev_elts + | (h, elt) :: rest -> + if Hashes.mem skips h then aux rev_elts rest + else + let elt' : P.elt = + match (elt : P.elt) with + | P.Inode { length; proofs } -> + apply_extenders ~length singleton_inodes skips proofs + | Node ls -> Node ls + | Contents c -> Contents c + | Inode_extender _ -> assert false + in + aux (elt' :: rev_elts) rest + in + aux [] stream + + let to_stream t = + match !t with + | Stream (Produce { rev_elts; singleton_inodes; _ }) -> + List.rev !rev_elts |> post_processing singleton_inodes |> List.to_seq + | _ -> assert false + + let is_empty_stream t = + match !t with + | Stream (Consume { stream; _ }) -> ( + (* Peek the sequence but do not advance the ref *) + match !stream () with Seq.Nil -> true | _ -> false) + | _ -> false + + let set_mode t (kind : kind) mode = + match kind with + | Set -> ( + match (!t, mode) with + | Empty, Produce -> t := Set Set.(producer ()) + | Empty, Deserialise -> t := Set Set.(deserialiser ()) + | Set (Produce set), Serialise -> t := Set Set.(Serialise set) + | Set (Deserialise set), Consume -> t := Set Set.(Consume set) + | _ -> assert false) + | Stream -> ( + match (!t, mode) with + | Empty, Produce -> t := Stream (Stream.producer ()) + | _ -> assert false) + + let with_set_consume f = + let t = ref Empty in + set_mode t Set Deserialise; + let stop_deserialise () = set_mode t Set Consume in + let+ res = f t ~stop_deserialise in + t := Empty; + res + + let with_set_produce f = + let t = ref Empty in + set_mode t Set Produce; + let start_serialise () = set_mode t Set Serialise in + let+ res = f t ~start_serialise in + t := Empty; + res + + let with_stream_produce f = + let t = ref Empty in + set_mode t Stream Produce; + let to_stream () = to_stream t in + let+ res = f t ~to_stream in + t := Empty; + res + + let with_stream_consume stream f = + let t = Stream (Stream.consumer stream) |> ref in + let is_empty () = is_empty_stream t in + let+ res = f t ~is_empty in + t := Empty; + res + + module Contents_hash = Hash.Typed (H) (B.Contents.Val) + + let check_contents_integrity v h = + let h' = Contents_hash.hash v in + if not (equal_hash h' h) then + bad_stream_exn_fmt "check_contents_integrity" "got %a expected %a" pp_hash + h' pp_hash h + + let check_node_integrity v h = + let h' = + try B.Node_portable.hash_exn ~force:false v + with Not_found -> + (* [v] is out of [of_proof], it is supposed to have its hash available + without IOs. + + If these IOs were to occur, it would corrupt the stream being read. + *) + assert false + in + if not (equal_hash h' h) then + bad_stream_exn_fmt "check_node_integrity" "got %a expected %a" pp_hash h' + pp_hash h + + let dehydrate_stream_node v = + (* [v] is fresh out of the node store, meaning that if it is represented + recursively it is still in a shallow state. + + [head v] might trigger IOs. It is fine because [v] is already wrapped + with [with_handler]. *) + match B.Node.Val.head v with + | `Node l -> + let l = + List.map + (function + | step, `Contents (k, m) -> + (step, `Contents (B.Contents.Key.to_hash k, m)) + | step, `Node k -> (step, `Node (B.Node.Key.to_hash k))) + l + in + P.Node l + | `Inode (length, proofs) -> P.Inode { length; proofs } + + let rehydrate_stream_node ~depth (elt : P.elt) h = + let bad_stream_exn_fmt = bad_stream_exn_fmt "rehydrate_stream_node" in + match elt with + | Contents _ -> + bad_stream_exn_fmt + "found contents at depth %d when looking for node with hash %a" depth + pp_hash h + | Node l -> ( + match B.Node_portable.of_proof ~depth (`Values l) with + | Some v -> v + | None -> + bad_stream_exn_fmt + "could not deserialise Node at depth %d when looking for hash %a" + depth pp_hash h) + | Inode { length; proofs } -> + let proofs = List.map (fun (i, h) -> (i, `Blinded h)) proofs in + let inode = `Inode (length, proofs) in + let v = + match B.Node_portable.of_proof ~depth inode with + | Some v -> v + | None -> + bad_stream_exn_fmt + "could not deserialise Inode at depth %d when looking for hash \ + %a" + depth pp_hash h + in + v + | Inode_extender { length; segments; proof } -> + let elt = + List.fold_left + (fun acc i -> `Inode (length, [ (i, acc) ])) + (`Blinded proof) (List.rev segments) + in + let v = + match B.Node_portable.of_proof ~depth elt with + | Some v -> v + | None -> + bad_stream_exn_fmt + "could not deserialise Inode at depth %d when looking for hash \ + %a" + depth pp_hash h + in + v + + let rehydrate_stream_contents (elt : P.elt) h = + let err k = + bad_stream_exn_fmt "find_contents" + "found %s when looking Contents with hash %a" k pp_hash h + in + match elt with + | Node _ -> err "Node" + | Inode _ -> err "Inode" + | Inode_extender _ -> err "Inode" + | Contents v -> v + + let find_contents t h = + match !t with + | Empty -> None + | Set (Produce set) -> + (* Sharing of contents is not strictly needed during this phase. It + could be disabled. *) + Hashes.find_opt set.contents h + | Set (Serialise set) -> + (* This is needed in order to differenciate between blinded contents + from others. *) + Hashes.find_opt set.contents h + | Set (Deserialise _) -> + (* This phase only fills the env, it should search for anything *) + assert false + | Set (Consume set) -> + (* Use the Env to feed the values during consume *) + Hashes.find_opt set.contents h + | Stream (Produce _) -> + (* There is no need for sharing with stream proofs *) + None + | Stream (Consume { contents; stream; _ }) -> ( + (* Use the Env to feed the values during consume *) + match Hashes.find_opt contents h with + | Some v -> Some v + | None -> ( + match !stream () with + | Seq.Nil -> + bad_stream_too_short_fmt "find_contents" + "empty stream when looking for hash %a" pp_hash h + | Cons (elt, rest) -> + let v = rehydrate_stream_contents elt h in + check_contents_integrity v h; + stream := rest; + Hashes.add contents h v; + Some v)) + + let add_contents_from_store t h v = + match !t with + | Empty -> () + | Set (Produce set) -> + (* Registering in [set] for traversal during [Serialise]. *) + assert (not (Hashes.mem set.contents h)); + Hashes.add set.contents h v + | Set (Serialise _) -> + (* There shouldn't be new contents during this phase *) + assert false + | Set (Deserialise _) -> + (* This phase has no repo pointer *) + assert false + | Set (Consume _) -> + (* This phase has no repo pointer *) + assert false + | Stream (Produce ({ set; _ } as cache)) -> + (* Registering when seen for the first time *) + if not @@ Hashes.mem set h then ( + Hashes.add set h (); + let h_elt : hash * P.elt = (h, Contents v) in + Stream.push cache h_elt 0) + | Stream (Consume _) -> + (* This phase has no repo pointer *) + assert false + + let add_contents_from_proof t h v = + match !t with + | Set (Deserialise set) -> + (* Using [replace] because there could be several instances of this + contents in the proof, we will not share as this is not strictly + needed. *) + Hashes.replace set.contents h v + | Empty -> + (* Happens during [hash_of_proof_state] *) + () + | _ -> assert false + + let find_node t h = + match !t with + | Empty -> None + | Set (Produce set) -> + (* This is needed in order to achieve sharing on inode's pointers. In + other words, each node present in the [before] tree should have a + single [P.Node.Val.t] representative that will witness all the lazy + inode loadings. *) + Hashes.find_opt set.nodes h + | Set (Serialise set) -> + (* This is needed in order to follow loaded paths in the [before] + tree. *) + Hashes.find_opt set.nodes h + | Set (Deserialise _) -> + (* This phase only fills the env, it should search for anything *) + assert false + | Set (Consume _) -> + (* This phase looks for portable nodes *) + None + | Stream (Produce _) -> + (* There is no need for sharing with stream proofs *) + None + | Stream (Consume _) -> + (* This phase looks for portable nodes *) + None + + let find_recpnode t _find ~expected_depth h = + assert (expected_depth > 0); + match !t with + | Stream (Consume { nodes; stream; _ }) -> ( + (* Use the Env to feed the values during consume *) + match Hashes.find_opt nodes h with + | Some v -> Some v + | None -> ( + match !stream () with + | Seq.Nil -> + bad_stream_too_short_fmt "find_recnode" + "empty stream when looking for hash %a" pp_hash h + | Cons (v, rest) -> + let v = rehydrate_stream_node ~depth:expected_depth v h in + (* There is no need to apply [with_handler] here because there + is no repo pointer in this inode. *) + check_node_integrity v h; + stream := rest; + Hashes.add nodes h v; + Some v)) + | _ -> assert false + + let find_pnode t h = + match !t with + | Set (Consume set) -> + (* [set] has been filled during deserialise. Using it to provide values + during consume. *) + Hashes.find_opt set.nodes h + | Stream (Consume { nodes; stream; _ }) -> ( + (* Use the Env to provide the values during consume. Since all hashes + are unique in [stream], [nodes] provides a hash-based sharing. *) + match Hashes.find_opt nodes h with + | Some v -> Some v + | None -> ( + match !stream () with + | Seq.Nil -> + bad_stream_too_short_fmt "find_node" + "empty stream when looking for hash %a" pp_hash h + | Cons (v, rest) -> + (* Shorten [stream] before calling [head] as it might itself + perform reads. *) + stream := rest; + let v = + (* [depth] is 0 because this context deals with root nodes *) + rehydrate_stream_node ~depth:0 v h + in + let v = + (* Call [with_handler] before [head] because the later might + perform reads *) + B.Node_portable.with_handler (find_recpnode t) v + in + let (_ : [ `Node of _ | `Inode of _ ]) = + (* At produce time [dehydrate_stream_node] called [head] which + might have performed IOs. If it did then we must consume + the stream accordingly right now in order to preserve + stream ordering. *) + B.Node_portable.head v + in + check_node_integrity v h; + Hashes.add nodes h v; + + Some v)) + | _ -> None + + let add_recnode_from_store t find ~expected_depth k = + assert (expected_depth > 0); + match !t with + | Stream (Produce ({ set; singleton_inodes; _ } as cache)) -> ( + (* Registering when seen for the first time, there is no need + for sharing. *) + match find ~expected_depth k with + | None -> None + | Some v -> + let h = B.Node.Key.to_hash k in + if not @@ Hashes.mem set h then ( + Hashes.add set h (); + let elt = dehydrate_stream_node v in + let () = + match elt with + | P.Inode { proofs = [ bucket ]; _ } -> + Hashes.add singleton_inodes h bucket + | _ -> () + in + Stream.push cache (h, elt) 0); + Some v) + | _ -> assert false + + let add_node_from_store t h v = + match !t with + | Empty -> v + | Set (Produce set) -> + (* Registering in [set] for sharing during [Produce] and traversal + during [Serialise]. This assertion is guarenteed because + [add_node_from_store] is guarded by a call to [find_node] in tree. *) + assert (not (Hashes.mem set.nodes h)); + Hashes.add set.nodes h v; + v + | Set (Serialise _) -> + (* There shouldn't be new nodes during this phase *) + assert false + | Set (Deserialise _) -> + (* This phase has no repo pointer *) + assert false + | Set (Consume _) -> + (* This phase has no repo pointer *) + assert false + | Stream (Produce ({ set; rev_elts_size; singleton_inodes; _ } as cache)) -> + (* Registering when seen for the first time and wrap its [find] + function. Since there is no sharing during the production of + streamed proofs, the hash may already have been seened. *) + let new_hash = not @@ Hashes.mem set h in + let v = + (* In all case [v] should be wrapped. + If [not new_hash] then wrap it for future IOs on it. + + If [new_hash] then it additionally should be wrapped before + calling [dehydrate_stream_node] as this call may trigger IOs. *) + B.Node.Val.with_handler (add_recnode_from_store t) v + in + if new_hash then ( + Hashes.add set h (); + let len0 = !rev_elts_size in + let elt = dehydrate_stream_node v in + let len1 = !rev_elts_size in + let delta = + (* [delta] is the number of reads that were performed by + [dehydrate_stream_node]. *) + len1 - len0 + in + let () = + match elt with + | P.Inode { proofs = [ bucket ]; _ } -> + Hashes.add singleton_inodes h bucket + | _ -> () + in + (* if [delta = 0] then push the pair at the head of the list. + + if [delta > 0] then insert it before the calls that it triggered. *) + Stream.push cache (h, elt) delta); + v + | Stream (Consume _) -> + (* This phase has no repo pointer *) + assert false + + let add_pnode_from_proof t h v = + match !t with + | Set (Deserialise set) -> + (* Using [replace] because there could be several instances of this + node in the proof, we will not share as this is not strictly + needed. + All the occurences of this node in the proof are expected to have + the same blinded/visible coverage (i.e. the same node proof). *) + Hashes.replace set.nodes h v + | Empty -> + (* Happens during [hash_of_proof_state] *) + () + | _ -> assert false +end diff --git a/vendors/irmin/src/irmin/proof.mli b/vendors/irmin/src/irmin/proof.mli new file mode 100644 index 000000000000..d2f22b543f18 --- /dev/null +++ b/vendors/irmin/src/irmin/proof.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Proof_intf.Proof diff --git a/vendors/irmin/src/irmin/proof_intf.ml b/vendors/irmin/src/irmin/proof_intf.ml new file mode 100644 index 000000000000..13858a798181 --- /dev/null +++ b/vendors/irmin/src/irmin/proof_intf.ml @@ -0,0 +1,357 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** Proofs are compact representations of trees which can be shared between + peers. + + This is expected to be used as follows: + + - A first peer runs a function [f] over a tree [t]. While performing this + computation, it records: the hash of [t] (called [before] below), the + hash of [f t] (called [after] below) and a subset of [t] which is needed + to replay [f] without any access to the first peer's storage. Once done, + all these informations are packed into a proof of type [t] that is sent + to the second peer. + + - The second peer generates an initial tree [t'] from [p] and computes + [f t']. Once done, it compares [t']'s hash and [f t']'s hash to [before] + and [after]. If they match, they know that the result state [f t'] is a + valid context state, without having to have access to the full storage + of the first peer. *) + + type contents + type hash + type step + type metadata + + type kinded_hash = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin] + + type 'a inode = { length : int; proofs : (int * 'a) list } [@@deriving irmin] + (** The type for (internal) inode proofs. + + These proofs encode large directories into a tree-like structure. + + Invariants are dependent on the backend. + + [length] is the total number of entries in the children of the inode. It's + the size of the "flattened" version of that inode. [length] can be used to + prove the correctness of operations such as [Tree.length] and + [Tree.list ~offset ~length] in an efficient way. + + [proofs] contains the children proofs. It is a sparse list of ['a] values. + These values are associated to their index in the list, and the list is + kept sorted in increasing order of indices. ['a] can be a concrete proof + or a hash of that proof. + + {e For [irmin-pack]}: [proofs] have a length of at most [Conf.entries] + entries. For binary trees, this boolean index is a step of the left-right + sequence / decision proof corresponding to the path in that binary tree. *) + + type 'a inode_extender = { length : int; segments : int list; proof : 'a } + [@@deriving irmin] + (** The type for inode extenders. + + An extender is a compact representation of a sequence of [inode] which + contain only one child. As for inodes, the ['a] parameter can be a + concrete proof or a hash of that proof. + + If an inode proof contains singleton children [i_0, ..., i_n] such as: + [{length=l; proofs = \[ (i_0, {proofs = ... { proofs = \[ (i_n, p) \] }})\]}], + then it is compressed into the inode extender + [{length=l; segment = \[i_0;..;i_n\]; proof=p}] sharing the same length + [l] and final proof [p]. *) + + (** The type for compressed and partial Merkle tree proofs. + + Tree proofs do not provide any guarantee with the ordering of + computations. For instance, if two effects commute, they won't be + distinguishable by this kind of proof. + + [Value v] proves that a value [v] exists in the store. + + [Blinded_value h] proves a value with hash [h] exists in the store. + + [Node ls] proves that a a "flat" node containing the list of files [ls] + exists in the store. {e For [irmin-pack]}: the length of [ls] is at most + [Conf.stable_hash]; + + [Blinded_node h] proves that a node with hash [h] exists in the store. + + [Inode i] proves that an inode [i] exists in the store. + + [Extender e] proves that an inode extender [e] exist in the store. *) + type tree = + | Contents of contents * metadata + | Blinded_contents of hash * metadata + | Node of (step * tree) list + | Blinded_node of hash + | Inode of inode_tree inode + | Extender of inode_tree inode_extender + [@@deriving irmin] + + (** The type for inode trees. It is a subset of [tree], limited to nodes. + + [Blinded_inode h] proves that an inode with hash [h] exists in the store. + + [Inode_values ls] is simliar to trees' [Node]. + + [Inode_tree i] is similar to tree's [Inode]. + + [Inode_extender e] is similar to trees' [Extender]. *) + and inode_tree = + | Blinded_inode of hash + | Inode_values of (step * tree) list + | Inode_tree of inode_tree inode + | Inode_extender of inode_tree inode_extender + [@@deriving irmin] + + (** Stream proofs represent an explicit traversal of a Merle tree proof. Every + element (a node, a value, or a shallow pointer) met is first "compressed" + by shallowing its children and then recorded in the proof. + + As stream proofs directly encode the recursive construction of the Merkle + root hash is slightly simpler to implement: the verifier simply needs to + hash the compressed elements lazily, without any memory or choice. + + Moreover, the minimality of stream proofs is trivial to check. Once the + computation has consumed the compressed elements required, it is + sufficient to check that no more compressed elements remain in the proof. + + However, as the compressed elements contain all the hashes of their + shallow children, the size of stream proofs is larger (at least double in + size in practice) than tree proofs, which only contains the hash for + intermediate shallow pointers. *) + + (** The type for elements of stream proofs. + + [Value v] is a proof that the next element read in the store is the value + [v]. + + [Node n] is a proof that the next element read in the store is the node + [n]. + + [Inode i] is a proof that the next element read in the store is the inode + [i]. + + [Inode_extender e] is a proof that the next element read in the store is + the node extender [e]. *) + type elt = + | Contents of contents + | Node of (step * kinded_hash) list + | Inode of hash inode + | Inode_extender of hash inode_extender + [@@deriving irmin] + + type stream = elt Seq.t [@@deriving irmin] + (** The type for stream proofs. + + The sequance [e_1 ... e_n] proves that the [e_1], ..., [e_n] are read in + the store in sequence. *) + + type 'a t [@@deriving irmin] + (** The type for proofs of kind ['a] (i.e. [stream] or [proof]). + + A proof [p] proves that the state advanced from [before p] to [after p]. + [state p]'s hash is [before p], and [state p] contains the minimal + information for the computation to reach [after p]. *) + + val v : before:kinded_hash -> after:kinded_hash -> 'a -> 'a t + (** [v ~before ~after p] proves that the state advanced from [before] to + [after]. [p]'s hash is [before], and [p] contains the minimal information + for the computation to reach [after]. *) + + val before : 'a t -> kinded_hash + (** [before t] it the state's hash at the beginning of the computation. *) + + val after : 'a t -> kinded_hash + (** [after t] is the state's hash at the end of the computation. *) + + val state : 'a t -> 'a + (** [proof t] is a subset of the initial state needed to prove that the proven + computation could run without performing any I/O. *) +end + +(** Environment that tracks side effects during the production/consumption of + proofs. + + {1 The Merkle Proof Construction Algorithm} + + This description stands for [Set] proofs and assumes that the large nodes + are represented by the backend as a tree structure (i.e. inodes). + + There are 4 distinct phases when working with Irmin's merkle proofs: + [Produce | Serialise | Deserialise | Consume]. + + {2 [Produce]} + + This phase runs the [f] function provided by the Irmin user. It builds an + [after] tree from a [before] tree that has been setup with an [Env] that + records every backend reads into two hash tables. + + During the next phase (i.e. [Serialise]) the cleared [before] tree will be + traversed from root to stems only following the paths that are referenced in + [Env]. + + In practice [Env] doesn't exactly record the reads, it keeps track of all + the [hash -> backend node] and [hash -> backend contents] mappings that are + directly output of the backend stores through [P.Node.find] and + [P.Contents.find]. This is obviously enough to remember the contents, the + nodes and the inodes tips, but the inner inodes are not directly referenced + in the hash tables. + + The inner inodes are in fact referenced in their inode tip which is itself + referenced in [Env]'s hash tables. Since an inode shares its lazy pointers + with the inodes derived from it, even the inner inodes that are loaded from + the derived tips will be available from the original inode tip. + + {2 [Serialise]} + + In this phase, the [Env] contains everything necessary for the computation + of a Merkle proof from a cleared [before]. The [Env] now affects + [Node.cached_value] and [Contents.cached_value] allowing for the discovery + of the cached closure. + + {2 [Deserialise]} + + In this phase the [Env] is filled by recursively destructing the proof and + filling it before the [Consume] phase. + + {2 [Consume]} + + In this last phase the [Env] is again made accessible through + [Node.cached_pvalue] and [Contents.cached_pvalue], making it possible for + the user to reference by [hash] everything that was contained in the proof. + + {1 Nodes and Portable Nodes} + + While the [Produce] phase must be connected to the backend to records reads, + the [Consume] phase must be disconnected from the backend. + + [Produce] manipulates backend nodes of type [Backend.Node.Val.t] (the ones + enriched with backend keys) + + [Consume] is restricted to manipulating nodes of type + [Backend.Node_portable.t]. + + {1 Hashing of Backend Nodes with Streamed Proofs} + + Hashing a backend node or calling [head] on it may trigger IOs in order to + load inner inodes (this is the case in irmin-pack). + + In various places, [Env] requires calling [head] or [hash_exn] on nodes. + + [Env] must be very careful that these two facts do not lead to chaos during + the recording of IOs' order. + + Two tricks are in place to prevent problems: + + - The [Node.of_proof] functions return nodes that don't require IOs to + produce their hash (i.e. they use caching if necessary). + - The [Node.head] function that is called on a node during + [dehydrate_stream_node] is also called just after [rehydrate_stream_node]. *) +module type Env = sig + type kind = Set | Stream + type mode = Produce | Serialise | Deserialise | Consume + type t [@@deriving irmin] + type hash + type node + type pnode + type contents + type stream + + val is_empty : t -> bool + val empty : unit -> t + val copy : into:t -> t -> unit + + (** {2 Modes} *) + + val set_mode : t -> kind -> mode -> unit + + val with_set_produce : + (t -> start_serialise:(unit -> unit) -> 'a Lwt.t) -> 'a Lwt.t + + val with_set_consume : + (t -> stop_deserialise:(unit -> unit) -> 'a Lwt.t) -> 'a Lwt.t + + val with_stream_produce : + (t -> to_stream:(unit -> stream) -> 'a Lwt.t) -> 'a Lwt.t + + val with_stream_consume : + stream -> (t -> is_empty:(unit -> bool) -> 'a Lwt.t) -> 'a Lwt.t + + (** {2 Interactions With [Tree]} *) + + val add_contents_from_store : t -> hash -> contents -> unit + + val add_node_from_store : t -> hash -> node -> node + (** [add_node_from_store] returns a [node] and not [unit] because [Env] may + take the opportunity to wrap the input node in [Node.Val.with_handler]. *) + + val add_contents_from_proof : t -> hash -> contents -> unit + val add_pnode_from_proof : t -> hash -> pnode -> unit + val find_contents : t -> hash -> contents option + val find_node : t -> hash -> node option + val find_pnode : t -> hash -> pnode option +end + +module type Proof = sig + module type S = S + module type Env = Env + + exception Bad_proof of { context : string } + + type bad_stream_exn = + | Stream_too_long of { context : string; reason : string } + | Stream_too_short of { context : string; reason : string } + | Proof_mismatch of { context : string; reason : string } + + exception Bad_stream of bad_stream_exn + + val bad_proof_exn : string -> 'a + val bad_stream_exn : string -> string -> 'a + val bad_stream_too_long : string -> string -> 'a + val bad_stream_too_short : string -> string -> 'a + + module Make + (C : Type.S) + (H : Hash.S) (P : sig + type step [@@deriving irmin] + end) + (M : Type.S) : sig + include + S + with type contents := C.t + and type hash := H.t + and type step := P.step + and type metadata := M.t + end + + module Env + (B : Backend.S) + (P : S + with type contents := B.Contents.Val.t + and type hash := B.Hash.t + and type step := B.Node.Val.step + and type metadata := B.Node.Val.metadata) : + Env + with type hash := B.Hash.t + and type contents := B.Contents.Val.t + and type node := B.Node.Val.t + and type pnode := B.Node_portable.t + and type stream := P.stream +end diff --git a/vendors/irmin/src/irmin/read_only.ml b/vendors/irmin/src/irmin/read_only.ml new file mode 100644 index 000000000000..95cc3d33a052 --- /dev/null +++ b/vendors/irmin/src/irmin/read_only.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Read_only_intf diff --git a/vendors/irmin/src/irmin/read_only.mli b/vendors/irmin/src/irmin/read_only.mli new file mode 100644 index 000000000000..0096f050cf63 --- /dev/null +++ b/vendors/irmin/src/irmin/read_only.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Read_only_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/read_only_intf.ml b/vendors/irmin/src/irmin/read_only_intf.ml new file mode 100644 index 000000000000..6191822305fd --- /dev/null +++ b/vendors/irmin/src/irmin/read_only_intf.ml @@ -0,0 +1,57 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +open Store_properties + +module type S = sig + (** {1 Read-only stores} + + Read-only stores are store where it is only possible to read existing + values. *) + + type -'a t + (** The type for stores. The ['a] phantom type carries information about the + store mutability. *) + + type key + (** The type for keys. *) + + type value + (** The type for raw values. *) + + val mem : [> read ] t -> key -> bool Lwt.t + (** [mem t k] is true iff [k] is present in [t]. *) + + val find : [> read ] t -> key -> value option Lwt.t + (** [find t k] is [Some v] if [k] is associated to [v] in [t] and [None] is + [k] is not present in [t]. *) + + include Closeable with type 'a t := 'a t + (** @inline *) +end + +module type Maker = functor (Key : Type.S) (Value : Type.S) -> sig + include S with type key = Key.t and type value = Value.t + + include Of_config with type 'a t := 'a t + (** @inline *) +end + +module type Sigs = sig + module type S = S + module type Maker = Maker +end diff --git a/vendors/irmin/src/irmin/remote.ml b/vendors/irmin/src/irmin/remote.ml new file mode 100644 index 000000000000..b4d2247985d8 --- /dev/null +++ b/vendors/irmin/src/irmin/remote.ml @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Remote_intf + +module None (H : Type.S) (R : Type.S) = struct + type t = unit + + let v _ = Lwt.return_unit + + type endpoint = unit + type commit = H.t + type branch = R.t + + let fetch () ?depth:_ _ _br = + Lwt.return (Error (`Msg "fetch operation is not available")) + + let push () ?depth:_ _ _br = + Lwt.return (Error (`Msg "push operation is not available")) +end diff --git a/vendors/irmin/src/irmin/remote.mli b/vendors/irmin/src/irmin/remote.mli new file mode 100644 index 000000000000..847535554664 --- /dev/null +++ b/vendors/irmin/src/irmin/remote.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Remote stores. *) + +include Remote_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/remote_intf.ml b/vendors/irmin/src/irmin/remote_intf.ml new file mode 100644 index 000000000000..4237c9a05868 --- /dev/null +++ b/vendors/irmin/src/irmin/remote_intf.ml @@ -0,0 +1,69 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type t = .. + +module type S = sig + (** {1 Remote synchronization} *) + + type t + (** The type for store handles. *) + + type commit + (** The type for store heads. *) + + type branch + (** The type for branch IDs. *) + + type endpoint + (** The type for sync endpoints. *) + + val fetch : + t -> + ?depth:int -> + endpoint -> + branch -> + (commit option, [ `Msg of string ]) result Lwt.t + (** [fetch t uri] fetches the contents of the remote store located at [uri] + into the local store [t]. Return the head of the remote branch with the + same name, which is now in the local store. [No_head] means no such branch + exists. *) + + val push : + t -> + ?depth:int -> + endpoint -> + branch -> + (unit, [ `Msg of string | `Detached_head ]) result Lwt.t + (** [push t uri] pushes the contents of the local store [t] into the remote + store located at [uri]. *) +end + +module type Sigs = sig + module type S = S + + type nonrec t = t = .. + + (** Provides stub implementations of the {!S} that always returns [Error] when + push/pull operations are attempted. *) + module None (H : Type.S) (R : Type.S) : sig + include + S with type commit = H.t and type branch = R.t and type endpoint = unit + + val v : 'a -> t Lwt.t + (** Create a remote store handle. *) + end +end diff --git a/vendors/irmin/src/irmin/reversed_list.ml b/vendors/irmin/src/irmin/reversed_list.ml new file mode 100644 index 000000000000..18d852311837 --- /dev/null +++ b/vendors/irmin/src/irmin/reversed_list.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type 'a t = 'a list = [] | ( :: ) of 'a * 'a t + +let t a_t = Type.list a_t +let rev = List.rev diff --git a/vendors/irmin/src/irmin/reversed_list.mli b/vendors/irmin/src/irmin/reversed_list.mli new file mode 100644 index 000000000000..9eb8aeba7caf --- /dev/null +++ b/vendors/irmin/src/irmin/reversed_list.mli @@ -0,0 +1,25 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Reversed_list.t] is constructed the same way as [List.t], but needs to be + reversed before it can be used as a regular list. + + This is helpful when building up a list in reverse in order to force + reversal at the end of the accumulation process. *) + +type 'a t = [] | ( :: ) of 'a * 'a t [@@deriving irmin] + +val rev : 'a t -> 'a list diff --git a/vendors/irmin/src/irmin/schema.ml b/vendors/irmin/src/irmin/schema.ml new file mode 100644 index 000000000000..6b4c178a570c --- /dev/null +++ b/vendors/irmin/src/irmin/schema.ml @@ -0,0 +1,73 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2020-2021 Craig Ferguson + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + module Hash : Hash.S + module Branch : Branch.S + module Info : Info.S + module Metadata : Metadata.S + module Path : Path.S + module Contents : Contents.S +end + +module type Extended = sig + include S + + module Node + (Contents_key : Key.S with type hash = Hash.t) + (Node_key : Key.S with type hash = Hash.t) : + Node.Generic_key.S + with type metadata = Metadata.t + and type step = Path.step + and type hash = Hash.t + and type contents_key = Contents_key.t + and type node_key = Node_key.t + + module Commit + (Node_key : Key.S with type hash = Hash.t) + (Commit_key : Key.S with type hash = Hash.t) : + Commit.Generic_key.S + with module Info := Info + and type node_key = Node_key.t + and type commit_key = Commit_key.t +end + +open struct + module Extended_is_a_schema (X : Extended) : S = X +end + +type default_hash = Hash.BLAKE2B.t + +module type KV = + Extended + with type Hash.t = default_hash + and type Branch.t = string + and type Info.t = Info.default + and type Metadata.t = unit + and type Path.step = string + and type Path.t = string list + +module KV (C : Contents.S) : KV with module Contents = C = struct + module Hash = Hash.BLAKE2B + module Info = Info.Default + module Branch = Branch.String + module Path = Path.String_list + module Metadata = Metadata.None + module Contents = C + module Node = Node.Generic_key.Make (Hash) (Path) (Metadata) + module Commit = Commit.Generic_key.Make (Hash) +end diff --git a/vendors/irmin/src/irmin/slice.ml b/vendors/irmin/src/irmin/slice.ml new file mode 100644 index 000000000000..9f3e7580a8af --- /dev/null +++ b/vendors/irmin/src/irmin/slice.ml @@ -0,0 +1,58 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Slice_intf + +module Make + (Contents : Contents.Store) + (Node : Node.Store) + (Commit : Commit.Store) = +struct + type contents = Contents.Hash.t * Contents.Val.t [@@deriving irmin] + type node = Node.Hash.t * Node.Val.t [@@deriving irmin] + type commit = Commit.Hash.t * Commit.Val.t [@@deriving irmin] + + type value = [ `Contents of contents | `Node of node | `Commit of commit ] + [@@deriving irmin] + + type t = { + mutable contents : contents list; + mutable nodes : node list; + mutable commits : commit list; + } + [@@deriving irmin] + + let empty () = Lwt.return { contents = []; nodes = []; commits = [] } + + let add t = function + | `Contents c -> + t.contents <- c :: t.contents; + Lwt.return_unit + | `Node n -> + t.nodes <- n :: t.nodes; + Lwt.return_unit + | `Commit c -> + t.commits <- c :: t.commits; + Lwt.return_unit + + let iter t f = + Lwt.join + [ + Lwt_list.iter_p (fun c -> f (`Contents c)) t.contents; + Lwt_list.iter_p (fun n -> f (`Node n)) t.nodes; + Lwt_list.iter_p (fun c -> f (`Commit c)) t.commits; + ] +end diff --git a/vendors/irmin/src/irmin/slice.mli b/vendors/irmin/src/irmin/slice.mli new file mode 100644 index 000000000000..2d673d627559 --- /dev/null +++ b/vendors/irmin/src/irmin/slice.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Slice_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/slice_intf.ml b/vendors/irmin/src/irmin/slice_intf.ml new file mode 100644 index 000000000000..fc71483f350d --- /dev/null +++ b/vendors/irmin/src/irmin/slice_intf.ml @@ -0,0 +1,56 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** {1 Slices} *) + + type t [@@deriving irmin] + (** The type for slices. *) + + type contents [@@deriving irmin] + (** The type for exported contents. *) + + type node [@@deriving irmin] + (** The type for exported nodes. *) + + type commit [@@deriving irmin] + (** The type for exported commits. *) + + type value = [ `Contents of contents | `Node of node | `Commit of commit ] + [@@deriving irmin] + (** The type for exported values. *) + + val empty : unit -> t Lwt.t + (** Create a new empty slice. *) + + val add : t -> value -> unit Lwt.t + (** [add t v] adds [v] to [t]. *) + + val iter : t -> (value -> unit Lwt.t) -> unit Lwt.t + (** [iter t f] calls [f] on all values of [t]. *) +end + +module type Sigs = sig + module type S = S + (** The signature for slices. *) + + (** Build simple slices. *) + module Make (C : Contents.Store) (N : Node.Store) (H : Commit.Store) : + S + with type contents = C.hash * C.value + and type node = N.hash * N.value + and type commit = H.hash * H.value +end diff --git a/vendors/irmin/src/irmin/storage.ml b/vendors/irmin/src/irmin/storage.ml new file mode 100644 index 000000000000..037d7ddb3b11 --- /dev/null +++ b/vendors/irmin/src/irmin/storage.ml @@ -0,0 +1,146 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import +include Storage_intf + +module Read_only (M : Make) = +functor + (K : Type.S) + (V : Type.S) + -> + struct + module S = M (K) (V) + + type 'a t = S.t + type key = S.key + type value = S.value + + let v = S.v + let mem = S.mem + let find = S.find + let close = S.close + end + +module Content_addressable (M : Make) : Content_addressable.Maker = +functor + (H : Hash.S) + (V : Type.S) + -> + struct + include Read_only (M) (H) (V) + module H = Hash.Typed (H) (V) + + let batch = S.batch + + let add t value = + let key = H.hash value in + let+ () = S.set t key value in + key + + let equal_hash = Type.(equal H.t |> unstage) + let pp_hash = Type.(pp H.t) + + let unsafe_add t k v = + let+ hash' = add t v in + if equal_hash k hash' then () + else + Fmt.failwith + "[unsafe_append] %a is not a valid key. Expecting %a instead.\n" + pp_hash k pp_hash hash' + end + +module Append_only (M : Make) : Append_only.Maker = +functor + (Key : Type.S) + (Value : Type.S) + -> + struct + include Read_only (M) (Key) (Value) + + let batch = S.batch + let add = S.set + end + +module Atomic_write (M : Make) : Atomic_write.Maker = +functor + (Key : Type.S) + (Value : Type.S) + -> + struct + module S = M (Key) (Value) + module W = Watch.Make (Key) (Value) + module L = Lock.Make (Key) + + type t = { t : S.t; w : W.t; l : L.t } + type key = S.key + type value = S.value + type watch = W.watch + + let watches = W.v () + let lock = L.v () + + let v config = + let* t = S.v config in + Lwt.return { t; w = watches; l = lock } + + let find { t; _ } = S.find t + let mem { t; _ } = S.mem t + + module Internal = struct + let set t w key value = + let* () = S.set t key value in + W.notify w key (Some value) + + let remove t w key = + let* () = S.remove t key in + W.notify w key None + end + + let list { t; _ } = S.keys t + + let set { t; l; w } key value = + L.with_lock l key @@ fun () -> Internal.set t w key value + + let remove { t; l; w } key = + L.with_lock l key @@ fun () -> Internal.remove t w key + + let test_and_set = + let value_equal = Type.(unstage (equal (option Value.t))) in + fun { t; l; w } key ~test ~set:set_value -> + L.with_lock l key @@ fun () -> + let* v = S.find t key in + if value_equal v test then + let* () = + match set_value with + | Some set_value -> Internal.set t w key set_value + | None -> Internal.remove t w key + in + Lwt.return_true + else Lwt.return_false + + let watch_key { w; _ } key = W.watch_key w key + let watch { w; _ } = W.watch w + let unwatch { w; _ } = W.unwatch w + + let clear { t; w; _ } = + let* () = W.clear w in + S.clear t + + let close { t; w; _ } = + let* () = W.clear w in + S.close t + end diff --git a/vendors/irmin/src/irmin/storage.mli b/vendors/irmin/src/irmin/storage.mli new file mode 100644 index 000000000000..aa45644aba38 --- /dev/null +++ b/vendors/irmin/src/irmin/storage.mli @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Storage_intf.Sigs +(** @inline *) + +module Read_only (M : Make) : Read_only.Maker +module Content_addressable (M : Make) : Content_addressable.Maker +module Append_only (M : Make) : Append_only.Maker +module Atomic_write (M : Make) : Atomic_write.Maker diff --git a/vendors/irmin/src/irmin/storage_intf.ml b/vendors/irmin/src/irmin/storage_intf.ml new file mode 100644 index 000000000000..34486228e8ac --- /dev/null +++ b/vendors/irmin/src/irmin/storage_intf.ml @@ -0,0 +1,62 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + type t + type key + type value + + val v : Conf.t -> t Lwt.t + (** [v config] initialises a storage layer, with the configuration [config]. *) + + val mem : t -> key -> bool Lwt.t + (** [mem t k] is true iff [k] is present in [t]. *) + + val find : t -> key -> value option Lwt.t + (** [find t k] is [Some v] if [k] is associated to [v] in [t] and [None] is + [k] is not present in [t]. *) + + val keys : t -> key list Lwt.t + (** [keys t] it the list of keys in [t]. *) + + val set : t -> key -> value -> unit Lwt.t + (** [set t k v] sets the contents of [k] to [v] in [t]. *) + + val remove : t -> key -> unit Lwt.t + (** [remove t k] removes the key [k] in [t]. *) + + val batch : t -> (t -> 'a Lwt.t) -> 'a Lwt.t + (** [batch t f] applies the operations in [f] in a batch. The exact guarantees + depend on the implementation. *) + + val clear : t -> unit Lwt.t + (** [clear t] clears the storage. This operation is expected to be slow. *) + + val close : t -> unit Lwt.t + (** [close t] frees up all the resources associated with [t]. *) +end + +module type Make = functor (Key : Type.S) (Value : Type.S) -> + S with type key = Key.t and type value = Value.t + +module type Sigs = sig + module type S = S + (** [S] is a storage layer that can be used to build Irmin stores. *) + + module type Make = Make + (** [Make] parameterizes a storage layer over a key [Key] and a value [Value]. + This is the signature to implement when building custom storage for Irmin. *) +end diff --git a/vendors/irmin/src/irmin/store.ml b/vendors/irmin/src/irmin/store.ml new file mode 100644 index 000000000000..d2c500221483 --- /dev/null +++ b/vendors/irmin/src/irmin/store.ml @@ -0,0 +1,1292 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Store_intf +open Merge.Infix + +let src = Logs.Src.create "irmin" ~doc:"Irmin branch-consistent store" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Generic_key = struct + module type S = S_generic_key + module type KV = KV_generic_key + module type Maker = Maker_generic_key + module type KV_maker = KV_maker_generic_key +end + +module Make (B : Backend.S) = struct + module Schema = B.Schema + module Contents_key = B.Contents.Key + module Node_key = B.Node.Key + module Commit_key = B.Commit.Key + module Metadata = B.Node.Metadata + module Typed = Hash.Typed (B.Hash) + module Hash = B.Hash + module Branch_store = B.Branch + module Path = B.Node.Path + module Commits = Commit.History (B.Commit) + module Backend = B + module Info = B.Commit.Info + module T = Tree.Make (B) + + module Contents = struct + include B.Contents.Val + module H = Typed (B.Contents.Val) + + let of_key r k = B.Contents.find (B.Repo.contents_t r) k + + let of_hash r h = + let store = B.Repo.contents_t r in + B.Contents.index store h >>= function + | None -> Lwt.return_none + | Some k -> B.Contents.find store k + + let hash c = H.hash c + end + + module Tree = struct + include T + + let find_key r t = + match key t with + | Some k -> Lwt.return (Some k) + | None -> ( + match hash t with + | `Node h -> ( + B.Node.index (B.Repo.node_t r) h >|= function + | None -> None + | Some k -> Some (`Node k)) + | `Contents (h, m) -> ( + B.Contents.index (B.Repo.contents_t r) h >|= function + | None -> None + | Some k -> Some (`Contents (k, m)))) + + let of_key r k = import r k + + let of_hash r = function + | `Node h -> ( + B.Node.index (B.Repo.node_t r) h >>= function + | None -> Lwt.return_none + | Some k -> of_key r (`Node k)) + | `Contents (h, m) -> ( + B.Contents.index (B.Repo.contents_t r) h >>= function + | None -> Lwt.return_none + | Some k -> of_key r (`Contents (k, m))) + + let shallow r h = import_no_check r h + let kinded_hash = hash + + let hash : ?cache:bool -> t -> hash = + fun ?cache tr -> + match hash ?cache tr with `Node h -> h | `Contents (h, _) -> h + end + + type branch = Branch_store.Key.t [@@deriving irmin ~equal ~pp] + type contents_key = B.Contents.Key.t [@@deriving irmin ~pp ~equal] + type node_key = B.Node.Key.t [@@deriving irmin ~pp ~equal] + type commit_key = B.Commit.Key.t [@@deriving irmin ~pp ~equal] + type repo = B.Repo.t + type commit = { r : repo; key : commit_key; v : B.Commit.value } + type hash = Hash.t [@@deriving irmin ~equal ~pp ~compare] + type node = Tree.node [@@deriving irmin] + type contents = Contents.t [@@deriving irmin ~equal] + type metadata = Metadata.t [@@deriving irmin] + type tree = Tree.t [@@deriving irmin ~pp] + type path = Path.t [@@deriving irmin ~pp] + type step = Path.step [@@deriving irmin] + type info = B.Commit.Info.t [@@deriving irmin] + type Remote.t += E of B.Remote.endpoint + type lca_error = [ `Max_depth_reached | `Too_many_lcas ] [@@deriving irmin] + type ff_error = [ `Rejected | `No_change | lca_error ] + + type write_error = + [ Merge.conflict | `Too_many_retries of int | `Test_was of tree option ] + + (* The deriver does not work here because of it cannot derive the + [Merge.conflict] inheritance. *) + let write_error_t = + let open Type in + variant "write-error" (fun c m e -> function + | `Conflict x -> c x | `Too_many_retries x -> m x | `Test_was x -> e x) + |~ case1 "conflict" string (fun x -> `Conflict x) + |~ case1 "too-many-retries" int (fun x -> `Too_many_retries x) + |~ case1 "test-got" (option tree_t) (fun x -> `Test_was x) + |> sealv + + (* The deriver does not work here because of it cannot derive the + [lca_error] inheritance. *) + let ff_error_t = + Type.enum "ff-error" + [ + ("max-depth-reached", `Max_depth_reached); + ("too-many-lcas", `Too_many_lcas); + ("no-change", `No_change); + ("rejected", `Rejected); + ] + + let pp_int = Type.pp Type.int + let save_contents b c = B.Contents.add b c + + let save_tree ?(clear = true) r x y (tr : Tree.t) = + match Tree.destruct tr with + | `Contents (c, _) -> + let* c = Tree.Contents.force_exn c in + let+ k = save_contents x c in + `Contents k + | `Node n -> + let+ k = Tree.export ~clear r x y n in + `Node k + + module Contents_keys = Set.Make (struct + type t = Contents_key.t [@@deriving irmin ~compare] + end) + + module Commit = struct + type t = commit + + let t r = + let open Type in + record "commit" (fun key v -> { r; key; v }) + |+ field "key" B.Commit.Key.t (fun t -> t.key) + |+ field "value" B.Commit.Val.t (fun t -> t.v) + |> sealr + + let v ?(clear = true) r ~info ~parents tree = + B.Repo.batch r @@ fun contents_t node_t commit_t -> + let* node = + match Tree.destruct tree with + | `Node t -> Tree.export ~clear r contents_t node_t t + | `Contents _ -> Lwt.fail_invalid_arg "cannot add contents at the root" + in + let v = B.Commit.Val.v ~info ~node ~parents in + let+ key = B.Commit.add commit_t v in + { r; key; v } + + let node t = B.Commit.Val.node t.v + let tree t = Tree.import_no_check t.r (`Node (node t)) + let equal x y = equal_commit_key x.key y.key + let key t = t.key + let hash t = B.Commit.Key.to_hash t.key + let info t = B.Commit.Val.info t.v + let parents t = B.Commit.Val.parents t.v + let pp_hash ppf t = Type.pp Hash.t ppf (hash t) + let pp_key ppf t = Type.pp B.Commit.Key.t ppf t.key + + let of_key r key = + B.Commit.find (B.Repo.commit_t r) key >|= function + | None -> None + | Some v -> Some { r; key; v } + + let of_hash r hash = + B.Commit.index (B.Repo.commit_t r) hash >>= function + | None -> Lwt.return_none + | Some key -> of_key r key + + module H = Typed (B.Commit.Val) + + let to_backend_commit t = t.v + let of_backend_commit r key v = { r; key; v } + + let equal_opt x y = + match (x, y) with + | None, None -> true + | Some x, Some y -> equal x y + | _ -> false + end + + let to_backend_portable_node = Tree.to_backend_portable_node + let to_backend_node = Tree.to_backend_node + let of_backend_node = Tree.of_backend_node + let to_backend_commit = Commit.to_backend_commit + let of_backend_commit = Commit.of_backend_commit + + type head_ref = [ `Branch of branch | `Head of commit option ref ] + + module OCamlGraph = Graph + module Graph = Node.Graph (B.Node) + + module KGraph = + Object_graph.Make (B.Contents.Key) (B.Node.Key) (B.Commit.Key) + (Branch_store.Key) + + type slice = B.Slice.t [@@deriving irmin] + type watch = unit -> unit Lwt.t + + let unwatch w = w () + + module Repo = struct + type t = repo + + let v = B.Repo.v + let config = B.Repo.config + let close = B.Repo.close + let branch_t t = B.Repo.branch_t t + let commit_t t = B.Repo.commit_t t + let node_t t = B.Repo.node_t t + let contents_t t = B.Repo.contents_t t + let branches t = B.Branch.list (branch_t t) + + let heads repo = + let t = branch_t repo in + let* bs = Branch_store.list t in + Lwt_list.fold_left_s + (fun acc r -> + Branch_store.find t r >>= function + | None -> Lwt.return acc + | Some k -> ( + Commit.of_key repo k >|= function + | None -> acc + | Some h -> h :: acc)) + [] bs + + let export ?(full = true) ?depth ?(min = []) ?(max = `Head) t = + [%log.debug + "export depth=%s full=%b min=%d max=%s" + (match depth with None -> "" | Some d -> string_of_int d) + full (List.length min) + (match max with + | `Head -> "heads" + | `Max m -> string_of_int (List.length m))]; + let* max = match max with `Head -> heads t | `Max m -> Lwt.return m in + let* slice = B.Slice.empty () in + let max = List.map (fun x -> `Commit x.key) max in + let min = List.map (fun x -> `Commit x.key) min in + let pred = function + | `Commit k -> + let+ parents = Commits.parents (commit_t t) k in + List.map (fun x -> `Commit x) parents + | _ -> Lwt.return_nil + in + let* g = KGraph.closure ?depth ~pred ~min ~max () in + let keys = + List.fold_left + (fun acc -> function `Commit c -> c :: acc | _ -> acc) + [] (KGraph.vertex g) + in + let root_nodes = ref [] in + let* () = + Lwt_list.iter_p + (fun k -> + B.Commit.find (commit_t t) k >>= function + | None -> Lwt.return_unit + | Some c -> + root_nodes := B.Commit.Val.node c :: !root_nodes; + B.Slice.add slice (`Commit (Commit_key.to_hash k, c))) + keys + in + if not full then Lwt.return slice + else + (* XXX: we can compute a [min] if needed *) + let* nodes = Graph.closure (node_t t) ~min:[] ~max:!root_nodes in + let contents = ref Contents_keys.empty in + let* () = + Lwt_list.iter_p + (fun k -> + B.Node.find (node_t t) k >>= function + | None -> Lwt.return_unit + | Some v -> + List.iter + (function + | _, `Contents (c, _) -> + contents := Contents_keys.add c !contents + | _ -> ()) + (B.Node.Val.list v); + B.Slice.add slice (`Node (Node_key.to_hash k, v))) + nodes + in + let+ () = + Lwt_list.iter_p + (fun k -> + B.Contents.find (contents_t t) k >>= function + | None -> Lwt.return_unit + | Some m -> + B.Slice.add slice (`Contents (Contents_key.to_hash k, m))) + (Contents_keys.elements !contents) + in + slice + + exception Import_error of string + + let import_error fmt = Fmt.kstr (fun x -> Lwt.fail (Import_error x)) fmt + + let import t s = + let aux name key_to_hash add (h, v) = + let* k' = add v in + let h' = key_to_hash k' in + if not (equal_hash h h') then + import_error "%s import error: expected %a, got %a" name pp_hash h + pp_hash h' + else Lwt.return_unit + in + let contents = ref [] in + let nodes = ref [] in + let commits = ref [] in + let* () = + B.Slice.iter s (function + | `Contents c -> + contents := c :: !contents; + Lwt.return_unit + | `Node n -> + nodes := n :: !nodes; + Lwt.return_unit + | `Commit c -> + commits := c :: !commits; + Lwt.return_unit) + in + B.Repo.batch t @@ fun contents_t node_t commit_t -> + Lwt.catch + (fun () -> + let* () = + Lwt_list.iter_p + (aux "Contents" B.Contents.Key.to_hash + (B.Contents.add contents_t)) + !contents + in + Lwt_list.iter_p + (aux "Node" B.Node.Key.to_hash (B.Node.add node_t)) + !nodes + >>= fun () -> + let+ () = + Lwt_list.iter_p + (aux "Commit" B.Commit.Key.to_hash (B.Commit.add commit_t)) + !commits + in + Ok ()) + (function + | Import_error e -> Lwt.return (Error (`Msg e)) + | e -> Fmt.kstr Lwt.fail_invalid_arg "impot error: %a" Fmt.exn e) + + type elt = + [ `Commit of commit_key + | `Node of node_key + | `Contents of contents_key + | `Branch of B.Branch.Key.t ] + [@@deriving irmin] + + let ignore_lwt _ = Lwt.return_unit + let return_false _ = Lwt.return false + let default_pred_contents _ _ = Lwt.return [] + + let default_pred_node t k = + B.Node.find (node_t t) k >|= function + | None -> [] + | Some v -> + List.rev_map + (function + | _, `Node n -> `Node n | _, `Contents (c, _) -> `Contents c) + (B.Node.Val.list v) + + let default_pred_commit t c = + B.Commit.find (commit_t t) c >|= function + | None -> + [%log.debug "%a: not found" pp_commit_key c]; + [] + | Some c -> + let node = B.Commit.Val.node c in + let parents = B.Commit.Val.parents c in + [ `Node node ] @ List.map (fun k -> `Commit k) parents + + let default_pred_branch t b = + B.Branch.find (branch_t t) b >|= function + | None -> + [%log.debug "%a: not found" pp_branch b]; + [] + | Some b -> [ `Commit b ] + + let iter ?cache_size ~min ~max ?edge ?(branch = ignore_lwt) + ?(commit = ignore_lwt) ?(node = ignore_lwt) ?(contents = ignore_lwt) + ?(skip_branch = return_false) ?(skip_commit = return_false) + ?(skip_node = return_false) ?(skip_contents = return_false) + ?(pred_branch = default_pred_branch) + ?(pred_commit = default_pred_commit) ?(pred_node = default_pred_node) + ?(pred_contents = default_pred_contents) ?(rev = true) t = + let node = function + | `Commit x -> commit x + | `Node x -> node x + | `Contents x -> contents x + | `Branch x -> branch x + in + let skip = function + | `Commit x -> skip_commit x + | `Node x -> skip_node x + | `Contents x -> skip_contents x + | `Branch x -> skip_branch x + in + let pred = function + | `Commit x -> pred_commit t x + | `Node x -> pred_node t x + | `Contents x -> pred_contents t x + | `Branch x -> pred_branch t x + in + KGraph.iter ?cache_size ~pred ~min ~max ~node ?edge ~skip ~rev () + + let breadth_first_traversal ?cache_size ~max ?(branch = ignore_lwt) + ?(commit = ignore_lwt) ?(node = ignore_lwt) ?(contents = ignore_lwt) + ?(pred_branch = default_pred_branch) + ?(pred_commit = default_pred_commit) ?(pred_node = default_pred_node) + ?(pred_contents = default_pred_contents) t = + let node = function + | `Commit x -> commit x + | `Node x -> node x + | `Contents x -> contents x + | `Branch x -> branch x + in + let pred = function + | `Commit x -> pred_commit t x + | `Node x -> pred_node t x + | `Contents x -> pred_contents t x + | `Branch x -> pred_branch t x + in + KGraph.breadth_first_traversal ?cache_size ~pred ~max ~node () + end + + type t = { + repo : Repo.t; + head_ref : head_ref; + mutable tree : (commit * tree) option; + (* cache for the store tree *) + lock : Lwt_mutex.t; + } + + let repo t = t.repo + let branch_store t = Repo.branch_t t.repo + let commit_store t = Repo.commit_t t.repo + + let status t = + match t.head_ref with + | `Branch b -> `Branch b + | `Head h -> ( match !h with None -> `Empty | Some c -> `Commit c) + + let head_ref t = + match t.head_ref with + | `Branch t -> `Branch t + | `Head h -> ( match !h with None -> `Empty | Some h -> `Head h) + + let branch t = + match head_ref t with + | `Branch t -> Lwt.return_some t + | `Empty | `Head _ -> Lwt.return_none + + let err_no_head s = Fmt.kstr Lwt.fail_invalid_arg "Irmin.%s: no head" s + + let retry_merge name fn = + let rec aux i = + fn () >>= function + | Error _ as c -> Lwt.return c + | Ok true -> Merge.ok () + | Ok false -> + [%log.debug "Irmin.%s: conflict, retrying (%d)." name i]; + aux (i + 1) + in + aux 1 + + let of_ref repo head_ref = + let lock = Lwt_mutex.create () in + Lwt.return { lock; head_ref; repo; tree = None } + + let err_invalid_branch t = + let err = Fmt.str "%a is not a valid branch name." pp_branch t in + Lwt.fail (Invalid_argument err) + + let of_branch repo key = + if Branch_store.Key.is_valid key then of_ref repo (`Branch key) + else err_invalid_branch key + + let main repo = of_branch repo Branch_store.Key.main + let master = main + let empty repo = of_ref repo (`Head (ref None)) + let of_commit c = of_ref c.r (`Head (ref (Some c))) + + let skip_key key = + [%log.debug "[watch-key] key %a has not changed" pp_path key]; + Lwt.return_unit + + let changed_key key old_t new_t = + [%log.debug + fun l -> + let pp = Fmt.option ~none:(Fmt.any "") pp_hash in + let old_h = Option.map Tree.hash old_t in + let new_h = Option.map Tree.hash new_t in + l "[watch-key] key %a has changed: %a -> %a" pp_path key pp old_h pp + new_h] + + let with_tree ~key x f = + x >>= function + | None -> skip_key key + | Some x -> + changed_key key None None; + f x + + let lift_tree_diff ~key tree fn = function + | `Removed x -> + with_tree ~key (tree x) @@ fun v -> + changed_key key (Some v) None; + fn @@ `Removed (x, v) + | `Added x -> + with_tree ~key (tree x) @@ fun v -> + changed_key key None (Some v); + fn @@ `Added (x, v) + | `Updated (x, y) -> ( + assert (not (Commit.equal x y)); + let* vx = tree x in + let* vy = tree y in + match (vx, vy) with + | None, None -> skip_key key + | None, Some vy -> + changed_key key None (Some vy); + fn @@ `Added (y, vy) + | Some vx, None -> + changed_key key (Some vx) None; + fn @@ `Removed (x, vx) + | Some vx, Some vy -> + if Tree.equal vx vy then skip_key key + else ( + changed_key key (Some vx) (Some vy); + fn @@ `Updated ((x, vx), (y, vy)))) + + let head t = + let h = + match head_ref t with + | `Head key -> Lwt.return_some key + | `Empty -> Lwt.return_none + | `Branch name -> ( + Branch_store.find (branch_store t) name >>= function + | None -> Lwt.return_none + | Some k -> Commit.of_key t.repo k) + in + let+ h = h in + [%log.debug "Head.find -> %a" Fmt.(option Commit.pp_key) h]; + h + + let tree_and_head t = + head t >|= function + | None -> None + | Some h -> ( + match t.tree with + | Some (o, t) when Commit.equal o h -> Some (o, t) + | _ -> + t.tree <- None; + + (* the tree cache needs to be invalidated *) + let tree = Tree.import_no_check (repo t) (`Node (Commit.node h)) in + t.tree <- Some (h, tree); + Some (h, tree)) + + let tree t = + tree_and_head t >|= function + | None -> Tree.empty () + | Some (_, tree) -> (tree :> tree) + + let lift_head_diff repo fn = function + | `Removed x -> ( + Commit.of_key repo x >>= function + | None -> Lwt.return_unit + | Some x -> fn (`Removed x)) + | `Updated (x, y) -> ( + let* x = Commit.of_key repo x in + let* y = Commit.of_key repo y in + match (x, y) with + | None, None -> Lwt.return_unit + | Some x, None -> fn (`Removed x) + | None, Some y -> fn (`Added y) + | Some x, Some y -> fn (`Updated (x, y))) + | `Added x -> ( + Commit.of_key repo x >>= function + | None -> Lwt.return_unit + | Some x -> fn (`Added x)) + + let watch t ?init fn = + branch t >>= function + | None -> failwith "watch a detached head: TODO" + | Some name0 -> + let init = + match init with + | None -> None + | Some head0 -> Some [ (name0, head0.key) ] + in + let+ key = + Branch_store.watch (branch_store t) ?init (fun name head -> + if equal_branch name0 name then lift_head_diff t.repo fn head + else Lwt.return_unit) + in + fun () -> Branch_store.unwatch (branch_store t) key + + let watch_key t key ?init fn = + [%log.debug "watch-key %a" pp_path key]; + let tree c = Tree.find_tree (Commit.tree c) key in + watch t ?init (lift_tree_diff ~key tree fn) + + module Head = struct + let list = Repo.heads + let find = head + + let get t = + find t >>= function None -> err_no_head "head" | Some k -> Lwt.return k + + let set t c = + match t.head_ref with + | `Head h -> + h := Some c; + Lwt.return_unit + | `Branch name -> Branch_store.set (branch_store t) name c.key + + let test_and_set_unsafe t ~test ~set = + match t.head_ref with + | `Head head -> + (* [head] is protected by [t.lock]. *) + if Commit.equal_opt !head test then ( + head := set; + Lwt.return_true) + else Lwt.return_false + | `Branch name -> + let h = function None -> None | Some c -> Some c.key in + Branch_store.test_and_set (branch_store t) name ~test:(h test) + ~set:(h set) + + let test_and_set t ~test ~set = + Lwt_mutex.with_lock t.lock (fun () -> test_and_set_unsafe t ~test ~set) + + let fast_forward t ?max_depth ?n new_head = + let return x = if x then Ok () else Error (`Rejected :> ff_error) in + find t >>= function + | None -> test_and_set t ~test:None ~set:(Some new_head) >|= return + | Some old_head -> ( + [%log.debug + "fast-forward-head old=%a new=%a" Commit.pp_hash old_head + Commit.pp_hash new_head]; + if Commit.equal new_head old_head then + (* we only update if there is a change *) + Lwt.return (Error `No_change) + else + Commits.lcas (commit_store t) ?max_depth ?n new_head.key + old_head.key + >>= function + | Ok [ x ] when equal_commit_key x old_head.key -> + (* we only update if new_head > old_head *) + test_and_set t ~test:(Some old_head) ~set:(Some new_head) + >|= return + | Ok _ -> Lwt.return (Error `Rejected) + | Error e -> Lwt.return (Error (e :> ff_error))) + + (* Merge two commits: + - Search for common ancestors + - Perform recursive 3-way merges *) + let three_way_merge t ?max_depth ?n ~info c1 c2 = + B.Repo.batch (repo t) @@ fun _ _ commit_t -> + Commits.three_way_merge commit_t ?max_depth ?n ~info c1.key c2.key + + (* FIXME: we might want to keep the new commit in case of conflict, + and use it as a base for the next merge. *) + let merge ~into:t ~info ?max_depth ?n c1 = + [%log.debug "merge_head"]; + let aux () = + let* head = head t in + match head with + | None -> test_and_set_unsafe t ~test:head ~set:(Some c1) >>= Merge.ok + | Some c2 -> + three_way_merge t ~info ?max_depth ?n c1 c2 >>=* fun c3 -> + let* c3 = Commit.of_key t.repo c3 in + test_and_set_unsafe t ~test:head ~set:c3 >>= Merge.ok + in + Lwt_mutex.with_lock t.lock (fun () -> retry_merge "merge_head" aux) + end + + (* Retry an operation until the optimistic lock is happy. Ensure + that the operation is done at least once. *) + let retry ~retries fn = + let done_once = ref false in + let rec aux i = + if !done_once && i > retries then + Lwt.return (Error (`Too_many_retries retries)) + else + fn () >>= function + | Ok (c, true) -> Lwt.return (Ok c) + | Error e -> Lwt.return (Error e) + | Ok (_, false) -> + done_once := true; + aux (i + 1) + in + aux 0 + + let root_tree = function + | `Node _ as n -> Tree.v n + | `Contents _ -> assert false + + let add_commit t old_head ((c, _) as tree) = + match t.head_ref with + | `Head head -> + Lwt_mutex.with_lock t.lock (fun () -> + if not (Commit.equal_opt old_head !head) then Lwt.return_false + else ( + (* [head] is protected by [t.lock] *) + head := Some c; + t.tree <- Some tree; + Lwt.return_true)) + | `Branch name -> + (* concurrent handlers and/or process can modify the + branch. Need to check that we are still working on the same + head. *) + let test = match old_head with None -> None | Some c -> Some c.key in + let set = Some c.key in + let+ r = Branch_store.test_and_set (branch_store t) name ~test ~set in + if r then t.tree <- Some tree; + r + + let pp_write_error ppf = function + | `Conflict e -> Fmt.pf ppf "Got a conflict: %s" e + | `Too_many_retries i -> + Fmt.pf ppf + "Failure after %d attempts to retry the operation: Too many attempts." + i + | `Test_was t -> + Fmt.pf ppf "Test-and-set failed: got %a when reading the store" + Fmt.(Dump.option pp_tree) + t + + let write_error e : ('a, write_error) result Lwt.t = Lwt.return (Error e) + let err_test v = write_error (`Test_was v) + + type snapshot = { + head : commit option; + root : tree; + tree : tree option; + (* the subtree used by the transaction *) + parents : commit list; + } + + let snapshot t key = + tree_and_head t >>= function + | None -> + Lwt.return + { head = None; root = Tree.empty (); tree = None; parents = [] } + | Some (c, root) -> + let root = (root :> tree) in + let+ tree = Tree.find_tree root key in + { head = Some c; root; tree; parents = [ c ] } + + let same_tree x y = + match (x, y) with + | None, None -> true + | None, _ | _, None -> false + | Some x, Some y -> Tree.equal x y + + (* Update the store with a new commit. Ensure the no commit becomes orphan + in the process. *) + let update ?(clear = true) ?(allow_empty = false) ~info ?parents t key + merge_tree f = + let* s = snapshot t key in + (* this might take a very long time *) + let* new_tree = f s.tree in + (* if no change and [allow_empty = true] then, do nothing *) + if same_tree s.tree new_tree && (not allow_empty) && s.head <> None then + Lwt.return (Ok (None, true)) + else + merge_tree s.root key ~current_tree:s.tree ~new_tree >>= function + | Error e -> Lwt.return (Error e) + | Ok root -> + let info = info () in + let parents = match parents with None -> s.parents | Some p -> p in + let parents = List.map Commit.key parents in + let* c = Commit.v ~clear (repo t) ~info ~parents root in + let* r = add_commit t s.head (c, root_tree (Tree.destruct root)) in + Lwt.return (Ok (Some c, r)) + + let ok x = Ok x + + let fail name = function + | Ok x -> Lwt.return x + | Error e -> Fmt.kstr Lwt.fail_with "%s: %a" name pp_write_error e + + let set_tree_once root key ~current_tree:_ ~new_tree = + match new_tree with + | None -> Tree.remove root key >|= ok + | Some tree -> Tree.add_tree root key tree >|= ok + + let ignore_commit + (c : (commit option, [> `Too_many_retries of int ]) result Lwt.t) = + Lwt_result.map (fun _ -> ()) c + + let set_tree ?clear ?(retries = 13) ?allow_empty ?parents ~info t k v = + [%log.debug "set %a" pp_path k]; + ignore_commit + @@ retry ~retries + @@ fun () -> + update t k ?clear ?allow_empty ?parents ~info set_tree_once @@ fun _tree -> + Lwt.return_some v + + let set_tree_exn ?clear ?retries ?allow_empty ?parents ~info t k v = + set_tree ?clear ?retries ?allow_empty ?parents ~info t k v + >>= fail "set_exn" + + let remove ?clear ?(retries = 13) ?allow_empty ?parents ~info t k = + [%log.debug "debug %a" pp_path k]; + ignore_commit + @@ retry ~retries + @@ fun () -> + update t k ?clear ?allow_empty ?parents ~info set_tree_once @@ fun _tree -> + Lwt.return_none + + let remove_exn ?clear ?retries ?allow_empty ?parents ~info t k = + remove ?clear ?retries ?allow_empty ?parents ~info t k >>= fail "remove_exn" + + let set ?clear ?retries ?allow_empty ?parents ~info t k v = + let v = Tree.of_contents v in + set_tree t k ?clear ?retries ?allow_empty ?parents ~info v + + let set_exn ?clear ?retries ?allow_empty ?parents ~info t k v = + set t k ?clear ?retries ?allow_empty ?parents ~info v >>= fail "set_exn" + + let test_and_set_tree_once ~test root key ~current_tree ~new_tree = + match (test, current_tree) with + | None, None -> set_tree_once root key ~new_tree ~current_tree + | None, _ | _, None -> err_test current_tree + | Some test, Some v -> + if Tree.equal test v then set_tree_once root key ~new_tree ~current_tree + else err_test current_tree + + let test_set_and_get_tree ?clear ?(retries = 13) ?allow_empty ?parents ~info t + k ~test ~set = + [%log.debug "test-and-set %a" pp_path k]; + retry ~retries @@ fun () -> + update t k ?clear ?allow_empty ?parents ~info (test_and_set_tree_once ~test) + @@ fun _tree -> Lwt.return set + + let test_set_and_get_tree_exn ?clear ?retries ?allow_empty ?parents ~info t k + ~test ~set = + test_set_and_get_tree ?clear ?retries ?allow_empty ?parents ~info t k ~test + ~set + >>= fail "test_set_and_get_tree_exn" + + let test_set_and_get ?clear ?retries ?allow_empty ?parents ~info t k ~test + ~set = + let test = Option.map Tree.of_contents test in + let set = Option.map Tree.of_contents set in + test_set_and_get_tree ?clear ?retries ?allow_empty ?parents ~info t k ~test + ~set + + let test_set_and_get_exn ?clear ?retries ?allow_empty ?parents ~info t k ~test + ~set = + test_set_and_get ?clear ?retries ?allow_empty ?parents ~info t k ~test ~set + >>= fail "test_set_and_get_exn" + + let test_and_set_tree ?clear ?(retries = 13) ?allow_empty ?parents ~info t k + ~test ~set = + [%log.debug "test-and-set %a" pp_path k]; + ignore_commit + @@ test_set_and_get_tree ~retries ?clear ?allow_empty ?parents ~info t k + ~test ~set + + let test_and_set_tree_exn ?clear ?retries ?allow_empty ?parents ~info t k + ~test ~set = + test_and_set_tree ?clear ?retries ?allow_empty ?parents ~info t k ~test ~set + >>= fail "test_and_set_tree_exn" + + let test_and_set ?clear ?retries ?allow_empty ?parents ~info t k ~test ~set = + ignore_commit + @@ test_set_and_get ?clear ?retries ?allow_empty ?parents ~info t k ~test + ~set + + let test_and_set_exn ?clear ?retries ?allow_empty ?parents ~info t k ~test + ~set = + test_and_set ?clear ?retries ?allow_empty ?parents ~info t k ~test ~set + >>= fail "test_and_set_exn" + + let merge_once ~old root key ~current_tree ~new_tree = + let old = Merge.promise old in + Merge.f (Merge.option Tree.merge) ~old current_tree new_tree >>= function + | Ok tr -> set_tree_once root key ~new_tree:tr ~current_tree + | Error e -> write_error (e :> write_error) + + let merge_tree ?clear ?(retries = 13) ?allow_empty ?parents ~info ~old t k + tree = + [%log.debug "merge %a" pp_path k]; + ignore_commit + @@ retry ~retries + @@ fun () -> + update t k ?clear ?allow_empty ?parents ~info (merge_once ~old) + @@ fun _tree -> Lwt.return tree + + let merge_tree_exn ?clear ?retries ?allow_empty ?parents ~info ~old t k tree = + merge_tree ?clear ?retries ?allow_empty ?parents ~info ~old t k tree + >>= fail "merge_tree_exn" + + let merge ?clear ?retries ?allow_empty ?parents ~info ~old t k v = + let old = Option.map Tree.of_contents old in + let v = Option.map Tree.of_contents v in + merge_tree ?clear ?retries ?allow_empty ?parents ~info ~old t k v + + let merge_exn ?clear ?retries ?allow_empty ?parents ~info ~old t k v = + merge ?clear ?retries ?allow_empty ?parents ~info ~old t k v + >>= fail "merge_exn" + + let mem t k = tree t >>= fun tree -> Tree.mem tree k + let mem_tree t k = tree t >>= fun tree -> Tree.mem_tree tree k + let find_all t k = tree t >>= fun tree -> Tree.find_all tree k + let find t k = tree t >>= fun tree -> Tree.find tree k + let get t k = tree t >>= fun tree -> Tree.get tree k + let find_tree t k = tree t >>= fun tree -> Tree.find_tree tree k + let get_tree t k = tree t >>= fun tree -> Tree.get_tree tree k + + let key t k = + find_tree t k >|= function + | None -> None + | Some tree -> ( + match Tree.key tree with + | Some (`Contents (key, _)) -> Some (`Contents key) + | Some (`Node key) -> Some (`Node key) + | None -> None) + + let hash t k = + find_tree t k >|= function + | None -> None + | Some tree -> Some (Tree.hash tree) + + let get_all t k = tree t >>= fun tree -> Tree.get_all tree k + let list t k = tree t >>= fun tree -> Tree.list tree k + let kind t k = tree t >>= fun tree -> Tree.kind tree k + + let with_tree ?clear ?(retries = 13) ?allow_empty ?parents + ?(strategy = `Test_and_set) ~info t key f = + let done_once = ref false in + let rec aux n old_tree = + [%log.debug "with_tree %a (%d/%d)" pp_path key n retries]; + if !done_once && n > retries then write_error (`Too_many_retries retries) + else + let* new_tree = f old_tree in + match (strategy, new_tree) with + | `Set, Some tree -> + set_tree ?clear t key ~retries ?allow_empty ?parents tree ~info + | `Set, None -> remove ?clear t key ~retries ?allow_empty ~info ?parents + | `Test_and_set, _ -> ( + test_and_set_tree ?clear t key ~retries ?allow_empty ?parents ~info + ~test:old_tree ~set:new_tree + >>= function + | Error (`Test_was tr) when retries > 0 && n <= retries -> + done_once := true; + aux (n + 1) tr + | e -> Lwt.return e) + | `Merge, _ -> ( + merge_tree ?clear ~old:old_tree ~retries ?allow_empty ?parents ~info + t key new_tree + >>= function + | Ok _ as x -> Lwt.return x + | Error (`Conflict _) when retries > 0 && n <= retries -> + done_once := true; + + (* use the store's current tree as the new 'old store' *) + let* old_tree = + tree_and_head t >>= function + | None -> Lwt.return_none + | Some (_, tr) -> Tree.find_tree (tr :> tree) key + in + aux (n + 1) old_tree + | Error e -> write_error e) + in + let* old_tree = find_tree t key in + aux 0 old_tree + + let with_tree_exn ?clear ?retries ?allow_empty ?parents ?strategy ~info f t + key = + with_tree ?clear ?retries ?allow_empty ?strategy ?parents ~info f t key + >>= fail "with_tree_exn" + + let clone ~src ~dst = + let* () = + Head.find src >>= function + | None -> Branch_store.remove (branch_store src) dst + | Some h -> Branch_store.set (branch_store src) dst h.key + in + of_branch (repo src) dst + + let return_lcas r = function + | Error _ as e -> Lwt.return e + | Ok commits -> + Lwt_list.filter_map_p (Commit.of_key r) commits >|= Result.ok + + let lcas ?max_depth ?n t1 t2 = + let* h1 = Head.get t1 in + let* h2 = Head.get t2 in + Commits.lcas (commit_store t1) ?max_depth ?n h1.key h2.key + >>= return_lcas t1.repo + + let lcas_with_commit t ?max_depth ?n c = + let* h = Head.get t in + Commits.lcas (commit_store t) ?max_depth ?n h.key c.key + >>= return_lcas t.repo + + let lcas_with_branch t ?max_depth ?n b = + let* h = Head.get t in + let* head = Head.get { t with head_ref = `Branch b } in + Commits.lcas (commit_store t) ?max_depth ?n h.key head.key + >>= return_lcas t.repo + + type 'a merge = + info:Info.f -> + ?max_depth:int -> + ?n:int -> + 'a -> + (unit, Merge.conflict) result Lwt.t + + let merge_with_branch t ~info ?max_depth ?n other = + [%log.debug "merge_with_branch %a" pp_branch other]; + Branch_store.find (branch_store t) other >>= function + | None -> + Fmt.kstr Lwt.fail_invalid_arg + "merge_with_branch: %a is not a valid branch ID" pp_branch other + | Some c -> ( + Commit.of_key t.repo c >>= function + | None -> Lwt.fail_invalid_arg "invalid commit" + | Some c -> Head.merge ~into:t ~info ?max_depth ?n c) + + let merge_with_commit t ~info ?max_depth ?n other = + Head.merge ~into:t ~info ?max_depth ?n other + + let merge_into ~into ~info ?max_depth ?n t = + [%log.debug "merge"]; + match head_ref t with + | `Branch name -> merge_with_branch into ~info ?max_depth ?n name + | `Head h -> merge_with_commit into ~info ?max_depth ?n h + | `Empty -> Merge.ok () + + module History = OCamlGraph.Persistent.Digraph.ConcreteBidirectional (struct + type t = commit + + let hash h = B.Hash.short_hash (Commit.hash h) + let compare_key = Type.(unstage (compare B.Commit.Key.t)) + let compare x y = compare_key x.key y.key + let equal x y = equal_commit_key x.key y.key + end) + + module Gmap = struct + module Src = KGraph + + module Dst = struct + include History + + let empty () = empty + end + + let filter_map f g = + let t = Dst.empty () in + if Src.nb_vertex g = 1 then + match Src.vertex g with + | [ v ] -> ( + f v >|= function Some v -> Dst.add_vertex t v | None -> t) + | _ -> assert false + else + Src.fold_edges + (fun x y t -> + let* t = t in + let* x = f x in + let+ y = f y in + match (x, y) with + | Some x, Some y -> + let t = Dst.add_vertex t x in + let t = Dst.add_vertex t y in + Dst.add_edge t x y + | _ -> t) + g (Lwt.return t) + end + + let history ?depth ?(min = []) ?(max = []) t = + [%log.debug "history"]; + let pred = function + | `Commit k -> + Commits.parents (commit_store t) k + >>= Lwt_list.filter_map_p (Commit.of_key t.repo) + >|= fun parents -> List.map (fun x -> `Commit x.key) parents + | _ -> Lwt.return_nil + in + let* max = Head.find t >|= function Some h -> [ h ] | None -> max in + let max = List.map (fun k -> `Commit k.key) max in + let min = List.map (fun k -> `Commit k.key) min in + let* g = Gmap.Src.closure ?depth ~min ~max ~pred () in + Gmap.filter_map + (function `Commit k -> Commit.of_key t.repo k | _ -> Lwt.return_none) + g + + module Heap = Binary_heap.Make (struct + type t = commit * int + + let compare c1 c2 = + (* [bheap] operates on miminums, we need to invert the comparison. *) + -Int64.compare + (Info.date (Commit.info (fst c1))) + (Info.date (Commit.info (fst c2))) + end) + + let last_modified ?depth ?(n = 1) t key = + [%log.debug + "last_modified depth=%a n=%d key=%a" + Fmt.(Dump.option pp_int) + depth n pp_path key]; + let repo = repo t in + let* commit = Head.get t in + let heap = Heap.create ~dummy:(commit, 0) 0 in + let () = Heap.add heap (commit, 0) in + let rec search acc = + if Heap.is_empty heap || List.length acc = n then Lwt.return acc + else + let current, current_depth = Heap.pop_minimum heap in + let parents = Commit.parents current in + let tree = Commit.tree current in + let* current_value = Tree.find tree key in + if List.length parents = 0 then + if current_value <> None then Lwt.return (current :: acc) + else Lwt.return acc + else + let max_depth = + match depth with + | Some depth -> current_depth >= depth + | None -> false + in + let* found = + Lwt_list.for_all_p + (fun hash -> + Commit.of_key repo hash >>= function + | Some commit -> ( + let () = + if not max_depth then + Heap.add heap (commit, current_depth + 1) + in + let tree = Commit.tree commit in + let+ e = Tree.find tree key in + match (e, current_value) with + | Some x, Some y -> not (equal_contents x y) + | Some _, None -> true + | None, Some _ -> true + | _, _ -> false) + | None -> Lwt.return_false) + parents + in + if found then search (current :: acc) else search acc + in + search [] + + module Branch = struct + include B.Branch.Key + + let mem t = B.Branch.mem (B.Repo.branch_t t) + + let find t br = + B.Branch.find (Repo.branch_t t) br >>= function + | None -> Lwt.return_none + | Some h -> Commit.of_key t h + + let set t br h = B.Branch.set (B.Repo.branch_t t) br h.key + let remove t = B.Branch.remove (B.Repo.branch_t t) + let list = Repo.branches + + let watch t k ?init f = + let init = match init with None -> None | Some h -> Some h.key in + let+ w = + B.Branch.watch_key (Repo.branch_t t) k ?init (lift_head_diff t f) + in + fun () -> Branch_store.unwatch (Repo.branch_t t) w + + let watch_all t ?init f = + let init = + match init with + | None -> None + | Some i -> Some (List.map (fun (k, v) -> (k, v.key)) i) + in + let f k v = lift_head_diff t (f k) v in + let+ w = B.Branch.watch (Repo.branch_t t) ?init f in + fun () -> Branch_store.unwatch (Repo.branch_t t) w + + let err_not_found k = + Fmt.kstr invalid_arg "Branch.get: %a not found" pp_branch k + + let get t k = + find t k >>= function None -> err_not_found k | Some v -> Lwt.return v + end + + module Status = struct + type t = [ `Empty | `Branch of branch | `Commit of commit ] + + let t r = + let open Type in + variant "status" (fun empty branch commit -> function + | `Empty -> empty | `Branch b -> branch b | `Commit c -> commit c) + |~ case0 "empty" `Empty + |~ case1 "branch" Branch.t (fun b -> `Branch b) + |~ case1 "commit" (Commit.t r) (fun c -> `Commit c) + |> sealv + + let pp ppf = function + | `Empty -> Fmt.string ppf "empty" + | `Branch b -> pp_branch ppf b + | `Commit c -> pp_hash ppf (Commit_key.to_hash c.key) + end + + let commit_t = Commit.t +end + +module Json_tree (Store : S with type Schema.Contents.t = Contents.json) = +struct + include Contents.Json_value + + type json = Contents.json + + let to_concrete_tree j : Store.Tree.concrete = + let rec obj j acc = + match j with + | [] -> `Tree acc + | (k, v) :: l -> ( + match Type.of_string Store.Path.step_t k with + | Ok key -> obj l ((key, node v []) :: acc) + | _ -> obj l acc) + and node j acc = + match j with + | `O j -> obj j acc + | _ -> `Contents (j, Store.Metadata.default) + in + node j [] + + let of_concrete_tree c : json = + let step = Type.to_string Store.Path.step_t in + let rec tree t acc = + match t with + | [] -> `O acc + | (k, v) :: l -> tree l ((step k, contents v []) :: acc) + and contents t acc = + match t with `Contents (c, _) -> c | `Tree c -> tree c acc + in + contents c [] + + let set_tree (tree : Store.tree) key j : Store.tree Lwt.t = + let c = to_concrete_tree j in + let c = Store.Tree.of_concrete c in + Store.Tree.add_tree tree key c + + let get_tree (tree : Store.tree) key = + let* t = Store.Tree.get_tree tree key in + let+ c = Store.Tree.to_concrete t in + of_concrete_tree c + + let set t key j ~info = + set_tree (Store.Tree.empty ()) Store.Path.empty j >>= function + | tree -> Store.set_tree_exn ~info t key tree + + let get t key = + let* tree = Store.get_tree t key in + get_tree tree Store.Path.empty +end + +type Remote.t += + | Store : (module Generic_key.S with type t = 'a) * 'a -> Remote.t diff --git a/vendors/irmin/src/irmin/store.mli b/vendors/irmin/src/irmin/store.mli new file mode 100644 index 000000000000..a79f53b71208 --- /dev/null +++ b/vendors/irmin/src/irmin/store.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Branch-consistent stores: read-write store with support fork/merge + operations. *) + +include Store_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/store_intf.ml b/vendors/irmin/src/irmin/store_intf.ml new file mode 100644 index 000000000000..bc6194ba54af --- /dev/null +++ b/vendors/irmin/src/irmin/store_intf.ml @@ -0,0 +1,1263 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Store_properties + +module type S_generic_key = sig + (** {1 Irmin stores} + + Irmin stores are tree-like read-write stores with extended capabilities. + They allow an application (or a collection of applications) to work with + multiple local states, which can be forked and merged programmatically, + without having to rely on a global state. In a way very similar to version + control systems, Irmin local states are called {i branches}. + + There are two kinds of store in Irmin: the ones based on {{!of_branch} + persistent} named branches and the ones based {{!of_commit} temporary} + detached heads. These exist relative to a local, larger (and shared) + store, and have some (shared) contents. This is exactly the same as usual + version control systems, that the informed user can see as an implicit + purely functional data-structure. *) + + module Schema : Schema.S + + type repo + (** The type for Irmin repositories. *) + + type t + (** The type for Irmin stores. *) + + type step = Schema.Path.step [@@deriving irmin] + (** The type for {!type-key} steps. *) + + type path = Schema.Path.t [@@deriving irmin] + (** The type for store keys. A key is a sequence of {!step}s. *) + + type metadata = Schema.Metadata.t [@@deriving irmin] + (** The type for store metadata. *) + + type contents = Schema.Contents.t [@@deriving irmin] + (** The type for store contents. *) + + type node [@@deriving irmin] + (** The type for store nodes. *) + + type tree [@@deriving irmin] + (** The type for store trees. *) + + type hash = Schema.Hash.t [@@deriving irmin] + (** The type for object hashes. *) + + type commit + (** Type for [`Commit] identifiers. Similar to Git's commit SHA1s. *) + + val commit_t : repo -> commit Type.t + (** [commit_t r] is the value type for {!commit}. *) + + type branch = Schema.Branch.t [@@deriving irmin] + (** Type for persistent branch names. Branches usually share a common global + namespace and it's the user's responsibility to avoid name clashes. *) + + type slice [@@deriving irmin] + (** Type for store slices. *) + + type info = Schema.Info.t [@@deriving irmin] + (** The type for commit info. *) + + type lca_error = [ `Max_depth_reached | `Too_many_lcas ] [@@deriving irmin] + (** The type for errors associated with functions computing least common + ancestors *) + + type ff_error = [ `No_change | `Rejected | lca_error ] [@@deriving irmin] + (** The type for errors for {!Head.fast_forward}. *) + + module Info : sig + include Info.S with type t = info + (** @inline *) + end + + type contents_key [@@deriving irmin] + type node_key [@@deriving irmin] + type commit_key [@@deriving irmin] + + (** Repositories. *) + module Repo : sig + (** {1 Repositories} + + A repository contains a set of branches. *) + + type t = repo + (** The type of repository handles. *) + + val v : Conf.t -> t Lwt.t + (** [v config] connects to a repository in a backend-specific manner. *) + + val config : t -> Conf.t + (** [config repo] is the configuration used to create [repo] *) + + include Closeable with type _ t := t + (** @inline *) + + val heads : t -> commit list Lwt.t + (** [heads] is {!Head.list}. *) + + val branches : t -> branch list Lwt.t + (** [branches] is {!Branch.list}. *) + + val export : + ?full:bool -> + ?depth:int -> + ?min:commit list -> + ?max:[ `Head | `Max of commit list ] -> + t -> + slice Lwt.t + (** [export t ~full ~depth ~min ~max] exports the store slice between [min] + and [max], using at most [depth] history depth (starting from the max). + + If [max] is `Head (also the default value), use the current [heads]. If + [min] is not specified, use an unbound past (but can still be limited by + [depth]). + + [depth] is used to limit the depth of the commit history. [None] here + means no limitation. + + If [full] is set (default is true), the full graph, including the + commits, nodes and contents, is exported, otherwise it is the commit + history graph only. *) + + val import : t -> slice -> (unit, [ `Msg of string ]) result Lwt.t + (** [import t s] imports the contents of the slice [s] in [t]. Does not + modify branches. *) + + type elt = + [ `Commit of commit_key + | `Node of node_key + | `Contents of contents_key + | `Branch of branch ] + [@@deriving irmin] + (** The type for elements iterated over by {!iter}. *) + + val default_pred_commit : t -> commit_key -> elt list Lwt.t + val default_pred_node : t -> node_key -> elt list Lwt.t + val default_pred_contents : t -> contents_key -> elt list Lwt.t + + val iter : + ?cache_size:int -> + min:elt list -> + max:elt list -> + ?edge:(elt -> elt -> unit Lwt.t) -> + ?branch:(branch -> unit Lwt.t) -> + ?commit:(commit_key -> unit Lwt.t) -> + ?node:(node_key -> unit Lwt.t) -> + ?contents:(contents_key -> unit Lwt.t) -> + ?skip_branch:(branch -> bool Lwt.t) -> + ?skip_commit:(commit_key -> bool Lwt.t) -> + ?skip_node:(node_key -> bool Lwt.t) -> + ?skip_contents:(contents_key -> bool Lwt.t) -> + ?pred_branch:(t -> branch -> elt list Lwt.t) -> + ?pred_commit:(t -> commit_key -> elt list Lwt.t) -> + ?pred_node:(t -> node_key -> elt list Lwt.t) -> + ?pred_contents:(t -> contents_key -> elt list Lwt.t) -> + ?rev:bool -> + t -> + unit Lwt.t + (** [iter t] iterates in topological order over the closure graph of [t]. If + [rev] is set (by default it is) the traversal is done in reverse order. + + [skip_branch], [skip_commit], [skip_node] and [skip_contents] allow the + traversal to be stopped when the corresponding objects are traversed. By + default no objects are skipped. + + The [branch], [commit], [node] and [contents] functions are called + whenever the corresponding objects are traversed. By default these + functions do nothing. These functions are not called on skipped objects. + + [pred_branch], [pred_commit], [pred_node] and [pred_contents] implicitly + define the graph underlying the traversal. By default they exactly match + the underlying Merkle graph of the repository [t]. These functions can + be used to traverse a slightly modified version of that graph, for + instance by modifying [pred_contents] to implicitly link structured + contents with other objects in the graph. + + The traversed objects are all included between [min] (included) and + [max] (included), following the Merkle graph order. Moreover, the [min] + boundary is extended as follows: + + - contents and node objects in [min] stop the traversal; their + predecessors are not traversed. + - commit objects in [min] stop the traversal for their commit + predecessors, but their sub-node are still traversed. This allows + users to define an inclusive range of commit to iterate over. + - branch objects in [min] implicitly add to [min] the commit they are + pointing to; this allow users to define the iteration between two + branches. + + [cache_size] is the size of the LRU used to store traversed objects. If + an entry is evicted from the LRU, it can be traversed multiple times by + {!Repo.iter}. When [cache_size] is [None] (the default), no entries is + ever evicted from the cache; hence every object is only traversed once, + at the cost of having to store all the traversed objects in memory. *) + + val breadth_first_traversal : + ?cache_size:int -> + max:elt list -> + ?branch:(branch -> unit Lwt.t) -> + ?commit:(commit_key -> unit Lwt.t) -> + ?node:(node_key -> unit Lwt.t) -> + ?contents:(contents_key -> unit Lwt.t) -> + ?pred_branch:(t -> branch -> elt list Lwt.t) -> + ?pred_commit:(t -> commit_key -> elt list Lwt.t) -> + ?pred_node:(t -> node_key -> elt list Lwt.t) -> + ?pred_contents:(t -> contents_key -> elt list Lwt.t) -> + t -> + unit Lwt.t + end + + val empty : repo -> t Lwt.t + (** [empty repo] is a temporary, empty store. Becomes a normal temporary store + after the first update. *) + + val main : repo -> t Lwt.t + (** [main r] is a persistent store based on [r]'s main branch. This operation + is cheap, can be repeated multiple times. *) + + val of_branch : repo -> branch -> t Lwt.t + (** [of_branch r name] is a persistent store based on the branch [name]. + Similar to {!main}, but use [name] instead of {!Irmin.Branch.S.main}. *) + + val of_commit : commit -> t Lwt.t + (** [of_commit c] is a temporary store, based on the commit [c]. + + Temporary stores do not have stable names: instead they can be addressed + using the hash of the current commit. Temporary stores are similar to + Git's detached heads. In a temporary store, all the operations are + performed relative to the current head and update operations can modify + the current head: the current stores's head will automatically become the + new head obtained after performing the update. *) + + val repo : t -> repo + (** [repo t] is the repository containing [t]. *) + + val tree : t -> tree Lwt.t + (** [tree t] is [t]'s current tree. Contents is not allowed at the root of the + tree. *) + + module Status : sig + type t = [ `Empty | `Branch of branch | `Commit of commit ] + (** The type for store status. *) + + val t : repo -> t Type.t + (** [t] is the value type for {!type-t}. *) + + val pp : t Fmt.t + (** [pp] is the pretty-printer for store status. *) + end + + val status : t -> Status.t + (** [status t] is [t]'s status. It can either be a branch, a commit or empty. *) + + (** Managing the store's heads. *) + module Head : sig + val list : repo -> commit list Lwt.t + (** [list t] is the list of all the heads in local store. Similar to + [git rev-list --all]. *) + + val find : t -> commit option Lwt.t + (** [find t] is the current head of the store [t]. This works for both + persistent and temporary branches. In the case of a persistent branch, + this involves getting the the head associated with the branch, so this + may block. In the case of a temporary store, it simply returns the + current head. Returns [None] if the store has no contents. Similar to + [git rev-parse HEAD]. *) + + val get : t -> commit Lwt.t + (** Same as {!find} but raise [Invalid_argument] if the store does not have + any contents. *) + + val set : t -> commit -> unit Lwt.t + (** [set t h] updates [t]'s contents with the contents of the commit [h]. + Can cause data loss as it discards the current contents. Similar to + [git reset --hard ]. *) + + val fast_forward : + t -> ?max_depth:int -> ?n:int -> commit -> (unit, ff_error) result Lwt.t + (** [fast_forward t h] is similar to {!set} but the [t]'s head is updated to + [h] only if [h] is stricly in the future of [t]'s current head. + [max_depth] or [n] are used to limit the search space of the lowest + common ancestors (see {!lcas}). + + The result is: + + - [Ok ()] if the operation is succesfull; + - [Error `No_change] if [h] is already [t]'s head; + - [Error `Rejected] if [h] is not in the strict future of [t]'s head. + - [Error e] if the history exploration has been cut before getting + useful results. In that case. the operation can be retried using + different parameters of [n] and [max_depth] to get better results. *) + + val test_and_set : + t -> test:commit option -> set:commit option -> bool Lwt.t + (** Same as {!set} but check that the value is [test] before updating to + [set]. Use {!set} or {!val-merge} instead if possible. *) + + val merge : + into:t -> + info:Info.f -> + ?max_depth:int -> + ?n:int -> + commit -> + (unit, Merge.conflict) result Lwt.t + (** [merge ~into:t ?max_head ?n commit] merges the contents of the commit + associated to [commit] into [t]. [max_depth] is the maximal depth used + for getting the lowest common ancestor. [n] is the maximum number of + lowest common ancestors. If present, [max_depth] or [n] are used to + limit the search space of the lowest common ancestors (see {!lcas}). *) + end + + module Hash : Hash.S with type t = hash + (** Object hashes. *) + + (** [Commit] defines immutable objects to describe store updates. *) + module Commit : sig + type t = commit + (** The type for store commits. *) + + val t : repo -> t Type.t + (** [t] is the value type for {!type-t}. *) + + val pp_hash : t Fmt.t + (** [pp] is the pretty-printer for commit. Display only the hash. *) + + val v : + ?clear:bool -> + repo -> + info:info -> + parents:commit_key list -> + tree -> + commit Lwt.t + (** [v r i ~parents:p t] is the commit [c] such that: + + - [info c = i] + - [parents c = p] + - [tree c = t] + + When [clear] is set (the default), the tree cache is emptied upon the + function's completion, mirroring the effect of invoking {!Tree.clear}. *) + + val tree : commit -> tree + (** [tree c] is [c]'s root tree. *) + + val parents : commit -> commit_key list + (** [parents c] are [c]'s parents. *) + + val info : commit -> info + (** [info c] is [c]'s info. *) + + val hash : commit -> hash + (** [hash c] is [c]'s hash. *) + + (** {1 Import/Export} *) + + val key : commit -> commit_key + (** [key c] is [c]'s key. *) + + val of_key : repo -> commit_key -> commit option Lwt.t + (** [of_key r k] is the the commit object in [r] with key [k], or [None] if + no such commit object exists. *) + + val of_hash : repo -> hash -> commit option Lwt.t + (** [of_hash r h] is the commit object in [r] with hash [h], or [None] if no + such commit object is indexed in [r]. + + {b Note:} in stores for which {!commit_key} = {!type-hash}, this + function has identical behaviour to {!of_key}. *) + end + + (** [Contents] provides base functions for the store's contents. *) + module Contents : sig + include Contents.S with type t = contents + + (** {1 Import/Export} *) + + val hash : contents -> hash + (** [hash c] it [c]'s hash. *) + + val of_key : repo -> contents_key -> contents option Lwt.t + (** [of_key r k] is the contents object in [r] with key [k], or [None] if no + such contents object exists. *) + + val of_hash : repo -> hash -> contents option Lwt.t + (** [of_hash r h] is the contents object in [r] with hash [h], or [None] if + no such contents object is indexed in [r]. + + {b Note:} in stores for which {!contents_key} = {!type-hash}, this + function has identical behaviour to {!of_key}. *) + end + + (** Managing store's trees. *) + module Tree : sig + include + Tree.S + with type t := tree + and type step := step + and type path := path + and type metadata := metadata + and type contents := contents + and type contents_key := contents_key + and type node := node + and type hash := hash + + (** {1 Import/Export} *) + + type kinded_key = + [ `Contents of contents_key * metadata | `Node of node_key ] + [@@deriving irmin] + (** Keys in the Irmin store are tagged with the type of the value they + reference (either {!contents} or {!node}). In the [contents] case, the + key is paired with corresponding {!metadata}. *) + + val key : tree -> kinded_key option + (** [key t] is the key of tree [t] in the underlying repository, if it + exists. Tree objects that exist entirely in memory (such as those built + with {!of_concrete}) have no backend key until they are exported to a + repository, and so will return [None]. *) + + val find_key : Repo.t -> tree -> kinded_key option Lwt.t + (** [find_key r t] is the key of a tree object with the same hash as [t] in + [r], if such a key exists and is indexed. *) + + val of_key : Repo.t -> kinded_key -> tree option Lwt.t + (** [of_key r h] is the tree object in [r] having [h] as key, or [None] if + no such tree object exists. *) + + val shallow : Repo.t -> kinded_key -> tree + (** [shallow r h] is the shallow tree object with the key [h]. No check is + performed to verify if [h] actually exists in [r]. *) + + val hash : ?cache:bool -> tree -> hash + (** [hash t] is the hash of tree [t]. *) + + type kinded_hash = [ `Contents of hash * metadata | `Node of hash ] + (** Like {!kinded_key}, but with hashes as value references rather than + keys. *) + + val kinded_hash : ?cache:bool -> tree -> kinded_hash + (** [kinded_hash t] is [c]'s kinded hash. *) + + val of_hash : Repo.t -> kinded_hash -> tree option Lwt.t + (** [of_hash r h] is the tree object in [r] with hash [h], or [None] if no + such tree object is indexed in [r]. + + {b Note:} in stores for which {!node_key} = {!contents_key} = + {!type-hash}, this function has identical behaviour to {!of_key}. *) + + (** {1 Proofs} *) + + type ('proof, 'result) producer := + repo -> + kinded_key -> + (tree -> (tree * 'result) Lwt.t) -> + ('proof * 'result) Lwt.t + (** [produce r h f] runs [f] on top of a real store [r], producing a proof + and a result using the initial root hash [h]. + + The trees produced during [f]'s computation will carry the full history + of reads. This history will be reset when [f] is complete so subtrees + escaping the scope of [f] will not cause memory leaks. + + Calling [produce_proof] recursively has an undefined behaviour. *) + + type verifier_error = + [ `Proof_mismatch of string + | `Stream_too_long of string + | `Stream_too_short of string ] + [@@deriving irmin] + (** The type for errors associated with functions that verify proofs. *) + + type ('proof, 'result) verifier := + 'proof -> + (tree -> (tree * 'result) Lwt.t) -> + (tree * 'result, verifier_error) result Lwt.t + (** [verify p f] runs [f] in checking mode. [f] is a function that takes a + tree as input and returns a new version of the tree and a result. [p] is + a proof, that is a minimal representation of the tree that contains what + [f] should be expecting. + + Therefore, contrary to trees found in a storage, the contents of the + trees passed to [f] may not be available. For this reason, looking up a + value at some [path] can now produce three distinct outcomes: + + - A value [v] is present in the proof [p] and returned : + [find tree path] is a promise returning [Some v]; + - [path] is known to have no value in [tree] : [find tree path] is a + promise returning [None]; and + - [path] is known to have a value in [tree] but [p] does not provide it + because [f] should not need it: [verify] returns an error classifying + [path] as an invalid path (see below). + + The same semantics apply to all operations on the tree [t] passed to [f] + and on all operations on the trees built from [f]. + + The generated tree is the tree after [f] has completed. That tree is + disconnected from the backend. It is possible to run operations on it as + long as they don't require loading shallowed subtrees, otherwise it + would raise [Dangling_hash]. + + The result is [Error _] if the proof is rejected: + + - For tree proofs: when [p.before] is different from the hash of + [p.state]; + - For tree and stream proofs: when [p.after] is different from the hash + of [f p.state]; + - For tree and stream proofs: when [f p.state] tries to access paths + invalid paths in [p.state]; + - For stream proofs: when the proof is not empty once [f] is done. *) + + type tree_proof := Proof.tree Proof.t + (** The type for tree proofs. + + Guarantee that the given computation performs exactly the same state + operations as the generating computation, *in some order*. *) + + val produce_proof : (tree_proof, 'a) producer + (** [produce_proof] is the producer of tree proofs. *) + + val verify_proof : (tree_proof, 'a) verifier + (** [verify_proof] is the verifier of tree proofs. *) + + val hash_of_proof_state : Proof.tree -> kinded_hash + + type stream_proof := Proof.stream Proof.t + (** The type for stream proofs. + + Guarantee that the given computation performs exactly the same state + operations as the generating computation, in the exact same order. + + Calling [fold] with [order = `Undefined] during the + production/verification of streamed proofs is undefined. *) + + val produce_stream : (stream_proof, 'a) producer + (** [produce_stream] is the producer of stream proofs. *) + + val verify_stream : (stream_proof, 'a) verifier + (** [verify_stream] is the verifier of stream proofs. *) + end + + (** {1 Reads} *) + + val kind : t -> path -> [ `Contents | `Node ] option Lwt.t + (** [kind] is {!Tree.kind} applied to [t]'s root tree. *) + + val list : t -> path -> (step * tree) list Lwt.t + (** [list t] is {!Tree.list} applied to [t]'s root tree. *) + + val mem : t -> path -> bool Lwt.t + (** [mem t] is {!Tree.mem} applied to [t]'s root tree. *) + + val mem_tree : t -> path -> bool Lwt.t + (** [mem_tree t] is {!Tree.mem_tree} applied to [t]'s root tree. *) + + val find_all : t -> path -> (contents * metadata) option Lwt.t + (** [find_all t] is {!Tree.find_all} applied to [t]'s root tree. *) + + val find : t -> path -> contents option Lwt.t + (** [find t] is {!Tree.find} applied to [t]'s root tree. *) + + val get_all : t -> path -> (contents * metadata) Lwt.t + (** [get_all t] is {!Tree.get_all} applied on [t]'s root tree. *) + + val get : t -> path -> contents Lwt.t + (** [get t] is {!Tree.get} applied to [t]'s root tree. *) + + val find_tree : t -> path -> tree option Lwt.t + (** [find_tree t] is {!Tree.find_tree} applied to [t]'s root tree. *) + + val get_tree : t -> path -> tree Lwt.t + (** [get_tree t k] is {!Tree.get_tree} applied to [t]'s root tree. *) + + type kinded_key := [ `Contents of contents_key | `Node of node_key ] + + val key : t -> path -> kinded_key option Lwt.t + (** [id t k] *) + + val hash : t -> path -> hash option Lwt.t + (** [hash t k] *) + + (** {1 Updates} *) + + type write_error = + [ Merge.conflict | `Too_many_retries of int | `Test_was of tree option ] + [@@deriving irmin] + (** The type for write errors. + + - Merge conflict. + - Concurrent transactions are competing to get the current operation + committed and too many attemps have been tried (livelock). + - A "test and set" operation has failed and the current value is [v] + instead of the one we were waiting for. *) + + val set : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + contents -> + (unit, write_error) result Lwt.t + (** [set t k ~info v] sets [k] to the value [v] in [t]. Discard any previous + results but ensure that no operation is lost in the history. + + This function always uses {!Metadata.default} as metadata. Use {!set_tree} + with `[Contents (c, m)] for different ones. + + When [clear] is set (the default), the tree cache is emptied upon the + function's completion, mirroring the effect of invoking {!Tree.clear}. + + The result is [Error `Too_many_retries] if the concurrent operations do + not allow the operation to commit to the underlying storage layer + (livelock). *) + + val set_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + contents -> + unit Lwt.t + (** [set_exn] is like {!set} but raise [Failure _] instead of using a result + type. *) + + val set_tree : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + tree -> + (unit, write_error) result Lwt.t + (** [set_tree] is like {!set} but for trees. *) + + val set_tree_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + tree -> + unit Lwt.t + (** [set_tree] is like {!set_exn} but for trees. *) + + val remove : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + (unit, write_error) result Lwt.t + (** [remove t ~info k] remove any bindings to [k] in [t]. + + The result is [Error `Too_many_retries] if the concurrent operations do + not allow the operation to commit to the underlying storage layer + (livelock). *) + + val remove_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + unit Lwt.t + (** [remove_exn] is like {!remove} but raise [Failure _] instead of a using + result type. *) + + val test_and_set : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + test:contents option -> + set:contents option -> + (unit, write_error) result Lwt.t + (** [test_and_set ~test ~set] is like {!set} but it atomically checks that the + tree is [test] before modifying it to [set]. + + This function always uses {!Metadata.default} as metadata. Use + {!test_and_set_tree} with `[Contents (c, m)] for different ones. + + The result is [Error (`Test t)] if the current tree is [t] instead of + [test]. + + The result is [Error `Too_many_retries] if the concurrent operations do + not allow the operation to commit to the underlying storage layer + (livelock). *) + + val test_and_set_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + test:contents option -> + set:contents option -> + unit Lwt.t + (** [test_and_set_exn] is like {!test_and_set} but raise [Failure _] instead + of using a result type. *) + + val test_and_set_tree : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + test:tree option -> + set:tree option -> + (unit, write_error) result Lwt.t + (** [test_and_set_tree] is like {!test_and_set} but for trees. *) + + val test_and_set_tree_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + t -> + path -> + test:tree option -> + set:tree option -> + unit Lwt.t + (** [test_and_set_tree_exn] is like {!test_and_set_exn} but for trees. *) + + val test_set_and_get : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:(unit -> info) -> + t -> + path -> + test:contents option -> + set:contents option -> + (commit option, write_error) result Lwt.t + (** [test_set_and_get] is like {!test_and_set} except it also returns the + commit associated with updating the store with the new value if the + [test_and_set] is successful. No commit is returned if there was no update + to the store. *) + + val test_set_and_get_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:(unit -> info) -> + t -> + path -> + test:contents option -> + set:contents option -> + commit option Lwt.t + (** [test_set_and_get_exn] is like {!test_set_and_get} but raises [Failure _] + instead. *) + + val test_set_and_get_tree : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:(unit -> info) -> + t -> + path -> + test:tree option -> + set:tree option -> + (commit option, write_error) result Lwt.t + (** [test_set_and_get_tree] is like {!test_set_and_get} but for a {!tree} *) + + val test_set_and_get_tree_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:(unit -> info) -> + t -> + path -> + test:tree option -> + set:tree option -> + commit option Lwt.t + (** [test_set_and_get_tree_exn] is like {!test_set_and_get_tree} but raises + [Failure _] instead. *) + + val merge : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + old:contents option -> + t -> + path -> + contents option -> + (unit, write_error) result Lwt.t + (** [merge ~old] is like {!set} but merge the current tree and the new tree + using [old] as ancestor in case of conflicts. + + This function always uses {!Metadata.default} as metadata. Use + {!merge_tree} with `[Contents (c, m)] for different ones. + + The result is [Error (`Conflict c)] if the merge failed with the conflict + [c]. + + The result is [Error `Too_many_retries] if the concurrent operations do + not allow the operation to commit to the underlying storage layer + (livelock). *) + + val merge_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + old:contents option -> + t -> + path -> + contents option -> + unit Lwt.t + (** [merge_exn] is like {!val-merge} but raise [Failure _] instead of using a + result type. *) + + val merge_tree : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + old:tree option -> + t -> + path -> + tree option -> + (unit, write_error) result Lwt.t + (** [merge_tree] is like {!merge_tree} but for trees. *) + + val merge_tree_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + info:Info.f -> + old:tree option -> + t -> + path -> + tree option -> + unit Lwt.t + (** [merge_tree] is like {!merge_tree} but for trees. *) + + val with_tree : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + ?strategy:[ `Set | `Test_and_set | `Merge ] -> + info:Info.f -> + t -> + path -> + (tree option -> tree option Lwt.t) -> + (unit, write_error) result Lwt.t + (** [with_tree t k ~info f] replaces {i atomically} the subtree [v] under [k] + in the store [t] by the contents of the tree [f v], using the commit info + [info ()]. + + If [v = f v] and [allow_empty] is unset (default) then, the operation is a + no-op. + + If [v != f v] and no other changes happen concurrently, [f v] becomes the + new subtree under [k]. If other changes happen concurrently to that + operations, the semantics depend on the value of [strategy]: + + - if [strategy = `Set], use {!set} and discard any concurrent updates to + [k]. + - if [strategy = `Test_and_set] (default), use {!test_and_set} and ensure + that no concurrent operations are updating [k]. + - if [strategy = `Merge], use {!val-merge} and ensure that concurrent + updates and merged with the values present at the beginning of the + transaction. + + {b Note:} Irmin transactions provides + {{:https://en.wikipedia.org/wiki/Snapshot_isolation} snapshot isolation} + guarantees: reads and writes are isolated in every transaction, but only + write conflicts are visible on commit. *) + + val with_tree_exn : + ?clear:bool -> + ?retries:int -> + ?allow_empty:bool -> + ?parents:commit list -> + ?strategy:[ `Set | `Test_and_set | `Merge ] -> + info:Info.f -> + t -> + path -> + (tree option -> tree option Lwt.t) -> + unit Lwt.t + (** [with_tree_exn] is like {!with_tree} but raise [Failure _] instead of + using a return type. *) + + (** {1 Clones} *) + + val clone : src:t -> dst:branch -> t Lwt.t + (** [clone ~src ~dst] makes [dst] points to [Head.get src]. [dst] is created + if needed. Remove the current contents en [dst] if [src] is {!empty}. *) + + (** {1 Watches} *) + + type watch + (** The type for store watches. *) + + val watch : t -> ?init:commit -> (commit Diff.t -> unit Lwt.t) -> watch Lwt.t + (** [watch t f] calls [f] every time the contents of [t]'s head is updated. + + {b Note:} even if [f] might skip some head updates, it will never be + called concurrently: all consecutive calls to [f] are done in sequence, so + we ensure that the previous one ended before calling the next one. *) + + val watch_key : + t -> + path -> + ?init:commit -> + ((commit * tree) Diff.t -> unit Lwt.t) -> + watch Lwt.t + (** [watch_key t key f] calls [f] every time the [key]'s value is added, + removed or updated. If the current branch is deleted, no signal is sent to + the watcher. *) + + val unwatch : watch -> unit Lwt.t + (** [unwatch w] disable [w]. Return once the [w] is fully disabled. *) + + (** {1 Merges and Common Ancestors} *) + + type 'a merge = + info:Info.f -> + ?max_depth:int -> + ?n:int -> + 'a -> + (unit, Merge.conflict) result Lwt.t + (** The type for merge functions. *) + + val merge_into : into:t -> t merge + (** [merge_into ~into:x ~info:i t] merges [t]'s current branch into [x]'s + current branch using the info [i]. After that operation, the two stores + are still independent. Similar to [git merge ]. *) + + val merge_with_branch : t -> branch merge + (** Same as {!val-merge} but with a branch ID. *) + + val merge_with_commit : t -> commit merge + (** Same as {!val-merge} but with a commit_id. *) + + val lcas : + ?max_depth:int -> ?n:int -> t -> t -> (commit list, lca_error) result Lwt.t + (** [lca ?max_depth ?n msg t1 t2] returns the collection of least common + ancestors between the heads of [t1] and [t2] branches. + + - [max_depth] is the maximum depth of the exploration (default is + [max_int]). Return [Error `Max_depth_reached] if this depth is exceeded. + - [n] is the maximum expected number of lcas. Stop the exploration as soon + as [n] lcas are found. Return [Error `Too_many_lcas] if more [lcas] are + found. *) + + val lcas_with_branch : + t -> + ?max_depth:int -> + ?n:int -> + branch -> + (commit list, lca_error) result Lwt.t + (** Same as {!lcas} but takes a branch ID as argument. *) + + val lcas_with_commit : + t -> + ?max_depth:int -> + ?n:int -> + commit -> + (commit list, lca_error) result Lwt.t + (** Same as {!lcas} but takes a commmit as argument. *) + + (** {1 History} *) + + module History : Graph.Sig.P with type V.t = commit + (** An history is a DAG of heads. *) + + val history : + ?depth:int -> ?min:commit list -> ?max:commit list -> t -> History.t Lwt.t + (** [history ?depth ?min ?max t] is a view of the history of the store [t], of + depth at most [depth], starting from the [t]'s head (or from [max] if the + head is not set) and stopping at [min] if specified. *) + + val last_modified : ?depth:int -> ?n:int -> t -> path -> commit list Lwt.t + (** [last_modified ?number c k] is the list of the last [number] commits that + modified [path], in ascending order of date. [depth] is the maximum depth + to be explored in the commit graph, if any. Default value for [number] is + 1. *) + + (** Manipulate branches. *) + module Branch : sig + (** {1 Branch Store} + + Manipulate relations between {{!branch} branches} and {{!commit} + commits}. *) + + val mem : repo -> branch -> bool Lwt.t + (** [mem r b] is true iff [b] is present in [r]. *) + + val find : repo -> branch -> commit option Lwt.t + (** [find r b] is [Some c] iff [c] is bound to [b] in [t]. It is [None] if + [b] is not present in [t]. *) + + val get : repo -> branch -> commit Lwt.t + (** [get t b] is similar to {!find} but raise [Invalid_argument] if [b] is + not present in [t]. *) + + val set : repo -> branch -> commit -> unit Lwt.t + (** [set t b c] bounds [c] to [b] in [t]. *) + + val remove : repo -> branch -> unit Lwt.t + (** [remove t b] removes [b] from [t]. *) + + val list : repo -> branch list Lwt.t + (** [list t] is the list of branches present in [t]. *) + + val watch : + repo -> + branch -> + ?init:commit -> + (commit Diff.t -> unit Lwt.t) -> + watch Lwt.t + (** [watch t b f] calls [f] on every change in [b]. *) + + val watch_all : + repo -> + ?init:(branch * commit) list -> + (branch -> commit Diff.t -> unit Lwt.t) -> + watch Lwt.t + (** [watch_all t f] calls [f] on every branch-related change in [t], + including creation/deletion events. *) + + include Branch.S with type t = branch + (** Base functions for branches. *) + end + + (** [Path] provides base functions for the stores's paths. *) + module Path : Path.S with type t = path and type step = step + + module Metadata : Metadata.S with type t = metadata + (** [Metadata] provides base functions for node metadata. *) + + (** Backend functions, which might be used by the backends. *) + module Backend : + Backend.S + with module Schema = Schema + with type Slice.t = slice + and type Repo.t = repo + and module Hash = Hash + and module Node.Path = Path + and type Contents.key = contents_key + and type Node.key = node_key + and type Commit.key = commit_key + + type Remote.t += + | E of Backend.Remote.endpoint + (** Extend the [remote] type with [endpoint]. *) + + (** {2 Converters to backend types} *) + + val of_backend_node : repo -> Backend.Node.value -> node + val to_backend_node : node -> Backend.Node.value Lwt.t + val to_backend_portable_node : node -> Backend.Node_portable.t Lwt.t + + val to_backend_commit : commit -> Backend.Commit.value + (** [to_backend_commit c] is the backend commit object associated with the + commit [c]. *) + + val of_backend_commit : + repo -> Backend.Commit.Key.t -> Backend.Commit.value -> commit + (** [of_backend_commit r k c] is the commit associated with the backend commit + object [c] that hash key [k] in [r]. *) + + val save_contents : + [> write ] Backend.Contents.t -> contents -> contents_key Lwt.t + (** Save a content into the database *) + + val save_tree : + ?clear:bool -> + repo -> + [> write ] Backend.Contents.t -> + [> read_write ] Backend.Node.t -> + tree -> + kinded_key Lwt.t + (** Save a tree into the database. Does not do any reads. + + When [clear] is set (the default), the tree cache is emptied upon the + function's completion, mirroring the effect of invoking {!Tree.clear}. *) + + (** {Deprecated} *) + + val master : repo -> t Lwt.t + [@@ocaml.deprecated "Use `main` instead."] + (** @deprecated Use {!main} instead *) +end + +module type S = sig + type hash + + (** @inline *) + include + S_generic_key + with type Schema.Hash.t = hash + and type hash := hash + and type contents_key = hash + and type node_key = hash + and type commit_key = hash +end + +module S_is_a_generic_keyed (X : S) : S_generic_key = X + +module type Maker_generic_key = sig + type endpoint + + include Key.Store_spec.S + + module Make (Schema : Schema.S) : + S_generic_key + with module Schema = Schema + and type Backend.Remote.endpoint = endpoint + and type contents_key = (Schema.Hash.t, Schema.Contents.t) contents_key + and type node_key = Schema.Hash.t node_key + and type commit_key = Schema.Hash.t commit_key +end + +module type Maker = + Maker_generic_key + with type ('h, _) contents_key = 'h + and type 'h node_key = 'h + and type 'h commit_key = 'h + +module type Json_tree = functor + (Store : S with type Schema.Contents.t = Contents.json) + -> sig + include Contents.S with type t = Contents.json + + val to_concrete_tree : t -> Store.Tree.concrete + val of_concrete_tree : Store.Tree.concrete -> t + + val get_tree : Store.tree -> Store.path -> t Lwt.t + (** Extract a [json] value from tree at the given key. *) + + val set_tree : Store.tree -> Store.path -> t -> Store.tree Lwt.t + (** Project a [json] value onto a tree at the given key. *) + + val get : Store.t -> Store.path -> t Lwt.t + (** Extract a [json] value from a store at the given key. *) + + val set : + Store.t -> Store.path -> t -> info:(unit -> Store.info) -> unit Lwt.t + (** Project a [json] value onto a store at the given key. *) +end + +module type KV_generic_key = + S_generic_key + with type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Branch.t = string + +module type KV = + S + with type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Branch.t = string + +module type KV_maker_generic_key = sig + type endpoint + type metadata + type hash + type info + + include Key.Store_spec.S + + module Make (C : Contents.S) : + KV_generic_key + with module Schema.Contents = C + and type Schema.Metadata.t = metadata + and type Backend.Remote.endpoint = endpoint + and type Schema.Hash.t = hash + and type contents_key = (hash, C.t) contents_key + and type node_key = hash node_key + and type commit_key = hash commit_key + and type Schema.Info.t = info +end + +module type KV_maker = + KV_maker_generic_key + with type ('h, _) contents_key = 'h + and type 'h node_key = 'h + and type 'h commit_key = 'h + +module type Sigs = sig + module type S = S + module type Maker = Maker + module type Json_tree = Json_tree + module type KV = KV + module type KV_maker = KV_maker + + module Generic_key : sig + module type S = S_generic_key + module type KV = KV_generic_key + module type Maker = Maker_generic_key + module type KV_maker = KV_maker_generic_key + end + + type Remote.t += + | Store : (module Generic_key.S with type t = 'a) * 'a -> Remote.t + + module Make (B : Backend.S) : + Generic_key.S + with module Schema = B.Schema + and type slice = B.Slice.t + and type repo = B.Repo.t + and type contents_key = B.Contents.key + and type node_key = B.Node.key + and type commit_key = B.Commit.key + and module Backend = B + + module Json_tree : Json_tree + (** [Json_tree] is used to project JSON values onto trees. Instead of the + entire object being stored under one key, it is split across several keys + starting at the specified root key. *) +end diff --git a/vendors/irmin/src/irmin/store_properties.ml b/vendors/irmin/src/irmin/store_properties.ml new file mode 100644 index 000000000000..8485c2f65e22 --- /dev/null +++ b/vendors/irmin/src/irmin/store_properties.ml @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Store_properties_intf + +exception Closed diff --git a/vendors/irmin/src/irmin/store_properties.mli b/vendors/irmin/src/irmin/store_properties.mli new file mode 100644 index 000000000000..5ac3f9086204 --- /dev/null +++ b/vendors/irmin/src/irmin/store_properties.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Store_properties_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/store_properties_intf.ml b/vendors/irmin/src/irmin/store_properties_intf.ml new file mode 100644 index 000000000000..ce56bf71dd6b --- /dev/null +++ b/vendors/irmin/src/irmin/store_properties_intf.ml @@ -0,0 +1,72 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Import + +module type Batch = sig + type 'a t + + val batch : read t -> ([ read | write ] t -> 'a Lwt.t) -> 'a Lwt.t + (** [batch t f] applies the writes in [f] in a separate batch. The exact + guarantees depend on the implementation. *) +end + +module type Closeable = sig + type 'a t + + val close : 'a t -> unit Lwt.t + (** [close t] frees up all the resources associated with [t]. Any operations + run on a closed handle will raise [Closed]. *) +end + +module type Of_config = sig + type 'a t + + val v : Conf.t -> read t Lwt.t + (** [v config] is a function returning fresh store handles, with the + configuration [config], which is provided by the backend. *) +end + +module type Clearable = sig + type 'a t + + val clear : 'a t -> unit Lwt.t + (** Clear the store. This operation is expected to be slow. *) +end + +module type Sigs = sig + exception Closed + + module type Batch = sig + include Batch + (** @inline *) + end + + module type Closeable = sig + include Closeable + (** @inline *) + end + + module type Of_config = sig + include Of_config + (** @inline *) + end + + module type Clearable = sig + include Clearable + (** @inline *) + end +end diff --git a/vendors/irmin/src/irmin/sync.ml b/vendors/irmin/src/irmin/sync.ml new file mode 100644 index 000000000000..513c72b68994 --- /dev/null +++ b/vendors/irmin/src/irmin/sync.ml @@ -0,0 +1,221 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Sync_intf + +module type REMOTE = Remote.S + +let invalid_argf fmt = Fmt.kstr Lwt.fail_invalid_arg fmt +let src = Logs.Src.create "irmin.sync" ~doc:"Irmin remote sync" + +module Log = (val Logs.src_log src : Logs.LOG) + +let remote_store m x = Store.Store (m, x) + +module Make (S : Store.Generic_key.S) = struct + module B = S.Backend.Remote + + type db = S.t + type commit = S.commit + type commit_key = S.commit_key [@@deriving irmin ~pp] + type info = S.info + + let conv dx dy = + let dx_to_bin_string = Type.(unstage (to_bin_string dx)) in + let dy_of_bin_string = Type.(unstage (of_bin_string dy)) in + Type.stage (fun x -> dy_of_bin_string (dx_to_bin_string x)) + + let convert_slice (type r s) (module RP : Backend.S with type Slice.t = r) + (module SP : Backend.S with type Slice.t = s) r = + let conv_contents_k = + Type.unstage (conv RP.Contents.Hash.t SP.Contents.Hash.t) + in + let conv_contents_v = + Type.unstage (conv RP.Contents.Val.t SP.Contents.Val.t) + in + let conv_node_k = Type.unstage (conv RP.Node.Hash.t SP.Node.Hash.t) in + let conv_node_v = Type.unstage (conv RP.Node.Val.t SP.Node.Val.t) in + let conv_commit_k = Type.unstage (conv RP.Commit.Hash.t SP.Commit.Hash.t) in + let conv_commit_v = Type.unstage (conv RP.Commit.Val.t SP.Commit.Val.t) in + let* s = SP.Slice.empty () in + let* () = + RP.Slice.iter r (function + | `Contents (k, v) -> ( + let k = conv_contents_k k in + let v = conv_contents_v v in + match (k, v) with + | Ok k, Ok v -> SP.Slice.add s (`Contents (k, v)) + | _ -> Lwt.return_unit) + | `Node (k, v) -> ( + let k = conv_node_k k in + let v = conv_node_v v in + match (k, v) with + | Ok k, Ok v -> SP.Slice.add s (`Node (k, v)) + | _ -> Lwt.return_unit) + | `Commit (k, v) -> ( + let k = conv_commit_k k in + let v = conv_commit_v v in + match (k, v) with + | Ok k, Ok v -> SP.Slice.add s (`Commit (k, v)) + | _ -> Lwt.return_unit)) + in + Lwt.return s + + let convs src dst l = + let conv = Type.unstage (conv src dst) in + List.fold_left + (fun acc x -> match conv x with Ok x -> x :: acc | _ -> acc) + [] l + + let pp_branch = Type.pp S.Branch.t + + type status = [ `Empty | `Head of commit ] + + let pp_status ppf = function + | `Empty -> Fmt.string ppf "empty" + | `Head c -> S.Commit.pp_hash ppf c + + let status_t t = + let open Type in + variant "status" (fun empty head -> function + | `Empty -> empty | `Head c -> head c) + |~ case0 "empty" `Empty + |~ case1 "head" S.(commit_t @@ repo t) (fun c -> `Head c) + |> sealv + + let fetch t ?depth remote = + match remote with + | Store.Store ((module R), r) -> ( + [%log.debug "fetch store"]; + let s_repo = S.repo t in + let r_repo = R.repo r in + let conv = + Type.unstage (conv R.(commit_t r_repo) S.(commit_t s_repo)) + in + let* min = S.Repo.heads s_repo in + let min = convs S.(commit_t s_repo) R.(commit_t r_repo) min in + R.Head.find r >>= function + | None -> Lwt.return (Ok `Empty) + | Some h -> ( + let* r_slice = + R.Repo.export (R.repo r) ?depth ~min ~max:(`Max [ h ]) + in + let* s_slice = + convert_slice (module R.Backend) (module S.Backend) r_slice + in + S.Repo.import s_repo s_slice >|= function + | Error e -> Error e + | Ok () -> ( + match conv h with Ok h -> Ok (`Head h) | Error e -> Error e))) + | S.E e -> ( + match S.status t with + | `Empty | `Commit _ -> Lwt.return (Ok `Empty) + | `Branch br -> ( + [%log.debug "Fetching branch %a" pp_branch br]; + let* g = B.v (S.repo t) in + B.fetch g ?depth e br >>= function + | Error _ as e -> Lwt.return e + | Ok (Some key) -> ( + [%log.debug "Fetched %a" pp_commit_key key]; + S.Commit.of_key (S.repo t) key >|= function + | None -> Ok `Empty + | Some x -> Ok (`Head x)) + | Ok None -> ( + S.Head.find t >>= function + | Some h -> Lwt.return (Ok (`Head h)) + | None -> Lwt.return (Ok `Empty)))) + | _ -> Lwt.return (Error (`Msg "fetch operation is not available")) + + let fetch_exn t ?depth remote = + fetch t ?depth remote >>= function + | Ok h -> Lwt.return h + | Error (`Msg e) -> invalid_argf "Sync.fetch_exn: %s" e + + type pull_error = [ `Msg of string | Merge.conflict ] + + let pp_pull_error ppf = function + | `Msg s -> Fmt.string ppf s + | `Conflict c -> Fmt.pf ppf "conflict: %s" c + + let pull t ?depth remote kind : (status, pull_error) result Lwt.t = + fetch t ?depth remote >>= function + | Error e -> Lwt.return (Error (e :> pull_error)) + | Ok (`Head k) -> ( + match kind with + | `Set -> S.Head.set t k >|= fun () -> Ok (`Head k) + | `Merge info -> ( + S.Head.merge ~into:t ~info k >>= function + | Ok () -> Lwt.return (Ok (`Head k)) + | Error e -> Lwt.return (Error (e :> pull_error)))) + | Ok `Empty -> Lwt.return (Ok `Empty) + + let pull_exn t ?depth remote kind = + pull t ?depth remote kind >>= function + | Ok x -> Lwt.return x + | Error e -> invalid_argf "Sync.pull_exn: %a" pp_pull_error e + + type push_error = [ `Msg of string | `Detached_head ] + + let pp_push_error ppf = function + | `Msg s -> Fmt.string ppf s + | `Detached_head -> Fmt.string ppf "cannot push to a non-persistent store" + + let push t ?depth remote = + [%log.debug "push"]; + match remote with + | Store.Store ((module R), r) -> ( + S.Head.find t >>= function + | None -> Lwt.return (Ok `Empty) + | Some h -> ( + [%log.debug "push store"]; + let* min = R.Repo.heads (R.repo r) in + let r_repo = R.repo r in + let s_repo = S.repo t in + let min = convs R.(commit_t r_repo) S.(commit_t s_repo) min in + let conv = + Type.unstage (conv S.(commit_t s_repo) R.(commit_t r_repo)) + in + let* s_slice = S.Repo.export (S.repo t) ?depth ~min in + let* r_slice = + convert_slice (module S.Backend) (module R.Backend) s_slice + in + R.Repo.import (R.repo r) r_slice >>= function + | Error e -> Lwt.return (Error (e :> push_error)) + | Ok () -> ( + match conv h with + | Error e -> Lwt.return (Error (e :> push_error)) + | Ok h -> + R.Head.set r h >>= fun () -> + let+ head = S.Head.get t in + Ok (`Head head)))) + | S.E e -> ( + match S.status t with + | `Empty -> Lwt.return (Ok `Empty) + | `Commit _ -> Lwt.return (Error `Detached_head) + | `Branch br -> ( + let* head = S.of_branch (S.repo t) br >>= S.Head.get in + let* g = B.v (S.repo t) in + B.push g ?depth e br >>= function + | Ok () -> Lwt.return (Ok (`Head head)) + | Error err -> Lwt.return (Error (err :> push_error)))) + | _ -> Lwt.return (Error (`Msg "push operation is not available")) + + let push_exn t ?depth remote = + push t ?depth remote >>= function + | Ok x -> Lwt.return x + | Error e -> invalid_argf "Sync.push_exn: %a" pp_push_error e +end diff --git a/vendors/irmin/src/irmin/sync.mli b/vendors/irmin/src/irmin/sync.mli new file mode 100644 index 000000000000..7a9e317dee37 --- /dev/null +++ b/vendors/irmin/src/irmin/sync.mli @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Store Synchronisation. *) + +include Sync_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/sync_intf.ml b/vendors/irmin/src/irmin/sync_intf.ml new file mode 100644 index 000000000000..1260e8665ca4 --- /dev/null +++ b/vendors/irmin/src/irmin/sync_intf.ml @@ -0,0 +1,102 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** {1 Native Synchronization} *) + + type db + (** Type type for store handles. *) + + type commit + (** The type for store heads. *) + + type status = [ `Empty | `Head of commit ] + (** The type for remote status. *) + + type info + (** The type for commit info. *) + + val status_t : db -> status Type.t + (** [status_t db] is the value type for {!status} of remote [db]. *) + + val pp_status : status Fmt.t + (** [pp_status] pretty-prints return statuses. *) + + val fetch : + db -> ?depth:int -> Remote.t -> (status, [ `Msg of string ]) result Lwt.t + (** [fetch t ?depth r] populate the local store [t] with objects from the + remote store [r], using [t]'s current branch. The [depth] parameter limits + the history depth. Return [`Empty] if either the local or remote store do + not have a valid head. *) + + val fetch_exn : db -> ?depth:int -> Remote.t -> status Lwt.t + (** Same as {!fetch} but raise [Invalid_argument] if either the local or + remote store do not have a valid head. *) + + type pull_error = [ `Msg of string | Merge.conflict ] + (** The type for pull errors. *) + + val pp_pull_error : pull_error Fmt.t + (** [pp_pull_error] pretty-prints pull errors. *) + + val pull : + db -> + ?depth:int -> + Remote.t -> + [ `Merge of unit -> info | `Set ] -> + (status, pull_error) result Lwt.t + (** [pull t ?depth r s] is similar to {{!Sync.fetch} fetch} but it also + updates [t]'s current branch. [s] is the update strategy: + + - [`Merge] uses [Head.merge]. Can return a conflict. + - [`Set] uses [S.Head.set]. *) + + val pull_exn : + db -> + ?depth:int -> + Remote.t -> + [ `Merge of unit -> info | `Set ] -> + status Lwt.t + (** Same as {!pull} but raise [Invalid_arg] in case of conflict. *) + + type push_error = [ `Msg of string | `Detached_head ] + (** The type for push errors. *) + + val pp_push_error : push_error Fmt.t + (** [pp_push_error] pretty-prints push errors. *) + + val push : db -> ?depth:int -> Remote.t -> (status, push_error) result Lwt.t + (** [push t ?depth r] populates the remote store [r] with objects from the + current store [t], using [t]'s current branch. If [b] is [t]'s current + branch, [push] also updates the head of [b] in [r] to be the same as in + [t]. + + {b Note:} {e Git} semantics is to update [b] only if the new head if more + recent. This is not the case in {e Irmin}. *) + + val push_exn : db -> ?depth:int -> Remote.t -> status Lwt.t + (** Same as {!push} but raise [Invalid_argument] if an error happens. *) +end + +module type Sigs = sig + module type S = S + + val remote_store : + (module Store.Generic_key.S with type t = 'a) -> 'a -> Remote.t + + module Make (X : Store.Generic_key.S) : + S with type db = X.t and type commit = X.commit and type info = X.info +end diff --git a/vendors/irmin/src/irmin/tree.ml b/vendors/irmin/src/irmin/tree.ml new file mode 100644 index 000000000000..3906ba14c822 --- /dev/null +++ b/vendors/irmin/src/irmin/tree.ml @@ -0,0 +1,2854 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2017 Grégoire Henry + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Tree_intf + +let src = Logs.Src.create "irmin.tree" ~doc:"Persistent lazy trees for Irmin" + +module Log = (val Logs.src_log src : Logs.LOG) + +type fuzzy_bool = False | True | Maybe +type ('a, 'r) cont = ('a -> 'r) -> 'r +type ('a, 'r) cont_lwt = ('a, 'r Lwt.t) cont + +let ok x = Lwt.return (Ok x) + +(* assume l1 and l2 are key-sorted *) +let alist_iter2 compare_k f l1 l2 = + let rec aux l1 l2 = + match (l1, l2) with + | [], t -> List.iter (fun (key, v) -> f key (`Right v)) t + | t, [] -> List.iter (fun (key, v) -> f key (`Left v)) t + | (k1, v1) :: t1, (k2, v2) :: t2 -> ( + match compare_k k1 k2 with + | 0 -> + f k1 (`Both (v1, v2)); + (aux [@tailcall]) t1 t2 + | x -> + if x < 0 then ( + f k1 (`Left v1); + (aux [@tailcall]) t1 l2) + else ( + f k2 (`Right v2); + (aux [@tailcall]) l1 t2)) + in + aux l1 l2 + +(* assume l1 and l2 are key-sorted *) +let alist_iter2_lwt compare_k f l1 l2 = + let l3 = ref [] in + alist_iter2 compare_k (fun left right -> l3 := f left right :: !l3) l1 l2; + Lwt_list.iter_s (fun b -> b >>= fun () -> Lwt.return_unit) (List.rev !l3) + +exception Backend_invariant_violation of string +exception Assertion_failure of string + +let backend_invariant_violation fmt = + Fmt.kstr (fun s -> raise (Backend_invariant_violation s)) fmt + +let assertion_failure fmt = Fmt.kstr (fun s -> raise (Assertion_failure s)) fmt + +module Make (P : Backend.S) = struct + type counters = { + mutable contents_hash : int; + mutable contents_find : int; + mutable contents_add : int; + mutable contents_mem : int; + mutable node_hash : int; + mutable node_mem : int; + mutable node_index : int; + mutable node_add : int; + mutable node_find : int; + mutable node_val_v : int; + mutable node_val_find : int; + mutable node_val_list : int; + } + [@@deriving irmin] + + let dump_counters ppf t = Type.pp_json ~minify:false counters_t ppf t + + let fresh_counters () = + { + contents_hash = 0; + contents_add = 0; + contents_find = 0; + contents_mem = 0; + node_hash = 0; + node_mem = 0; + node_index = 0; + node_add = 0; + node_find = 0; + node_val_v = 0; + node_val_find = 0; + node_val_list = 0; + } + + let reset_counters t = + t.contents_hash <- 0; + t.contents_add <- 0; + t.contents_find <- 0; + t.contents_mem <- 0; + t.node_hash <- 0; + t.node_mem <- 0; + t.node_index <- 0; + t.node_add <- 0; + t.node_find <- 0; + t.node_val_v <- 0; + t.node_val_find <- 0; + t.node_val_list <- 0 + + let cnt = fresh_counters () + + module Path = struct + include P.Node.Path + + let fold_right t ~f ~init = + let steps = map t Fun.id in + List.fold_right f steps init + end + + module Metadata = P.Node.Metadata + module Irmin_proof = Proof + module Tree_proof = Proof.Make (P.Contents.Val) (P.Hash) (Path) (Metadata) + module Env = Proof.Env (P) (Tree_proof) + + let merge_env x y = + match (Env.is_empty x, Env.is_empty y) with + | true, _ -> Ok y + | _, true -> Ok x + | false, false -> Error (`Conflict "merge env") + + module Hashes = Hash.Set.Make (P.Hash) + + module StepMap = struct + module X = struct + type t = Path.step [@@deriving irmin ~compare] + end + + include Map.Make (X) + + let stdlib_merge = merge + + include Merge.Map (X) + + let to_array m = + let length = cardinal m in + if length = 0 then [||] + else + let arr = Array.make length (choose m) in + let (_ : int) = + fold + (fun k v i -> + arr.(i) <- (k, v); + i + 1) + m 0 + in + arr + end + + type metadata = Metadata.t [@@deriving irmin ~equal] + type path = Path.t [@@deriving irmin ~pp] + type hash = P.Hash.t [@@deriving irmin ~pp ~equal ~compare] + type step = Path.step [@@deriving irmin ~pp ~compare] + type contents = P.Contents.Val.t [@@deriving irmin ~equal ~pp] + type repo = P.Repo.t + type marks = Hashes.t + + type error = + [ `Dangling_hash of hash | `Pruned_hash of hash | `Portable_value ] + + type 'a or_error = ('a, error) result + type 'a force = [ `True | `False of path -> 'a -> 'a Lwt.t ] + type uniq = [ `False | `True | `Marks of marks ] + type ('a, 'b) folder = path -> 'b -> 'a -> 'a Lwt.t + + type depth = [ `Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int ] + [@@deriving irmin] + + let dummy_marks = Hashes.create ~initial_slots:0 () + let empty_marks () = Hashes.create ~initial_slots:39 () + + exception Pruned_hash of { context : string; hash : hash } + exception Dangling_hash of { context : string; hash : hash } + exception Portable_value of { context : string } + + let () = + Printexc.register_printer (function + | Dangling_hash { context; hash } -> + Some + (Fmt.str "Irmin.Tree.%s: encountered dangling hash %a" context + pp_hash hash) + | Pruned_hash { context; hash } -> + Some + (Fmt.str "Irmin.Tree.%s: encountered pruned hash %a" context pp_hash + hash) + | Portable_value { context } -> + Some + (Fmt.str "Irmin.Tree.%s: unsupported operation on portable tree." + context) + | _ -> None) + + let err_pruned_hash h = Error (`Pruned_hash h) + let err_dangling_hash h = Error (`Dangling_hash h) + let err_portable_value = Error `Portable_value + let pruned_hash_exn context hash = raise (Pruned_hash { context; hash }) + let portable_value_exn context = raise (Portable_value { context }) + + let get_ok : type a. string -> a or_error -> a = + fun context -> function + | Ok x -> x + | Error (`Pruned_hash hash) -> pruned_hash_exn context hash + | Error (`Dangling_hash hash) -> raise (Dangling_hash { context; hash }) + | Error `Portable_value -> portable_value_exn context + + type 'key ptr_option = Key of 'key | Hash of hash | Ptr_none + (* NOTE: given the choice, we prefer caching [Key] over [Hash] as it can + be used to avoid storing duplicate contents values on export. *) + + module Contents = struct + type key = P.Contents.Key.t [@@deriving irmin] + type v = Key of repo * key | Value of contents | Pruned of hash + type nonrec ptr_option = key ptr_option + + type info = { + mutable ptr : ptr_option; + mutable value : contents option; + env : Env.t; + } + + type t = { mutable v : v; info : info } + + let info_is_empty i = i.ptr = Ptr_none && i.value = None + + let v = + let open Type in + variant "Node.Contents.v" (fun key value pruned (v : v) -> + match v with + | Key (_, x) -> key x + | Value v -> value v + | Pruned h -> pruned h) + |~ case1 "key" P.Contents.Key.t (fun _ -> assert false) + |~ case1 "value" P.Contents.Val.t (fun v -> Value v) + |~ case1 "pruned" hash_t (fun h -> Pruned h) + |> sealv + + let clear_info i = + if not (info_is_empty i) then ( + i.value <- None; + i.ptr <- Ptr_none) + + let clear t = clear_info t.info + + let of_v ~env (v : v) = + let ptr, value = + match v with + | Key (_, k) -> ((Key k : ptr_option), None) + | Value v -> (Ptr_none, Some v) + | Pruned _ -> (Ptr_none, None) + in + let info = { ptr; value; env } in + { v; info } + + let export ?clear:(c = true) repo t k = + let ptr = t.info.ptr in + if c then clear t; + match (t.v, ptr) with + | Key (repo', _), (Ptr_none | Hash _) -> + if repo != repo' then t.v <- Key (repo, k) + | Key (repo', _), Key k -> if repo != repo' then t.v <- Key (repo, k) + | Value _, (Ptr_none | Hash _) -> t.v <- Key (repo, k) + | Value _, Key k -> t.v <- Key (repo, k) + | Pruned _, _ -> + (* The main export function never exports a pruned position. *) + assert false + + let of_value c = of_v (Value c) + let of_key repo k = of_v (Key (repo, k)) + let pruned h = of_v (Pruned h) + + let cached_hash t = + match (t.v, t.info.ptr) with + | Key (_, k), _ -> Some (P.Contents.Key.to_hash k) + | Value _, Key k -> Some (P.Contents.Key.to_hash k) + | Pruned h, _ -> Some h + | Value _, Hash h -> Some h + | Value _, Ptr_none -> None + + let cached_key t = + match (t.v, t.info.ptr) with + | Key (_, k), _ -> Some k + | (Value _ | Pruned _), Key k -> Some k + | (Value _ | Pruned _), (Hash _ | Ptr_none) -> None + + let cached_value t = + match (t.v, t.info.value) with + | Value v, None -> Some v + | (Key _ | Value _ | Pruned _), (Some _ as v) -> v + | (Key _ | Pruned _), None -> ( + match cached_hash t with + | None -> None + | Some h -> ( + match Env.find_contents t.info.env h with + | None -> None + | Some c -> Some c)) + + let hash ?(cache = true) c = + match cached_hash c with + | Some k -> k + | None -> ( + match cached_value c with + | None -> assert false + | Some v -> + cnt.contents_hash <- cnt.contents_hash + 1; + let h = P.Contents.Hash.hash v in + assert (c.info.ptr = Ptr_none); + if cache then c.info.ptr <- Hash h; + h) + + let key t = + match t.v with Key (_, k) -> Some k | Value _ | Pruned _ -> None + + let value_of_key ~cache t repo k = + cnt.contents_find <- cnt.contents_find + 1; + let h = P.Contents.Key.to_hash k in + let+ v_opt = P.Contents.find (P.Repo.contents_t repo) k in + Option.iter (Env.add_contents_from_store t.info.env h) v_opt; + match v_opt with + | None -> err_dangling_hash h + | Some v -> + if cache then t.info.value <- v_opt; + Ok v + + let to_value ~cache t = + match cached_value t with + | Some v -> ok v + | None -> ( + match t.v with + | Value _ -> assert false (* [cached_value == None] *) + | Key (repo, k) -> value_of_key ~cache t repo k + | Pruned h -> err_pruned_hash h |> Lwt.return) + + let force = to_value ~cache:true + + let force_exn t = + let+ v = force t in + get_ok "force" v + + let equal (x : t) (y : t) = + x == y + || + match (cached_hash x, cached_hash y) with + | Some x, Some y -> equal_hash x y + | _ -> ( + match (cached_value x, cached_value y) with + | Some x, Some y -> equal_contents x y + | _ -> equal_hash (hash ~cache:true x) (hash ~cache:true y)) + + let compare (x : t) (y : t) = + if x == y then 0 + else compare_hash (hash ~cache:true x) (hash ~cache:true y) + + let t = + let of_v v = of_v ~env:(Env.empty ()) v in + Type.map ~equal ~compare v of_v (fun t -> t.v) + + let merge : t Merge.t = + let f ~old x y = + let old = + Merge.bind_promise old (fun old () -> + let+ c = to_value ~cache:true old >|= Option.of_result in + Ok (Some c)) + in + match merge_env x.info.env y.info.env with + | Error _ as e -> Lwt.return e + | Ok env -> ( + let* x = to_value ~cache:true x >|= Option.of_result in + let* y = to_value ~cache:true y >|= Option.of_result in + Merge.(f P.Contents.Val.merge) ~old x y >|= function + | Ok (Some c) -> Ok (of_value ~env c) + | Ok None -> Error (`Conflict "empty contents") + | Error _ as e -> e) + in + Merge.v t f + + let fold ~force ~cache ~path f_value f_tree t acc = + match force with + | `True -> + let* c = to_value ~cache t in + f_value path (get_ok "fold" c) acc >>= f_tree path + | `False skip -> ( + match cached_value t with + | None -> skip path acc + | Some c -> f_value path c acc >>= f_tree path) + end + + module Node = struct + type value = P.Node.Val.t [@@deriving irmin ~equal ~pp] + type key = P.Node.Key.t [@@deriving irmin] + type nonrec ptr_option = key ptr_option + + open struct + module Portable = P.Node_portable + end + + type portable = Portable.t [@@deriving irmin ~equal ~pp] + + (* [elt] is a tree *) + type elt = [ `Node of t | `Contents of Contents.t * Metadata.t ] + and update = Add of elt | Remove + and updatemap = update StepMap.t + and map = elt StepMap.t + + and info = { + mutable value : value option; + mutable map : map option; + mutable ptr : ptr_option; + mutable findv_cache : map option; + env : Env.t; + } + + and v = + | Map of map + | Key of repo * key + | Value of repo * value * updatemap option + | Portable_dirty of portable * updatemap + | Pruned of hash + + and t = { mutable v : v; info : info } + (** For discussion of [t.v]'s states, see {!Tree_intf.S.inspect}. + + [t.info.map] is only populated during a call to [Node.to_map]. *) + + let elt_t (t : t Type.t) : elt Type.t = + let open Type in + variant "Node.value" (fun node contents contents_m -> function + | `Node x -> node x + | `Contents (c, m) -> + if equal_metadata m Metadata.default then contents c + else contents_m (c, m)) + |~ case1 "Node" t (fun x -> `Node x) + |~ case1 "Contents" Contents.t (fun x -> `Contents (x, Metadata.default)) + |~ case1 "Contents-x" (pair Contents.t Metadata.t) (fun x -> `Contents x) + |> sealv + + let stepmap_t : 'a. 'a Type.t -> 'a StepMap.t Type.t = + fun elt -> + let open Type in + let to_map x = + List.fold_left (fun acc (k, v) -> StepMap.add k v acc) StepMap.empty x + in + let of_map m = StepMap.fold (fun k v acc -> (k, v) :: acc) m [] in + map (list (pair Path.step_t elt)) to_map of_map + + let update_t (elt : elt Type.t) : update Type.t = + let open Type in + variant "Node.update" (fun add remove -> function + | Add elt -> add elt | Remove -> remove) + |~ case1 "add" elt (fun elt -> Add elt) + |~ case0 "remove" Remove + |> sealv + + let v_t (elt : elt Type.t) : v Type.t = + let m = stepmap_t elt in + let um = stepmap_t (update_t elt) in + let open Type in + variant "Node.node" (fun map key value pruned portable_dirty -> function + | Map m -> map m + | Key (_, y) -> key y + | Value (_, v, m) -> value (v, m) + | Pruned h -> pruned h + | Portable_dirty (v, m) -> portable_dirty (v, m)) + |~ case1 "map" m (fun m -> Map m) + |~ case1 "key" P.Node.Key.t (fun _ -> assert false) + |~ case1 "value" (pair P.Node.Val.t (option um)) (fun _ -> assert false) + |~ case1 "pruned" hash_t (fun h -> Pruned h) + |~ case1 "portable_dirty" (pair portable_t um) (fun (v, m) -> + Portable_dirty (v, m)) + |> sealv + + let of_v ~env v = + let ptr, map, value = + match v with + | Map m -> (Ptr_none, Some m, None) + | Key (_, k) -> (Key k, None, None) + | Value (_, v, None) -> (Ptr_none, None, Some v) + | Value _ | Portable_dirty _ | Pruned _ -> (Ptr_none, None, None) + in + let findv_cache = None in + let info = { ptr; map; value; findv_cache; env } in + { v; info } + + let of_map m = of_v (Map m) + let of_key repo k = of_v (Key (repo, k)) + let of_value ?updates repo v = of_v (Value (repo, v, updates)) + let of_portable_dirty p updates = of_v (Portable_dirty (p, updates)) + let pruned h = of_v (Pruned h) + + let info_is_empty i = + i.map = None && i.value = None && i.findv_cache = None && i.ptr = Ptr_none + + let add_to_findv_cache t step v = + match t.info.findv_cache with + | None -> t.info.findv_cache <- Some (StepMap.singleton step v) + | Some m -> t.info.findv_cache <- Some (StepMap.add step v m) + + let clear_info_fields i = + if not (info_is_empty i) then ( + i.value <- None; + i.map <- None; + i.ptr <- Ptr_none; + i.findv_cache <- None) + + let rec clear_elt ~max_depth depth v = + match v with + | `Contents (c, _) -> if depth + 1 > max_depth then Contents.clear c + | `Node t -> clear ~max_depth (depth + 1) t + + and clear_info ~max_depth ~v depth i = + let clear _ v = clear_elt ~max_depth depth v in + let () = + match v with + | Value (_, _, Some um) -> + StepMap.iter + (fun k -> function Remove -> () | Add v -> clear k v) + um + | Value (_, _, None) | Map _ | Key _ | Portable_dirty _ | Pruned _ -> () + in + let () = + match (v, i.map) with + | Map m, _ | (Key _ | Value _ | Portable_dirty _ | Pruned _), Some m -> + StepMap.iter clear m + | (Key _ | Value _ | Portable_dirty _ | Pruned _), None -> () + in + let () = + match i.findv_cache with Some m -> StepMap.iter clear m | None -> () + in + if depth >= max_depth then clear_info_fields i + + and clear ~max_depth depth t = clear_info ~v:t.v ~max_depth depth t.info + + (* export t to the given repo and clear the cache *) + let export ?clear:(c = true) repo t k = + let ptr = t.info.ptr in + if c then clear_info_fields t.info; + match t.v with + | Key (repo', k) -> if repo != repo' then t.v <- Key (repo, k) + | Value _ | Map _ -> ( + match ptr with + | Ptr_none | Hash _ -> t.v <- Key (repo, k) + | Key k -> t.v <- Key (repo, k)) + | Portable_dirty _ | Pruned _ -> + (* The main export function never exports a pruned position. *) + assert false + + module Core_value + (N : Node.Generic_key.Core + with type step := step + and type hash := hash + and type metadata := metadata) + (To_elt : sig + type repo + + val t : env:Env.t -> repo -> N.value -> elt + end) = + struct + let to_map ~cache ~env repo t = + cnt.node_val_list <- cnt.node_val_list + 1; + let entries = N.seq ~cache t in + Seq.fold_left + (fun acc (k, v) -> StepMap.add k (To_elt.t ~env repo v) acc) + StepMap.empty entries + + (** Does [um] empties [v]? + + Gotcha: Some [Remove] entries in [um] might not be in [v]. *) + let is_empty_after_updates ~cache t um = + let any_add = + StepMap.to_seq um + |> Seq.exists (function _, Remove -> false | _, Add _ -> true) + in + if any_add then false + else + let val_is_empty = N.is_empty t in + if val_is_empty then true + else + let remove_count = StepMap.cardinal um in + if (not val_is_empty) && remove_count = 0 then false + else if N.length t > remove_count then false + else ( + (* Starting from this point the function is expensive, but there is + no alternative. *) + cnt.node_val_list <- cnt.node_val_list + 1; + let entries = N.seq ~cache t in + Seq.for_all (fun (step, _) -> StepMap.mem step um) entries) + + let findv ~cache ~env step node repo t = + match N.find ~cache t step with + | None -> None + | Some v -> + let tree = To_elt.t ~env repo v in + if cache then add_to_findv_cache node step tree; + Some tree + + let seq ~env ?offset ?length ~cache repo v = + cnt.node_val_list <- cnt.node_val_list + 1; + let seq = N.seq ?offset ?length ~cache v in + Seq.map (fun (k, v) -> (k, To_elt.t ~env repo v)) seq + end + + module Regular_value = + Core_value + (P.Node.Val) + (struct + type nonrec repo = repo + + let t ~env repo = function + | `Node k -> `Node (of_key ~env repo k) + | `Contents (k, m) -> `Contents (Contents.of_key ~env repo k, m) + end) + + module Portable_value = + Core_value + (P.Node_portable) + (struct + type repo = unit + + let t ~env () = function + | `Node h -> `Node (pruned ~env h) + | `Contents (h, m) -> `Contents (Contents.pruned ~env h, m) + end) + + (** This [Scan] module contains function that scan the content of [t.v] and + [t.info], looking for specific patterns. *) + module Scan = struct + let iter_hash t hit miss miss_arg = + match (t.v, t.info.ptr) with + | Key (_, k), _ -> hit (P.Node.Key.to_hash k) + | (Map _ | Value _ | Portable_dirty _), Key k -> + hit (P.Node.Key.to_hash k) + | Pruned h, _ -> hit h + | (Map _ | Value _ | Portable_dirty _), Hash h -> hit h + | (Map _ | Value _ | Portable_dirty _), Ptr_none -> miss t miss_arg + + let iter_key t hit miss miss_arg = + match (t.v, t.info.ptr) with + | Key (_, k), _ -> hit k + | (Map _ | Value _ | Portable_dirty _ | Pruned _), Key k -> hit k + | (Map _ | Value _ | Portable_dirty _ | Pruned _), (Hash _ | Ptr_none) + -> + miss t miss_arg + + let iter_map t hit miss miss_arg = + match (t.v, t.info.map) with + | (Key _ | Value _ | Portable_dirty _ | Pruned _), Some m -> hit m + | Map m, _ -> hit m + | (Key _ | Value _ | Portable_dirty _ | Pruned _), None -> + miss t miss_arg + + let iter_value t hit miss miss_arg = + match (t.v, t.info.value) with + | Value (_, v, None), None -> hit v + | (Map _ | Key _ | Value _ | Portable_dirty _ | Pruned _), Some v -> + hit v + | ( (Map _ | Key _ | Value (_, _, Some _) | Portable_dirty _ | Pruned _), + None ) -> + iter_hash t + (fun h -> + (* The need for [t], [miss] and [miss_arg] allocates a closure *) + match Env.find_node t.info.env h with + | None -> miss t miss_arg + | Some v -> hit v) + miss miss_arg + + let iter_portable t hit miss miss_arg = + match t.v with + | Pruned h -> ( + match Env.find_pnode t.info.env h with + | None -> miss t miss_arg + | Some v -> hit v) + | Map _ | Key _ | Value _ | Portable_dirty _ -> + (* No need to peek in [env]in these cases because [env] + is in practice expected to only hit on [Pruned]. *) + miss t miss_arg + + let iter_repo_key t hit miss miss_arg = + match (t.v, t.info.ptr) with + | Key (repo, k), _ -> hit repo k + | Value (repo, _, _), Key k -> hit repo k + | (Map _ | Portable_dirty _ | Pruned _ | Value _), _ -> miss t miss_arg + + let iter_repo_value t hit miss miss_arg = + match (t.v, t.info.value) with + | Value (repo, v, None), _ -> hit repo v + | (Value (repo, _, _) | Key (repo, _)), Some v -> hit repo v + | (Value (repo, _, _) | Key (repo, _)), None -> + iter_hash t + (fun h -> + match Env.find_node t.info.env h with + | None -> miss t miss_arg + | Some v -> hit repo v) + miss miss_arg + | (Map _ | Portable_dirty _ | Pruned _), _ -> miss t miss_arg + + type node = t + + (** An instance of [t] is expected to be the result of a chain of [to_*] + function calls. + + The [to_*] functions scan a [node] and look for a specific pattern. + The first function in the chain to match a pattern will return the + instance of [t] and ignore the rest of the chain. + + The functions in the chain should be carefuly ordered so that the + computation that follows is as quick as possible (e.g. if the goal is + to convert a [node] to hash, [to_hash] should be checked before + [to_map]). + + [cascade] may be used in order to build chains. *) + + type _ t = + | Hash : hash -> [> `hash ] t + | Map : map -> [> `map ] t + | Value : value -> [> `value ] t + | Value_dirty : (repo * value * updatemap) -> [> `value_dirty ] t + | Portable : portable -> [> `portable ] t + | Portable_dirty : (portable * updatemap) -> [> `portable_dirty ] t + | Pruned : hash -> [> `pruned ] t + | Repo_key : (repo * key) -> [> `repo_key ] t + | Repo_value : (repo * value) -> [> `repo_value ] t + | Any : [> `any ] t + + module View_kind = struct + type _ t = + | Hash : [> `hash ] t + | Map : [> `map ] t + | Value : [> `value ] t + | Value_dirty : [> `value_dirty ] t + | Portable : [> `portable ] t + | Portable_dirty : [> `portable_dirty ] t + | Pruned : [> `pruned ] t + | Repo_key : [> `repo_key ] t + | Repo_value : [> `repo_value ] t + | Any : [> `any ] t + end + + let to_hash t miss = iter_hash t (fun h -> Hash h) miss + let to_map t miss = iter_map t (fun m -> Map m) miss + let to_value t miss = iter_value t (fun v -> Value v) miss + let to_portable t miss = iter_portable t (fun v -> Portable v) miss + + let to_value_dirty t miss miss_arg = + match t.v with + | Value (repo, v, Some um) -> Value_dirty (repo, v, um) + | Map _ | Key _ | Value (_, _, None) | Portable_dirty _ | Pruned _ -> + miss t miss_arg + + let to_portable_dirty t miss miss_arg = + match t.v with + | Portable_dirty (v, um) -> Portable_dirty (v, um) + | Map _ | Key _ | Value _ | Pruned _ -> miss t miss_arg + + let to_pruned t miss miss_arg = + match t.v with + | Pruned h -> Pruned h + | Map _ | Key _ | Value _ | Portable_dirty _ -> miss t miss_arg + + let to_repo_key t miss miss_arg = + iter_repo_key t (fun repo k -> Repo_key (repo, k)) miss miss_arg + + let to_repo_value t miss miss_arg = + iter_repo_value t (fun repo v -> Repo_value (repo, v)) miss miss_arg + + let rec cascade : type k. node -> k View_kind.t list -> k t = + fun t -> function + | [] -> + (* The declared cascade doesn't cover all cases *) + assert false + | x :: xs -> ( + match x with + | Hash -> to_hash t cascade xs + | Map -> to_map t cascade xs + | Value -> to_value t cascade xs + | Value_dirty -> to_value_dirty t cascade xs + | Portable -> to_portable t cascade xs + | Portable_dirty -> to_portable_dirty t cascade xs + | Pruned -> to_pruned t cascade xs + | Repo_key -> to_repo_key t cascade xs + | Repo_value -> to_repo_value t cascade xs + | Any -> Any) + end + + let get_none _ () = None + let cached_hash t = Scan.iter_hash t Option.some get_none () + let cached_key t = Scan.iter_key t Option.some get_none () + let cached_map t = Scan.iter_map t Option.some get_none () + let cached_value t = Scan.iter_value t Option.some get_none () + let cached_portable t = Scan.iter_portable t Option.some get_none () + + let key t = + match t.v with + | Key (_, k) -> Some k + | Map _ | Value _ | Portable_dirty _ | Pruned _ -> None + + (* When computing hashes of nodes, we try to use [P.Node.Val.t] as a + pre-image if possible so that this intermediate value can be cached + within [t.info.value] (in case it is about to be written to the backend). + + This is only possible if all of the child pointers have pre-existing + keys, otherwise we must convert to portable nodes as a fallback. *) + type hash_preimage = Node of P.Node.Val.t | Pnode of Portable.t + type node_value = P.Node.Val.value + type pnode_value = Portable.value + + type hash_preimage_value = + | Node_value of node_value + | Pnode_value of pnode_value + + let weaken_value : node_value -> pnode_value = function + | `Contents (key, m) -> `Contents (P.Contents.Key.to_hash key, m) + | `Node key -> `Node (P.Node.Key.to_hash key) + + let rec hash : type a. cache:bool -> t -> (hash -> a) -> a = + fun ~cache t k -> + let a_of_hashable hash v = + cnt.node_hash <- cnt.node_hash + 1; + let hash = hash v in + assert (t.info.ptr = Ptr_none); + if cache then t.info.ptr <- Hash hash; + k hash + in + match + (Scan.cascade t [ Hash; Value; Value_dirty; Portable_dirty; Map ] + : [ `hash | `value | `value_dirty | `portable_dirty | `map ] Scan.t) + with + | Hash h -> k h + | Value v -> a_of_hashable P.Node.Val.hash_exn v + | Value_dirty (_repo, v, um) -> + hash_preimage_of_updates ~cache t (Node v) um (function + | Node x -> a_of_hashable P.Node.Val.hash_exn x + | Pnode x -> a_of_hashable P.Node_portable.hash_exn x) + | Portable_dirty (p, um) -> + hash_preimage_of_updates ~cache t (Pnode p) um (function + | Node x -> a_of_hashable P.Node.Val.hash_exn x + | Pnode x -> a_of_hashable P.Node_portable.hash_exn x) + | Map m -> + hash_preimage_of_map ~cache t m (function + | Node x -> a_of_hashable P.Node.Val.hash_exn x + | Pnode x -> a_of_hashable P.Node_portable.hash_exn x) + + and hash_preimage_of_map : + type r. cache:bool -> t -> map -> (hash_preimage, r) cont = + fun ~cache t map k -> + cnt.node_val_v <- cnt.node_val_v + 1; + let bindings = StepMap.to_seq map in + let must_build_portable_node = + bindings + |> Seq.exists (fun (_, v) -> + match v with + | `Node n -> Option.is_none (cached_key n) + | `Contents (c, _) -> Option.is_none (Contents.cached_key c)) + in + if must_build_portable_node then + let pnode = + bindings + |> Seq.map (fun (step, v) -> + match v with + | `Contents (c, m) -> (step, `Contents (Contents.hash c, m)) + | `Node n -> hash ~cache n (fun k -> (step, `Node k))) + |> Portable.of_seq + in + k (Pnode pnode) + else + let node = + bindings + |> Seq.map (fun (step, v) -> + match v with + | `Contents (c, m) -> ( + match Contents.cached_key c with + | Some k -> (step, `Contents (k, m)) + | None -> + (* We checked that all child keys are cached above *) + assert false) + | `Node n -> ( + match cached_key n with + | Some k -> (step, `Node k) + | None -> + (* We checked that all child keys are cached above *) + assert false)) + |> P.Node.Val.of_seq + in + if cache then t.info.value <- Some node; + k (Node node) + + and hash_preimage_value_of_elt : + type r. cache:bool -> elt -> (hash_preimage_value, r) cont = + fun ~cache e k -> + match e with + | `Contents (c, m) -> ( + match Contents.key c with + | Some key -> k (Node_value (`Contents (key, m))) + | None -> k (Pnode_value (`Contents (Contents.hash c, m)))) + | `Node n -> ( + match key n with + | Some key -> k (Node_value (`Node key)) + | None -> hash ~cache n (fun hash -> k (Pnode_value (`Node hash)))) + + and hash_preimage_of_updates : + type r. + cache:bool -> t -> hash_preimage -> updatemap -> (hash_preimage, r) cont + = + fun ~cache t v updates k -> + let updates = StepMap.bindings updates in + let rec aux acc = function + | [] -> + (if cache then + match acc with Node n -> t.info.value <- Some n | Pnode _ -> ()); + k acc + | (k, Add e) :: rest -> + hash_preimage_value_of_elt ~cache e (fun e -> + let acc = + match (acc, e) with + | Node n, Node_value v -> Node (P.Node.Val.add n k v) + | Node n, Pnode_value v -> + Pnode (Portable.add (Portable.of_node n) k v) + | Pnode n, Node_value v -> + Pnode (Portable.add n k (weaken_value v)) + | Pnode n, Pnode_value v -> Pnode (Portable.add n k v) + in + aux acc rest) + | (k, Remove) :: rest -> + let acc = + match acc with + | Node n -> Node (P.Node.Val.remove n k) + | Pnode n -> Pnode (Portable.remove n k) + in + aux acc rest + in + aux v updates + + let hash ~cache k = hash ~cache k (fun x -> x) + + let value_of_key ~cache t repo k = + match cached_value t with + | Some v -> ok v + | None -> ( + cnt.node_find <- cnt.node_find + 1; + let+ v_opt = P.Node.find (P.Repo.node_t repo) k in + let h = P.Node.Key.to_hash k in + let v_opt = Option.map (Env.add_node_from_store t.info.env h) v_opt in + match v_opt with + | None -> err_dangling_hash h + | Some v -> + if cache then t.info.value <- v_opt; + Ok v) + + let to_value ~cache t = + match + (Scan.cascade t [ Value; Repo_key; Any ] + : [ `value | `repo_key | `any ] Scan.t) + with + | Value v -> ok v + | Repo_key (repo, k) -> value_of_key ~cache t repo k + | Any -> ( + match t.v with + | Key _ | Value (_, _, None) -> assert false + | Pruned h -> err_pruned_hash h |> Lwt.return + | Portable_dirty _ -> err_portable_value |> Lwt.return + | Map _ | Value (_, _, Some _) -> + invalid_arg + "Tree.Node.to_value: the supplied node has not been written to \ + disk. Either export it or convert it to a portable value \ + instead.") + + let to_portable_value_aux ~cache ~value_of_key ~return ~bind:( let* ) t = + let ok x = return (Ok x) in + match + (Scan.cascade t + [ + Portable; Value; Repo_key; Portable_dirty; Value_dirty; Map; Pruned; + ] + : [ `portable + | `value + | `repo_key + | `portable_dirty + | `value_dirty + | `map + | `pruned ] + Scan.t) + with + | Portable p -> ok p + | Value v -> ok (P.Node_portable.of_node v) + | Portable_dirty (p, um) -> + hash_preimage_of_updates ~cache t (Pnode p) um (function + | Node _ -> assert false + | Pnode x -> ok x) + | Repo_key (repo, k) -> + let* value_res = value_of_key ~cache t repo k in + Result.map P.Node_portable.of_node value_res |> return + | Value_dirty (_repo, v, um) -> + hash_preimage_of_updates ~cache t (Node v) um (function + | Node x -> ok (Portable.of_node x) + | Pnode x -> ok x) + | Map m -> + hash_preimage_of_map ~cache t m (function + | Node x -> ok (Portable.of_node x) + | Pnode x -> ok x) + | Pruned h -> err_pruned_hash h |> return + + let to_portable_value = + to_portable_value_aux ~value_of_key ~return:Lwt.return ~bind:Lwt.bind + + let to_map ~cache t = + let of_maps m updates = + let m = + match updates with + | None -> m + | Some updates -> + StepMap.stdlib_merge + (fun _ left right -> + match (left, right) with + | None, None -> assert false + | (Some _ as v), None -> v + | _, Some (Add v) -> Some v + | _, Some Remove -> None) + m updates + in + if cache then t.info.map <- Some m; + m + in + let of_value repo v um = + let env = t.info.env in + let m = Regular_value.to_map ~env ~cache repo v in + of_maps m um + in + let of_portable_value v um = + let env = t.info.env in + let m = Portable_value.to_map ~env ~cache () v in + of_maps m um + in + match + (Scan.cascade t + [ + Map; + Repo_value; + Repo_key; + Value_dirty; + Portable; + Portable_dirty; + Pruned; + ] + : [ `map + | `repo_key + | `repo_value + | `value_dirty + | `portable + | `portable_dirty + | `pruned ] + Scan.t) + with + | Map m -> ok m + | Repo_value (repo, v) -> ok (of_value repo v None) + | Repo_key (repo, k) -> ( + value_of_key ~cache t repo k >|= function + | Error _ as e -> e + | Ok v -> Ok (of_value repo v None)) + | Value_dirty (repo, v, um) -> ok (of_value repo v (Some um)) + | Portable p -> ok (of_portable_value p None) + | Portable_dirty (p, um) -> ok (of_portable_value p (Some um)) + | Pruned h -> err_pruned_hash h |> Lwt.return + + let contents_equal ((c1, m1) as x1) ((c2, m2) as x2) = + x1 == x2 || (Contents.equal c1 c2 && equal_metadata m1 m2) + + let rec elt_equal (x : elt) (y : elt) = + x == y + || + match (x, y) with + | `Contents x, `Contents y -> contents_equal x y + | `Node x, `Node y -> equal x y + | _ -> false + + and map_equal (x : map) (y : map) = StepMap.equal elt_equal x y + + and equal (x : t) (y : t) = + x == y + || + match (cached_hash x, cached_hash y) with + | Some x, Some y -> equal_hash x y + | _ -> ( + match (cached_value x, cached_value y) with + | Some x, Some y -> equal_value x y + | _ -> ( + match (cached_portable x, cached_portable y) with + | Some x, Some y -> equal_portable x y + | _ -> ( + match (cached_map x, cached_map y) with + | Some x, Some y -> map_equal x y + | _ -> equal_hash (hash ~cache:true x) (hash ~cache:true y)))) + + (* same as [equal] but do not compare in-memory maps + recursively. *) + let maybe_equal (x : t) (y : t) = + if x == y then True + else + match (cached_hash x, cached_hash y) with + | Some x, Some y -> if equal_hash x y then True else False + | _ -> ( + match (cached_value x, cached_value y) with + | Some x, Some y -> if equal_value x y then True else False + | _ -> ( + match (cached_portable x, cached_portable y) with + | Some x, Some y -> if equal_portable x y then True else False + | _ -> Maybe)) + + let empty () = of_map StepMap.empty ~env:(Env.empty ()) + let empty_hash = hash ~cache:false (empty ()) + let singleton k v = of_map (StepMap.singleton k v) + + let length ~cache t = + match + (Scan.cascade t + [ + Map; Value; Portable; Repo_key; Value_dirty; Portable_dirty; Pruned; + ] + : [ `map + | `value + | `portable + | `repo_key + | `value_dirty + | `portable_dirty + | `pruned ] + Scan.t) + with + | Map m -> StepMap.cardinal m |> Lwt.return + | Value v -> P.Node.Val.length v |> Lwt.return + | Portable p -> P.Node_portable.length p |> Lwt.return + | Repo_key (repo, k) -> + value_of_key ~cache t repo k >|= get_ok "length" >|= P.Node.Val.length + | Value_dirty (_repo, v, um) -> + hash_preimage_of_updates ~cache t (Node v) um (function + | Node x -> P.Node.Val.length x |> Lwt.return + | Pnode x -> P.Node_portable.length x |> Lwt.return) + | Portable_dirty (p, um) -> + hash_preimage_of_updates ~cache t (Pnode p) um (function + | Node _ -> assert false + | Pnode x -> P.Node_portable.length x |> Lwt.return) + | Pruned h -> pruned_hash_exn "length" h + + let is_empty ~cache t = + match + (Scan.cascade t + [ Map; Value; Portable; Hash; Value_dirty; Portable_dirty ] + : [ `map + | `value + | `portable + | `hash + | `value_dirty + | `portable_dirty ] + Scan.t) + with + | Map m -> StepMap.is_empty m + | Value v -> P.Node.Val.is_empty v + | Portable p -> P.Node_portable.is_empty p + | Hash h -> equal_hash h empty_hash + | Value_dirty (_repo, v, um) -> + Regular_value.is_empty_after_updates ~cache v um + | Portable_dirty (p, um) -> + Portable_value.is_empty_after_updates ~cache p um + + let findv_aux ~cache ~value_of_key ~return ~bind:( let* ) ctx t step = + let of_map m = try Some (StepMap.find step m) with Not_found -> None in + let of_value = Regular_value.findv ~cache ~env:t.info.env step t in + let of_portable = Portable_value.findv ~cache ~env:t.info.env step t () in + let of_t () = + match + (Scan.cascade t + [ + Map; + Repo_value; + Repo_key; + Value_dirty; + Portable; + Portable_dirty; + Pruned; + ] + : [ `map + | `repo_key + | `repo_value + | `value_dirty + | `portable + | `portable_dirty + | `pruned ] + Scan.t) + with + | Map m -> return (of_map m) + | Repo_value (repo, v) -> return (of_value repo v) + | Repo_key (repo, k) -> + let* v = value_of_key ~cache t repo k in + let v = get_ok ctx v in + return (of_value repo v) + | Value_dirty (repo, v, um) -> ( + match StepMap.find_opt step um with + | Some (Add v) -> return (Some v) + | Some Remove -> return None + | None -> return (of_value repo v)) + | Portable p -> return (of_portable p) + | Portable_dirty (p, um) -> ( + match StepMap.find_opt step um with + | Some (Add v) -> return (Some v) + | Some Remove -> return None + | None -> return (of_portable p)) + | Pruned h -> pruned_hash_exn ctx h + in + match t.info.findv_cache with + | None -> of_t () + | Some m -> ( + match of_map m with None -> of_t () | Some _ as r -> return r) + + let findv = findv_aux ~value_of_key ~return:Lwt.return ~bind:Lwt.bind + + let seq_of_map ?(offset = 0) ?length m : (step * elt) Seq.t = + let take seq = + match length with None -> seq | Some n -> Seq.take n seq + in + StepMap.to_seq m |> Seq.drop offset |> take + + let seq ?offset ?length ~cache t : (step * elt) Seq.t or_error Lwt.t = + let env = t.info.env in + match + (Scan.cascade t + [ + Map; + Repo_value; + Repo_key; + Value_dirty; + Portable; + Portable_dirty; + Pruned; + ] + : [ `map + | `repo_key + | `repo_value + | `value_dirty + | `portable + | `portable_dirty + | `pruned ] + Scan.t) + with + | Map m -> ok (seq_of_map ?offset ?length m) + | Repo_value (repo, v) -> + ok (Regular_value.seq ~env ?offset ?length ~cache repo v) + | Repo_key (repo, k) -> ( + value_of_key ~cache t repo k >>= function + | Error _ as e -> Lwt.return e + | Ok v -> ok (Regular_value.seq ~env ?offset ?length ~cache repo v)) + | Value_dirty _ | Portable_dirty _ -> ( + to_map ~cache t >>= function + | Error _ as e -> Lwt.return e + | Ok m -> ok (seq_of_map ?offset ?length m)) + | Portable p -> ok (Portable_value.seq ~env ?offset ?length ~cache () p) + | Pruned h -> err_pruned_hash h |> Lwt.return + + let bindings ~cache t = + (* XXX: If [t] is value, no need to [to_map]. Let's remove and inline + this into Tree.entries. *) + to_map ~cache t >|= function + | Error _ as e -> e + | Ok m -> Ok (StepMap.bindings m) + + let seq_of_updates updates value_bindings = + (* This operation can be costly for large updates. *) + if StepMap.is_empty updates then + (* Short-circuit return if we have no more updates to apply. *) + value_bindings + else + let value_bindings = + Seq.filter (fun (s, _) -> not (StepMap.mem s updates)) value_bindings + in + let updates = + StepMap.to_seq updates + |> Seq.filter_map (fun (s, elt) -> + match elt with Remove -> None | Add e -> Some (s, e)) + in + Seq.append value_bindings updates + + type ('v, 'acc, 'r) cps_folder = + path:Path.t -> 'acc -> int -> 'v -> ('acc, 'r) cont_lwt + (** A ('val, 'acc, 'r) cps_folder is a CPS, threaded fold function over + values of type ['v] producing an accumulator of type ['acc]. *) + + let fold : + type acc. + order:[ `Sorted | `Undefined | `Random of Random.State.t ] -> + force:acc force -> + cache:bool -> + uniq:uniq -> + pre:(acc, step list) folder option -> + post:(acc, step list) folder option -> + path:Path.t -> + ?depth:depth -> + node:(acc, _) folder -> + contents:(acc, contents) folder -> + tree:(acc, _) folder -> + t -> + acc -> + acc Lwt.t = + fun ~order ~force ~cache ~uniq ~pre ~post ~path ?depth ~node ~contents + ~tree t acc -> + let env = t.info.env in + let marks = + match uniq with + | `False -> dummy_marks + | `True -> empty_marks () + | `Marks n -> n + in + let pre path bindings acc = + match pre with + | None -> Lwt.return acc + | Some pre -> + let s = Seq.fold_left (fun acc (s, _) -> s :: acc) [] bindings in + pre path s acc + in + let post path bindings acc = + match post with + | None -> Lwt.return acc + | Some post -> + let s = Seq.fold_left (fun acc (s, _) -> s :: acc) [] bindings in + post path s acc + in + let rec aux : type r. (t, acc, r) cps_folder = + fun ~path acc d t k -> + let apply acc = node path t acc >>= tree path (`Node t) in + let next acc = + match force with + | `True -> ( + match order with + | `Random state -> + let* m = to_map ~cache t >|= get_ok "fold" in + let arr = StepMap.to_array m in + let () = shuffle state arr in + let s = Array.to_seq arr in + (seq [@tailcall]) ~path acc d s k + | `Sorted -> + let* m = to_map ~cache t >|= get_ok "fold" in + (map [@tailcall]) ~path acc d (Some m) k + | `Undefined -> ( + match + (Scan.cascade t + [ + Map; + Repo_value; + Repo_key; + Value_dirty; + Portable; + Portable_dirty; + Pruned; + ] + : [ `map + | `repo_key + | `repo_value + | `value_dirty + | `portable + | `portable_dirty + | `pruned ] + Scan.t) + with + | Map m -> (map [@tailcall]) ~path acc d (Some m) k + | Repo_value (repo, v) -> + (value [@tailcall]) ~path acc d (repo, v, None) k + | Repo_key (repo, _key) -> + let* v = to_value ~cache t >|= get_ok "fold" in + (value [@tailcall]) ~path acc d (repo, v, None) k + | Value_dirty (repo, v, um) -> + (value [@tailcall]) ~path acc d (repo, v, Some um) k + | Portable p -> (portable [@tailcall]) ~path acc d (p, None) k + | Portable_dirty (p, um) -> + (portable [@tailcall]) ~path acc d (p, Some um) k + | Pruned h -> pruned_hash_exn "fold" h)) + | `False skip -> ( + match cached_map t with + | Some n -> ( + match order with + | `Sorted | `Undefined -> + (map [@tailcall]) ~path acc d (Some n) k + | `Random state -> + let arr = StepMap.to_array n in + shuffle state arr; + let s = Array.to_seq arr in + (seq [@tailcall]) ~path acc d s k) + | None -> + (* XXX: That node is skipped if is is of tag Value *) + skip path acc >>= k) + in + match depth with + | None -> apply acc >>= next + | Some (`Eq depth) -> if d < depth then next acc else apply acc >>= k + | Some (`Le depth) -> + if d < depth then apply acc >>= next else apply acc >>= k + | Some (`Lt depth) -> + if d < depth - 1 then apply acc >>= next else apply acc >>= k + | Some (`Ge depth) -> if d < depth then next acc else apply acc >>= next + | Some (`Gt depth) -> + if d <= depth then next acc else apply acc >>= next + and aux_uniq : type r. (t, acc, r) cps_folder = + fun ~path acc d t k -> + if uniq = `False then (aux [@tailcall]) ~path acc d t k + else + let h = hash ~cache t in + match Hashes.add marks h with + | `Duplicate -> k acc + | `Ok -> (aux [@tailcall]) ~path acc d t k + and step : type r. (step * elt, acc, r) cps_folder = + fun ~path acc d (s, v) k -> + let path = Path.rcons path s in + match v with + | `Node n -> (aux_uniq [@tailcall]) ~path acc (d + 1) n k + | `Contents c -> ( + let apply () = + let tree path = tree path (`Contents c) in + Contents.fold ~force ~cache ~path contents tree (fst c) acc >>= k + in + match depth with + | None -> apply () + | Some (`Eq depth) -> if d = depth - 1 then apply () else k acc + | Some (`Le depth) -> if d < depth then apply () else k acc + | Some (`Lt depth) -> if d < depth - 1 then apply () else k acc + | Some (`Ge depth) -> if d >= depth - 1 then apply () else k acc + | Some (`Gt depth) -> if d >= depth then apply () else k acc) + and steps : type r. ((step * elt) Seq.t, acc, r) cps_folder = + fun ~path acc d s k -> + match s () with + | Seq.Nil -> k acc + | Seq.Cons (h, t) -> + (step [@tailcall]) ~path acc d h (fun acc -> + (steps [@tailcall]) ~path acc d t k) + and map : type r. (map option, acc, r) cps_folder = + fun ~path acc d m k -> + match m with + | None -> k acc + | Some m -> + let bindings = StepMap.to_seq m in + seq ~path acc d bindings k + and value : type r. (repo * value * updatemap option, acc, r) cps_folder = + fun ~path acc d (repo, v, updates) k -> + let bindings = Regular_value.seq ~env ~cache repo v in + let bindings = + match updates with + | None -> bindings + | Some updates -> seq_of_updates updates bindings + in + seq ~path acc d bindings k + and portable : type r. (portable * updatemap option, acc, r) cps_folder = + fun ~path acc d (v, updates) k -> + let bindings = Portable_value.seq ~env ~cache () v in + let bindings = + match updates with + | None -> bindings + | Some updates -> seq_of_updates updates bindings + in + seq ~path acc d bindings k + and seq : type r. ((step * elt) Seq.t, acc, r) cps_folder = + fun ~path acc d bindings k -> + let* acc = pre path bindings acc in + (steps [@tailcall]) ~path acc d bindings (fun acc -> + post path bindings acc >>= k) + in + aux_uniq ~path acc 0 t Lwt.return + + let update t step up = + let env = t.info.env in + let of_map m = + let m' = + match up with + | Remove -> StepMap.remove step m + | Add v -> StepMap.add step v m + in + if m == m' then t else of_map ~env m' + in + let of_value repo n updates = + let updates' = StepMap.add step up updates in + if updates == updates' then t + else of_value ~env repo n ~updates:updates' + in + let of_portable n updates = + let updates' = StepMap.add step up updates in + if updates == updates' then t else of_portable_dirty ~env n updates' + in + match + (Scan.cascade t + [ + Map; + Repo_value; + Repo_key; + Value_dirty; + Portable; + Portable_dirty; + Pruned; + ] + : [ `map + | `repo_key + | `repo_value + | `value_dirty + | `portable + | `portable_dirty + | `pruned ] + Scan.t) + with + | Map m -> Lwt.return (of_map m) + | Repo_value (repo, v) -> Lwt.return (of_value repo v StepMap.empty) + | Repo_key (repo, k) -> + let+ v = value_of_key ~cache:true t repo k >|= get_ok "update" in + of_value repo v StepMap.empty + | Value_dirty (repo, v, um) -> Lwt.return (of_value repo v um) + | Portable p -> Lwt.return (of_portable p StepMap.empty) + | Portable_dirty (p, um) -> Lwt.return (of_portable p um) + | Pruned h -> pruned_hash_exn "update" h + + let remove t step = update t step Remove + let add t step v = update t step (Add v) + + let compare (x : t) (y : t) = + if x == y then 0 + else compare_hash (hash ~cache:true x) (hash ~cache:true y) + + let t node = + let of_v v = of_v ~env:(Env.empty ()) v in + Type.map ~equal ~compare node of_v (fun t -> t.v) + + let _, t = + Type.mu2 (fun _ y -> + let elt = elt_t y in + let v = v_t elt in + let t = t v in + (v, t)) + + let elt_t = elt_t t + let dump = Type.pp_dump t + + let rec merge : type a. (t Merge.t -> a) -> a = + fun k -> + let f ~old x y = + let old = + Merge.bind_promise old (fun old () -> + let+ m = to_map ~cache:true old >|= Option.of_result in + Ok (Some m)) + in + match merge_env x.info.env y.info.env with + | Error _ as e -> Lwt.return e + | Ok env -> ( + let* x = to_map ~cache:true x >|= Option.of_result in + let* y = to_map ~cache:true y >|= Option.of_result in + let m = + StepMap.merge elt_t (fun _step -> + (merge_elt [@tailcall]) Merge.option) + in + Merge.(f @@ option m) ~old x y >|= function + | Ok (Some map) -> Ok (of_map ~env map) + | Ok None -> Error (`Conflict "empty map") + | Error _ as e -> e) + in + k (Merge.v t f) + + and merge_elt : type r. (elt Merge.t, r) cont = + fun k -> + let open Merge.Infix in + let f : elt Merge.f = + fun ~old x y -> + match (x, y) with + | `Contents (x, cx), `Contents (y, cy) -> + let mold = + Merge.bind_promise old (fun old () -> + match old with + | `Contents (_, m) -> ok (Some m) + | `Node _ -> ok None) + in + Merge.(f Metadata.merge) ~old:mold cx cy >>=* fun m -> + let old = + Merge.bind_promise old (fun old () -> + match old with + | `Contents (c, _) -> ok (Some c) + | `Node _ -> ok None) + in + Merge.(f Contents.merge) ~old x y >>=* fun c -> + Merge.ok (`Contents (c, m)) + | `Node x, `Node y -> + (merge [@tailcall]) (fun m -> + let old = + Merge.bind_promise old (fun old () -> + match old with + | `Contents _ -> ok None + | `Node n -> ok (Some n)) + in + Merge.(f m ~old x y) >>=* fun n -> Merge.ok (`Node n)) + | _ -> Merge.conflict "add/add values" + in + k (Merge.seq [ Merge.default elt_t; Merge.v elt_t f ]) + + let merge_elt = merge_elt (fun x -> x) + end + + type node = Node.t [@@deriving irmin ~pp] + type node_key = Node.key [@@deriving irmin ~pp] + type contents_key = Contents.key [@@deriving irmin ~pp] + + type kinded_key = [ `Contents of Contents.key * metadata | `Node of Node.key ] + [@@deriving irmin] + + type kinded_hash = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin ~equal] + + type t = [ `Node of node | `Contents of Contents.t * Metadata.t ] + [@@deriving irmin] + + let to_backend_node n = + Node.to_value ~cache:true n >|= get_ok "to_backend_node" + + let to_backend_portable_node n = + Node.to_portable_value ~cache:true n >|= get_ok "to_backend_portable_node" + + let of_backend_node repo n = + let env = Env.empty () in + Node.of_value ~env repo n + + let dump ppf = function + | `Node n -> Fmt.pf ppf "node: %a" Node.dump n + | `Contents (c, _) -> Fmt.pf ppf "contents: %a" (Type.pp Contents.t) c + + let contents_equal ((c1, m1) as x1) ((c2, m2) as x2) = + x1 == x2 + || (c1 == c2 && m1 == m2) + || (Contents.equal c1 c2 && equal_metadata m1 m2) + + let equal (x : t) (y : t) = + x == y + || + match (x, y) with + | `Node x, `Node y -> Node.equal x y + | `Contents x, `Contents y -> contents_equal x y + | `Node _, `Contents _ | `Contents _, `Node _ -> false + + let is_empty = function + | `Node n -> Node.is_empty ~cache:true n + | `Contents _ -> false + + type elt = [ `Node of node | `Contents of contents * metadata ] + + let of_node n = `Node n + + let of_contents ?(metadata = Metadata.default) c = + let env = Env.empty () in + let c = Contents.of_value ~env c in + `Contents (c, metadata) + + let v : elt -> t = function + | `Contents (c, metadata) -> of_contents ~metadata c + | `Node n -> `Node n + + let pruned_with_env ~env = function + | `Contents (h, meta) -> `Contents (Contents.pruned ~env h, meta) + | `Node h -> `Node (Node.pruned ~env h) + + let pruned h = + let env = Env.empty () in + pruned_with_env ~env h + + let destruct x = x + + let clear ?(depth = 0) = function + | `Node n -> Node.clear ~max_depth:depth 0 n + | `Contents _ -> () + + let sub ~cache ctx t path = + let rec aux node path = + match Path.decons path with + | None -> Lwt.return_some node + | Some (h, p) -> ( + Node.findv ~cache ctx node h >>= function + | None | Some (`Contents _) -> Lwt.return_none + | Some (`Node n) -> (aux [@tailcall]) n p) + in + match t with + | `Node n -> (aux [@tailcall]) n path + | `Contents _ -> Lwt.return_none + + let find_tree (t : t) path = + let cache = true in + [%log.debug "Tree.find_tree %a" pp_path path]; + match (t, Path.rdecons path) with + | v, None -> Lwt.return_some v + | _, Some (path, file) -> ( + sub ~cache "find_tree.sub" t path >>= function + | None -> Lwt.return_none + | Some n -> Node.findv ~cache "find_tree.findv" n file) + + let id _ _ acc = Lwt.return acc + + let fold ?(order = `Sorted) ?(force = `True) ?(cache = false) ?(uniq = `False) + ?pre ?post ?depth ?(contents = id) ?(node = id) ?(tree = id) (t : t) acc = + match t with + | `Contents (c, _) as c' -> + let tree path = tree path c' in + Contents.fold ~force ~cache ~path:Path.empty contents tree c acc + | `Node n -> + Node.fold ~order ~force ~cache ~uniq ~pre ~post ~path:Path.empty ?depth + ~contents ~node ~tree n acc + + type stats = { + nodes : int; + leafs : int; + skips : int; + depth : int; + width : int; + } + [@@deriving irmin] + + let empty_stats = { nodes = 0; leafs = 0; skips = 0; depth = 0; width = 0 } + let incr_nodes s = { s with nodes = s.nodes + 1 } + let incr_leafs s = { s with leafs = s.leafs + 1 } + let incr_skips s = { s with skips = s.skips + 1 } + + let set_depth p s = + let n_depth = List.length (Path.map p (fun _ -> ())) in + let depth = max n_depth s.depth in + { s with depth } + + let set_width childs s = + let width = max s.width (List.length childs) in + { s with width } + + let err_not_found n k = + Fmt.kstr invalid_arg "Irmin.Tree.%s: %a not found" n pp_path k + + let get_tree (t : t) path = + find_tree t path >|= function + | None -> err_not_found "get_tree" path + | Some v -> v + + let find_all t k = + find_tree t k >>= function + | None | Some (`Node _) -> Lwt.return_none + | Some (`Contents (c, m)) -> + let+ c = Contents.to_value ~cache:true c in + Some (get_ok "find_all" c, m) + + let find t k = + find_all t k >|= function None -> None | Some (c, _) -> Some c + + let get_all t k = + find_all t k >>= function + | None -> err_not_found "get" k + | Some v -> Lwt.return v + + let get t k = get_all t k >|= fun (c, _) -> c + let mem t k = find t k >|= function None -> false | _ -> true + let mem_tree t k = find_tree t k >|= function None -> false | _ -> true + + let kind t path = + let cache = true in + [%log.debug "Tree.kind %a" pp_path path]; + match (t, Path.rdecons path) with + | `Contents _, None -> Lwt.return_some `Contents + | `Node _, None -> Lwt.return_some `Node + | _, Some (dir, file) -> ( + sub ~cache "kind.sub" t dir >>= function + | None -> Lwt.return_none + | Some m -> ( + Node.findv ~cache "kind.findv" m file >>= function + | None -> Lwt.return_none + | Some (`Contents _) -> Lwt.return_some `Contents + | Some (`Node _) -> Lwt.return_some `Node)) + + let length t ?(cache = true) path = + [%log.debug "Tree.length %a" pp_path path]; + sub ~cache "length" t path >>= function + | None -> Lwt.return 0 + | Some n -> Node.length ~cache:true n + + let seq t ?offset ?length ?(cache = true) path = + [%log.debug "Tree.seq %a" pp_path path]; + sub ~cache "seq.sub" t path >>= function + | None -> Lwt.return Seq.empty + | Some n -> Node.seq ?offset ?length ~cache n >|= get_ok "seq" + + let list t ?offset ?length ?(cache = true) path = + seq t ?offset ?length ~cache path >|= List.of_seq + + let empty () = `Node (Node.empty ()) + + let singleton k ?(metadata = Metadata.default) c = + [%log.debug "Tree.singleton %a" pp_path k]; + let env = Env.empty () in + let base_tree = `Contents (Contents.of_value ~env c, metadata) in + Path.fold_right k + ~f:(fun step child -> `Node (Node.singleton ~env step child)) + ~init:base_tree + + (** During recursive updates, we keep track of whether or not we've made a + modification in order to avoid unnecessary allocations of identical tree + objects. *) + type 'a updated = Changed of 'a | Unchanged + + let maybe_equal (x : t) (y : t) = + if x == y then True + else + match (x, y) with + | `Node x, `Node y -> Node.maybe_equal x y + | _ -> if equal x y then True else False + + let get_env = function + | `Node n -> n.Node.info.env + | `Contents (c, _) -> c.Contents.info.env + + let update_tree ~cache ~f_might_return_empty_node ~f root_tree path = + (* User-introduced empty nodes will be removed immediately if necessary. *) + let prune_empty : node -> bool = + if not f_might_return_empty_node then Fun.const false + else Node.is_empty ~cache + in + match Path.rdecons path with + | None -> ( + let empty_tree = + match is_empty root_tree with + | true -> root_tree + | false -> `Node (Node.empty ()) + in + f (Some root_tree) >>= function + (* Here we consider "deleting" a root contents value or node to consist + of changing it to an empty node. Note that this introduces + sensitivity to ordering of subtree operations: updating in a subtree + and adding the subtree are not necessarily commutative. *) + | None -> Lwt.return empty_tree + | Some (`Node _ as new_root) -> ( + match maybe_equal root_tree new_root with + | True -> Lwt.return root_tree + | Maybe | False -> Lwt.return new_root) + | Some (`Contents c' as new_root) -> ( + match root_tree with + | `Contents c when contents_equal c c' -> Lwt.return root_tree + | _ -> Lwt.return new_root)) + | Some (path, file) -> ( + let rec aux : type r. path -> node -> (node updated, r) cont_lwt = + fun path parent_node k -> + let changed n = k (Changed n) in + match Path.decons path with + | None -> ( + let with_new_child t = Node.add parent_node file t >>= changed in + let* old_binding = + Node.findv ~cache "update_tree.findv" parent_node file + in + let* new_binding = f old_binding in + match (old_binding, new_binding) with + | None, None -> k Unchanged + | None, Some (`Contents _ as t) -> with_new_child t + | None, Some (`Node n as t) -> ( + match prune_empty n with + | true -> k Unchanged + | false -> with_new_child t) + | Some _, None -> Node.remove parent_node file >>= changed + | Some old_value, Some (`Node n as t) -> ( + match prune_empty n with + | true -> Node.remove parent_node file >>= changed + | false -> ( + match maybe_equal old_value t with + | True -> k Unchanged + | Maybe | False -> with_new_child t)) + | Some (`Contents c), Some (`Contents c' as t) -> ( + match contents_equal c c' with + | true -> k Unchanged + | false -> with_new_child t) + | Some (`Node _), Some (`Contents _ as t) -> with_new_child t) + | Some (step, key_suffix) -> + let* old_binding = + Node.findv ~cache "update_tree.findv" parent_node step + in + let to_recurse = + match old_binding with + | Some (`Node child) -> child + | None | Some (`Contents _) -> Node.empty () + in + (aux [@tailcall]) key_suffix to_recurse (function + | Unchanged -> + (* This includes [remove]s in an empty node, in which case we + want to avoid adding a binding anyway. *) + k Unchanged + | Changed child -> ( + match Node.is_empty ~cache child with + | true -> + (* A [remove] has emptied previously non-empty child with + binding [h], so we remove the binding. *) + Node.remove parent_node step >>= changed + | false -> + Node.add parent_node step (`Node child) >>= changed)) + in + let top_node = + match root_tree with `Node n -> n | `Contents _ -> Node.empty () + in + aux path top_node @@ function + | Unchanged -> Lwt.return root_tree + | Changed node -> + Env.copy ~into:node.info.env (get_env root_tree); + Lwt.return (`Node node)) + + let update t k ?(metadata = Metadata.default) f = + let cache = true in + [%log.debug "Tree.update %a" pp_path k]; + update_tree ~cache t k ~f_might_return_empty_node:false ~f:(fun t -> + let+ old_contents = + match t with + | Some (`Node _) | None -> Lwt.return_none + | Some (`Contents (c, _)) -> + let+ c = Contents.to_value ~cache c in + Some (get_ok "update" c) + in + match f old_contents with + | None -> None + | Some c -> of_contents ~metadata c |> Option.some) + + let add t k ?(metadata = Metadata.default) c = + [%log.debug "Tree.add %a" pp_path k]; + update_tree ~cache:true t k + ~f:(fun _ -> Lwt.return_some (of_contents ~metadata c)) + ~f_might_return_empty_node:false + + let add_tree t k v = + [%log.debug "Tree.add_tree %a" pp_path k]; + update_tree ~cache:true t k + ~f:(fun _ -> Lwt.return_some v) + ~f_might_return_empty_node:true + + let remove t k = + [%log.debug "Tree.remove %a" pp_path k]; + update_tree ~cache:true t k + ~f:(fun _ -> Lwt.return_none) + ~f_might_return_empty_node:false + + let update_tree t k f = + [%log.debug "Tree.update_tree %a" pp_path k]; + update_tree ~cache:true t k ~f:(Lwt.wrap1 f) ~f_might_return_empty_node:true + + let import repo = function + | `Contents (k, m) -> ( + cnt.contents_mem <- cnt.contents_mem + 1; + P.Contents.mem (P.Repo.contents_t repo) k >|= function + | true -> + let env = Env.empty () in + Some (`Contents (Contents.of_key ~env repo k, m)) + | false -> None) + | `Node k -> ( + cnt.node_mem <- cnt.node_mem + 1; + P.Node.mem (P.Repo.node_t repo) k >|= function + | true -> + let env = Env.empty () in + Some (`Node (Node.of_key ~env repo k)) + | false -> None) + + let import_with_env ~env repo = function + | `Node k -> `Node (Node.of_key ~env repo k) + | `Contents (k, m) -> `Contents (Contents.of_key ~env repo k, m) + + let import_no_check repo f = + let env = Env.empty () in + import_with_env ~env repo f + + let same_repo r1 r2 = + r1 == r2 || Conf.equal (P.Repo.config r1) (P.Repo.config r2) + + (* Given an arbitrary tree value, persist its contents to the given contents + and node stores via a depth-first {i post-order} traversal. We must export + a node's children before the node itself in order to get the {i keys} of + any un-persisted child values. *) + let export ?clear repo contents_t node_t n = + [%log.debug "Tree.export clear=%a" Fmt.(option bool) clear]; + let cache = + match clear with + | Some true | None -> + (* This choice of [cache] flag has no impact, since we either + immediately clear the corresponding cache or are certain that + the it is already filled. *) + false + | Some false -> true + in + + let add_node n v k = + cnt.node_add <- cnt.node_add + 1; + let* key = P.Node.add node_t v in + let () = + (* Sanity check: Did we just store the same hash as the one represented + by the Tree.Node [n]? *) + match Node.cached_hash n with + | None -> + (* No hash is in [n]. Computing it would result in getting it from + [v] or rebuilding a private node. *) + () + | Some h' -> + let h = P.Node.Key.to_hash key in + if not (equal_hash h h') then + backend_invariant_violation + "@[Tree.export: added inconsistent node binding@,\ + key: %a@,\ + value: %a@,\ + computed hash: %a@]" pp_node_key key Node.pp_value v pp_hash h' + in + k key + in + + let add_node_map n (x : Node.map) k = + let node = + (* Since we traverse in post-order, all children of [x] have already + been added. Thus, their keys are cached and we can retrieve them. *) + cnt.node_val_v <- cnt.node_val_v + 1; + StepMap.to_seq x + |> Seq.map (fun (step, v) -> + match v with + | `Node n -> ( + match Node.cached_key n with + | Some k -> (step, `Node k) + | None -> + assertion_failure + "Encountered child node value with uncached key \ + during export:@,\ + @ @[%a@]" dump v) + | `Contents (c, m) -> ( + match Contents.cached_key c with + | Some k -> (step, `Contents (k, m)) + | None -> + assertion_failure + "Encountered child contents value with uncached key \ + during export:@,\ + @ @[%a@]" dump v)) + |> P.Node.Val.of_seq + in + add_node n node k + in + + let add_updated_node n (v : Node.value) (updates : Node.updatemap) k = + let node = + StepMap.fold + (fun k v acc -> + match v with + | Node.Remove -> P.Node.Val.remove acc k + | Node.Add (`Node n as v) -> ( + match Node.cached_key n with + | Some ptr -> P.Node.Val.add acc k (`Node ptr) + | None -> + assertion_failure + "Encountered child node value with uncached key during \ + export:@,\ + @ @[%a@]" dump v) + | Add (`Contents (c, m) as v) -> ( + match Contents.cached_key c with + | Some ptr -> P.Node.Val.add acc k (`Contents (ptr, m)) + | None -> + assertion_failure + "Encountered child contents value with uncached key \ + during export:@,\ + @ @[%a@]" dump v)) + updates v + in + add_node n node k + in + + let rec on_node : type r. [ `Node of node ] -> (node_key, r) cont_lwt = + fun (`Node n) k -> + let k key = + (* All the nodes in the exported tree should be cleaned using + [Node.export]. This ensures that [key] is stored in [n]. *) + Node.export ?clear repo n key; + k key + in + let has_repo = + match n.Node.v with + | Node.Key (repo', _) -> + if same_repo repo repo' then true + else + (* Case 1. [n] is a key from another repo. Let's crash. + + We could also only crash if the hash in the key is unknown to + [repo], or completely ignore the issue. *) + failwith "Can't export the node key from another repo" + | Value (repo', _, _) -> + if same_repo repo repo' then true + else + (* Case 2. [n] is a value from another repo. Let's crash. + + We could also ignore the issue. *) + failwith "Can't export a node value from another repo" + | Pruned _ | Portable_dirty _ | Map _ -> false + in + match n.Node.v with + | Pruned h -> + (* Case 3. [n] is a pruned hash. [P.Node.index node_t h] could be + different than [None], but let's always crash. *) + pruned_hash_exn "export" h + | Portable_dirty _ -> + (* Case 4. [n] is a portable value with diffs. The hash of the + reconstructed portable value could be known by [repo], but let's + always crash. *) + portable_value_exn "export" + | Map _ | Value _ | Key _ -> ( + match Node.cached_key n with + | Some key -> + if has_repo then + (* Case 5. [n] is a key that is accompanied by the [repo]. Let's + assume that [P.Node.mem node_t key] is [true] for performance + reason (not benched). *) + k key + else ( + cnt.node_mem <- cnt.node_mem + 1; + let* mem = P.Node.mem node_t key in + if not mem then + (* Case 6. [n] contains a key that is not known by [repo]. + Let's abort. *) + failwith "Can't export a key unkown from the repo" + else + (* Case 7. [n] contains a key that is known by the [repo]. *) + k key) + | None -> ( + let* skip_when_some = + match Node.cached_hash n with + | None -> + (* No pre-computed hash. *) + Lwt.return_none + | Some h -> ( + cnt.node_index <- cnt.node_index + 1; + P.Node.index node_t h >>= function + | None -> + (* Pre-computed hash is unknown by repo. + + NOTE: it's possible that this value already has a key + in the store, but it's not indexed. If so, we're + adding a duplicate here – this isn't an issue for + correctness, but does waste space. *) + Lwt.return_none + | Some key -> + cnt.node_mem <- cnt.node_mem + 1; + let+ mem = P.Node.mem node_t key in + if mem then + (* Case 8. The pre-computed hash is converted into + a key *) + Some key + else + (* The backend could produce a key from [h] but + doesn't know [h]. *) + None) + in + match skip_when_some with + | Some key -> k key + | None -> ( + (* Only [Map _ | Value _] possible now. + + Case 9. Let's export it to the backend. *) + let new_children_seq = + let seq = + match n.Node.v with + | Value (_, _, Some m) -> + StepMap.to_seq m + |> Seq.filter_map (function + | step, Node.Add v -> Some (step, v) + | _, Remove -> None) + | Map m -> StepMap.to_seq m + | Value (_, _, None) -> Seq.empty + | Key _ | Portable_dirty _ | Pruned _ -> + (* [n.v = (Key _ | Portable_dirty _ | Pruned _)] is + excluded above. *) + assert false + in + Seq.map (fun (_, x) -> x) seq + in + on_node_seq new_children_seq @@ fun `Node_children_exported -> + match (n.Node.v, Node.cached_value n) with + | Map x, _ -> add_node_map n x k + | Value (_, v, None), None | _, Some v -> add_node n v k + | Value (_, v, Some um), _ -> add_updated_node n v um k + | (Key _ | Portable_dirty _ | Pruned _), _ -> + (* [n.v = (Key _ | Portable_dirty _ | Pruned _)] is + excluded above. *) + assert false))) + and on_contents : + type r. + [ `Contents of Contents.t * metadata ] -> + ([ `Content_exported ], r) cont_lwt = + fun (`Contents (c, _)) k -> + match c.Contents.v with + | Contents.Key (_, key) -> + Contents.export ?clear repo c key; + k `Content_exported + | Contents.Value _ -> + let* v = Contents.to_value ~cache c in + let v = get_ok "export" v in + cnt.contents_add <- cnt.contents_add + 1; + let* key = P.Contents.add contents_t v in + let () = + let h = P.Contents.Key.to_hash key in + let h' = Contents.hash ~cache c in + if not (equal_hash h h') then + backend_invariant_violation + "@[Tree.export: added inconsistent contents binding@,\ + key: %a@,\ + value: %a@,\ + computed hash: %a@]" pp_contents_key key pp_contents v pp_hash + h' + in + Contents.export ?clear repo c key; + k `Content_exported + | Contents.Pruned h -> pruned_hash_exn "export" h + and on_node_seq : + type r. Node.elt Seq.t -> ([ `Node_children_exported ], r) cont_lwt = + fun seq k -> + match seq () with + | Seq.Nil -> + (* Have iterated on all children, let's export parent now *) + k `Node_children_exported + | Seq.Cons ((`Node _ as n), rest) -> + on_node n (fun _node_key -> on_node_seq rest k) + | Seq.Cons ((`Contents _ as c), rest) -> + on_contents c (fun `Content_exported -> on_node_seq rest k) + in + on_node (`Node n) (fun key -> Lwt.return key) + + let merge : t Merge.t = + let f ~old (x : t) y = + Merge.(f Node.merge_elt) ~old x y >>= function + | Ok t -> Merge.ok t + | Error e -> Lwt.return (Error e) + in + Merge.v t f + + let entries path tree = + let rec aux acc = function + | [] -> Lwt.return acc + | (path, h) :: todo -> + let* childs = Node.bindings ~cache:true h >|= get_ok "entries" in + let acc, todo = + List.fold_left + (fun (acc, todo) (k, v) -> + let path = Path.rcons path k in + match v with + | `Node v -> (acc, (path, v) :: todo) + | `Contents c -> ((path, c) :: acc, todo)) + (acc, todo) childs + in + (aux [@tailcall]) acc todo + in + (aux [@tailcall]) [] [ (path, tree) ] + + (** Given two forced lazy values, return an empty diff if they both use the + same dangling hash. *) + let diff_force_result (type a b) ~(empty : b) ~(diff_ok : a * a -> b) + (x : a or_error) (y : a or_error) : b = + match (x, y) with + | ( Error (`Dangling_hash h1 | `Pruned_hash h1), + Error (`Dangling_hash h2 | `Pruned_hash h2) ) -> ( + match equal_hash h1 h2 with true -> empty | false -> assert false) + | Error _, Ok _ -> assert false + | Ok _, Error _ -> assert false + | Ok x, Ok y -> diff_ok (x, y) + | Error _, Error _ -> assert false + + let diff_contents x y = + if Node.contents_equal x y then Lwt.return_nil + else + let* cx = Contents.to_value ~cache:true (fst x) in + let+ cy = Contents.to_value ~cache:true (fst y) in + diff_force_result cx cy ~empty:[] ~diff_ok:(fun (cx, cy) -> + [ `Updated ((cx, snd x), (cy, snd y)) ]) + + let diff_node (x : node) (y : node) = + let bindings n = + Node.to_map ~cache:true n >|= function + | Ok m -> Ok (StepMap.bindings m) + | Error _ as e -> e + in + let removed acc (k, (c, m)) = + let+ c = Contents.to_value ~cache:true c >|= get_ok "diff_node" in + (k, `Removed (c, m)) :: acc + in + let added acc (k, (c, m)) = + let+ c = Contents.to_value ~cache:true c >|= get_ok "diff_node" in + (k, `Added (c, m)) :: acc + in + let rec diff_bindings acc todo path x y = + let acc = ref acc in + let todo = ref todo in + let* () = + alist_iter2_lwt compare_step + (fun key v -> + let path = Path.rcons path key in + match v with + (* Left *) + | `Left (`Contents x) -> + let+ x = removed !acc (path, x) in + acc := x + | `Left (`Node x) -> + let* xs = entries path x in + let+ xs = Lwt_list.fold_left_s removed !acc xs in + acc := xs + (* Right *) + | `Right (`Contents y) -> + let+ y = added !acc (path, y) in + acc := y + | `Right (`Node y) -> + let* ys = entries path y in + let+ ys = Lwt_list.fold_left_s added !acc ys in + acc := ys + (* Both *) + | `Both (`Node x, `Node y) -> + todo := (path, x, y) :: !todo; + Lwt.return_unit + | `Both (`Contents x, `Node y) -> + let* ys = entries path y in + let* x = removed !acc (path, x) in + let+ ys = Lwt_list.fold_left_s added x ys in + acc := ys + | `Both (`Node x, `Contents y) -> + let* xs = entries path x in + let* y = added !acc (path, y) in + let+ ys = Lwt_list.fold_left_s removed y xs in + acc := ys + | `Both (`Contents x, `Contents y) -> + let+ content_diffs = + diff_contents x y >|= List.map (fun d -> (path, d)) + in + acc := content_diffs @ !acc) + x y + in + (diff_node [@tailcall]) !acc !todo + and diff_node acc = function + | [] -> Lwt.return acc + | (path, x, y) :: todo -> + if Node.equal x y then (diff_node [@tailcall]) acc todo + else + let* x = bindings x in + let* y = bindings y in + diff_force_result ~empty:Lwt.return_nil + ~diff_ok:(fun (x, y) -> diff_bindings acc todo path x y) + x y + in + (diff_node [@tailcall]) [] [ (Path.empty, x, y) ] + + let diff (x : t) (y : t) = + match (x, y) with + | `Contents ((c1, m1) as x), `Contents ((c2, m2) as y) -> + if contents_equal x y then Lwt.return_nil + else + let* c1 = Contents.to_value ~cache:true c1 >|= get_ok "diff" in + let* c2 = Contents.to_value ~cache:true c2 >|= get_ok "diff" in + Lwt.return [ (Path.empty, `Updated ((c1, m1), (c2, m2))) ] + | `Node x, `Node y -> diff_node x y + | `Contents (x, m), `Node y -> + let* diff = diff_node (Node.empty ()) y in + let+ x = Contents.to_value ~cache:true x >|= get_ok "diff" in + (Path.empty, `Removed (x, m)) :: diff + | `Node x, `Contents (y, m) -> + let* diff = diff_node x (Node.empty ()) in + let+ y = Contents.to_value ~cache:true y >|= get_ok "diff" in + (Path.empty, `Added (y, m)) :: diff + + type concrete = + [ `Tree of (Path.step * concrete) list + | `Contents of P.Contents.Val.t * Metadata.t ] + [@@deriving irmin] + + type 'a or_empty = Empty | Non_empty of 'a + + let of_concrete c = + let rec concrete : type r. concrete -> (t or_empty, r) cont = + fun t k -> + match t with + | `Contents (c, m) -> k (Non_empty (of_contents ~metadata:m c)) + | `Tree childs -> + tree StepMap.empty childs (function + | Empty -> k Empty + | Non_empty n -> k (Non_empty (`Node n))) + and tree : + type r. + Node.elt StepMap.t -> (step * concrete) list -> (node or_empty, r) cont + = + fun map t k -> + match t with + | [] -> + k + (if StepMap.is_empty map then Empty + else Non_empty (Node.of_map ~env:(Env.empty ()) map)) + | (s, n) :: t -> + (concrete [@tailcall]) n (fun v -> + (tree [@tailcall]) + (StepMap.update s + (function + | None -> ( + match v with + | Empty -> None (* Discard empty sub-directories *) + | Non_empty v -> Some v) + | Some _ -> + Fmt.invalid_arg + "of_concrete: duplicate bindings for step `%a`" + pp_step s) + map) + t k) + in + (concrete [@tailcall]) c (function Empty -> empty () | Non_empty x -> x) + + let to_concrete t = + let rec tree : type r. t -> (concrete, r) cont_lwt = + fun t k -> + match t with + | `Contents c -> contents c k + | `Node n -> + let* m = Node.to_map ~cache:true n in + let bindings = m |> get_ok "to_concrete" |> StepMap.bindings in + (node [@tailcall]) [] bindings (fun n -> + let n = List.sort (fun (s, _) (s', _) -> compare_step s s') n in + k (`Tree n)) + and contents : type r. Contents.t * metadata -> (concrete, r) cont_lwt = + fun (c, m) k -> + let* c = Contents.to_value ~cache:true c >|= get_ok "to_concrete" in + k (`Contents (c, m)) + and node : + type r. + (step * concrete) list -> + (step * Node.elt) list -> + ((step * concrete) list, r) cont_lwt = + fun childs x k -> + match x with + | [] -> k childs + | (s, n) :: t -> ( + match n with + | `Node _ as n -> + (tree [@tailcall]) n (fun tree -> node ((s, tree) :: childs) t k) + | `Contents c -> + (contents [@tailcall]) c (fun c -> + (node [@tailcall]) ((s, c) :: childs) t k)) + in + tree t (fun x -> Lwt.return x) + + let key (t : t) = + [%log.debug "Tree.key"]; + match t with + | `Node n -> ( + match Node.key n with Some key -> Some (`Node key) | None -> None) + | `Contents (c, m) -> ( + match Contents.key c with + | Some key -> Some (`Contents (key, m)) + | None -> None) + + let hash ?(cache = true) (t : t) = + [%log.debug "Tree.hash"]; + match t with + | `Node n -> `Node (Node.hash ~cache n) + | `Contents (c, m) -> `Contents (Contents.hash ~cache c, m) + + let stats ?(force = false) (t : t) = + let cache = true in + let force = + if force then `True + else `False (fun k s -> set_depth k s |> incr_skips |> Lwt.return) + in + let contents k _ s = set_depth k s |> incr_leafs |> Lwt.return in + let pre k childs s = + if childs = [] then Lwt.return s + else set_depth k s |> set_width childs |> incr_nodes |> Lwt.return + in + let post _ _ acc = Lwt.return acc in + fold ~force ~cache ~pre ~post ~contents t empty_stats + + let counters () = cnt + let dump_counters ppf () = dump_counters ppf cnt + let reset_counters () = reset_counters cnt + + let inspect = function + | `Contents _ -> `Contents + | `Node n -> + `Node + (match n.Node.v with + | Map _ -> `Map + | Value _ -> `Value + | Key _ -> `Key + | Portable_dirty _ -> `Portable_dirty + | Pruned _ -> `Pruned) + + module Proof = struct + type irmin_tree = t + + include Tree_proof + + type proof_tree = tree + type proof_inode = inode_tree + type node_proof = P.Node_portable.proof + + let proof_of_iproof : proof_inode -> proof_tree = function + | Blinded_inode h -> Blinded_node h + | Inode_values l -> Node l + | Inode_tree i -> Inode i + | Inode_extender ext -> Extender ext + + let rec proof_of_tree : type a. irmin_tree -> (proof_tree -> a) -> a = + fun tree k -> + match tree with + | `Contents (c, h) -> proof_of_contents c h k + | `Node node -> proof_of_node node k + + and proof_of_contents : + type a. Contents.t -> metadata -> (proof_tree -> a) -> a = + fun c m k -> + match Contents.cached_value c with + | Some v -> k (Contents (v, m)) + | None -> k (Blinded_contents (Contents.hash c, m)) + + and proof_of_node : type a. node -> (proof_tree -> a) -> a = + fun node k -> + (* Let's convert [node] to [node_proof]. + + As [node] might not be exported, we can only turn it into a portable + node. *) + let to_portable_value = + let value_of_key ~cache:_ _node _repo k = + let h = P.Node.Key.to_hash k in + err_dangling_hash h + in + Node.to_portable_value_aux ~cache:false ~value_of_key ~return:Fun.id + ~bind:(fun x f -> f x) + in + match to_portable_value node with + | Error (`Dangling_hash h) -> k (Blinded_node h) + | Error (`Pruned_hash h) -> k (Blinded_node h) + | Ok v -> + (* [to_proof] may trigger reads. This is fine. *) + let node_proof = P.Node_portable.to_proof v in + proof_of_node_proof node node_proof k + + (** [of_node_proof n np] is [p] (of type [Tree.Proof.t]) which is very + similar to [np] (of type [P.Node.Val.proof]) except that the values + loaded in [n] have been expanded. *) + and proof_of_node_proof : + type a. node -> node_proof -> (proof_tree -> a) -> a = + fun node p k -> + match p with + | `Blinded h -> k (Blinded_node h) + | `Inode (length, proofs) -> + iproof_of_inode node length proofs (fun p -> proof_of_iproof p |> k) + | `Values vs -> iproof_of_values node vs (fun p -> proof_of_iproof p |> k) + + and iproof_of_node_proof : + type a. node -> node_proof -> (proof_inode -> a) -> a = + fun node p k -> + match p with + | `Blinded h -> k (Blinded_inode h) + | `Inode (length, proofs) -> iproof_of_inode node length proofs k + | `Values vs -> iproof_of_values node vs k + + and iproof_of_inode : + type a. node -> int -> (_ * node_proof) list -> (proof_inode -> a) -> a + = + fun node length proofs k -> + let rec aux acc = function + | [] -> k (Inode_tree { length; proofs = List.rev acc }) + | (index, proof) :: rest -> + iproof_of_node_proof node proof (fun proof -> + aux ((index, proof) :: acc) rest) + in + (* We are dealing with an inode A. + Its children are Bs. + The children of Bs are Cs. + *) + match proofs with + | [ (index, proof) ] -> + (* A has 1 child. *) + iproof_of_node_proof node proof (function + | Inode_tree { length = length'; proofs = [ (i, p) ] } -> + (* B is an inode with 1 child, C isn't. *) + assert (length = length'); + k + (Inode_extender { length; segments = [ index; i ]; proof = p }) + | Inode_extender { length = length'; segments; proof } -> + (* B is an inode with 1 child, so is C. *) + assert (length = length'); + k + (Inode_extender + { length; segments = index :: segments; proof }) + | (Blinded_inode _ | Inode_values _ | Inode_tree _) as p -> + (* B is not an inode with 1 child. *) + k (Inode_tree { length; proofs = [ (index, p) ] })) + | _ -> aux [] proofs + + and iproof_of_values : + type a. + node -> (step * Node.pnode_value) list -> (proof_inode -> a) -> a = + let findv = + let value_of_key ~cache:_ _node _repo k = + let h = P.Node.Key.to_hash k in + err_dangling_hash h + in + Node.findv_aux ~value_of_key ~return:Fun.id ~bind:(fun x f -> f x) + in + fun node steps k -> + let rec aux acc = function + | [] -> k (Inode_values (List.rev acc)) + | (step, _) :: rest -> ( + match findv ~cache:false "Proof.iproof_of_values" node step with + | None -> assert false + | Some t -> + let k p = aux ((step, p) :: acc) rest in + proof_of_tree t k) + in + aux [] steps + + let of_tree t = proof_of_tree t Fun.id + + let rec load_proof : type a. env:_ -> proof_tree -> (kinded_hash -> a) -> a + = + fun ~env p k -> + match p with + | Blinded_node h -> k (`Node h) + | Node n -> load_node_proof ~env n k + | Inode { length; proofs } -> load_inode_proof ~env length proofs k + | Blinded_contents (h, m) -> k (`Contents (h, m)) + | Contents (v, m) -> + let h = P.Contents.Hash.hash v in + Env.add_contents_from_proof env h v; + k (`Contents (h, m)) + | Extender { length; segments; proof } -> + load_extender_proof ~env length segments proof k + + (* Recontruct private node from [P.Node.Val.proof] *) + and load_extender_proof : + type a. + env:_ -> int -> int list -> proof_inode -> (kinded_hash -> a) -> a = + fun ~env len segments p k -> + node_proof_of_proof ~env p (fun p -> + let np = proof_of_extender len segments p in + let v = P.Node_portable.of_proof ~depth:0 np in + let v = + match v with + | None -> Proof.bad_proof_exn "Invalid proof" + | Some v -> v + in + let h = P.Node_portable.hash_exn v in + Env.add_pnode_from_proof env h v; + k (`Node h)) + + and proof_of_extender len segments p : node_proof = + List.fold_left + (fun acc index -> `Inode (len, [ (index, acc) ])) + p (List.rev segments) + + (* Recontruct private node from [P.Node.Val.empty] *) + and load_node_proof : + type a. env:_ -> (step * proof_tree) list -> (kinded_hash -> a) -> a = + fun ~env n k -> + let rec aux acc = function + | [] -> + let h = P.Node_portable.hash_exn acc in + Env.add_pnode_from_proof env h acc; + k (`Node h) + | (s, p) :: rest -> + let k h = aux (P.Node_portable.add acc s h) rest in + load_proof ~env p k + in + aux (P.Node_portable.empty ()) n + + (* Recontruct private node from [P.Node.Val.proof] *) + and load_inode_proof : + type a. + env:_ -> int -> (_ * proof_inode) list -> (kinded_hash -> a) -> a = + fun ~env len proofs k -> + let rec aux : _ list -> _ list -> a = + fun acc proofs -> + match proofs with + | [] -> + let np = `Inode (len, List.rev acc) in + let v = P.Node_portable.of_proof ~depth:0 np in + let v = + match v with + | None -> Proof.bad_proof_exn "Invalid proof" + | Some v -> v + in + let h = P.Node_portable.hash_exn v in + Env.add_pnode_from_proof env h v; + k (`Node h) + | (i, p) :: rest -> + let k p = aux ((i, p) :: acc) rest in + node_proof_of_proof ~env p k + in + aux [] proofs + + and node_proof_of_proof : + type a. env:_ -> proof_inode -> (node_proof -> a) -> a = + fun ~env t k -> + match t with + | Blinded_inode x -> k (`Blinded x) + | Inode_tree { length; proofs } -> + node_proof_of_inode ~env length proofs k + | Inode_values n -> node_proof_of_node ~env n k + | Inode_extender { length; segments; proof } -> + node_proof_of_proof ~env proof (fun p -> + k (proof_of_extender length segments p)) + + and node_proof_of_inode : + type a. env:_ -> int -> (_ * proof_inode) list -> (node_proof -> a) -> a + = + fun ~env length proofs k -> + let rec aux acc = function + | [] -> k (`Inode (length, List.rev acc)) + | (i, p) :: rest -> + node_proof_of_proof ~env p (fun p -> aux ((i, p) :: acc) rest) + in + aux [] proofs + + and node_proof_of_node : + type a. env:_ -> (step * proof_tree) list -> (node_proof -> a) -> a = + fun ~env node k -> + let rec aux acc = function + | [] -> k (`Values (List.rev acc)) + | (s, p) :: rest -> + load_proof ~env p (fun n -> aux ((s, n) :: acc) rest) + in + aux [] node + + let to_tree p = + let env = Env.empty () in + Env.set_mode env Env.Set Env.Deserialise; + let h = load_proof ~env (state p) Fun.id in + let tree = pruned_with_env ~env h in + Env.set_mode env Env.Set Env.Consume; + tree + end + + let produce_proof repo kinded_key f = + Env.with_set_produce @@ fun env ~start_serialise -> + let tree = import_with_env ~env repo kinded_key in + let+ tree_after, result = f tree in + let after = hash tree_after in + (* Here, we build a proof from [tree] (not from [tree_after]!), on purpose: + we look at the effect on [f] on [tree]'s caches and we rely on the fact + that the caches are env across copy-on-write copies of [tree]. *) + clear tree; + start_serialise (); + let proof = Proof.of_tree tree in + (* [env] will be purged when leaving the scope, that should avoid any memory + leaks *) + let kinded_hash = Node.weaken_value kinded_key in + (Proof.v ~before:kinded_hash ~after proof, result) + + let produce_stream repo kinded_key f = + Env.with_stream_produce @@ fun env ~to_stream -> + let tree = import_with_env ~env repo kinded_key in + let+ tree_after, result = f tree in + let after = hash tree_after in + clear tree; + let proof = to_stream () in + let kinded_hash = Node.weaken_value kinded_key in + (Proof.v ~before:kinded_hash ~after proof, result) + + let verify_proof_exn p f = + Env.with_set_consume @@ fun env ~stop_deserialise -> + let before = Proof.before p in + let after = Proof.after p in + (* First convert to proof to [Env] *) + let h = Proof.(load_proof ~env (state p) Fun.id) in + (* Then check that the consistency of the proof *) + if not (equal_kinded_hash before h) then + Irmin_proof.bad_proof_exn "verify_proof: invalid before hash"; + let tree = pruned_with_env ~env h in + Lwt.catch + (fun () -> + stop_deserialise (); + (* Then apply [f] on a cleaned tree, an exception will be raised if [f] + reads out of the proof. *) + let+ tree_after, result = f tree in + (* then check that [after] corresponds to [tree_after]'s hash. *) + if not (equal_kinded_hash after (hash tree_after)) then + Irmin_proof.bad_proof_exn "verify_proof: invalid after hash"; + (tree_after, result)) + (function + | Pruned_hash h -> + (* finaly check that [f] only access valid parts of the proof. *) + Fmt.kstr Irmin_proof.bad_proof_exn + "verify_proof: %s is trying to read through a blinded node or \ + object (%a)" + h.context pp_hash h.hash + | e -> raise e) + + type verifier_error = + [ `Proof_mismatch of string + | `Stream_too_long of string + | `Stream_too_short of string ] + [@@deriving irmin] + + let verify_proof p f = + Lwt.catch + (fun () -> + let+ r = verify_proof_exn p f in + Ok r) + (function + | Irmin_proof.Bad_proof e -> + Lwt.return (Error (`Proof_mismatch e.context)) + | e -> Lwt.fail e) + + let verify_stream_exn p f = + let before = Proof.before p in + let after = Proof.after p in + let stream = Proof.state p in + Env.with_stream_consume stream @@ fun env ~is_empty -> + let tree = pruned_with_env ~env before in + Lwt.catch + (fun () -> + let+ tree_after, result = f tree in + if not (is_empty ()) then + Irmin_proof.bad_stream_too_long "verify_stream" + "did not consume the full stream"; + if not (equal_kinded_hash after (hash tree_after)) then + Irmin_proof.bad_stream_exn "verify_stream" "invalid after hash"; + (tree_after, result)) + (function + | Pruned_hash h -> + Fmt.kstr + (Irmin_proof.bad_stream_exn "verify_stream") + "%s is trying to read through a blinded node or object (%a)" + h.context pp_hash h.hash + | e -> raise e) + + let verify_stream p f = + Lwt.catch + (fun () -> + let+ r = verify_stream_exn p f in + Ok r) + (function + | Irmin_proof.Bad_stream (Stream_too_long e) -> + Fmt.kstr + (fun e -> Lwt.return (Error (`Stream_too_long e))) + "Bad_stream %s: %s" e.context e.reason + | Irmin_proof.Bad_stream (Stream_too_short e) -> + Fmt.kstr + (fun e -> Lwt.return (Error (`Stream_too_short e))) + "Bad_stream %s: %s" e.context e.reason + | Irmin_proof.Bad_stream (Proof_mismatch e) -> + Fmt.kstr + (fun e -> Lwt.return (Error (`Proof_mismatch e))) + "Bad_stream %s: %s" e.context e.reason + | e -> Lwt.fail e) + + let hash_of_proof_state state = + let env = Env.empty () in + Proof.load_proof ~env state Fun.id + + module Private = struct + let get_env = get_env + + module Env = Env + end +end diff --git a/vendors/irmin/src/irmin/tree.mli b/vendors/irmin/src/irmin/tree.mli new file mode 100644 index 000000000000..53cb60905ca4 --- /dev/null +++ b/vendors/irmin/src/irmin/tree.mli @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2017 Grégoire Henry + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Tree_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/tree_intf.ml b/vendors/irmin/src/irmin/tree_intf.ml new file mode 100644 index 000000000000..4ea8f7028711 --- /dev/null +++ b/vendors/irmin/src/irmin/tree_intf.ml @@ -0,0 +1,504 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2017 Grégoire Henry + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +module type S = sig + type path [@@deriving irmin] + type step [@@deriving irmin] + type metadata [@@deriving irmin] + type contents [@@deriving irmin] + type contents_key [@@deriving irmin] + type node [@@deriving irmin] + type hash [@@deriving irmin] + + (** [Tree] provides immutable, in-memory partial mirror of the store, with + lazy reads and delayed writes. + + Trees are like staging area in Git: they are immutable temporary + non-persistent areas (they disappear if the host crash), held in memory + for efficiency, where reads are done lazily and writes are done only when + needed on commit: if you modify a key twice, only the last change will be + written to the store when you commit. *) + + type t [@@deriving irmin] + (** The type of trees. *) + + (** {1 Constructors} *) + + val empty : unit -> t + (** [empty ()] is the empty tree. The empty tree does not have associated + backend configuration values, as they can perform in-memory operation, + independently of any given backend. *) + + val singleton : path -> ?metadata:metadata -> contents -> t + (** [singleton k c] is the tree with a single binding mapping the key [k] to + the contents [c]. *) + + val of_contents : ?metadata:metadata -> contents -> t + (** [of_contents c] is the subtree built from the contents [c]. *) + + val of_node : node -> t + (** [of_node n] is the subtree built from the node [n]. *) + + type elt = [ `Node of node | `Contents of contents * metadata ] + (** The type for tree elements. *) + + val v : elt -> t + (** General-purpose constructor for trees. *) + + type kinded_hash = [ `Contents of hash * metadata | `Node of hash ] + [@@deriving irmin] + + val pruned : kinded_hash -> t + (** [pruned h] is a purely in-memory tree with the hash [h]. Such trees can be + used as children of other in-memory tree nodes, for instance in order to + compute the hash of the parent, but they cannot be dereferenced. + + Any operation that would require loading the contents of a pruned node + (e.g. calling {!find} on one of its children) will instead raise a + {!Pruned_hash} exception. Attempting to export a tree containing pruned + sub-trees to a repository will fail similarly. *) + + val kind : t -> path -> [ `Contents | `Node ] option Lwt.t + (** [kind t k] is the type of [s] in [t]. It could either be a tree node or + some file contents. It is [None] if [k] is not present in [t]. *) + + val is_empty : t -> bool + (** [is_empty t] is true iff [t] is {!empty} (i.e. a tree node with no + children). Trees with {!kind} = [`Contents] are never considered empty. *) + + (** {1 Diffs} *) + + val diff : t -> t -> (path * (contents * metadata) Diff.t) list Lwt.t + (** [diff x y] is the difference of contents between [x] and [y]. *) + + (** {1 Manipulating Contents} *) + + exception Dangling_hash of { context : string; hash : hash } + (** The exception raised by functions that can force lazy tree nodes but do + not return an explicit {!or_error}. *) + + exception Pruned_hash of { context : string; hash : hash } + (** The exception raised by functions that attempts to load {!pruned} tree + nodes. *) + + exception Portable_value of { context : string } + (** The exception raised by functions that attemps to perform IO on a portable + tree. *) + + type error = + [ `Dangling_hash of hash | `Pruned_hash of hash | `Portable_value ] + + type 'a or_error = ('a, error) result + + (** Operations on lazy tree contents. *) + module Contents : sig + type t + (** The type of lazy tree contents. *) + + val hash : ?cache:bool -> t -> hash + (** [hash t] is the hash of the {!contents} value returned when [t] is + {!val-force}d successfully. See {!caching} for an explanation of the + [cache] parameter. *) + + val key : t -> contents_key option + (** [key t] is the key of the {!contents} value returned when [t] is + {!val-force}d successfully. *) + + val force : t -> contents or_error Lwt.t + (** [force t] forces evaluation of the lazy content value [t], or returns an + error if no such value exists in the underlying repository. *) + + val force_exn : t -> contents Lwt.t + (** Equivalent to {!val-force}, but raises an exception if the lazy content + value is not present in the underlying repository. *) + + val clear : t -> unit + (** [clear t] clears [t]'s cache. *) + + (** {2:caching caching} + + [cache] regulates the caching behaviour regarding the node's internal + data which are be lazily loaded from the backend. + + [cache] defaults to [true] which may greatly reduce the IOs and the + runtime but may also grealy increase the memory consumption. + + [cache = false] doesn't replace a call to [clear], it only prevents the + storing of new data, it doesn't discard the existing one. *) + end + + val mem : t -> path -> bool Lwt.t + (** [mem t k] is true iff [k] is associated to some contents in [t]. *) + + val find_all : t -> path -> (contents * metadata) option Lwt.t + (** [find_all t k] is [Some (b, m)] if [k] is associated to the contents [b] + and metadata [m] in [t] and [None] if [k] is not present in [t]. *) + + val length : t -> ?cache:bool -> path -> int Lwt.t + (** [length t key] is the number of files and sub-nodes stored under [key] in + [t]. + + It is equivalent to [List.length (list t k)] but backends might optimise + this call: for instance it's a constant time operation in [irmin-pack]. + + [cache] defaults to [true], see {!caching} for an explanation of the + parameter.*) + + val find : t -> path -> contents option Lwt.t + (** [find] is similar to {!find_all} but it discards metadata. *) + + val get_all : t -> path -> (contents * metadata) Lwt.t + (** Same as {!find_all} but raise [Invalid_arg] if [k] is not present in [t]. *) + + val list : + t -> + ?offset:int -> + ?length:int -> + ?cache:bool -> + path -> + (step * t) list Lwt.t + (** [list t key] is the list of files and sub-nodes stored under [k] in [t]. + The result order is not specified but is stable. + + [offset] and [length] are used for pagination. + + [cache] defaults to [true], see {!Contents.caching} for an explanation of + the parameter. *) + + val seq : + t -> + ?offset:int -> + ?length:int -> + ?cache:bool -> + path -> + (step * t) Seq.t Lwt.t + (** [seq t key] follows the same behavior as {!list} but returns a sequence. *) + + val get : t -> path -> contents Lwt.t + (** Same as {!get_all} but ignore the metadata. *) + + val add : t -> path -> ?metadata:metadata -> contents -> t Lwt.t + (** [add t k c] is the tree where the key [k] is bound to the contents [c] but + is similar to [t] for other bindings. *) + + val update : + t -> + path -> + ?metadata:metadata -> + (contents option -> contents option) -> + t Lwt.t + (** [update t k f] is the tree [t'] that is the same as [t] for all keys + except [k], and whose binding for [k] is determined by [f (find t k)]. + + If [k] refers to an internal node of [t], [f] is called with [None] to + determine the value with which to replace it. *) + + val remove : t -> path -> t Lwt.t + (** [remove t k] is the tree where [k] bindings has been removed but is + similar to [t] for other bindings. *) + + (** {1 Manipulating Subtrees} *) + + val mem_tree : t -> path -> bool Lwt.t + (** [mem_tree t k] is false iff [find_tree k = None]. *) + + val find_tree : t -> path -> t option Lwt.t + (** [find_tree t k] is [Some v] if [k] is associated to [v] in [t]. It is + [None] if [k] is not present in [t]. *) + + val get_tree : t -> path -> t Lwt.t + (** [get_tree t k] is [v] if [k] is associated to [v] in [t]. Raise + [Invalid_arg] if [k] is not present in [t].*) + + val add_tree : t -> path -> t -> t Lwt.t + (** [add_tree t k v] is the tree where the key [k] is bound to the non-empty + tree [v] but is similar to [t] for other bindings. + + If [v] is empty, this is equivalent to [remove t k]. *) + + val update_tree : t -> path -> (t option -> t option) -> t Lwt.t + (** [update_tree t k f] is the tree [t'] that is the same as [t] for all + subtrees except under [k], and whose subtree at [k] is determined by + [f (find_tree t k)]. + + [f] returning either [None] or [Some empty] causes the subtree at [k] to + be unbound (i.e. it is equivalent to [remove t k]). *) + + val merge : t Merge.t + (** [merge] is the 3-way merge function for trees. *) + + (** {1 Folds} *) + + val destruct : t -> [ `Node of node | `Contents of Contents.t * metadata ] + (** General-purpose destructor for trees. *) + + type marks + (** The type for fold marks. *) + + val empty_marks : unit -> marks + (** [empty_marks ()] is an empty collection of marks. *) + + type 'a force = [ `True | `False of path -> 'a -> 'a Lwt.t ] + (** The type for {!fold}'s [force] parameter. [`True] forces the fold to read + the objects of the lazy nodes and contents. [`False f] is applying [f] on + every lazy node and content value instead. *) + + type uniq = [ `False | `True | `Marks of marks ] + (** The type for {!fold}'s [uniq] parameters. [`False] folds over all the + nodes. [`True] does not recurse on nodes already seen. [`Marks m] uses the + collection of marks [m] to store the cache of keys: the fold will modify + [m]. This can be used for incremental folds. *) + + type ('a, 'b) folder = path -> 'b -> 'a -> 'a Lwt.t + (** The type for {!fold}'s folders: [pre], [post], [contents], [node], and + [tree], where ['a] is the accumulator and ['b] is the item folded. *) + + type depth = [ `Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int ] + [@@deriving irmin] + (** The type for fold depths. + + - [Eq d] folds over nodes and contents of depth exactly [d]. + - [Lt d] folds over nodes and contents of depth strictly less than [d]. + - [Gt d] folds over nodes and contents of depth strictly more than [d]. + + [Le d] is [Eq d] and [Lt d]. [Ge d] is [Eq d] and [Gt d]. *) + + val fold : + ?order:[ `Sorted | `Undefined | `Random of Random.State.t ] -> + ?force:'a force -> + ?cache:bool -> + ?uniq:uniq -> + ?pre:('a, step list) folder -> + ?post:('a, step list) folder -> + ?depth:depth -> + ?contents:('a, contents) folder -> + ?node:('a, node) folder -> + ?tree:('a, t) folder -> + t -> + 'a -> + 'a Lwt.t + (** [fold t acc] folds over [t]'s nodes with node-specific folders: + [contents], [node], and [tree], based on a node's {!kind}. + + The default for all folders is identity. + + For every node [n] of [t], including itself: + + - If [n] is a [`Contents] kind, call [contents path c] where [c] is the + {!contents} of [n]. + - If [n] is a [`Node] kind, (1) call [pre path steps]; (2) call + [node path n]; (3) recursively fold on each child; (4) call + [post path steps]. + - If [n] is any kind, call [tree path t'] where [t'] is the tree of [n]. + + See {{:https://github.com/mirage/irmin/blob/main/examples/fold.ml} + examples/fold.ml} for a demo of the different {!folder}s. + + See {!force} for details about the [force] parameters. By default it is + [`True]. + + See {!uniq} for details about the [uniq] parameters. By default it is + [`False]. + + The fold depth is controlled by the [depth] parameter. + + [cache] defaults to [false], see {!Contents.caching} for an explanation of + the parameter. + + If [order] is [`Sorted] (the default), the elements are traversed in + lexicographic order of their keys. If [`Random state], they are traversed + in a random order. For large nodes, these two modes are memory-consuming, + use [`Undefined] for a more memory efficient [fold]. *) + + (** {1 Stats} *) + + type stats = { + nodes : int; (** Number of node. *) + leafs : int; (** Number of leafs. *) + skips : int; (** Number of lazy nodes. *) + depth : int; (** Maximal depth. *) + width : int; (** Maximal width. *) + } + [@@deriving irmin] + (** The type for tree stats. *) + + val stats : ?force:bool -> t -> stats Lwt.t + (** [stats ~force t] are [t]'s statistics. If [force] is true, this will force + the reading of lazy nodes. By default it is [false]. *) + + (** {1 Concrete Trees} *) + + type concrete = + [ `Tree of (step * concrete) list | `Contents of contents * metadata ] + [@@deriving irmin] + (** The type for concrete trees. *) + + val of_concrete : concrete -> t + (** [of_concrete c] is the subtree equivalent of the concrete tree [c]. + + @raise Invalid_argument + if [c] contains duplicate bindings for a given path. *) + + val to_concrete : t -> concrete Lwt.t + (** [to_concrete t] is the concrete tree equivalent of the subtree [t]. *) + + (** {1 Proofs} *) + + module Proof : sig + include + Proof.S + with type contents := contents + and type hash := hash + and type step := step + and type metadata := metadata + + type irmin_tree + + val to_tree : tree t -> irmin_tree + (** [to_tree p] is the tree [t] representing the tree proof [p]. Blinded + parts of the proof will raise [Dangling_hash] when traversed. *) + end + with type irmin_tree := t + + (** {1 Caches} *) + + val clear : ?depth:int -> t -> unit + (** [clear ?depth t] clears all caches in the tree [t] for subtrees with a + depth higher than [depth]. If [depth] is not set, all of the subtrees are + cleared. + + A call to [clear] doesn't discard the subtrees of [t], only their cache + are discarded. Even the lazily loaded and unmodified subtrees remain. *) + + (** {1 Performance counters} *) + + type counters = { + mutable contents_hash : int; + mutable contents_find : int; + mutable contents_add : int; + mutable contents_mem : int; + mutable node_hash : int; + mutable node_mem : int; + mutable node_index : int; + mutable node_add : int; + mutable node_find : int; + mutable node_val_v : int; + mutable node_val_find : int; + mutable node_val_list : int; + } + + val counters : unit -> counters + val dump_counters : unit Fmt.t + val reset_counters : unit -> unit + + val inspect : + t -> + [ `Contents | `Node of [ `Map | `Key | `Value | `Portable_dirty | `Pruned ] ] + (** [inspect t] is similar to {!kind}, with additional state information for + nodes. It is primarily useful for debugging and testing. + + If [t] holds a node, additional information about its state is included: + + - [`Map], if [t] is from {!of_concrete}. + - [`Value], if [t]'s node has modifications that have not been persisted + to a store. + - [`Portable_dirty], if [t]'s node has modifications and is + {!Node.Portable}. Currently only used with {!Proof}. + - [`Pruned], if [t] is from {!pruned}. + - Otherwise [`Key], the default state for a node loaded from a store. *) + + module Private : sig + module Env : sig + type t [@@deriving irmin] + + val is_empty : t -> bool + end + + val get_env : t -> Env.t + end +end + +module type Sigs = sig + module type S = sig + include S + (** @inline *) + end + + module Make (B : Backend.S) : sig + include + S + with type path = B.Node.Path.t + and type step = B.Node.Path.step + and type metadata = B.Node.Metadata.t + and type contents = B.Contents.value + and type contents_key = B.Contents.Key.t + and type hash = B.Hash.t + + type kinded_key = + [ `Contents of B.Contents.Key.t * metadata | `Node of B.Node.Key.t ] + [@@deriving irmin] + + val import : B.Repo.t -> kinded_key -> t option Lwt.t + val import_no_check : B.Repo.t -> kinded_key -> t + + val export : + ?clear:bool -> + B.Repo.t -> + [> write ] B.Contents.t -> + [> read_write ] B.Node.t -> + node -> + B.Node.key Lwt.t + + val dump : t Fmt.t + val equal : t -> t -> bool + val key : t -> kinded_key option + val hash : ?cache:bool -> t -> kinded_hash + val to_backend_node : node -> B.Node.Val.t Lwt.t + val to_backend_portable_node : node -> B.Node_portable.t Lwt.t + val of_backend_node : B.Repo.t -> B.Node.value -> node + + type ('proof, 'result) producer := + B.Repo.t -> + kinded_key -> + (t -> (t * 'result) Lwt.t) -> + ('proof * 'result) Lwt.t + + type verifier_error = + [ `Proof_mismatch of string + | `Stream_too_long of string + | `Stream_too_short of string ] + [@@deriving irmin] + + type ('proof, 'result) verifier := + 'proof -> + (t -> (t * 'result) Lwt.t) -> + (t * 'result, verifier_error) result Lwt.t + + type tree_proof := Proof.tree Proof.t + + val produce_proof : (tree_proof, 'a) producer + val verify_proof : (tree_proof, 'a) verifier + val hash_of_proof_state : Proof.tree -> kinded_hash + + type stream_proof := Proof.stream Proof.t + + val produce_stream : (stream_proof, 'a) producer + val verify_stream : (stream_proof, 'a) verifier + end +end diff --git a/vendors/irmin/src/irmin/type.ml b/vendors/irmin/src/irmin/type.ml new file mode 100644 index 000000000000..dbf9c2346544 --- /dev/null +++ b/vendors/irmin/src/irmin/type.ml @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Repr + +module type Defaultable = sig + include S + + val default : t +end diff --git a/vendors/irmin/src/irmin/type.mli b/vendors/irmin/src/irmin/type.mli new file mode 100644 index 000000000000..af092cd15043 --- /dev/null +++ b/vendors/irmin/src/irmin/type.mli @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include module type of Repr +(** @inline *) + +module type Defaultable = sig + include S + + val default : t +end diff --git a/vendors/irmin/src/irmin/unix/dune b/vendors/irmin/src/irmin/unix/dune new file mode 100644 index 000000000000..7813313a3f74 --- /dev/null +++ b/vendors/irmin/src/irmin/unix/dune @@ -0,0 +1,8 @@ +(library + (name irmin_unix) + (public_name irmin.unix) + (libraries irmin unix) + (preprocess + (pps ppx_irmin.internal)) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/irmin/unix/info.ml b/vendors/irmin/src/irmin/unix/info.ml new file mode 100644 index 000000000000..fc9c616befae --- /dev/null +++ b/vendors/irmin/src/irmin/unix/info.ml @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Irmin.Info.S) = struct + include I + + let v ?author fmt = + Fmt.kstr + (fun message () -> + let date = Int64.of_float (Unix.gettimeofday ()) in + let author = + match author with + | Some a -> a + | None -> + Printf.sprintf "Irmin %s.[%d]" (Unix.gethostname ()) + (Unix.getpid ()) + in + v ~author ~message date) + fmt +end diff --git a/vendors/irmin/src/irmin/unix/info.mli b/vendors/irmin/src/irmin/unix/info.mli new file mode 100644 index 000000000000..ac89da221d9e --- /dev/null +++ b/vendors/irmin/src/irmin/unix/info.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Irmin.Info.S) : sig + include Irmin.Info.S with type t = I.t + + val v : ?author:string -> ('b, Format.formatter, unit, f) format4 -> 'b +end diff --git a/vendors/irmin/src/irmin/unix/irmin_unix.ml b/vendors/irmin/src/irmin/unix/irmin_unix.ml new file mode 100644 index 000000000000..4d1307ba8a0a --- /dev/null +++ b/vendors/irmin/src/irmin/unix/irmin_unix.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Info = Info.Make +module I = Info (Irmin.Info.Default) + +let info = I.v diff --git a/vendors/irmin/src/irmin/unix/irmin_unix.mli b/vendors/irmin/src/irmin/unix/irmin_unix.mli new file mode 100644 index 000000000000..2440d321b75c --- /dev/null +++ b/vendors/irmin/src/irmin/unix/irmin_unix.mli @@ -0,0 +1,30 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** {1 Irmin Unix utilities} + + This module provides utilities for Unix applications. *) + +module Info = Info.Make + +val info : + ?author:string -> + ('a, Format.formatter, unit, unit -> Irmin.Info.default) format4 -> + 'a +(** [info fmt ()] creates a fresh commit info, with the {{!Irmin.Info.S.date} + date} set to [Unix.gettimeoday ()] and the {{!Irmin.Info.S.author} author} + built using [Unix.gethostname()] and [Unix.getpid()] if [author] is not + provided. *) diff --git a/vendors/irmin/src/irmin/version.ml b/vendors/irmin/src/irmin/version.ml new file mode 100644 index 000000000000..50da68aa2625 --- /dev/null +++ b/vendors/irmin/src/irmin/version.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let current = "%%VERSION%%" diff --git a/vendors/irmin/src/irmin/watch.ml b/vendors/irmin/src/irmin/watch.ml new file mode 100644 index 000000000000..55723d184f90 --- /dev/null +++ b/vendors/irmin/src/irmin/watch.ml @@ -0,0 +1,326 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +include Watch_intf + +let src = Logs.Src.create "irmin.watch" ~doc:"Irmin watch notifications" + +module Log = (val Logs.src_log src : Logs.LOG) + +let none _ _ = + Printf.eprintf "Listen hook not set!\n%!"; + assert false + +let listen_dir_hook = ref none + +type hook = + int -> string -> (string -> unit Lwt.t) -> (unit -> unit Lwt.t) Lwt.t + +let set_listen_dir_hook (h : hook) = listen_dir_hook := h + +let id () = + let c = ref 0 in + fun () -> + incr c; + !c + +let global = id () +let workers_r = ref 0 +let workers () = !workers_r + +let scheduler () = + let p = ref None in + let niet () = () in + let c = ref niet in + let push elt = + match !p with + | Some p -> p elt + | None -> + let stream, push = Lwt_stream.create () in + incr workers_r; + Lwt.async (fun () -> + (* FIXME: we would like to skip some updates if more recent ones + are at the back of the queue. *) + Lwt_stream.iter_s (fun f -> f ()) stream); + p := Some push; + (c := fun () -> push None); + push elt + in + let clean () = + !c (); + decr workers_r; + c := niet; + p := None + in + let enqueue v = push (Some v) in + (clean, enqueue) + +module Make (K : sig + type t + + val t : t Type.t +end) (V : sig + type t + + val t : t Type.t +end) = +struct + type key = K.t + type value = V.t + type watch = int + + module KMap = Map.Make (struct + type t = K.t + + let compare = Type.(unstage (compare K.t)) + end) + + module IMap = Map.Make (struct + type t = int + + let compare (x : int) (y : int) = compare x y + end) + + type key_handler = value Diff.t -> unit Lwt.t + type all_handler = key -> value Diff.t -> unit Lwt.t + + let pp_value = Type.pp V.t + let equal_opt_values = Type.(unstage (equal (option V.t))) + let equal_keys = Type.(unstage (equal K.t)) + + type t = { + id : int; + (* unique watch manager id. *) + lock : Lwt_mutex.t; + (* protect [keys] and [glob]. *) + mutable next : int; + (* next id, to identify watch handlers. *) + mutable keys : (key * value option * key_handler) IMap.t; + (* key handlers. *) + mutable glob : (value KMap.t * all_handler) IMap.t; + (* global handlers. *) + enqueue : (unit -> unit Lwt.t) -> unit; + (* enqueue notifications. *) + clean : unit -> unit; + (* destroy the notification thread. *) + mutable listeners : int; + (* number of listeners. *) + mutable stop_listening : unit -> unit Lwt.t; + (* clean-up listen resources. *) + mutable notifications : int; (* number of notifcations. *) + } + + let stats t = (IMap.cardinal t.keys, IMap.cardinal t.glob) + + let to_string t = + let k, a = stats t in + Printf.sprintf "[%d: %dk/%dg|%d]" t.id k a t.listeners + + let next t = + let id = t.next in + t.next <- id + 1; + id + + let is_empty t = IMap.is_empty t.keys && IMap.is_empty t.glob + + let clear_unsafe t = + t.keys <- IMap.empty; + t.glob <- IMap.empty; + t.next <- 0 + + let clear t = + Lwt_mutex.with_lock t.lock (fun () -> + clear_unsafe t; + Lwt.return_unit) + + let v () = + let lock = Lwt_mutex.create () in + let clean, enqueue = scheduler () in + { + lock; + clean; + enqueue; + id = global (); + next = 0; + keys = IMap.empty; + glob = IMap.empty; + listeners = 0; + stop_listening = (fun () -> Lwt.return_unit); + notifications = 0; + } + + let unwatch_unsafe t id = + [%log.debug "unwatch %s: id=%d" (to_string t) id]; + let glob = IMap.remove id t.glob in + let keys = IMap.remove id t.keys in + t.glob <- glob; + t.keys <- keys + + let unwatch t id = + Lwt_mutex.with_lock t.lock (fun () -> + unwatch_unsafe t id; + if is_empty t then t.clean (); + Lwt.return_unit) + + let mk old value = + match (old, value) with + | None, None -> assert false + | Some v, None -> `Removed v + | None, Some v -> `Added v + | Some x, Some y -> `Updated (x, y) + + let protect f () = + Lwt.catch f (fun e -> + [%log.err + "watch callback got: %a\n%s" Fmt.exn e (Printexc.get_backtrace ())]; + Lwt.return_unit) + + let pp_option = Fmt.option ~none:(Fmt.any "") + let pp_key = Type.pp K.t + + let notify_all_unsafe t key value = + let todo = ref [] in + let glob = + IMap.fold + (fun id ((init, f) as arg) acc -> + let fire old_value = + todo := + protect (fun () -> + [%log.debug + "notify-all[%d.%d:%a]: %d firing! (%a -> %a)" t.id id pp_key + key t.notifications (pp_option pp_value) old_value + (pp_option pp_value) value]; + t.notifications <- t.notifications + 1; + f key (mk old_value value)) + :: !todo; + let init = + match value with + | None -> KMap.remove key init + | Some v -> KMap.add key v init + in + IMap.add id (init, f) acc + in + let old_value = + try Some (KMap.find key init) with Not_found -> None + in + if equal_opt_values old_value value then ( + [%log.debug + "notify-all[%d:%d:%a]: same value, skipping." t.id id pp_key key]; + IMap.add id arg acc) + else fire old_value) + t.glob IMap.empty + in + t.glob <- glob; + match !todo with + | [] -> () + | ts -> t.enqueue (fun () -> Lwt_list.iter_p (fun x -> x ()) ts) + + let notify_key_unsafe t key value = + let todo = ref [] in + let keys = + IMap.fold + (fun id ((k, old_value, f) as arg) acc -> + if not (equal_keys key k) then IMap.add id arg acc + else if equal_opt_values value old_value then ( + [%log.debug + "notify-key[%d.%d:%a]: same value, skipping." t.id id pp_key key]; + IMap.add id arg acc) + else ( + todo := + protect (fun () -> + [%log.debug + "notify-key[%d:%d:%a] %d firing! (%a -> %a)" t.id id pp_key + key t.notifications (pp_option pp_value) old_value + (pp_option pp_value) value]; + t.notifications <- t.notifications + 1; + f (mk old_value value)) + :: !todo; + IMap.add id (k, value, f) acc)) + t.keys IMap.empty + in + t.keys <- keys; + match !todo with + | [] -> () + | ts -> t.enqueue (fun () -> Lwt_list.iter_p (fun x -> x ()) ts) + + let notify t key value = + Lwt_mutex.with_lock t.lock (fun () -> + if is_empty t then Lwt.return_unit + else ( + notify_all_unsafe t key value; + notify_key_unsafe t key value; + Lwt.return_unit)) + + let watch_key_unsafe t key ?init f = + let id = next t in + [%log.debug "watch-key %s: id=%d" (to_string t) id]; + t.keys <- IMap.add id (key, init, f) t.keys; + id + + let watch_key t key ?init f = + Lwt_mutex.with_lock t.lock (fun () -> + let id = watch_key_unsafe t ?init key f in + Lwt.return id) + + let kmap_of_alist l = + List.fold_left (fun map (k, v) -> KMap.add k v map) KMap.empty l + + let watch_unsafe t ?(init = []) f = + let id = next t in + [%log.debug "watch %s: id=%d" (to_string t) id]; + t.glob <- IMap.add id (kmap_of_alist init, f) t.glob; + id + + let watch t ?init f = + Lwt_mutex.with_lock t.lock (fun () -> + let id = watch_unsafe t ?init f in + Lwt.return id) + + let listen_dir t dir ~key ~value = + let init () = + if t.listeners = 0 then ( + [%log.debug "%s: start listening to %s" (to_string t) dir]; + let+ f = + !listen_dir_hook t.id dir (fun file -> + match key file with + | None -> Lwt.return_unit + | Some key -> + let rec read n = + let* value = value key in + let n' = t.notifications in + if n = n' then notify t key value + else ( + [%log.debug "Stale event, trying reading again"]; + read n') + in + read t.notifications) + in + t.stop_listening <- f) + else ( + [%log.debug "%s: already listening on %s" (to_string t) dir]; + Lwt.return_unit) + in + init () >|= fun () -> + t.listeners <- t.listeners + 1; + function + | () -> + if t.listeners > 0 then t.listeners <- t.listeners - 1; + if t.listeners <> 0 then Lwt.return_unit + else ( + [%log.debug "%s: stop listening to %s" (to_string t) dir]; + t.stop_listening ()) +end diff --git a/vendors/irmin/src/irmin/watch.mli b/vendors/irmin/src/irmin/watch.mli new file mode 100644 index 000000000000..38f6002ff328 --- /dev/null +++ b/vendors/irmin/src/irmin/watch.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** [Watch] provides helpers to register event notifications on read-write + stores. *) + +include Watch_intf.Sigs +(** @inline *) diff --git a/vendors/irmin/src/irmin/watch_intf.ml b/vendors/irmin/src/irmin/watch_intf.ml new file mode 100644 index 000000000000..fad0d17a1431 --- /dev/null +++ b/vendors/irmin/src/irmin/watch_intf.ml @@ -0,0 +1,96 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module type S = sig + (** {1 Watch Helpers} *) + + type key + (** The type for store keys. *) + + type value + (** The type for store values. *) + + type watch + (** The type for watch handlers. *) + + type t + (** The type for watch state. *) + + val stats : t -> int * int + (** [stats t] is a tuple [(k,a)] represeting watch stats. [k] is the number of + single key watchers for the store [t] and [a] the number of global + watchers for [t]. *) + + val notify : t -> key -> value option -> unit Lwt.t + (** Notify all listeners in the given watch state that a key has changed, with + the new value associated to this key. [None] means the key has been + removed. *) + + val v : unit -> t + (** Create a watch state. *) + + val clear : t -> unit Lwt.t + (** Clear all register listeners in the given watch state. *) + + val watch_key : + t -> key -> ?init:value -> (value Diff.t -> unit Lwt.t) -> watch Lwt.t + (** Watch a given key for changes. More efficient than {!watch}. *) + + val watch : + t -> + ?init:(key * value) list -> + (key -> value Diff.t -> unit Lwt.t) -> + watch Lwt.t + (** Add a watch handler. To watch a specific key, use {!watch_key} which is + more efficient. *) + + val unwatch : t -> watch -> unit Lwt.t + (** Remove a watch handler. *) + + val listen_dir : + t -> + string -> + key:(string -> key option) -> + value:(key -> value option Lwt.t) -> + (unit -> unit Lwt.t) Lwt.t + (** Register a thread looking for changes in the given directory and return a + function to stop watching and free up resources. *) +end + +module type Sigs = sig + module type S = S + (** The signature for watch helpers. *) + + val workers : unit -> int + (** [workers ()] is the number of background worker threads managing event + notification currently active. *) + + type hook = + int -> string -> (string -> unit Lwt.t) -> (unit -> unit Lwt.t) Lwt.t + (** The type for watch hooks. *) + + val none : hook + (** [none] is the hooks which asserts false. *) + + val set_listen_dir_hook : hook -> unit + (** Register a function which looks for file changes in a directory and return + a function to stop watching. It is probably best to use + {!Irmin_watcher.hook} there. By default, it uses {!none}. *) + + (** [Make] builds an implementation of watch helpers. *) + module Make (K : Type.S) (V : Type.S) : + S with type key = K.t and type value = V.t +end diff --git a/vendors/irmin/src/libirmin/commit.ml b/vendors/irmin/src/libirmin/commit.ml new file mode 100644 index 000000000000..e796c0c2a13f --- /dev/null +++ b/vendors/irmin/src/libirmin/commit.ml @@ -0,0 +1,160 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "commit_info" + (repo @-> commit @-> returning info) + (fun (type repo) repo commit -> + with_repo' repo info + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let commit = Root.get_commit (module Store) commit in + Root.create_info (module Store) (Store.Commit.info commit))) + + let () = + fn "commit_hash" + (repo @-> commit @-> returning hash) + (fun (type repo) repo commit -> + with_repo' repo hash + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let commit = Root.get_commit (module Store) commit in + Root.create_hash (module Store) (Store.Commit.hash commit))) + + let () = + fn "commit_key" + (repo @-> commit @-> returning commit_key) + (fun (type repo) repo commit -> + with_repo' repo commit_key + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let commit = Root.get_commit (module Store) commit in + Root.create_commit_key (module Store) (Store.Commit.key commit))) + + let () = + fn "commit_of_hash" + (repo @-> hash @-> returning commit) + (fun (type repo) repo hash -> + with_repo' repo commit + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let hash = Root.get_hash (module Store) hash in + let c = run (Store.Commit.of_hash repo hash) in + match c with + | Some c -> Root.create_commit (module Store) c + | None -> null commit)) + + let () = + fn "commit_of_key" + (repo @-> commit_key @-> returning commit) + (fun (type repo) repo hash -> + with_repo' repo commit + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let hash = Root.get_commit_key (module Store) hash in + let c = run (Store.Commit.of_key repo hash) in + match c with + | Some c -> Root.create_commit (module Store) c + | None -> null commit)) + + let () = + fn "commit_new" + (repo @-> ptr commit @-> uint64_t @-> tree @-> info @-> returning commit) + (fun (type repo) repo parents n tree info -> + with_repo' repo commit + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let n = UInt64.to_int n in + let parents = + if is_null parents || n = 0 then [] + else + CArray.from_ptr parents n + |> CArray.to_list + |> List.map (Root.get_commit (module Store)) + |> List.map Store.Commit.key + in + let tree = Root.get_tree (module Store) tree in + let info = Root.get_info (module Store) info in + let commit = run (Store.Commit.v repo ~parents ~info tree) in + Root.create_commit (module Store) commit)) + + let () = + let open Lwt.Infix in + fn "commit_parents" + (repo @-> commit @-> returning commit_array) + (fun (type repo) repo commit -> + with_repo' repo commit_array + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let commit = Root.get_commit (module Store) commit in + let parents = Store.Commit.parents commit in + let parents = + run + (Lwt_list.filter_map_s + (fun x -> + Store.Commit.of_key repo x >|= function + | None -> None + | Some x -> Some x) + parents) + in + Root.create_commit_array (module Store) parents)) + + let () = + fn "commit_equal" + (repo @-> commit @-> commit @-> returning bool) + (fun (type repo) repo a b -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let a = Root.get_commit (module Store) a in + let b = Root.get_commit (module Store) b in + Irmin.Type.(unstage (equal (Store.commit_t repo))) a b)) + + let () = + fn "commit_tree" + (repo @-> commit @-> returning tree) + (fun (type repo) repo commit -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let commit = Root.get_commit (module Store) commit in + Root.create_tree (module Store) (Store.Commit.tree commit))) + + let () = + fn "commit_array_length" + (repo @-> commit_array @-> returning uint64_t) + (fun (type repo) repo p -> + with_repo repo UInt64.zero + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let arr = Root.get_commit_array (module Store) p in + UInt64.of_int (Array.length arr))) + + let () = + fn "commit_array_get" + (repo @-> commit_array @-> uint64_t @-> returning commit) + (fun (type repo) repo p i -> + with_repo' repo commit + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let i = UInt64.to_int i in + let arr = Root.get_commit_array (module Store) p in + if i >= Array.length arr then failwith "index out of bounds" + else + let x = Array.unsafe_get arr i in + Root.create_commit (module Store) x)) + + let () = fn "commit_array_free" (commit_array @-> returning void) free + let () = fn "commit_free" (commit @-> returning void) free + let () = fn "commit_key_free" (commit_key @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/config.ml b/vendors/irmin/src/libirmin/config.ml new file mode 100644 index 000000000000..29fab1e0d6d2 --- /dev/null +++ b/vendors/irmin/src/libirmin/config.ml @@ -0,0 +1,150 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "log_level" + (string_opt @-> returning bool) + (fun level -> + try + match level with + | None -> + Logs.set_level None; + true + | Some level -> ( + Fmt_tty.setup_std_outputs (); + Logs.set_reporter (Logs_fmt.reporter ()); + match Logs.level_of_string level with + | Error _ -> false + | Ok level -> + Logs.set_level level; + true) + with _ -> false) + + let () = + fn "config_pack" + (string_opt @-> string_opt @-> returning config) + (fun hash contents -> + try + let hash = Option.map Irmin_cli.Resolver.Hash.find hash in + let c : config = + Irmin_cli.Resolver.load_config ~store:"pack" ?hash ?contents () + in + Root.create_config c + with _ -> null config) + + let () = + fn "config_tezos" + (void @-> returning config) + (fun () -> + try + let c : config = Irmin_cli.Resolver.load_config ~store:"tezos" () in + Root.create_config c + with _ -> null config) + + let () = + fn "config_git" + (string_opt @-> returning config) + (fun contents -> + try + let c = Irmin_cli.Resolver.load_config ~store:"git" ?contents () in + Root.create_config c + with _ -> null config) + + let () = + fn "config_git_mem" + (string_opt @-> returning config) + (fun contents -> + try + let c = + Irmin_cli.Resolver.load_config ~store:"git-mem" ?contents () + in + Root.create_config c + with _ -> null config) + + let () = + fn "config_fs" + (string_opt @-> string_opt @-> returning config) + (fun hash contents -> + try + let hash = Option.map Irmin_cli.Resolver.Hash.find hash in + let c = + Irmin_cli.Resolver.load_config ~store:"irf" ?hash ?contents () + in + Root.create_config c + with _ -> null config) + + let () = + fn "config_mem" + (string_opt @-> string_opt @-> returning config) + (fun hash contents -> + try + let hash = Option.map Irmin_cli.Resolver.Hash.find hash in + let c = + Irmin_cli.Resolver.load_config ~store:"mem" ?hash ?contents () + in + Root.create_config c + with _ -> null config) + + let () = fn "config_free" (config @-> returning void) free + + let () = + fn "config_set" + (config @-> string @-> ty @-> value @-> returning bool) + (fun (type a) c key ty value -> + try + let (s, config) : config = Root.get_config c in + let (module S) = Irmin_cli.Resolver.Store.generic_keyed s in + let k = find_config_key config key in + let ok, config = + match k with + | None -> (false, config) + | Some (Irmin.Backend.Conf.K k) -> + let t : a Irmin.Type.t = Root.get_ty ty in + if type_name t <> type_name (Irmin.Backend.Conf.ty k) then + (false, config) + else + let value = Root.get_value value in + (true, Irmin.Backend.Conf.add config k value) + in + Root.set_config c (s, config); + ok + with _ -> false) + + let () = + fn "config_set_root" + (config @-> string @-> returning bool) + (fun c path -> + try + let (s, config) : config = Root.get_config c in + let (module S) = Irmin_cli.Resolver.Store.generic_keyed s in + let k = find_config_key config "root" in + let ok, config = + match k with + | None -> (false, config) + | Some (Irmin.Backend.Conf.K k) -> + let path = + Irmin.Type.of_string (Irmin.Backend.Conf.ty k) path + |> Result.get_ok + in + (true, Irmin.Backend.Conf.add config k path) + in + Root.set_config c (s, config); + ok + with _ -> false) +end diff --git a/vendors/irmin/src/libirmin/dune b/vendors/irmin/src/libirmin/dune new file mode 100644 index 000000000000..1672aa7e6927 --- /dev/null +++ b/vendors/irmin/src/libirmin/dune @@ -0,0 +1,5 @@ +(library + (name libirmin_bindings) + (libraries irmin-cli irmin.unix ctypes.foreign) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/libirmin/gen/dune b/vendors/irmin/src/libirmin/gen/dune new file mode 100644 index 000000000000..52692a0b2060 --- /dev/null +++ b/vendors/irmin/src/libirmin/gen/dune @@ -0,0 +1,4 @@ +(executable + (name generate) + (modules generate) + (libraries libirmin_bindings)) diff --git a/vendors/irmin/src/libirmin/gen/generate.ml b/vendors/irmin/src/libirmin/gen/generate.ml new file mode 100644 index 000000000000..90943b7f1495 --- /dev/null +++ b/vendors/irmin/src/libirmin/gen/generate.ml @@ -0,0 +1,98 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let generate dirname = + let prefix = "irmin" in + let path basename = Filename.concat dirname basename in + let ml_fd = open_out (path "irmin_bindings.ml") in + let c_fd = open_out (path "irmin.c") in + let h_fd = open_out (path "irmin.h") in + let stubs = (module Libirmin_bindings.Stubs : Cstubs_inverted.BINDINGS) in + let writeln fd s = output_string fd (s ^ "\n") in + let types fd names = + List.iter + (fun n -> writeln fd (Printf.sprintf "typedef struct %s %s;" n n)) + names + in + (* Generate the ML module that links in the generated C. *) + Cstubs_inverted.write_ml (Format.formatter_of_out_channel ml_fd) ~prefix stubs; + + (* Generate the C source file that exports OCaml functions. *) + Format.fprintf + (Format.formatter_of_out_channel c_fd) + "#include \"irmin.h\"@\n%a" + (Cstubs_inverted.write_c ~prefix) + stubs; + writeln c_fd + {| +#ifndef IRMIN_NO_INIT +static char *_libirmin_args[] = {"libirmin", NULL}; +void irmin_init(void){ + caml_startup(_libirmin_args); +} +#ifdef __APPLE__ +__attribute__((section("__DATA,__mod_init_func"))) typeof(irmin_init) *p_irmin_init = irmin_init; +#else +__attribute__((section(".init_array"))) void (*p_irmin_init)(void) = irmin_init; +#endif +#endif + |}; + + (* Generate the C header file that exports OCaml functions. *) + writeln h_fd "#pragma once"; + writeln h_fd "#include "; + writeln h_fd "#include "; + types h_fd + [ + "IrminType"; + "IrminValue"; + "IrminMetadata"; + "IrminContents"; + "IrminConfig"; + "IrminRepo"; + "Irmin"; + "IrminPath"; + "IrminCommitKey"; + "IrminKindedKey"; + "IrminTree"; + "IrminCommit"; + "IrminInfo"; + "IrminHash"; + "IrminString"; + "IrminPathArray"; + "IrminCommitArray"; + "IrminBranchArray"; + "IrminRemote"; + ]; + writeln h_fd "void caml_startup(char *argv[]);"; + writeln h_fd "void caml_shutdown();"; + + Cstubs_inverted.write_c_header + (Format.formatter_of_out_channel h_fd) + ~prefix stubs; + writeln h_fd + {| +#ifndef IRMIN_NO_AUTO +static void _irmin_cleanup(void *p) { if (p) { irmin_free(*(Irmin**)p); p = (void*)0;} }; +#define AUTO __attribute__((cleanup(_irmin_cleanup))) +#endif + |}; + + close_out h_fd; + close_out c_fd; + close_out ml_fd + +let () = generate Sys.argv.(1) diff --git a/vendors/irmin/src/libirmin/info.ml b/vendors/irmin/src/libirmin/info.ml new file mode 100644 index 000000000000..dfe46d4e668c --- /dev/null +++ b/vendors/irmin/src/libirmin/info.ml @@ -0,0 +1,69 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "info_new" + (repo @-> string_opt @-> string @-> returning info) + (fun (type repo) repo author message -> + with_repo' repo info + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let module Info = Irmin_unix.Info (Store.Info) in + let info : Info.t = Info.v ?author "%s" message () in + Root.create_info (module Store) info)) + + let () = + fn "info_update" + (repo @-> info @-> string_opt @-> string @-> returning void) + (fun (type repo) repo info author message -> + with_repo repo () + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let module Info = Irmin_unix.Info (Store.Info) in + Root.set_info (module Store) info (Info.v ?author "%s" message ()))) + + let () = + fn "info_message" + (repo @-> info @-> returning irmin_string) + (fun (type repo) repo info -> + with_repo' repo irmin_string + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let info = Root.get_info (module Store) info in + let s = Store.Info.message info in + Root.create_string s)) + + let () = + fn "info_author" + (repo @-> info @-> returning irmin_string) + (fun (type repo) repo info -> + with_repo' repo irmin_string + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let info = Root.get_info (module Store) info in + let s = Store.Info.author info in + Root.create_string s)) + + let () = + fn "info_date" + (repo @-> info @-> returning int64_t) + (fun (type repo) repo info -> + with_repo repo (-1L) + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let info = Root.get_info (module Store) info in + Store.Info.date info)) + + let () = fn "info_free" (info @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/lib/dune b/vendors/irmin/src/libirmin/lib/dune new file mode 100644 index 000000000000..dbfd80157a6f --- /dev/null +++ b/vendors/irmin/src/libirmin/lib/dune @@ -0,0 +1,31 @@ +(rule + (targets irmin_bindings.ml irmin.c irmin.h) + (deps + (:gen ../gen/generate.exe)) + (action + (run %{gen} .))) + +(executable + (name libirmin) + (package libirmin) + (public_name libirmin) + (libraries libirmin_bindings) + (modes + (native shared_object) + native) + (modules libirmin irmin_bindings) + (foreign_stubs + (language c) + (names irmin))) + +(install + (package libirmin) + (section lib) + (files + (irmin.h as include/irmin.h) + (libirmin.so as lib/libirmin.so))) + +(env + (dev + (flags + (:standard -w -unused-var-strict)))) diff --git a/vendors/irmin/src/libirmin/lib/libirmin.ml b/vendors/irmin/src/libirmin/lib/libirmin.ml new file mode 100644 index 000000000000..27dbd2d086f3 --- /dev/null +++ b/vendors/irmin/src/libirmin/lib/libirmin.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Libirmin_bindings.Stubs (Irmin_bindings) diff --git a/vendors/irmin/src/libirmin/libirmin_bindings.ml b/vendors/irmin/src/libirmin/libirmin_bindings.ml new file mode 100644 index 000000000000..6a2dc1f584c0 --- /dev/null +++ b/vendors/irmin/src/libirmin/libirmin_bindings.ml @@ -0,0 +1,27 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Stubs (I : Cstubs_inverted.INTERNAL) = struct + include Type.Make (I) + include Value.Make (I) + include Info.Make (I) + include Config.Make (I) + include Store.Make (I) + include Tree.Make (I) + include Repo.Make (I) + include Commit.Make (I) + include Path.Make (I) +end diff --git a/vendors/irmin/src/libirmin/path.ml b/vendors/irmin/src/libirmin/path.ml new file mode 100644 index 000000000000..80d38dae2659 --- /dev/null +++ b/vendors/irmin/src/libirmin/path.ml @@ -0,0 +1,123 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "path" + (repo @-> ptr string_opt @-> returning path) + (fun (type repo) repo arr -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let rec loop i acc = + if is_null arr then acc + else + match !@(arr +@ i) with + | None -> List.rev acc + | Some x -> loop (i + 1) (x :: acc) + in + let l = loop 0 [] in + let l = + List.map + (fun x -> Irmin.Type.of_string Store.step_t x |> Result.get_ok) + l + in + Store.Path.v l |> Root.create_path (module Store))) + + let () = + fn "path_of_string" + (repo @-> ptr char @-> int64_t @-> returning path) + (fun (type repo) repo s length -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let length = get_length length s in + let s = string_from_ptr s ~length in + match Irmin.Type.of_string Store.Path.t s with + | Ok p -> Root.create_path (module Store) p + | Error (`Msg e) -> failwith e)) + + let () = + fn "path_empty" + (repo @-> returning path) + (fun (type repo) repo -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_path (module Store) Store.Path.empty)) + + let () = + fn "path_to_string" + (repo @-> path @-> returning irmin_string) + (fun (type repo) repo p -> + with_repo' repo irmin_string + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let path = Root.get_path (module Store) p in + let s = Irmin.Type.to_string Store.Path.t path in + Root.create_string s)) + + let () = + fn "path_parent" + (repo @-> path @-> returning path) + (fun (type repo) repo p -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let p = Root.get_path (module Store) p in + let p = Store.Path.rdecons p |> Option.map fst in + match p with + | Some p -> Root.create_path (module Store) p + | None -> null path)) + + let () = + fn "path_append" + (repo @-> path @-> ptr char @-> int64_t @-> returning path) + (fun (type repo) repo p s length -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let length = get_length length s in + let p = Root.get_path (module Store) p in + let s = string_from_ptr s ~length in + match Irmin.Type.of_string Store.step_t s with + | Ok s -> Root.create_path (module Store) (Store.Path.rcons p s) + | Error (`Msg e) -> failwith e)) + + let () = + fn "path_append_path" + (repo @-> path @-> path @-> returning path) + (fun (type repo) repo p s -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let rec concat_paths a b = + match Store.Path.decons b with + | Some (step, path) -> concat_paths (Store.Path.rcons a step) path + | None -> a + in + let path = Root.get_path (module Store) p in + let path' = Root.get_path (module Store) s in + let dest = concat_paths path path' in + Root.create_path (module Store) dest)) + + let () = + fn "path_equal" + (repo @-> path @-> path @-> returning bool) + (fun (type repo) repo a b -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let a = Root.get_path (module Store) a in + let b = Root.get_path (module Store) b in + Irmin.Type.(unstage (equal Store.path_t)) a b)) + + let () = fn "path_free" (path @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/repo.ml b/vendors/irmin/src/libirmin/repo.ml new file mode 100644 index 000000000000..417bc160ed94 --- /dev/null +++ b/vendors/irmin/src/libirmin/repo.ml @@ -0,0 +1,193 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "repo_new" + (config @-> returning repo) + (fun config -> + let (s, config) : config = Root.get_config config in + let (module Store) = Irmin_cli.Resolver.Store.generic_keyed s in + let remote = Irmin_cli.Resolver.Store.remote s in + let repo : Store.repo = run (Store.Repo.v config) in + Root.create_repo + (module Store) + { + error = None; + repo_mod = + (module Store : Irmin.Generic_key.S with type repo = Store.repo); + repo; + remote; + }) + + let () = + fn "repo_branches" + (repo @-> returning branch_array) + (fun (type repo) repo -> + with_repo' repo branch_array + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let b = run (Store.Repo.branches repo) in + Root.create_branch_array (module Store) b)) + + let () = + fn "branch_array_length" + (repo @-> branch_array @-> returning uint64_t) + (fun (type repo) repo p -> + with_repo repo UInt64.zero + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let arr = Root.get_branch_array (module Store) p in + UInt64.of_int (Array.length arr))) + + let () = + fn "branch_array_get" + (repo @-> branch_array @-> uint64_t @-> returning irmin_string) + (fun (type repo) repo p i -> + with_repo' repo irmin_string + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let i = UInt64.to_int i in + let arr = Root.get_branch_array (module Store) p in + if i >= Array.length arr then failwith "index out of bounds" + else + let x = Array.unsafe_get arr i in + Root.create_string (Irmin.Type.to_string Store.Branch.t x))) + + let () = + fn "hash_equal" + (repo @-> hash @-> hash @-> returning bool) + (fun (type repo) repo a b -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let a = Root.get_hash (module Store) a in + let b = Root.get_hash (module Store) b in + Irmin.Type.(unstage (equal Store.hash_t)) a b)) + + let () = + fn "contents_hash" + (repo @-> contents @-> returning hash) + (fun (type repo) repo a -> + with_repo' repo hash + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let a = Root.get_contents (module Store) a in + Root.create_hash (module Store) (Store.Contents.hash a))) + + let () = + fn "contents_of_hash" + (repo @-> hash @-> returning contents) + (fun (type repo) repo a -> + with_repo' repo contents + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let a = Root.get_hash (module Store) a in + let c = run @@ Store.Contents.of_hash repo a in + match c with + | Some c -> Root.create_contents (module Store) c + | None -> null contents)) + + let () = + fn "contents_of_key" + (repo @-> kinded_key @-> returning contents) + (fun (type repo) repo a -> + with_repo' repo contents + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let a = Root.get_kinded_key (module Store) a in + match a with + | `Contents (a, _) -> ( + let c = run @@ Store.Contents.of_key repo a in + match c with + | Some c -> Root.create_contents (module Store) c + | None -> null contents) + | `Node _ -> null contents)) + + let () = + fn "contents_to_string" + (repo @-> contents @-> returning irmin_string) + (fun (type repo) repo contents -> + with_repo' repo irmin_string + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let contents = Root.get_contents (module Store) contents in + let s = Irmin.Type.to_string Store.contents_t contents in + Root.create_string s)) + + let () = + fn "contents_of_string" + (repo @-> ptr char @-> int64_t @-> returning contents) + (fun (type repo) repo s length -> + with_repo' repo contents + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let length = get_length length s in + let s = string_from_ptr s ~length in + let hash = Irmin.Type.of_string Store.contents_t s in + match hash with + | Ok hash -> Root.create_contents (module Store) hash + | Error (`Msg e) -> failwith e)) + + let () = + fn "hash_to_string" + (repo @-> hash @-> returning irmin_string) + (fun (type repo) repo hash -> + with_repo' repo irmin_string + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let hash = Root.get_hash (module Store) hash in + let s = Irmin.Type.to_string Store.hash_t hash in + Root.create_string s)) + + let () = + fn "hash_of_string" + (repo @-> ptr char @-> int64_t @-> returning hash) + (fun (type repo) repo s length -> + with_repo' repo hash + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let length = get_length length s in + let s = string_from_ptr s ~length in + let h = Irmin.Type.of_string Store.Hash.t s in + match h with + | Ok h -> Root.create_hash (module Store) h + | Error (`Msg e) -> failwith e)) + + let () = + fn "metadata_default" + (repo @-> returning metadata) + (fun (type repo) repo -> + with_repo' repo metadata + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_metadata (module Store) Store.Metadata.default)) + + let () = + fn "repo_has_error" + (repo @-> returning bool) + (fun repo -> + let r = Root.get_repo repo in + Option.is_some r.error) + + let () = + fn "repo_get_error" + (repo @-> returning irmin_string) + (fun repo -> + let r = Root.get_repo repo in + match r.error with + | Some x -> Root.create_string x + | None -> null irmin_string) + + let () = fn "hash_free" (hash @-> returning void) free + let () = fn "branch_array_free" (branch_array @-> returning void) free + let () = fn "repo_free" (repo @-> returning void) free + let () = fn "metadata_free" (metadata @-> returning void) free + let () = fn "contents_free" (contents @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/store.ml b/vendors/irmin/src/libirmin/store.ml new file mode 100644 index 000000000000..be17aa7c2404 --- /dev/null +++ b/vendors/irmin/src/libirmin/store.ml @@ -0,0 +1,450 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "main" + (repo @-> returning store) + (fun (type repo) repo' -> + let r = Root.to_voidp repo repo' in + with_repo' repo' store + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + Root.create_store + (module Store) + { + repo = r; + store_mod = + (module Store : Irmin.Generic_key.S with type t = Store.t); + store = run (Store.main repo); + })) + + let () = + fn "of_branch" + (repo @-> string @-> returning store) + (fun (type repo) repo' name -> + let r = Root.to_voidp repo repo' in + with_repo' repo' store + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + match Irmin.Type.of_string Store.Branch.t name with + | Error (`Msg err) -> failwith err + | Ok branch -> + Root.create_store + (module Store) + { + repo = r; + store_mod = + (module Store : Irmin.Generic_key.S with type t = Store.t); + store = run (Store.of_branch repo branch); + })) + + let () = + fn "of_commit" + (repo @-> commit @-> returning store) + (fun (type repo) repo' commit -> + let r = Root.to_voidp repo repo' in + with_repo' repo' store + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let commit = Root.get_commit (module Store) commit in + Root.create_store + (module Store) + { + repo = r; + store_mod = + (module Store : Irmin.Generic_key.S with type t = Store.t); + store = run (Store.of_commit commit); + })) + + let () = + fn "get_head" + (store @-> returning commit) + (fun (type t) store -> + with_store' store commit + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let c = run (Store.Head.find store) in + match c with + | None -> null commit + | Some x -> Root.create_commit (module Store) x)) + + let () = + fn "set_head" + (store @-> commit @-> returning void) + (fun (type t) store commit -> + with_store store () + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let commit : Store.commit = Root.get_commit (module Store) commit in + run (Store.Head.set store commit))) + + let () = + fn "fast_forward" + (store @-> commit @-> returning bool) + (fun (type t) store commit -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let commit : Store.commit = Root.get_commit (module Store) commit in + let res = run (Store.Head.fast_forward store commit) in + match res with + | Ok () -> true + | Error e -> failwith (Irmin.Type.to_string Store.ff_error_t e))) + + let () = + fn "merge_with_branch" + (store @-> string @-> info @-> returning bool) + (fun (type t) store branch info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let info = Root.get_info (module Store) info in + let branch = + Irmin.Type.of_string Store.branch_t branch |> Result.get_ok + in + let res = + run (Store.merge_with_branch store branch ~info:(fun () -> info)) + in + match res with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Irmin.Merge.conflict_t e in + failwith s)) + + let () = + fn "merge_with_commit" + (store @-> commit @-> info @-> returning bool) + (fun (type t) store commit info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let info = Root.get_info (module Store) info in + let commit = Root.get_commit (module Store) commit in + let res = + run (Store.merge_with_commit store commit ~info:(fun () -> info)) + in + match res with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Irmin.Merge.conflict_t e in + failwith s)) + + let () = + fn "merge_into" + (store @-> store @-> info @-> returning bool) + (fun (type t) store store1 info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let store1 = Root.get_store store1 in + let info = Root.get_info (module Store) info in + let res = + run + (Store.merge_into ~into:store store1.store ~info:(fun () -> + info)) + in + match res with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Irmin.Merge.conflict_t e in + failwith s)) + + let () = + fn "set" + (store @-> path @-> contents @-> info @-> returning bool) + (fun (type t) store path value info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let info = Root.get_info (module Store) info in + let path : Store.path = Root.get_path (module Store) path in + let value : Store.contents = + Root.get_contents (module Store) value + in + let x = run (Store.set store path value ~info:(fun () -> info)) in + match x with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Store.write_error_t e in + failwith s)) + + let () = + fn "test_and_set" + (store @-> path @-> contents @-> contents @-> info @-> returning bool) + (fun (type t) store path test set info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let info = Root.get_info (module Store) info in + let path : Store.path = Root.get_path (module Store) path in + let test : Store.contents option = + if is_null test then None + else Some (Root.get_contents (module Store) test) + in + let set : Store.contents option = + if is_null set then None + else Some (Root.get_contents (module Store) set) + in + let x = + run + (Store.test_and_set store path ~test ~set ~info:(fun () -> info)) + in + match x with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Store.write_error_t e in + failwith s)) + + let () = + fn "test_and_set_tree" + (store @-> path @-> tree @-> tree @-> info @-> returning bool) + (fun (type t) store path test set info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let info = Root.get_info (module Store) info in + let path : Store.path = Root.get_path (module Store) path in + let test : Store.tree option = + if is_null test then None + else Some (Root.get_tree (module Store) test) + in + let set : Store.tree option = + if is_null set then None + else Some (Root.get_tree (module Store) set) + in + let x = + run + (Store.test_and_set_tree store path ~test ~set ~info:(fun () -> + info)) + in + match x with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Store.write_error_t e in + failwith s)) + + let () = + fn "set_tree" + (store @-> path @-> tree @-> info @-> returning bool) + (fun (type t) store path tree info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let info : Store.info = Root.get_info (module Store) info in + let path : Store.path = Root.get_path (module Store) path in + let tree' : Store.tree = Root.get_tree (module Store) tree in + let x = + run (Store.set_tree store path tree' ~info:(fun () -> info)) + in + match x with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Store.write_error_t e in + failwith s)) + + let () = + fn "find" + (store @-> path @-> returning contents) + (fun (type t) store path -> + with_store' store contents + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let path : Store.path = Root.get_path (module Store) path in + let x = run (Store.find store path) in + match x with + | Some x -> Root.create_contents (module Store) x + | None -> null contents)) + + let () = + fn "find_metadata" + (store @-> path @-> returning metadata) + (fun (type t) store path -> + with_store' store metadata + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let path : Store.path = Root.get_path (module Store) path in + let x = run (Store.find_all store path) in + match x with + | Some (_, m) -> Root.create_metadata (module Store) m + | None -> null metadata)) + + let () = + fn "find_tree" + (store @-> path @-> returning tree) + (fun (type t) store path -> + with_store' store tree + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let path : Store.path = Root.get_path (module Store) path in + let x : Store.tree option = run (Store.find_tree store path) in + match x with + | Some x -> Root.create_tree (module Store) x + | None -> null tree)) + + let () = + fn "remove" + (store @-> path @-> info @-> returning bool) + (fun (type t) store path info -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let module Info = Irmin_unix.Info (Store.Info) in + let info = Root.get_info (module Store) info in + let path : Store.path = Root.get_path (module Store) path in + match run (Store.remove store path ~info:(fun () -> info)) with + | Ok () -> true + | Error e -> + let s = Irmin.Type.to_string Store.write_error_t e in + failwith s)) + + let () = + fn "mem" + (store @-> path @-> returning bool) + (fun (type t) store path -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let path : Store.path = Root.get_path (module Store) path in + run (Store.mem store path))) + + let () = + fn "mem_tree" + (store @-> path @-> returning bool) + (fun (type t) store path -> + with_store store false + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let path : Store.path = Root.get_path (module Store) path in + run (Store.mem_tree store path))) + + let () = + fn "list" + (store @-> path @-> returning path_array) + (fun (type t) store path -> + with_store' store path_array + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let path : Store.path = Root.get_path (module Store) path in + let items = run (Store.list store path) in + let items = List.map (fun (k, _v) -> Store.Path.v [ k ]) items in + Root.create_path_array (module Store) items)) + + let () = + fn "path_array_length" + (repo @-> path_array @-> returning uint64_t) + (fun (type repo) repo p -> + with_repo repo UInt64.zero + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let arr = Root.get_path_array (module Store) p in + UInt64.of_int (Array.length arr))) + + let () = + fn "path_array_get" + (repo @-> path_array @-> uint64_t @-> returning path) + (fun (type repo) repo p i -> + with_repo' repo path + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let i = UInt64.to_int i in + let arr = Root.get_path_array (module Store) p in + if i >= Array.length arr then failwith "index out of bounds" + else + let x = Array.unsafe_get arr i in + Root.create_path (module Store) x)) + + let () = + fn "remote_store" + (store @-> returning remote) + (fun (type t) store -> + with_store' store remote + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + Root.create_remote (Irmin.remote_store (module Store) store))) + + let () = + fn "remote" + (repo @-> string @-> returning remote) + (fun (type repo) repo url -> + let r = Root.get_repo repo in + let remote_fn = r.remote in + with_repo' repo remote + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + match remote_fn with + | None -> + failwith "sync is not implemented for the selected backend" + | Some f -> Root.create_remote (run (f url)))) + + let () = + fn "remote_with_auth" + (repo @-> string @-> string @-> string_opt @-> returning remote) + (fun (type repo) repo url user token -> + let r = Root.get_repo repo in + let remote_fn = r.remote in + with_repo' repo remote + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + match remote_fn with + | None -> + failwith "sync is not implemented for the selected backend" + | Some f -> + let headers = Cohttp.Header.init () in + let headers = + match token with + | Some token -> + Cohttp.Header.add_authorization headers + (`Basic (user, token)) + | _ -> Cohttp.Header.add_authorization headers (`Other user) + in + Root.create_remote (run (f ~headers url)))) + + let () = + fn "fetch" + (store @-> int @-> remote @-> returning commit) + (fun (type t) store depth remote -> + with_store' store commit + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let module Sync = Irmin.Sync.Make (Store) in + let remote = + if is_null remote then failwith "Invalid remote" + else Root.get_remote remote + in + let depth = if depth <= 0 then None else Some depth in + match run (Sync.fetch_exn ?depth store remote) with + | `Empty -> null commit + | `Head head -> Root.create_commit (module Store) head)) + + let () = + fn "pull" + (store @-> int @-> remote @-> info @-> returning commit) + (fun (type t) store depth remote info -> + with_store' store commit + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let module Sync = Irmin.Sync.Make (Store) in + let remote = + if is_null remote then failwith "Invalid remote" + else Root.get_remote remote + in + let x = + if is_null info then `Set + else `Merge (fun () -> Root.get_info (module Store) info) + in + let depth = if depth <= 0 then None else Some depth in + match run (Sync.pull_exn ?depth store remote x) with + | `Empty -> null commit + | `Head head -> Root.create_commit (module Store) head)) + + let () = + fn "push" + (store @-> int @-> remote @-> returning commit) + (fun (type t) store depth remote -> + with_store' store commit + (fun (module Store : Irmin.Generic_key.S with type t = t) store -> + let module Sync = Irmin.Sync.Make (Store) in + let remote = + if is_null remote then failwith "Invalid remote" + else Root.get_remote remote + in + let depth = if depth <= 0 then None else Some depth in + match run (Sync.push_exn ?depth store remote) with + | `Empty -> null commit + | `Head head -> Root.create_commit (module Store) head)) + + let () = fn "remote_free" (remote @-> returning void) free + let () = fn "path_array_free" (path_array @-> returning void) free + let () = fn "free" (store @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/tree.ml b/vendors/irmin/src/libirmin/tree.ml new file mode 100644 index 000000000000..4160d643cbc3 --- /dev/null +++ b/vendors/irmin/src/libirmin/tree.ml @@ -0,0 +1,242 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "tree_new" + (repo @-> returning tree) + (fun (type repo) repo -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_tree (module Store) (Store.Tree.empty ()))) + + let () = + fn "tree_of_contents" + (repo @-> contents @-> metadata @-> returning tree) + (fun (type repo) repo value metadata -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let metadata = + if is_null metadata then None + else Some (Root.get_metadata (module Store) metadata) + in + let value = Root.get_contents (module Store) value in + Root.create_tree + (module Store) + (Store.Tree.of_contents ?metadata value))) + + let () = + fn "tree_clone" + (repo @-> tree @-> returning tree) + (fun (type repo) repo tr -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tr in + Root.create_tree (module Store) tree)) + + let () = + fn "tree_hash" + (repo @-> tree @-> returning hash) + (fun (type repo) repo tree -> + with_repo' repo hash + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tree in + let k = Store.Tree.hash tree in + Root.create_hash (module Store) k)) + + let () = + fn "tree_of_hash" + (repo @-> hash @-> returning tree) + (fun (type repo) repo k -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let k = Root.get_hash (module Store) k in + let t = run (Store.Tree.of_hash repo (`Node k)) in + match t with + | Some t -> Root.create_tree (module Store) t + | None -> null tree)) + + let () = + fn "tree_key" + (repo @-> tree @-> returning kinded_key) + (fun (type repo) repo tree -> + with_repo' repo kinded_key + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tree in + let k = Store.Tree.key tree in + match k with + | Some k -> Root.create_kinded_key (module Store) k + | _ -> null kinded_key)) + + let () = + fn "tree_of_key" + (repo @-> kinded_key @-> returning tree) + (fun (type repo) repo k -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> + let k = Root.get_kinded_key (module Store) k in + let t = run (Store.Tree.of_key repo k) in + match t with + | Some t -> Root.create_tree (module Store) t + | None -> null tree)) + + let () = + fn "tree_mem" + (repo @-> tree @-> path @-> returning bool) + (fun (type repo) repo tree path -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + run (Store.Tree.mem tree path))) + + let () = + fn "tree_mem_tree" + (repo @-> tree @-> path @-> returning bool) + (fun (type repo) repo tree path -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + run (Store.Tree.mem_tree tree path))) + + let () = + fn "tree_find" + (repo @-> tree @-> path @-> returning contents) + (fun (type repo) repo tree path -> + with_repo' repo contents + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + match run (Store.Tree.find tree path) with + | None -> null contents + | Some x -> Root.create_contents (module Store) x)) + + let () = + fn "tree_find_metadata" + (repo @-> tree @-> path @-> returning metadata) + (fun (type repo) repo tree path -> + with_repo' repo metadata + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + match run (Store.Tree.find_all tree path) with + | None -> null metadata + | Some (_, m) -> Root.create_metadata (module Store) m)) + + let () = + fn "tree_find_tree" + (repo @-> tree @-> path @-> returning tree) + (fun (type repo) repo t path -> + with_repo' repo tree + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let t : Store.tree = Root.get_tree (module Store) t in + let path : Store.path = Root.get_path (module Store) path in + match run (Store.Tree.find_tree t path) with + | None -> null tree + | Some x -> Root.create_tree (module Store) x)) + + let () = + fn "tree_add" + (repo @-> tree @-> path @-> contents @-> metadata @-> returning bool) + (fun (type repo) repo tree path value metadata -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree' : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + let value : Store.contents = + Root.get_contents (module Store) value + in + let metadata = + if is_null metadata then None + else Some (Root.get_metadata (module Store) metadata) + in + let t = run (Store.Tree.add tree' path value ?metadata) in + Root.set_tree (module Store) tree t; + true)) + + let () = + fn "tree_add_tree" + (repo @-> tree @-> path @-> tree @-> returning bool) + (fun (type repo) repo tree path tr -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree' : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + let value : Store.tree = Root.get_tree (module Store) tr in + let t = run (Store.Tree.add_tree tree' path value) in + Root.set_tree (module Store) tree t; + true)) + + let () = + fn "tree_remove" + (repo @-> tree @-> path @-> returning bool) + (fun (type repo) repo tree path -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree' : Store.tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + let t = run (Store.Tree.remove tree' path) in + Root.set_tree (module Store) tree t; + true)) + + let () = + fn "tree_equal" + (repo @-> tree @-> tree @-> returning bool) + (fun (type repo) repo a b -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let a = Root.get_tree (module Store) a in + let b = Root.get_tree (module Store) b in + Irmin.Type.(unstage (equal Store.tree_t)) a b)) + + let () = + fn "tree_list" + (repo @-> tree @-> path @-> returning path_array) + (fun (type repo) repo tree path -> + with_repo' repo path_array + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let tree = Root.get_tree (module Store) tree in + let path : Store.path = Root.get_path (module Store) path in + let items = run (Store.Tree.list tree path) in + let items = List.map (fun (k, _v) -> Store.Path.v [ k ]) items in + Root.create_path_array (module Store) items)) + + let () = + fn "kinded_key_is_contents" + (repo @-> kinded_key @-> returning bool) + (fun (type repo) repo k -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let k = Root.get_kinded_key (module Store) k in + match k with `Contents _ -> true | _ -> false)) + + let () = + fn "kinded_key_is_node" + (repo @-> kinded_key @-> returning bool) + (fun (type repo) repo k -> + with_repo repo false + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + let k = Root.get_kinded_key (module Store) k in + match k with `Node _ -> true | _ -> false)) + + let () = fn "tree_free" (tree @-> returning void) free + let () = fn "kinded_key_free" (kinded_key @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/type.ml b/vendors/irmin/src/libirmin/type.ml new file mode 100644 index 000000000000..bf5247d21fa2 --- /dev/null +++ b/vendors/irmin/src/libirmin/type.ml @@ -0,0 +1,194 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "type_unit" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Type.unit) + + let () = + fn "type_bool" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Type.bool) + + let () = + fn "type_int" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Type.int) + + let () = + fn "type_float" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Type.float) + + let () = + fn "type_string" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Type.string) + + let () = + fn "type_bytes" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Type.bytes) + + let () = + fn "type_list" + (ty @-> returning ty) + (fun elem -> + let elem : 'a Irmin.Type.t = Root.get_ty elem in + Root.create_ty (Irmin.Type.list elem)) + + let () = + fn "type_array" + (ty @-> returning ty) + (fun elem -> + let elem : 'a Irmin.Type.t = Root.get_ty elem in + Root.create_ty (Irmin.Type.array elem)) + + let () = + fn "type_option" + (ty @-> returning ty) + (fun elem -> + let elem : 'a Irmin.Type.t = Root.get_ty elem in + Root.create_ty (Irmin.Type.option elem)) + + let () = + fn "type_json" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Contents.Json.t) + + let () = + fn "type_json_value" + (void @-> returning ty) + (fun () -> Root.create_ty Irmin.Contents.Json_value.t) + + let () = + fn "type_path" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.path_t)) + + let () = + fn "type_commit" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) repo + -> Root.create_ty (Store.commit_t repo))) + + let () = + fn "type_metadata" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.metadata_t)) + + let () = + fn "type_tree" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.tree_t)) + + let () = + fn "type_hash" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.hash_t)) + + let () = + fn "type_commit_key" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.commit_key_t)) + + let () = + fn "type_contents_key" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.contents_key_t)) + + let () = + fn "type_node_key" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.node_key_t)) + + let () = + fn "type_kinded_key" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.Tree.kinded_key_t)) + + let () = + fn "type_contents" + (repo @-> returning ty) + (fun (type repo) repo -> + with_repo' repo ty + (fun (module Store : Irmin.Generic_key.S with type repo = repo) _ -> + Root.create_ty Store.contents_t)) + + let () = + fn "type_pair" + (ty @-> ty @-> returning ty) + (fun a b -> + let a : 'a Irmin.Type.t = Root.get_ty a in + let b : 'b Irmin.Type.t = Root.get_ty b in + Root.create_ty (Irmin.Type.pair a b)) + + let () = + fn "type_triple" + (ty @-> ty @-> ty @-> returning ty) + (fun a b c -> + let a : 'a Irmin.Type.t = Root.get_ty a in + let b : 'b Irmin.Type.t = Root.get_ty b in + let c : 'c Irmin.Type.t = Root.get_ty c in + Root.create_ty (Irmin.Type.triple a b c)) + + let () = + fn "type_name" + (ty @-> returning irmin_string) + (fun ty -> + let ty = Root.get_ty ty in + let s = Fmt.to_to_string Irmin.Type.pp_ty ty in + Root.create_string s) + + let () = + fn "type_diff" + (ty @-> returning ty) + (fun ty -> + let ty = Root.get_ty ty in + Root.create_ty (Irmin.Diff.t ty)) + + let () = fn "type_free" (ty @-> returning void) free +end diff --git a/vendors/irmin/src/libirmin/types.ml b/vendors/irmin/src/libirmin/types.ml new file mode 100644 index 000000000000..a82e7e372463 --- /dev/null +++ b/vendors/irmin/src/libirmin/types.ml @@ -0,0 +1,68 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Ctypes +include Types_intf + +module Struct = struct + type config = unit + type repo = unit + type store = unit + type ty = unit + type value = unit + type metadata = unit + type contents = unit + type path = unit + type tree = unit + type commit = unit + type hash = unit + type info = unit + type irmin_string = unit + type path_array = unit + type commit_array = unit + type branch_array = unit + type commit_key = unit + type kinded_key = unit + type remote = unit +end + +let config : Struct.config ptr typ = ptr (typedef void "IrminConfig") +let repo : Struct.repo ptr typ = ptr (typedef void "IrminRepo") +let store : Struct.store ptr typ = ptr (typedef void "Irmin") +let ty : Struct.ty ptr typ = ptr (typedef void "IrminType") +let value : Struct.value ptr typ = ptr (typedef void "IrminValue") +let metadata : Struct.metadata ptr typ = ptr (typedef void "IrminMetadata") +let contents : Struct.metadata ptr typ = ptr (typedef void "IrminContents") +let path : Struct.path ptr typ = ptr (typedef void "IrminPath") +let tree : Struct.tree ptr typ = ptr (typedef void "IrminTree") +let commit : Struct.commit ptr typ = ptr (typedef void "IrminCommit") +let hash : Struct.hash ptr typ = ptr (typedef void "IrminHash") +let info : Struct.info ptr typ = ptr (typedef void "IrminInfo") +let remote : Struct.remote ptr typ = ptr (typedef void "IrminRemote") + +let irmin_string : Struct.irmin_string ptr typ = + ptr (typedef void "IrminString") + +let path_array : Struct.path_array ptr typ = ptr (typedef void "IrminPathArray") + +let commit_array : Struct.commit_array ptr typ = + ptr (typedef void "IrminCommitArray") + +let branch_array : Struct.branch_array ptr typ = + ptr (typedef void "IrminBranchArray") + +let commit_key : Struct.commit_key ptr typ = ptr (typedef void "IrminCommitKey") +let kinded_key : Struct.kinded_key ptr typ = ptr (typedef void "IrminKindedKey") diff --git a/vendors/irmin/src/libirmin/types.mli b/vendors/irmin/src/libirmin/types.mli new file mode 100644 index 000000000000..eff19f25a506 --- /dev/null +++ b/vendors/irmin/src/libirmin/types.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Types_intf.Sigs diff --git a/vendors/irmin/src/libirmin/types_intf.ml b/vendors/irmin/src/libirmin/types_intf.ml new file mode 100644 index 000000000000..c3246efa284f --- /dev/null +++ b/vendors/irmin/src/libirmin/types_intf.ml @@ -0,0 +1,82 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Ctypes + +type config = Irmin_cli.Resolver.Store.t * Irmin.config + +type 'a repo = { + mutable error : string option; + repo_mod : (module Irmin.Generic_key.S with type repo = 'a); + repo : 'a; + remote : Irmin_cli.Resolver.Store.remote_fn option; +} + +type 'a store = { + repo : unit ptr; + store_mod : (module Irmin.Generic_key.S with type t = 'a); + store : 'a; +} + +module type P = sig + type config + type repo + type store + type ty + type value + type metadata + type contents + type path + type tree + type commit + type hash + type info + type irmin_string + type path_array + type commit_array + type branch_array + type commit_key + type kinded_key + type remote +end + +module type Sigs = sig + module Struct : P + + type nonrec config = config + type nonrec 'a repo = 'a repo + type nonrec 'a store = 'a store + + val config : Struct.config ptr typ + val repo : Struct.repo ptr typ + val store : Struct.store ptr typ + val ty : Struct.ty ptr typ + val value : Struct.value ptr typ + val metadata : Struct.metadata ptr typ + val contents : Struct.contents ptr typ + val path : Struct.path ptr typ + val tree : Struct.tree ptr typ + val commit : Struct.commit ptr typ + val hash : Struct.hash ptr typ + val info : Struct.info ptr typ + val irmin_string : Struct.irmin_string ptr typ + val path_array : Struct.path_array ptr typ + val commit_array : Struct.commit_array ptr typ + val branch_array : Struct.branch_array ptr typ + val commit_key : Struct.commit_key ptr typ + val kinded_key : Struct.kinded_key ptr typ + val remote : Struct.remote ptr typ +end diff --git a/vendors/irmin/src/libirmin/util.ml b/vendors/irmin/src/libirmin/util.ml new file mode 100644 index 000000000000..27ed6a6c4dd6 --- /dev/null +++ b/vendors/irmin/src/libirmin/util.ml @@ -0,0 +1,286 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + include Ctypes + include Types + include Unsigned + + let find_config_key config name = + Irmin.Backend.Conf.Spec.find_key (Irmin.Backend.Conf.spec config) name + + let type_name x = Fmt.to_to_string Irmin.Type.pp_ty x + + (* Generic free function for all rooted values *) + let free x = + let ptr = Ctypes.to_voidp x in + if not (is_null ptr) then (fun x -> Ctypes.Root.release x) ptr + + let strlen ptr = + if is_null ptr then 0 + else + let rec loop i = + if !@(ptr +@ i) = char_of_int 0 then i else loop (i + 1) + in + loop 0 + + let get_length length s = + let length = Int64.to_int length in + if length < 0 then strlen s else length + + let fn name t f = I.internal ~runtime_lock:false ("irmin_" ^ name) t f + + (* Minimal executor for lwt promises *) + let rec run x = + Lwt.wakeup_paused (); + match Lwt.poll x with + | Some x -> x + | None -> + let () = Lwt_engine.iter true in + run x + + module Root = struct + let to_voidp t x = Ctypes.coerce t (ptr void) x + + let of_voidp t x = + if is_null x then failwith "null pointer" + else Ctypes.coerce (ptr void) t x + + let get_repo (type a) (x : Struct.repo ptr) : a repo = + Root.get (to_voidp repo x) + [@@inline] + + let create_repo (type a) (module S : Irmin.Generic_key.S with type repo = a) + (r : a repo) : Struct.repo ptr = + Root.create r |> of_voidp repo + [@@inline] + + let get_store (type a) (x : Struct.store ptr) : a store = + Root.get (to_voidp store x) + [@@inline] + + let create_store (type a) (module S : Irmin.Generic_key.S with type t = a) + (r : a store) : Struct.store ptr = + Root.create r |> of_voidp store + [@@inline] + + let get_config (x : Struct.config ptr) : config = + Root.get (to_voidp config x) + + let create_config (r : config) : Struct.config ptr = + Root.create r |> of_voidp config + + let set_config (ptr : Struct.config ptr) (x : config) = + Root.set (to_voidp config ptr) x + + let get_ty (x : Struct.ty ptr) : 'a Irmin.Type.t = Root.get (to_voidp ty x) + + let create_ty (x : 'a Irmin.Type.t) : Struct.ty ptr = + Root.create x |> of_voidp ty + + let get_value (x : Struct.value ptr) : 'a = Root.get (to_voidp value x) + let set_value (ptr : Struct.value ptr) x = Root.set (to_voidp value ptr) x + + let create_value (x : 'a) : Struct.value ptr = + Root.create x |> of_voidp value + + let get_path (type a) + (module S : Irmin.Generic_key.S with type Schema.Path.t = a) + (x : Struct.path ptr) : S.path = + Root.get (to_voidp path x) + + let create_path (type a) + (module S : Irmin.Generic_key.S with type Schema.Path.t = a) + (r : S.path) : Struct.path ptr = + Root.create r |> of_voidp path + + let get_metadata (type a) + (module S : Irmin.Generic_key.S with type Schema.Metadata.t = a) + (x : Struct.metadata ptr) : S.metadata = + Root.get (to_voidp metadata x) + + let create_metadata (type a) + (module S : Irmin.Generic_key.S with type Schema.Metadata.t = a) + (r : S.metadata) : Struct.metadata ptr = + Root.create r |> of_voidp metadata + + let get_hash (type a) + (module S : Irmin.Generic_key.S with type Schema.Hash.t = a) + (x : Struct.hash ptr) : S.hash = + Root.get (to_voidp hash x) + + let create_hash (type a) + (module S : Irmin.Generic_key.S with type Schema.Hash.t = a) + (r : S.hash) : Struct.hash ptr = + Root.create r |> of_voidp hash + + let get_commit_key (type a) + (module S : Irmin.Generic_key.S with type commit_key = a) + (x : Struct.commit_key ptr) : S.commit_key = + Root.get (to_voidp commit_key x) + + let create_commit_key (type a) + (module S : Irmin.Generic_key.S with type commit_key = a) + (r : S.commit_key) : Struct.commit_key ptr = + Root.create r |> of_voidp commit_key + + let get_kinded_key (type a b c) + (module S : Irmin.Generic_key.S + with type node_key = a + and type contents_key = b + and type Schema.Metadata.t = c) (x : Struct.kinded_key ptr) : + S.Tree.kinded_key = + Root.get (to_voidp kinded_key x) + + let create_kinded_key (type a b c) + (module S : Irmin.Generic_key.S + with type node_key = a + and type contents_key = b + and type Schema.Metadata.t = c) (r : S.Tree.kinded_key) : + Struct.kinded_key ptr = + Root.create r |> of_voidp kinded_key + + let get_tree (type a) (module S : Irmin.Generic_key.S with type tree = a) + (x : Struct.tree ptr) : S.tree = + Root.get (to_voidp tree x) + + let create_tree (type a) (module S : Irmin.Generic_key.S with type tree = a) + (r : S.tree) : Struct.tree ptr = + Root.create r |> of_voidp tree + + let set_tree (type a) (module S : Irmin.Generic_key.S with type tree = a) + (ptr : Struct.tree ptr) (r : S.tree) = + Root.set (to_voidp tree ptr) r + + let get_commit (type a) + (module S : Irmin.Generic_key.S with type commit = a) + (x : Struct.commit ptr) : S.commit = + Root.get (to_voidp commit x) + + let create_commit (type a) + (module S : Irmin.Generic_key.S with type commit = a) (r : S.commit) : + Struct.commit ptr = + Root.create r |> of_voidp commit + + let get_contents (type a) + (module S : Irmin.Generic_key.S with type Schema.Contents.t = a) + (x : Struct.contents ptr) : S.contents = + Root.get (to_voidp contents x) + + let create_contents (type a) + (module S : Irmin.Generic_key.S with type Schema.Contents.t = a) + (r : S.contents) : Struct.contents ptr = + Root.create r |> of_voidp contents + + let get_info (type a) + (module S : Irmin.Generic_key.S with type Schema.Info.t = a) + (x : Struct.info ptr) : S.info = + Root.get (to_voidp info x) + + let set_info (type a) + (module S : Irmin.Generic_key.S with type Schema.Info.t = a) + (ptr : Struct.info ptr) (x : S.info) : unit = + Root.set (to_voidp info ptr) x + + let create_info (type a) + (module S : Irmin.Generic_key.S with type Schema.Info.t = a) + (r : S.info) : Struct.info ptr = + Root.create r |> of_voidp info + + let get_string (x : Struct.irmin_string ptr) : string = + Root.get (to_voidp irmin_string x) + + let set_string (ptr : Struct.irmin_string ptr) (x : string) : unit = + Root.set (to_voidp irmin_string ptr) x + + let create_string (s : string) : Struct.irmin_string ptr = + Root.create s |> of_voidp irmin_string + + let get_branch_array (type a) + (module S : Irmin.Generic_key.S with type Schema.Branch.t = a) + (x : Struct.branch_array ptr) : a array = + Root.get (to_voidp branch_array x) + + let create_branch_array (type a) + (module S : Irmin.Generic_key.S with type Schema.Branch.t = a) + (x : S.Branch.t list) : Struct.branch_array ptr = + Root.create (Array.of_list x) |> of_voidp branch_array + + let get_path_array (type a) + (module S : Irmin.Generic_key.S with type Schema.Path.t = a) + (x : Struct.path_array ptr) : a array = + Root.get (to_voidp path_array x) + + let create_path_array (type a) + (module S : Irmin.Generic_key.S with type Schema.Path.t = a) + (x : S.Path.t list) : Struct.path_array ptr = + Root.create (Array.of_list x) |> of_voidp path_array + + let get_commit_array (type a) + (module S : Irmin.Generic_key.S with type commit = a) + (x : Struct.commit_array ptr) : a array = + Root.get (to_voidp commit_array x) + + let create_commit_array (type a) + (module S : Irmin.Generic_key.S with type commit = a) (x : a list) : + Struct.commit_array ptr = + Root.create (Array.of_list x) |> of_voidp commit_array + + let get_remote (x : Struct.remote ptr) : Irmin.remote = + Root.get (to_voidp remote x) + + let create_remote (x : Irmin.remote) : Struct.remote ptr = + Root.create x |> of_voidp remote + end + + (* Handle errors and set error function, returns [return] if an exception is raised *) + let with_repo (repo : Struct.repo ptr) return f = + let repo = Root.get_repo repo in + try + repo.error <- None; + f repo.repo_mod repo.repo + with + | Failure msg | Invalid_argument msg -> + repo.error <- Some msg; + return + | exn -> + repo.error <- Some (Printexc.to_string exn); + return + [@@inline] + + let null t = Ctypes.coerce (ptr void) t null + + (* Similar to [with_repo] but returns a null pointer *) + let with_repo' (repo : Struct.repo ptr) t f = with_repo repo (null t) f + + let with_store (store : Struct.store ptr) return f = + let store = Root.get_store store in + let ctx = Root.get_repo (Root.of_voidp repo store.repo) in + try + ctx.error <- None; + f store.store_mod store.store + with + | Failure msg | Invalid_argument msg -> + ctx.error <- Some msg; + return + | exn -> + ctx.error <- Some (Printexc.to_string exn); + return + [@@inline] + + (* Similar to [with_store] but returns a null pointer *) + let with_store' (store : Struct.store ptr) t f = with_store store (null t) f +end diff --git a/vendors/irmin/src/libirmin/value.ml b/vendors/irmin/src/libirmin/value.ml new file mode 100644 index 000000000000..eafdc8e8ff22 --- /dev/null +++ b/vendors/irmin/src/libirmin/value.ml @@ -0,0 +1,250 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Make (I : Cstubs_inverted.INTERNAL) = struct + open Util.Make (I) + + let () = + fn "value_unit" (void @-> returning value) (fun () -> Root.create_value ()) + + let () = + fn "value_int" + (int64_t @-> returning value) + (fun i -> Root.create_value (Int64.to_int i)) + + let () = + fn "value_float" (double @-> returning value) (fun i -> Root.create_value i) + + let () = + fn "value_bool" (bool @-> returning value) (fun b -> Root.create_value b) + + let () = + fn "value_clone" + (value @-> returning value) + (fun x -> Root.create_value (Root.get_value x)) + + let () = + fn "realloc" + (ptr void @-> ptr void @-> returning (ptr void)) + (fun src dest -> + Ctypes.Root.set src (Ctypes.Root.get dest); + src) + + let () = + fn "value_get_string" + (value @-> returning irmin_string) + (fun value -> + let obj = Root.get_value value |> Obj.repr in + if Obj.tag obj = Obj.string_tag then Root.create_string (Obj.obj obj) + else null irmin_string) + + let () = + fn "value_get_int" + (value @-> returning int64_t) + (fun x -> + let obj = Root.get_value x |> Obj.repr in + if Obj.is_int obj then Int64.of_int (Obj.obj obj) else Int64.zero) + + let () = + fn "value_get_bool" + (value @-> returning bool) + (fun x -> + let obj = Root.get_value x |> Obj.repr in + if Obj.is_int obj then Obj.obj obj else false) + + let () = + fn "value_get_float" + (value @-> returning double) + (fun x -> + let obj = Root.get_value x |> Obj.repr in + if Obj.is_int obj then Obj.obj obj else 0.) + + let () = + fn "value_bytes" + (ptr char @-> int64_t @-> returning value) + (fun s length -> + let length = get_length length s in + Root.create_value (Bytes.of_string (string_from_ptr s ~length))) + + let () = + fn "value_string" + (ptr char @-> int64_t @-> returning value) + (fun s length -> + let length = get_length length s in + Root.create_value (string_from_ptr s ~length)) + + let () = + fn "value_array" + (ptr value @-> uint64_t @-> returning value) + (fun arr n -> + let n = UInt64.to_int n in + let a = + if is_null arr || n = 0 then [||] + else + CArray.from_ptr arr n + |> CArray.to_list + |> List.map Root.get_value + |> Array.of_list + in + Root.create_value a) + + let () = + fn "value_list" + (ptr value @-> uint64_t @-> returning value) + (fun arr n -> + let n = UInt64.to_int n in + let l = + if is_null arr || n = 0 then [] + else + CArray.from_ptr arr n |> CArray.to_list |> List.map Root.get_value + in + Root.create_value l) + + let () = + fn "value_option" + (value @-> returning value) + (fun value -> + if is_null value then Root.create_value None + else + let x = Root.get_value value in + Root.create_value (Some x)) + + let () = + fn "value_pair" + (value @-> value @-> returning value) + (fun a b -> + let a = Root.get_value a in + let b = Root.get_value b in + Root.create_value (a, b)) + + let () = + fn "value_triple" + (value @-> value @-> value @-> returning value) + (fun a b c -> + let a = Root.get_value a in + let b = Root.get_value b in + let c = Root.get_value c in + Root.create_value (a, b, c)) + + let () = + fn "value_to_string" + (ty @-> value @-> returning irmin_string) + (fun ty value -> + let t = Root.get_ty ty in + let v = Root.get_value value in + let s = Irmin.Type.to_string t v in + Root.create_string s) + + let () = + fn "value_of_string" + (ty @-> ptr char @-> int64_t @-> returning value) + (fun ty s length -> + let length = get_length length s in + let ty = Root.get_ty ty in + let s = string_from_ptr s ~length in + match Irmin.Type.(of_string ty) s with + | Ok x -> Root.create_value x + | Error (`Msg _) -> null value) + + let () = + fn "value_to_bin" + (ty @-> value @-> returning irmin_string) + (fun ty v -> + let t = Root.get_ty ty in + let v = Root.get_value v in + let s = Irmin.Type.(unstage (to_bin_string t)) v in + Root.create_string s) + + let () = + fn "value_of_bin" + (ty @-> ptr char @-> int64_t @-> returning value) + (fun ty s length -> + let length = get_length length s in + let ty = Root.get_ty ty in + let s = string_from_ptr s ~length in + match Irmin.Type.(unstage (of_bin_string ty)) s with + | Ok x -> Root.create_value x + | Error (`Msg _) -> null value) + + let () = + fn "value_to_json" + (ty @-> value @-> returning irmin_string) + (fun ty v -> + let t = Root.get_ty ty in + let v = Root.get_value v in + let s = Irmin.Type.(to_json_string t) v in + Root.create_string s) + + let () = + fn "value_of_json" + (ty @-> ptr char @-> int64_t @-> returning value) + (fun ty s length -> + let length = get_length length s in + let ty = Root.get_ty ty in + let s = string_from_ptr s ~length in + match Irmin.Type.(of_json_string ty) s with + | Ok x -> Root.create_value x + | Error (`Msg _) -> null value) + + let () = + fn "value_equal" + (ty @-> value @-> value @-> returning bool) + (fun ty a b -> + let ty = Root.get_ty ty in + let a = Root.get_value a in + let b = Root.get_value b in + Irmin.Type.(unstage (equal ty)) a b) + + let () = + fn "value_compare" + (ty @-> value @-> value @-> returning int) + (fun ty a b -> + let ty = Root.get_ty ty in + let a = Root.get_value a in + let b = Root.get_value b in + Irmin.Type.(unstage (compare ty)) a b) + + let () = fn "value_free" (value @-> returning void) free + + let () = + fn "string_new" + (ptr char @-> int64_t @-> returning irmin_string) + (fun ptr i -> + let i = Int64.to_int i in + let length = if i < 0 then strlen ptr else i in + let s = string_from_ptr ptr ~length in + Root.create_string s) + + let () = + fn "string_data" + (irmin_string @-> returning (ptr char)) + (fun s -> + if is_null s then null (ptr char) + else + let s : string = Root.get_string s in + coerce string (ptr char) s) + + let () = + fn "string_length" + (irmin_string @-> returning uint64_t) + (fun s -> + if is_null s then UInt64.zero + else + let s : string = Root.get_string s in + String.length s |> UInt64.of_int) + + let () = fn "string_free" (irmin_string @-> returning void) free +end diff --git a/vendors/irmin/src/ppx_irmin/dune b/vendors/irmin/src/ppx_irmin/dune new file mode 100644 index 000000000000..5fda5ca9c60f --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/dune @@ -0,0 +1,9 @@ +;; The publicly-available PPX for consumers of the Irmin API + +(library + (public_name ppx_irmin) + (modules ppx_irmin) + (kind ppx_deriver) + (libraries ppx_repr.lib) + (instrumentation + (backend bisect_ppx))) diff --git a/vendors/irmin/src/ppx_irmin/internal/dune b/vendors/irmin/src/ppx_irmin/internal/dune new file mode 100644 index 000000000000..b0fbd3c29a6f --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/internal/dune @@ -0,0 +1,21 @@ +;; Extensions to `ppx_irmin` intended for Irmin developers only + +(library + (kind ppx_rewriter) + (name ppx_irmin_internal) + (public_name ppx_irmin.internal) + (modules ppx_irmin_internal) + (ppx_runtime_libraries logs ppx_irmin.internal-lib) + (preprocess + (pps ppxlib.metaquot)) + (libraries + ppxlib + ppx_irmin.internal-lib + ;; Depending on [ppx_irmin.internal] implies a dependency on [ppx_irmin] + ppx_irmin)) + +(library + (name ppx_irmin_internal_lib) + (public_name ppx_irmin.internal-lib) + (modules ppx_irmin_internal_lib) + (libraries logs)) diff --git a/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.ml b/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.ml new file mode 100644 index 000000000000..67bddf5b2d2d --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.ml @@ -0,0 +1,103 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Ppxlib + +let rewriter_name = "ppx_irmin.internal" + +(* Provides a PPX wrapper around the Logs library that attaches source code + postitions to log lines via Logs' tags system. + + Input: [%log(s?). ] + Output: Log(s?).() (fun f -> f ~tags:(...)) + + (The extension node payload can also be written in the standard CPSed form, + for instance in order to perform computation before constructing the log + line.) +*) + +module Source = struct + type t = + | Logs (** default (source-less) logging functions *) + | Log (** referencing a "Log" module, specifying a particular source *) + + let to_string = function Logs -> "logs" | Log -> "log" +end + +let level_to_function_name : Logs.level -> string = function + | App -> "app" + | Error -> "err" + | Warning -> "warn" + | Info -> "info" + | Debug -> "debug" + +let log_function ~loc (source : Source.t) (level : Logs.level) = + let prefix = match source with Logs -> "Logs." | Log -> "Log." in + Ast_builder.Default.evar ~loc (prefix ^ level_to_function_name level) + +let tags ~loc = + [%expr + Logs.Tag.add Ppx_irmin_internal_lib.Source_code_position.tag __POS__ + Logs.Tag.empty] + +let expansion_function source level ~loc ~path:_ payload = + let log_fn = log_function ~loc source level in + let open Ast_builder.Default in + match payload with + | [%expr fun [%p? _] -> [%e? _]] -> + (* Payload is already in CPS-ed form: we just need to attach the tags. *) + [%expr + [%e log_fn] (fun f -> + ([%e payload] : (?header:string -> (_, _, _, _) format4 -> _) -> _) + (f ~tags:[%e tags ~loc]))] + | _ -> + (* The user hasn't wrapped the payload in [fun f -> ...; f ...], so we + should attempt to do so. This requires re-interpreting top-level + [Pexp_apply] nodes in the AST, for example: + + > [%log.debug "fmt_string" ...args] + + This parses ["fmt_string"] as a _function_, but it's going to become + the first argument of a function [debug]. *) + let input_args = + match payload with + | { pexp_desc = Pexp_constant (Pconst_string _); _ } -> + [ (Nolabel, payload) ] + (* Special case for ( @@ ), e.g. [%log.err "%d" @@ 1 + 2] *) + | [%expr [%e? fmt] @@ [%e? args]] -> [ (Nolabel, fmt); (Nolabel, args) ] + | { pexp_desc = Pexp_apply (fmt, args); _ } -> (Nolabel, fmt) :: args + | _ -> Location.raise_errorf ~loc "%s: invalid payload" rewriter_name + in + let args = input_args @ [ (Labelled "tags", tags ~loc) ] in + [%expr [%e log_fn] (fun f -> [%e pexp_apply ~loc [%expr f] args])] + +let ( let* ) x f = List.concat_map f x + +let rules = + let* source = [ Source.Logs; Log ] in + let* level = [ Logs.App; Error; Warning; Info; Debug ] in + let extension_name = + Format.sprintf "irmin.%s.%s" (Source.to_string source) + (level_to_function_name level) + in + [ + Extension.declare extension_name Extension.Context.expression + Ast_pattern.(single_expr_payload __) + (expansion_function source level) + |> Context_free.Rule.extension; + ] + +let () = Driver.register_transformation ~rules rewriter_name diff --git a/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.mli b/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal_lib.ml b/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal_lib.ml new file mode 100644 index 000000000000..73be6aa171b3 --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/internal/ppx_irmin_internal_lib.ml @@ -0,0 +1,30 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Source_code_position = struct + type t = string * int * int * int + (** The type of inclusive ranges of source code positions, as generated by the + OCaml {!__POS__} macro. The 4-tuple components are 'file name', 'line + number', 'column start' and 'column end' respectively. *) + + let pp ppf (fname, line_number, col_start, col_end) = + Format.fprintf ppf "File %S, line %d, characters %d-%d" fname line_number + col_start col_end + + let tag : t Logs.Tag.def = + Logs.Tag.def "Source_code_position" + ~doc:"The source code location at which the log entry was generated." pp +end diff --git a/vendors/irmin/src/ppx_irmin/ppx_irmin.ml b/vendors/irmin/src/ppx_irmin/ppx_irmin.ml new file mode 100644 index 000000000000..dfc757c35ab7 --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/ppx_irmin.ml @@ -0,0 +1,25 @@ +(* + * Copyright (c) 2019-2021 Craig Ferguson + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Plugins = Ppx_repr_lib.Plugins.Make (struct + let default_library = "Irmin.Type" + let namespace = "irmin" +end) + +let () = + Plugins.register_deriver (); + Plugins.register_extension ~no_reserve_namespace:() () diff --git a/vendors/irmin/src/ppx_irmin/ppx_irmin.mli b/vendors/irmin/src/ppx_irmin/ppx_irmin.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/src/ppx_irmin/ppx_irmin.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-bench/data/tezos_actions_1commit.repr b/vendors/irmin/test/irmin-bench/data/tezos_actions_1commit.repr new file mode 100644 index 0000000000000000000000000000000000000000..8dc02daeb592fe9d641b4c2450d217db7bac401d GIT binary patch literal 300 zcmeY)$_+{_a0+1n0ZA4nmXySjME0`OqTYABd_iJSVs2_lY7yKtMmt7Ej)J26lKkZS90iLv_dcBENZ~i^n#~%Y z&C4_Efx$$pcG=l;+kUqsi{DZN8_&SNzzDN~Ns*C}t0c9!BtAJKF*6S)%)r0|V=@P_ zGnzQ(hgk#%mgZ)Lg<2LTW|kVeh54nr_@$P6C3<;SREDP%ySo{O`=k^H6&VFs2Alg< WIcI_FiZ)+$gxwv@d&~|Dj3xlxa7IA@ literal 0 HcmV?d00001 diff --git a/vendors/irmin/test/irmin-bench/dune b/vendors/irmin/test/irmin-bench/dune new file mode 100644 index 000000000000..643ec4038a3a --- /dev/null +++ b/vendors/irmin/test/irmin-bench/dune @@ -0,0 +1,17 @@ +(executable + (name test) + (libraries + alcotest + irmin_traces + fpath + irmin-tezos + irmin-pack.mem + irmin-test) + (preprocess + (pps ppx_irmin.internal))) + +(rule + (alias runtest) + (package irmin-bench) + (action + (run ./test.exe -q --color=always))) diff --git a/vendors/irmin/test/irmin-bench/ema.ml b/vendors/irmin/test/irmin-bench/ema.ml new file mode 100644 index 000000000000..b0c5519b755a --- /dev/null +++ b/vendors/irmin/test/irmin-bench/ema.ml @@ -0,0 +1,179 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Ema = Irmin_traces.Trace_stat_summary_utils.Exponential_moving_average + +(* Section 1/2 - Tools *) + +let pp_ema ppf ema = + let open Ema in + Format.fprintf ppf "peek:%g; hs:%g; vf:%g" (peek_or_nan ema) + (hidden_state ema) (void_fraction ema) + +let feed ~n v ema = + assert (n >= 0); + let rec aux ema = function 0 -> ema | i -> aux (Ema.update ema v) (i - 1) in + aux ema n + +let feed_none ~n ema = + assert (n >= 0); + let rec aux ema = function 0 -> ema | i -> aux (Ema.forget ema) (i - 1) in + aux ema n + +(* Section 2/2 - Tests *) + +let test_momentum () = + let ema = Ema.create 0.5 in + let ema = feed ~n:9999 1000. ema in + Alcotest.(check (float 1e-100)) "Ema primed" (Ema.void_fraction ema) 0.; + let ema = feed ~n:1 0. ema in + Alcotest.(check (float 0.1)) "1st half life" (Ema.peek_exn ema) 500.; + let ema = feed ~n:1 0. ema in + Alcotest.(check (float 0.1)) "2nd half life" (Ema.peek_exn ema) 250.; + let ema = feed ~n:1 0. ema in + Alcotest.(check (float 0.1)) "3rd half life" (Ema.peek_exn ema) 125. + +let test_momentum_zero () = + let ema = Ema.create 0. in + let ema = feed ~n:1 500. ema in + Alcotest.(check (float 0.1)) "1st value" (Ema.peek_exn ema) 500.; + let ema = feed ~n:1 250. ema in + Alcotest.(check (float 0.1)) "2nd value" (Ema.peek_exn ema) 250.; + let ema = feed ~n:1 125. ema in + Alcotest.(check (float 0.1)) "3rd value" (Ema.peek_exn ema) 125. + +let test_momentum_high () = + let ema = Ema.create 0.9999999 in + let ema = feed ~n:1 500. ema in + Alcotest.(check (float 0.1)) "1st mean" (Ema.peek_exn ema) 500.; + let ema = feed ~n:1 300. ema in + Alcotest.(check (float 0.1)) + "2nd mean" (Ema.peek_exn ema) + ((500. +. 300.) /. 2.); + let ema = feed ~n:1 100. ema in + Alcotest.(check (float 0.1)) + "3rd mean" (Ema.peek_exn ema) + ((500. +. 300. +. 100.) /. 3.); + + let ema = feed ~n:10000 1000. ema in + Alcotest.(check (float 10.)) "4th mean" (Ema.peek_exn ema) 1000.; + let ema = feed ~n:10000 2000. ema in + Alcotest.(check (float 10.)) "5th mean" (Ema.peek_exn ema) 1500. + +let test_from_half_life () = + let ema = Ema.from_half_life 10. in + let ema = feed ~n:9999 1000. ema in + Alcotest.(check (float 1e-100)) "Ema primed" (Ema.void_fraction ema) 0.; + let ema = feed ~n:10 0. ema in + Alcotest.(check (float 0.1)) "1st half life" (Ema.peek_exn ema) 500.; + let ema = feed ~n:10 0. ema in + Alcotest.(check (float 0.1)) "2nd half life" (Ema.peek_exn ema) 250.; + let ema = feed ~n:10 0. ema in + Alcotest.(check (float 0.1)) "3rd half life" (Ema.peek_exn ema) 125. + +let test_from_half_life_ratio () = + let ema = Ema.from_half_life_ratio 0.1 100. in + let ema = feed ~n:9999 1000. ema in + Alcotest.(check (float 1e-100)) "Ema primed" (Ema.void_fraction ema) 0.; + let ema = feed ~n:10 0. ema in + Alcotest.(check (float 0.1)) "1st half life" (Ema.peek_exn ema) 500.; + let ema = feed ~n:10 0. ema in + Alcotest.(check (float 0.1)) "2nd half life" (Ema.peek_exn ema) 250.; + let ema = feed ~n:10 0. ema in + Alcotest.(check (float 0.1)) "3rd half life" (Ema.peek_exn ema) 125. + +let test_update_batch () = + let ema0 = Ema.create 0.5 |> feed ~n:10 42. in + let ema1 = feed ~n:5 21. ema0 in + let ema1' = Ema.update_batch ema0 21. 5. in + Alcotest.(check (float 0.0001)) + "2way batch" (Ema.peek_exn ema1) (Ema.peek_exn ema1') + +let test_relevance () = + let ema = Ema.create ~relevance_threshold:0.51 0.5 in + Alcotest.(check bool) "Ema empty" (Ema.is_relevant ema) false; + let ema = feed ~n:1 42. ema in + Alcotest.(check bool) "1U" (Ema.is_relevant ema) true; + let ema = feed_none ~n:1 ema in + Alcotest.(check bool) "1U, 1F" (Ema.is_relevant ema) false; + let ema = feed ~n:1 42. ema in + Alcotest.(check bool) "1U, 1F, 1U" (Ema.is_relevant ema) true; + let ema = feed ~n:99 42. ema |> feed_none ~n:1 in + Alcotest.(check bool) "1U, 1F, 100U, 1F" (Ema.is_relevant ema) true; + let ema = feed_none ~n:1 ema in + Alcotest.(check bool) "1U, 1F, 100U, 2F" (Ema.is_relevant ema) false + +let test_relevance_low () = + let ema = Ema.create ~relevance_threshold:0.01 0.5 in + Alcotest.(check bool) "Ema empty" (Ema.is_relevant ema) false; + let ema = feed ~n:5 42. ema in + Alcotest.(check bool) "5U" (Ema.is_relevant ema) false; + let ema = feed ~n:10 42. ema in + Alcotest.(check bool) "10U" (Ema.is_relevant ema) true; + let ema = feed_none ~n:1 ema in + Alcotest.(check bool) "10U, 1F" (Ema.is_relevant ema) false + +let test_relevance_one () = + let ema = Ema.create ~relevance_threshold:1.0 0.5 in + Alcotest.(check bool) "Ema empty" (Ema.is_relevant ema) false; + let ema = feed ~n:1 42. ema in + Alcotest.(check bool) "1U" (Ema.is_relevant ema) true; + let ema = feed_none ~n:10 ema in + Alcotest.(check bool) "1U, 10F" (Ema.is_relevant ema) true + +let test_commutativity_shift () = + let add a b = List.map2 ( +. ) a b in + let mom = 0.1 in + let xs = [ 10.0; -5.0; 6.0; -7.0; -20.0; 5.0; 9.0 ] in + let ys = [ 7.0; 3.0; -6.0; -1.0; -3.0; 4.0; 7.0 ] in + let res = Ema.map mom (add xs ys) in + let res' = add (Ema.map mom xs) (Ema.map mom ys) in + Alcotest.(check (list (float 0.0001))) "ema(a + b) = ema(a) + ema(b)" res res' + +let test_commutativity_log_mul () = + let mul a b = List.map2 ( *. ) a b in + let log l = List.map Float.log l in + let exp l = List.map Float.exp l in + let mom = 0.1 in + let xs = [ 10.0; 5.0; 6.0; 7.0; 20.0; 5.0; 9.0 ] in + let ys = [ 7.0; 3.0; 6.0; 1.0; 3.0; 4.0; 7.0 ] in + let res = mul xs ys |> log |> Ema.map mom |> exp in + let res' = + mul (xs |> log |> Ema.map mom |> exp) (ys |> log |> Ema.map mom |> exp) + in + Alcotest.(check (list (float 0.0001))) + "exp(ema(log(a))) * exp(ema(log(b))) = exp(ema(log(a * b)))" res res' + +let test_cases = + [ + ( "ema", + [ + Alcotest.test_case "momentum" `Quick test_momentum; + Alcotest.test_case "momentum_zero" `Quick test_momentum_zero; + Alcotest.test_case "momentum_high" `Quick test_momentum_high; + Alcotest.test_case "from_half_life" `Quick test_from_half_life; + Alcotest.test_case "from_half_life_ratio" `Quick + test_from_half_life_ratio; + Alcotest.test_case "batch" `Quick test_update_batch; + Alcotest.test_case "relevance" `Quick test_relevance; + Alcotest.test_case "relevance_low" `Quick test_relevance_low; + Alcotest.test_case "relevance_one" `Quick test_relevance_one; + Alcotest.test_case "commutativity shift" `Quick test_commutativity_shift; + Alcotest.test_case "commutativity logmul" `Quick + test_commutativity_log_mul; + ] ); + ] diff --git a/vendors/irmin/test/irmin-bench/import.ml b/vendors/irmin/test/irmin-bench/import.ml new file mode 100644 index 000000000000..2fed488f984d --- /dev/null +++ b/vendors/irmin/test/irmin-bench/import.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/test/irmin-bench/misc.ml b/vendors/irmin/test/irmin-bench/misc.ml new file mode 100644 index 000000000000..34fdc04b4e48 --- /dev/null +++ b/vendors/irmin/test/irmin-bench/misc.ml @@ -0,0 +1,86 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +let snap_around_42 () = + let f ~sd = + Irmin_traces.Trace_stat_summary_utils.snap_to_integer ~significant_digits:sd + in + Alcotest.(check (float 0.)) "Already integer" (f ~sd:0 42.) 42.; + Alcotest.(check (float 0.)) "Always snap" (f ~sd:0 42.1) 42.; + Alcotest.(check (float 0.)) "Always snap" (f ~sd:0 42.4999999999) 42.; + Alcotest.(check (float 0.)) "Always snap" (f ~sd:0 42.5000000001) 43.; + + Alcotest.(check (float 0.)) "No snap" (f ~sd:4 42.1) 42.1; + Alcotest.(check (float 0.)) "No snap" (f ~sd:4 42.01) 42.01; + Alcotest.(check (float 0.)) "No snap" (f ~sd:4 42.00110000) 42.00110000; + Alcotest.(check (float 0.)) "No snap" (f ~sd:4 42.00100000) 42.00100000; + Alcotest.(check (float 0.)) "No snap" (f ~sd:4 42.00099999) 42.00099999; + Alcotest.(check (float 0.)) "No snap" (f ~sd:4 42.00011000) 42.00011000; + + Alcotest.(check (float 0.)) "Snap" (f ~sd:4 42.00009999) 42.; + Alcotest.(check (float 0.)) "Snap" (f ~sd:4 42.00001100) 42.; + Alcotest.(check (float 0.)) "Snap" (f ~sd:4 42.00001000) 42.; + Alcotest.(check (float 0.)) "Snap" (f ~sd:4 42.00000999) 42.; + Alcotest.(check (float 0.)) "Already integer" (f ~sd:4 42.) 42. + +let test_transaction_count () = + let f = + Irmin_traces.Trace_stat_summary_utils + .approx_transaction_count_of_block_count + in + let b0, t0 = (1814, 497) in + let b1, t1 = (10031, 10337) in + let b2, t2 = (8478, 6444) in + Alcotest.(check int) "1st week" (f b0) t0; + Alcotest.(check int) "2 1st weeks" (f (b0 + b1)) (t0 + t1); + Alcotest.(check int) "3 1st weeks" (f (b0 + b1 + b2)) (t0 + t1 + t2); + Alcotest.(check int) + "2 weeks & half of one" + (f (b0 + b1 + (b2 / 2))) + (t0 + t1 + (t2 / 2)); + Alcotest.(check int) "only 3rd week" (f ~first_block_idx:(b0 + b1) b2) t2; + Alcotest.(check int) + "a third of second week" + (f ~first_block_idx:(b0 + (b1 / 3)) (b1 / 3)) + (t1 / 3); + Alcotest.(check (float 0.5e6)) + "Tx count may 5th 2021" + (f 1457727 |> float_of_int) + 15_000_000. + +let test_operation_count () = + let f = + Irmin_traces.Trace_stat_summary_utils.approx_operation_count_of_block_count + in + Alcotest.(check (float 0.5e6)) + "Ops count may 5th 2021" + (f 1457727 |> float_of_int) + 47_500_000. + +let test_cases = + [ + ("snap int", [ Alcotest.test_case "snap_around_42" `Quick snap_around_42 ]); + ( "tx count", + [ + Alcotest.test_case "test_transaction_count" `Quick + test_transaction_count; + ] ); + ( "ops count", + [ Alcotest.test_case "test_operation_count" `Quick test_operation_count ] + ); + ] diff --git a/vendors/irmin/test/irmin-bench/replay.ml b/vendors/irmin/test/irmin-bench/replay.ml new file mode 100644 index 000000000000..65495fc5ab7b --- /dev/null +++ b/vendors/irmin/test/irmin-bench/replay.ml @@ -0,0 +1,187 @@ +open! Import + +let test_dir = Filename.concat "_build" "test-pack-trace-replay" + +let () = + Logs.set_level (Some Logs.Debug); + Logs.set_reporter (Irmin_test.reporter ()) + +module Conf = Irmin_tezos.Conf + +module Store = struct + type store_config = unit + + module Store = Irmin_tezos.Store + include Store + + type key = commit_key + + let create_repo ~root () = + (* make sure the parent dir exists *) + let () = + match Sys.file_exists (Filename.dirname root) with + | false -> Unix.mkdir (Filename.dirname root) 0o755 + | true -> () + in + let conf = Irmin_pack.config ~readonly:false ~fresh:true root in + let* repo = Store.Repo.v conf in + let on_commit _ _ = Lwt.return_unit in + let on_end () = Lwt.return_unit in + Lwt.return (repo, on_commit, on_end) + + let gc_wait repo = + let* r = Store.Gc.wait repo in + match r with Ok _ -> Lwt.return_unit | Error (`Msg err) -> failwith err + + let gc_run ?(finished = fun _ -> Lwt.return_unit) repo key = + let f (result : (_, Store.Gc.msg) result) = + match result with + | Error (`Msg err) -> finished @@ Error err + | Ok stats -> finished @@ Ok stats + in + let* launched = Store.Gc.run ~finished:f repo key in + match launched with + | Ok true -> Lwt.return_unit + | Ok false -> [%logs.app "GC skipped"] |> Lwt.return + | Error (`Msg err) -> failwith err +end + +module Replay = Irmin_traces.Trace_replay.Make (Store) + +let rec repeat = function + | 0 -> fun _f x -> x + | n -> fun f x -> f (repeat (n - 1) f x) + +(** The current working directory depends on whether the test binary is directly + run or is triggered with [dune exec], [dune runtest]. We normalise by + switching to the project root first. *) +let goto_project_root () = + let cwd = Fpath.v (Sys.getcwd ()) in + match cwd |> Fpath.segs |> List.rev with + | "irmin-bench" :: "test" :: "default" :: "_build" :: _ -> + let root = cwd |> repeat 4 Fpath.parent in + Unix.chdir (Fpath.to_string root) + | _ -> () + +let setup_env () = + goto_project_root (); + let trace_path = + let open Fpath in + v "test" / "irmin-bench" / "data" / "tezos_actions_1commit.repr" + |> to_string + in + assert (Sys.file_exists trace_path); + if Sys.file_exists test_dir then ( + let cmd = Printf.sprintf "rm -rf %s" test_dir in + [%logs.debug "exec: %s\n%!" cmd]; + let _ = Sys.command cmd in + ()); + trace_path + +let replay_1_commit () = + let trace_path = setup_env () in + let replay_config : _ Replay.config = + { + number_of_commits_to_replay = 1; + path_conversion = `None; + inode_config = (Conf.entries, Conf.stable_hash); + store_type = `Pack; + replay_trace_path = trace_path; + artefacts_path = test_dir; + keep_store = false; + keep_stat_trace = false; + empty_blobs = false; + return_type = Summary; + gc_every = 0; + gc_distance_in_the_past = 0; + gc_wait_after = 0; + add_volume_every = 0; + } + in + let+ summary = Replay.run () replay_config in + [%logs.debug + "%a" (Irmin_traces.Trace_stat_summary_pp.pp 5) ([ "" ], [ summary ])]; + let check name = Alcotest.(check int) ("Stats_counters" ^ name) in + let pack_got = Irmin_pack.Stats.get () in + let unix_got = Irmin_pack_unix.Stats.get () in + let pack_store = + Irmin_pack_unix.Stats.(Pack_store.export unix_got.pack_store) + in + let inode = Irmin_pack.Stats.(Inode.export pack_got.inode) in + check "appended_hashes" pack_store.appended_hashes 0; + check "appended_offsets" pack_store.appended_offsets 5; + check "total" pack_store.total 2; + check "from_staging" pack_store.from_staging 0; + check "from_lru" pack_store.from_lru 2; + check "from_pack_direct" pack_store.from_pack_direct 0; + check "from_pack_indexed" pack_store.from_pack_indexed 0; + check "inode_add" inode.inode_add 0; + check "inode_remove" inode.inode_remove 0; + check "inode_of_seq" inode.inode_of_seq 2; + check "inode_of_raw" inode.inode_of_raw 2; + check "inode_rec_add" inode.inode_rec_add 0; + check "inode_rec_remove" inode.inode_rec_remove 0; + check "inode_to_binv" inode.inode_to_binv 2; + check "inode_decode_bin" inode.inode_decode_bin 0; + check "inode_encode_bin" inode.inode_encode_bin 2 + +module Store_mem = struct + type store_config = unit + + module Maker = Irmin_pack_mem.Maker (Conf) + module Store = Maker.Make (Irmin_tezos.Schema) + include Store + + type key = commit_key + + let create_repo ~root () = + let conf = Irmin_pack.config ~readonly:false ~fresh:true root in + let* repo = Store.Repo.v conf in + let on_commit _ _ = Lwt.return_unit in + let on_end () = Lwt.return_unit in + Lwt.return (repo, on_commit, on_end) + + let split _repo = () + let add_volume _repo = () + let gc_wait _repo = Lwt.return_unit + let gc_run ?finished:_ _repo _key = Lwt.return_unit +end + +module Replay_mem = Irmin_traces.Trace_replay.Make (Store_mem) + +let replay_1_commit_mem () = + let trace_path = setup_env () in + let replay_config : _ Irmin_traces.Trace_replay.config = + { + number_of_commits_to_replay = 1; + path_conversion = `None; + inode_config = (Conf.entries, Conf.stable_hash); + store_type = `Pack; + replay_trace_path = trace_path; + artefacts_path = test_dir; + keep_store = false; + keep_stat_trace = false; + empty_blobs = false; + return_type = Summary; + gc_every = 0; + gc_distance_in_the_past = 0; + gc_wait_after = 0; + add_volume_every = 0; + } + in + let+ summary = Replay_mem.run () replay_config in + [%logs.debug + "%a" (Irmin_traces.Trace_stat_summary_pp.pp 5) ([ "" ], [ summary ])]; + () + +let test_cases = + let tc msg f = + Alcotest.test_case msg `Quick (fun () -> Lwt_main.run (f ())) + in + [ + ( "replay", + [ + tc "replay_1_commit" replay_1_commit; + tc "replay_1_commit_in_memory" replay_1_commit_mem; + ] ); + ] diff --git a/vendors/irmin/test/irmin-bench/test.ml b/vendors/irmin/test/irmin-bench/test.ml new file mode 100644 index 000000000000..3d09831eaf35 --- /dev/null +++ b/vendors/irmin/test/irmin-bench/test.ml @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Alcotest.run "irmin-bench" + (Ema.test_cases @ Misc.test_cases @ Replay.test_cases) diff --git a/vendors/irmin/test/irmin-bench/test.mli b/vendors/irmin/test/irmin-bench/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-bench/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-chunk/dune b/vendors/irmin/test/irmin-chunk/dune new file mode 100644 index 000000000000..8b275e8a8a85 --- /dev/null +++ b/vendors/irmin/test/irmin-chunk/dune @@ -0,0 +1,15 @@ +(library + (name test_chunk) + (modules test_chunk) + (libraries fmt irmin irmin-test irmin-chunk irmin.mem lwt)) + +(executable + (name test) + (modules test) + (libraries alcotest fmt irmin irmin-test lwt lwt.unix test_chunk)) + +(rule + (alias runtest) + (package irmin-chunk) + (action + (run ./test.exe -q --color=always))) diff --git a/vendors/irmin/test/irmin-chunk/test.ml b/vendors/irmin/test/irmin-chunk/test.ml new file mode 100644 index 000000000000..eef06a60f24c --- /dev/null +++ b/vendors/irmin/test/irmin-chunk/test.ml @@ -0,0 +1,83 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2015 Mounir Nasr Allah + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends + +let () = Printexc.record_backtrace true +let key_t : Test_chunk.Key.t Alcotest.testable = (module Test_chunk.Key) +let value_t : Test_chunk.Value.t Alcotest.testable = (module Test_chunk.Value) + +let run f () = + let+ () = f () in + flush stderr; + flush stdout + +let hash x = Test_chunk.Key.hash (fun l -> l x) +let hash_contents x = hash ("B" ^ x) +let value_to_bin = Irmin.Type.(unstage (to_bin_string Test_chunk.Value.t)) + +let test_add_read ?(stable = false) (module AO : Test_chunk.S) () = + let* t = AO.v () in + let test size = + let name = Printf.sprintf "size %d" size in + let v = String.make size 'x' in + let* k = AO.batch t (fun t -> AO.add t v) in + (if stable then + let str = value_to_bin v in + Alcotest.(check key_t) (name ^ " is stable") k (hash_contents str)); + let+ v' = AO.find t k in + Alcotest.(check @@ option value_t) name (Some v) v' + in + let x = 40 in + Lwt_list.iter_s test + [ + x - 1; + x; + x + 1; + (x * 2) - 1; + x * 2; + (x * 2) + 1; + (x * x) - 1; + x * x; + (x * x) + 1; + x * x * x; + ] + +let simple = + ( "simple", + [ + ( "add/read: in-memory", + `Quick, + run @@ test_add_read (module Test_chunk.Mem) ); + ( "add/read: in-memory+chunks", + `Quick, + run @@ test_add_read (module Test_chunk.MemChunk) ); + ] ) + +let stable = + let test stable = test_add_read ~stable (module Test_chunk.MemChunk) in + ( "stable", + [ + ("add/read: simple", `Quick, run @@ test false); + ("add/read: stable", `Quick, run @@ test true); + ] ) + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-chunk" ~slow:true ~misc:[ simple; stable ] + ~sleep:Lwt_unix.sleep + [ (`Quick, Test_chunk.suite) ] diff --git a/vendors/irmin/test/irmin-chunk/test.mli b/vendors/irmin/test/irmin-chunk/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-chunk/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-chunk/test_chunk.ml b/vendors/irmin/test/irmin-chunk/test_chunk.ml new file mode 100644 index 000000000000..3469e7fb9e5b --- /dev/null +++ b/vendors/irmin/test/irmin-chunk/test_chunk.ml @@ -0,0 +1,77 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * Copyright (c) 2015 Mounir Nasr Allah + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends +module Hash = Irmin.Hash.SHA1 + +module Key = struct + include Irmin.Hash.SHA1 + + let pp = Irmin.Type.pp t + let equal = Irmin.Type.(unstage (equal t)) +end + +module Value = struct + include Irmin.Contents.String + + let pp = Fmt.string + let equal = String.equal + + type hash = Key.t + + module H = Irmin.Hash.Typed (Key) (Irmin.Contents.String) + + let hash = H.hash +end + +module type S = sig + include + Irmin.Content_addressable.S with type key = Key.t and type value = Value.t + + val v : unit -> read t Lwt.t +end + +module Append_only = Irmin_mem.Append_only + +module Content_addressable = + Irmin.Content_addressable.Make (Append_only) (Key) (Value) + +module Mem = struct + include Content_addressable + + let v () = v @@ Irmin_mem.config () +end + +module MemChunk = struct + include Content_addressable + + let small_config = + Irmin_chunk.config ~min_size:44 ~size:44 (Irmin_mem.config ()) + + let v () = v small_config +end + +let store = + Irmin_test.store + (module Irmin.Maker + (Irmin_chunk.Content_addressable + (Append_only)) + (Irmin_mem.Atomic_write)) + (module Irmin.Metadata.None) + +let config = Irmin_chunk.config (Irmin_mem.config ()) +let suite = Irmin_test.Suite.create ~name:"CHUNK" ~store ~config () diff --git a/vendors/irmin/test/irmin-cli/dune b/vendors/irmin/test/irmin-cli/dune new file mode 100644 index 000000000000..11ec9069d99e --- /dev/null +++ b/vendors/irmin/test/irmin-cli/dune @@ -0,0 +1,17 @@ +(executable + (name test) + (modules test) + (libraries irmin-cli alcotest)) + +(rule + (alias runtest) + (package irmin-cli) + (deps test.yml) + (action + (chdir + %{workspace_root} + (run %{exe:test.exe} -q --color=always)))) + +(cram + (package irmin-cli) + (deps %{bin:irmin})) diff --git a/vendors/irmin/test/irmin-cli/test.ml b/vendors/irmin/test/irmin-cli/test.ml new file mode 100644 index 000000000000..8f777bb7c86d --- /dev/null +++ b/vendors/irmin/test/irmin-cli/test.ml @@ -0,0 +1,42 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends + +module Conf = struct + let test_config () = + let hash = Irmin_cli.Resolver.Hash.find "blake2b" in + let _, cfg = + Irmin_cli.Resolver.load_config ~config_path:"test/irmin-cli/test.yml" + ~store:"pack" ~contents:"string" ~hash () + in + let spec = Irmin.Backend.Conf.spec cfg in + let index_log_size = + Irmin.Backend.Conf.get cfg Irmin_pack.Conf.Key.index_log_size + in + let fresh = Irmin.Backend.Conf.get cfg Irmin_pack.Conf.Key.fresh in + Alcotest.(check string) + "Spec name" "pack" + (Irmin.Backend.Conf.Spec.name spec); + Alcotest.(check int) "index-log-size" 1234 index_log_size; + Alcotest.(check bool) "fresh" true fresh; + Lwt.return_unit + + let misc : unit Alcotest.test_case list = + [ ("config", `Quick, fun () -> Lwt_main.run (test_config ())) ] +end + +let () = Alcotest.run "irmin-cli" [ ("conf", Conf.misc) ] diff --git a/vendors/irmin/test/irmin-cli/test.yml b/vendors/irmin/test/irmin-cli/test.yml new file mode 100644 index 000000000000..811f6d032438 --- /dev/null +++ b/vendors/irmin/test/irmin-cli/test.yml @@ -0,0 +1,4 @@ +store: pack +hash: blake2b +index-log-size: 1234 +fresh: true diff --git a/vendors/irmin/test/irmin-cli/test_command_line.t b/vendors/irmin/test/irmin-cli/test_command_line.t new file mode 100644 index 000000000000..14f316d0b52d --- /dev/null +++ b/vendors/irmin/test/irmin-cli/test_command_line.t @@ -0,0 +1,96 @@ +Create default config file + $ cat > irmin.yml < root: ./test + > store: pack + > EOF + +Set a/b/c => 123 in ./test + $ irmin set a/b/c 123 + irmin: [WARNING] Updating the control file to [Used_non_minimal_indexing_strategy]. It won't be possible to GC this irmin-pack store anymore. + +Set foo => bar in ./test1 + $ irmin set --root ./test1 foo bar + irmin: [WARNING] Updating the control file to [Used_non_minimal_indexing_strategy]. It won't be possible to GC this irmin-pack store anymore. + +Check for a/b/c in ./test + $ irmin get --root ./test a/b/c + 123 + +Check for the non-existence of foo in ./test + $ irmin get foo + + [1] + +Check for foo in ./test1 + $ irmin get --root ./test1 foo + bar + +Try getting foo from ./test1 using the wrong store type + $ irmin get --root ./test1 -s irf foo + + [1] + +Set d/e/f => 456 in ./test + $ irmin set d/e/f 456 + +List keys in ./test + $ irmin list / + DIR a + DIR d + +List keys in ./test but no path is specified + $ irmin list + DIR a + DIR d + +Set g/h/i => 789 in ./test + $ irmin set /g/h/i/ 789 + +Snapshot main branch + $ export SNAPSHOT=`irmin snapshot` + +List keys under g/h in ./test + $ irmin list g/h + FILE i + +Remove g in ./test + $ irmin remove g + +List keys under g in ./test + $ irmin list g + +Load snapshot commit as store + $ irmin get --commit $SNAPSHOT g/h/i + 789 + +Restore snapshot + $ irmin revert $SNAPSHOT + +Get g/h/i in ./test + $ irmin get g/h/i/ + 789 + +Create branch a from main + $ irmin merge --branch a main + +Remove g/h/i in branch a + $ irmin remove --branch a /g/h/i/ + +Merge branch a in main + $ irmin merge a + +Check that g/h/i has been deleted after merge + $ irmin get g/h/i/ + + [1] + +Check mismatched hash function + $ irmin set --root ./test-hash -s irf -h sha1 abc 123 + $ irmin snapshot --root ./test-hash -s irf -h blake2b 2> /dev/null + [1] + +Clone a local repo + $ irmin clone --root ./cloned ./test + irmin: [WARNING] Updating the control file to [Used_non_minimal_indexing_strategy]. It won't be possible to GC this irmin-pack store anymore. + $ irmin get --root ./cloned a/b/c + 123 diff --git a/vendors/irmin/test/irmin-containers/blob_log.ml b/vendors/irmin/test/irmin-containers/blob_log.ml new file mode 100644 index 000000000000..c4b4fa97e7e8 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/blob_log.ml @@ -0,0 +1,90 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common +module B = Irmin_containers.Blob_log.Mem (Irmin.Contents.String) + +let path = [ "tmp"; "blob" ] +let config () = B.Store.Repo.v (Irmin_mem.config ()) +let merge_into_exn = merge_into_exn (module B.Store) + +let test_empty_read _ () = + config () + >>= B.Store.main + >>= B.read_all ~path + >|= Alcotest.(check (list string)) "checked - reading empty log" [] + +let test_append _ () = + let* t = config () >>= B.Store.main in + B.append ~path t "main.1" >>= fun () -> + B.append ~path t "main.2" >>= fun () -> + B.read_all ~path t + >|= Alcotest.(check (list string)) + "checked - log after appending" [ "main.2"; "main.1" ] + +let test_clone_merge _ () = + let* t = config () >>= B.Store.main in + let* b = B.Store.clone ~src:t ~dst:"cl" in + B.append ~path b "clone.1" >>= fun () -> + B.append ~path t "main.3" >>= fun () -> + merge_into_exn b ~into:t >>= fun () -> + B.read_all ~path t + >|= Alcotest.(check (list string)) + "checked - log after appending" + [ "main.3"; "clone.1"; "main.2"; "main.1" ] + +let test_branch_merge _ () = + let* r = config () in + let* b1 = B.Store.of_branch r "b1" in + let* b2 = B.Store.of_branch r "b2" in + let* b3 = B.Store.of_branch r "b3" in + let* b4 = B.Store.of_branch r "b4" in + B.append ~path b1 "b1.1" >>= fun () -> + B.append ~path b2 "b2.1" >>= fun () -> + B.append ~path b1 "b1.2" >>= fun () -> + B.append ~path b1 "b1.3" >>= fun () -> + B.append ~path b2 "b2.2" >>= fun () -> + B.append ~path b1 "b1.4" >>= fun () -> + merge_into_exn b1 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b4 >>= fun () -> + merge_into_exn b1 ~into:b4 >>= fun () -> + let* () = + B.read_all ~path b3 + >|= Alcotest.(check (list string)) + "checked - value of b3" + [ "b1.4"; "b2.2"; "b1.3"; "b1.2"; "b2.1"; "b1.1" ] + in + B.read_all ~path b4 + >|= Alcotest.(check (list string)) + "checked - value of b4" + [ "b1.4"; "b2.2"; "b1.3"; "b1.2"; "b2.1"; "b1.1" ] + +let test_cases = + [ + ( "blob_log", + [ + Alcotest_lwt.test_case "Read empty log" `Quick test_empty_read; + Alcotest_lwt.test_case "Append" `Quick test_append; + ] ); + ( "blob_log store", + [ + Alcotest_lwt.test_case "Clone and merge" `Quick test_clone_merge; + Alcotest_lwt.test_case "Branch and merge" `Quick test_branch_merge; + ] ); + ] diff --git a/vendors/irmin/test/irmin-containers/common.ml b/vendors/irmin/test/irmin-containers/common.ml new file mode 100644 index 000000000000..530192c2aece --- /dev/null +++ b/vendors/irmin/test/irmin-containers/common.ml @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import + +let merge_into_exn (type s) (module S : Irmin.S with type t = s) store ~into = + S.merge_into ~info:S.Info.none store ~into >|= function + | Error (`Conflict msg) -> + Alcotest.failf "Encountered a conflict while merging: %s" msg + | Ok () -> () diff --git a/vendors/irmin/test/irmin-containers/common.mli b/vendors/irmin/test/irmin-containers/common.mli new file mode 100644 index 000000000000..f3c27a0d8559 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/common.mli @@ -0,0 +1,19 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val merge_into_exn : + (module Irmin.S with type t = 's) -> 's -> into:'s -> unit Lwt.t diff --git a/vendors/irmin/test/irmin-containers/counter.ml b/vendors/irmin/test/irmin-containers/counter.ml new file mode 100644 index 000000000000..cdcac2ef9791 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/counter.ml @@ -0,0 +1,91 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common +module C = Irmin_containers.Counter.Mem + +let path = [ "tmp"; "counter" ] +let config () = C.Store.Repo.v (Irmin_mem.config ()) +let merge_into_exn = merge_into_exn (module C.Store) + +let test_inc _ () = + let* t = config () >>= C.Store.main in + C.inc ~path t >>= fun () -> + let* () = + C.read ~path t + >|= Alcotest.(check int64) "checked - increment without using by" 1L + in + C.inc ~by:2L ~path t >>= fun () -> + C.read ~path t >|= Alcotest.(check int64) "checked - increment using by" 3L + +let test_dec _ () = + let* t = config () >>= C.Store.main in + C.dec ~path t >>= fun () -> + let* () = + C.read ~path t + >|= Alcotest.(check int64) "checked - decrement without using by" 2L + in + C.dec ~by:2L ~path t >>= fun () -> + C.read ~path t >|= Alcotest.(check int64) "checked - decrement using by" 0L + +let test_clone_merge _ () = + let* t = config () >>= C.Store.main in + C.inc ~by:5L ~path t >>= fun () -> + let* b = C.Store.clone ~src:t ~dst:"cl" in + C.inc ~by:2L ~path b >>= fun () -> + C.dec ~by:4L ~path t >>= fun () -> + let* () = + C.read ~path t >|= Alcotest.(check int64) "checked - value of main" 1L + in + let* () = + C.read ~path b >|= Alcotest.(check int64) "checked - value of clone" 7L + in + merge_into_exn b ~into:t >>= fun () -> + C.read t ~path + >|= Alcotest.(check int64) "checked - value of main after merging" 3L + +let test_branch_merge _ () = + let* r = config () in + let* b1 = C.Store.of_branch r "b1" in + let* b2 = C.Store.of_branch r "b2" in + let* b3 = C.Store.of_branch r "b3" in + let* b4 = C.Store.of_branch r "b4" in + C.inc ~by:5L ~path b1 >>= fun () -> + C.dec ~by:2L ~path b2 >>= fun () -> + merge_into_exn b1 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b4 >>= fun () -> + merge_into_exn b1 ~into:b4 >>= fun () -> + let* () = + C.read ~path b3 >|= Alcotest.(check int64) "checked - value of b3" 3L + in + C.read ~path b4 >|= Alcotest.(check int64) "checked - value of b4" 3L + +let test_cases = + [ + ( "counter", + [ + Alcotest_lwt.test_case "Increment" `Quick test_inc; + Alcotest_lwt.test_case "Decrement" `Quick test_dec; + ] ); + ( "counter store", + [ + Alcotest_lwt.test_case "Clone and merge" `Quick test_clone_merge; + Alcotest_lwt.test_case "Branch and merge" `Quick test_branch_merge; + ] ); + ] diff --git a/vendors/irmin/test/irmin-containers/dune b/vendors/irmin/test/irmin-containers/dune new file mode 100644 index 000000000000..1d60b6a971db --- /dev/null +++ b/vendors/irmin/test/irmin-containers/dune @@ -0,0 +1,9 @@ +(executable + (name test) + (libraries alcotest alcotest-lwt irmin-containers)) + +(rule + (alias runtest) + (package irmin-containers) + (action + (run ./test.exe -q --color=always))) diff --git a/vendors/irmin/test/irmin-containers/import.ml b/vendors/irmin/test/irmin-containers/import.ml new file mode 100644 index 000000000000..e6f13c7c2129 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/import.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/test/irmin-containers/linked_log.ml b/vendors/irmin/test/irmin-containers/linked_log.ml new file mode 100644 index 000000000000..08d6a7241b13 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/linked_log.ml @@ -0,0 +1,115 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +module CAS = struct + module Make = Irmin.Content_addressable.Make (Irmin_mem.Append_only) + + let config = Irmin_mem.config () +end + +module L = Irmin_containers.Linked_log.Mem (CAS) (Irmin.Contents.String) () + +let merge_into_exn = merge_into_exn (module L.Store) +let path = [ "tmp"; "link" ] +let config () = L.Store.Repo.v (Irmin_mem.config ()) + +let test_empty_read _ () = + config () + >>= L.Store.main + >>= L.read_all ~path + >|= Alcotest.(check (list string)) "checked - reading empty log" [] + +let test_append_read_all _ () = + let* t = config () >>= L.Store.main in + L.append ~path t "main.1" >>= fun () -> + L.append ~path t "main.2" >>= fun () -> + L.read_all ~path t + >|= Alcotest.(check (list string)) + "checked - log after appending" [ "main.2"; "main.1" ] + +let test_read_incr _ () = + let* cur = config () >>= L.Store.main >>= L.get_cursor ~path in + let* l, cur = L.read ~num_items:1 cur in + Alcotest.(check (list string)) "checked - read one item" [ "main.2" ] l; + let* l, cur = L.read ~num_items:1 cur in + Alcotest.(check (list string)) "checked - read one more item" [ "main.1" ] l; + let+ l, _ = L.read ~num_items:1 cur in + Alcotest.(check (list string)) "checked - read one more item" [] l + +let test_read_excess _ () = + let* cur = config () >>= L.Store.main >>= L.get_cursor ~path in + let+ l, _ = L.read ~num_items:10 cur in + Alcotest.(check (list string)) + "checked - read 10 items" [ "main.2"; "main.1" ] l + +let test_clone_merge _ () = + let* t = config () >>= L.Store.main in + let* b = L.Store.clone ~src:t ~dst:"cl" in + L.append ~path b "clone.1" >>= fun () -> + L.append ~path t "main.3" >>= fun () -> + merge_into_exn b ~into:t >>= fun () -> + L.read_all ~path t + >|= Alcotest.(check (list string)) + "checked - log after appending" + [ "main.3"; "clone.1"; "main.2"; "main.1" ] + +let test_branch_merge _ () = + let* r = config () in + let* b1 = L.Store.of_branch r "b1" in + let* b2 = L.Store.of_branch r "b2" in + let* b3 = L.Store.of_branch r "b3" in + let* b4 = L.Store.of_branch r "b4" in + L.append ~path b1 "b1.1" >>= fun () -> + L.append ~path b2 "b2.1" >>= fun () -> + L.append ~path b1 "b1.2" >>= fun () -> + L.append ~path b1 "b1.3" >>= fun () -> + L.append ~path b2 "b2.2" >>= fun () -> + L.append ~path b1 "b1.4" >>= fun () -> + merge_into_exn b1 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b4 >>= fun () -> + merge_into_exn b1 ~into:b4 >>= fun () -> + let* () = + L.read_all ~path b3 + >|= Alcotest.(check (list string)) + "checked - value of b3" + [ "b1.4"; "b2.2"; "b1.3"; "b1.2"; "b2.1"; "b1.1" ] + in + L.read_all ~path b4 + >|= Alcotest.(check (list string)) + "checked - value of b4" + [ "b1.4"; "b2.2"; "b1.3"; "b1.2"; "b2.1"; "b1.1" ] + +let test_cases = + [ + ( "linked_log", + [ + Alcotest_lwt.test_case "Read empty log" `Quick test_empty_read; + Alcotest_lwt.test_case "Append and real all" `Quick test_append_read_all; + Alcotest_lwt.test_case "Read incrementally with cursor" `Quick + test_read_incr; + Alcotest_lwt.test_case "Read excess with cursor" `Quick test_read_excess; + ] ); + ( "linked_log store", + [ + Alcotest_lwt.test_case "Clone and merge" `Quick test_clone_merge; + Alcotest_lwt.test_case "Branch and merge" `Quick test_branch_merge; + ] ); + ] diff --git a/vendors/irmin/test/irmin-containers/lww_register.ml b/vendors/irmin/test/irmin-containers/lww_register.ml new file mode 100644 index 000000000000..5ab78db3c286 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/lww_register.ml @@ -0,0 +1,96 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +module In = struct + type t = int + + let t = Irmin.Type.int +end + +module L = Irmin_containers.Lww_register.Mem (In) + +let merge_into_exn = merge_into_exn (module L.Store) +let path = [ "tmp"; "lww" ] +let config () = L.Store.Repo.v (Irmin_mem.config ()) + +let test_empty_read _ () = + config () + >>= L.Store.main + >>= L.read ~path + >|= Alcotest.(check (option int)) + "checked - reading register without writing" None + +let test_write _ () = + let* t = config () >>= L.Store.main in + L.write ~path t 1 >>= fun () -> + L.write ~path t 3 >>= fun () -> + L.read ~path t + >|= Alcotest.(check (option int)) "checked - writing to register" (Some 3) + +let test_clone_merge _ () = + let* t = config () >>= L.Store.main in + let* b = L.Store.clone ~src:t ~dst:"cl" in + L.write ~path t 5 >>= fun () -> + L.write ~path b 10 >>= fun () -> + let* () = + L.read ~path t + >|= Alcotest.(check (option int)) "checked - value of main" (Some 5) + in + let* () = + L.read ~path b + >|= Alcotest.(check (option int)) "checked - value of clone" (Some 10) + in + merge_into_exn b ~into:t >>= fun () -> + L.read ~path t + >|= Alcotest.(check (option int)) + "checked - value of main after merging" (Some 10) + +let test_branch_merge _ () = + let* r = config () in + let* b1 = L.Store.of_branch r "b1" in + let* b2 = L.Store.of_branch r "b2" in + let* b3 = L.Store.of_branch r "b3" in + let* b4 = L.Store.of_branch r "b4" in + L.write ~path b1 6 >>= fun () -> + L.write ~path b2 3 >>= fun () -> + merge_into_exn b1 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b3 >>= fun () -> + merge_into_exn b2 ~into:b4 >>= fun () -> + merge_into_exn b1 ~into:b4 >>= fun () -> + let* () = + L.read ~path b3 + >|= Alcotest.(check (option int)) "checked - value of b3" (Some 3) + in + L.read ~path b4 + >|= Alcotest.(check (option int)) "checked - value of b4" (Some 3) + +let test_cases = + [ + ( "lww_register", + [ + Alcotest_lwt.test_case "Read" `Quick test_empty_read; + Alcotest_lwt.test_case "Write" `Quick test_write; + ] ); + ( "lww_register store", + [ + Alcotest_lwt.test_case "Clone and merge" `Quick test_clone_merge; + Alcotest_lwt.test_case "Branch and merge" `Quick test_branch_merge; + ] ); + ] diff --git a/vendors/irmin/test/irmin-containers/test.ml b/vendors/irmin/test/irmin-containers/test.ml new file mode 100644 index 000000000000..50483d8ed186 --- /dev/null +++ b/vendors/irmin/test/irmin-containers/test.ml @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2020 KC Sivaramakrishnan + * Copyright (c) 2020 Anirudh Sunder Raj + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Lwt_main.run + @@ Alcotest_lwt.run "irmin-containers" + (Counter.test_cases + @ Lww_register.test_cases + @ Blob_log.test_cases + @ Linked_log.test_cases) diff --git a/vendors/irmin/test/irmin-containers/test.mli b/vendors/irmin/test/irmin-containers/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-containers/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-fs/dune b/vendors/irmin/test/irmin-fs/dune new file mode 100644 index 000000000000..87614dbcb5d8 --- /dev/null +++ b/vendors/irmin/test/irmin-fs/dune @@ -0,0 +1,31 @@ +(library + (name test_fs) + (modules test_fs) + (libraries irmin-fs irmin-test lwt)) + +(library + (name test_fs_unix) + (modules test_fs_unix) + (libraries test_fs irmin irmin-fs.unix irmin-test irmin-watcher lwt)) + +(executable + (name test) + (modules test) + (libraries alcotest lwt.unix irmin irmin-test test_fs)) + +(executable + (name test_unix) + (modules test_unix) + (libraries alcotest irmin irmin-test test_fs_unix)) + +(rule + (alias runtest) + (package irmin-fs) + (action + (run %{exe:test.exe} -q --color=always))) + +(rule + (alias runtest) + (package irmin-fs) + (action + (run %{exe:test_unix.exe} -q --color=always))) diff --git a/vendors/irmin/test/irmin-fs/test.ml b/vendors/irmin/test/irmin-fs/test.ml new file mode 100644 index 000000000000..2ab8c18fcef2 --- /dev/null +++ b/vendors/irmin/test/irmin-fs/test.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-fs" ~slow:true ~misc:[] ~sleep:Lwt_unix.sleep + [ (`Quick, Test_fs.suite) ] diff --git a/vendors/irmin/test/irmin-fs/test.mli b/vendors/irmin/test/irmin-fs/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-fs/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-fs/test_fs.ml b/vendors/irmin/test/irmin-fs/test_fs.ml new file mode 100644 index 000000000000..f87198ac92c4 --- /dev/null +++ b/vendors/irmin/test/irmin-fs/test_fs.ml @@ -0,0 +1,28 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Infix +module IO = Irmin_fs.IO_mem + +let test_db = Filename.concat "_build" "test-db" +let init ~config:_ = IO.clear () >|= fun () -> IO.set_listen_hook () +let config = Irmin_fs.config test_db +let clean ~config:_ = Lwt.return_unit + +let store = + Irmin_test.store (module Irmin_fs.Maker (IO)) (module Irmin.Metadata.None) + +let suite = Irmin_test.Suite.create ~name:"FS" ~init ~store ~config ~clean () diff --git a/vendors/irmin/test/irmin-fs/test_fs_unix.ml b/vendors/irmin/test/irmin-fs/test_fs_unix.ml new file mode 100644 index 000000000000..01aef3c06b95 --- /dev/null +++ b/vendors/irmin/test/irmin-fs/test_fs_unix.ml @@ -0,0 +1,45 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let stats () = + let stats = Irmin_watcher.stats () in + (stats.Irmin_watcher.watchdogs, Irmin.Backend.Watch.workers ()) + +let test_db = Test_fs.test_db +let config = Test_fs.config +let store = Irmin_test.store (module Irmin_fs_unix) (module Irmin.Metadata.None) + +let clean_dirs config = + let test_db = + Irmin.Backend.Conf.find_root config |> Option.value ~default:test_db + in + if Sys.file_exists test_db then + let cmd = Printf.sprintf "rm -rf %s" test_db in + let _ = Sys.command cmd in + () + +let init ~config = + clean_dirs config; + Irmin.Backend.Watch.set_listen_dir_hook Irmin_watcher.hook; + Lwt.return_unit + +let clean ~config = + clean_dirs config; + Irmin.Backend.Watch.(set_listen_dir_hook none); + Lwt.return_unit + +let suite = + Irmin_test.Suite.create ~name:"FS.UNIX" ~init ~store ~config ~clean ~stats () diff --git a/vendors/irmin/test/irmin-fs/test_unix.ml b/vendors/irmin/test/irmin-fs/test_unix.ml new file mode 100644 index 000000000000..1bc071b6392d --- /dev/null +++ b/vendors/irmin/test/irmin-fs/test_unix.ml @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2021 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-fs.unix" ~slow:false ~sleep:Lwt_unix.sleep + ~misc:[] + [ (`Quick, Test_fs_unix.suite) ] diff --git a/vendors/irmin/test/irmin-git/dune b/vendors/irmin/test/irmin-git/dune new file mode 100644 index 000000000000..7bd68385fba7 --- /dev/null +++ b/vendors/irmin/test/irmin-git/dune @@ -0,0 +1,46 @@ +(library + (name test_git) + (modules test_git) + (libraries + alcotest + fmt + fpath + irmin + irmin-test + irmin.mem + irmin-git + git + git-unix + lwt + lwt.unix) + (preprocess + (pps ppx_irmin ppx_irmin.internal))) + +(library + (name test_git_unix) + (modules test_git_unix) + (libraries test_git irmin.unix irmin-git.unix irmin-watcher) + (preprocess + (pps ppx_irmin ppx_irmin.internal))) + +(executable + (name test) + (modules test) + (libraries alcotest irmin irmin-test test_git)) + +(executable + (name test_unix) + (modules test_unix) + (libraries alcotest irmin irmin-test test_git_unix)) + +(rule + (alias runtest) + (package irmin-git) + (action + (run %{exe:test.exe} -q --color=always))) + +(rule + (alias runtest) + (package irmin-git) + (action + (run %{exe:test_unix.exe} -q --color=always))) diff --git a/vendors/irmin/test/irmin-git/test.ml b/vendors/irmin/test/irmin-git/test.ml new file mode 100644 index 000000000000..154b15db4c04 --- /dev/null +++ b/vendors/irmin/test/irmin-git/test.ml @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let misc = [ ("misc", Test_git.(misc mem)) ] + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-git" ~slow:true ~misc ~sleep:Lwt_unix.sleep + [ (`Quick, Test_git.suite); (`Quick, Test_git.suite_generic) ] diff --git a/vendors/irmin/test/irmin-git/test.mli b/vendors/irmin/test/irmin-git/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-git/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-git/test_git.ml b/vendors/irmin/test/irmin-git/test_git.ml new file mode 100644 index 000000000000..1fae8fa6ccc7 --- /dev/null +++ b/vendors/irmin/test/irmin-git/test_git.ml @@ -0,0 +1,240 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends + +let test_db = Filename.concat "_build" "test-db-git" + +let config = + let head = Git.Reference.v "refs/heads/test" in + Irmin_git.config ~head ~bare:true test_db + +module type S = sig + include Irmin_test.S + + val init : config:Irmin.config -> unit Lwt.t +end + +module type G = sig + include S + module Git : Irmin_git.G +end + +module X = struct + type t = X of (int * int) | Y of string list [@@deriving irmin] + + let merge = Irmin.Merge.idempotent [%typ: t option] +end + +module type X = + Irmin.S + with type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Contents.t = X.t + and type Schema.Branch.t = string + +module Mem (C : Irmin.Contents.S) = struct + module G = Irmin_git.Mem + module M = Irmin_git.KV (G) (Git_unix.Sync (G)) + module S = M.Make (C) + include S + + let init ~config = + let test_db = + Irmin.Backend.Conf.find_root config |> Option.value ~default:test_db + in + Git.v (Fpath.v test_db) >>= function + | Ok t -> S.Git.reset t >|= fun _ -> () + | _ -> Lwt.return_unit +end + +module Generic (C : Irmin.Contents.S) = struct + module CA = Irmin.Content_addressable.Make (Irmin_mem.Append_only) + module M = Irmin_git.Generic_KV (CA) (Irmin_mem.Atomic_write) + include M.Make (C) + + let init ~config = + let* repo = Repo.v config in + Repo.branches repo >>= Lwt_list.iter_p (Branch.remove repo) + + let clean ~config = + let* repo = Repo.v config in + Repo.branches repo >>= Lwt_list.iter_p (Branch.remove repo) >>= fun () -> + Repo.close repo +end + +let suite = + let module S = Mem (Irmin.Contents.String) in + let store = (module S : Irmin_test.S) in + let init ~config = S.init ~config in + let clean ~config = S.init ~config in + Irmin_test.Suite.create ~name:"GIT" ~init ~store ~config ~clean () + +let suite_generic = + let module S = Generic (Irmin.Contents.String) in + let store = (module S : Irmin_test.S) in + let clean ~config = S.clean ~config in + let init ~config = S.init ~config in + Irmin_test.Suite.create ~name:"GIT.generic" ~init ~store ~config ~clean () + +let get = function Some x -> x | None -> Alcotest.fail "get" + +let test_sort_order (module S : S) = + let config = Irmin_git.config test_db in + S.init ~config >>= fun () -> + let* repo = S.Repo.v config in + let commit_t = S.Backend.Repo.commit_t repo in + let node_t = S.Backend.Repo.node_t repo in + let head_tree_id branch = + let* head = S.Head.get branch in + let+ commit = S.Backend.Commit.find commit_t (S.Commit.hash head) in + S.Backend.Commit.Val.node (get commit) + in + let ls branch = + let* tree_id = head_tree_id branch in + let+ tree = S.Backend.Node.find node_t tree_id in + S.Backend.Node.Val.list (get tree) |> List.map fst + in + let info = S.Info.none in + let* main = S.main repo in + S.remove_exn main ~info [] >>= fun () -> + S.set_exn main ~info [ "foo.c" ] "foo.c" >>= fun () -> + S.set_exn main ~info [ "foo1" ] "foo1" >>= fun () -> + S.set_exn main ~info [ "foo"; "foo.o" ] "foo.o" >>= fun () -> + let* items = ls main in + Alcotest.(check (list string)) "Sort order" [ "foo.c"; "foo"; "foo1" ] items; + let* tree_id = head_tree_id main in + Alcotest.(check string) + "Sort hash" "00c5f5e40e37fde61911f71373813c0b6cad1477" + (Irmin.Type.to_string S.Backend.Node.Key.t tree_id); + + (* Convert dir to file; changes order in listing *) + S.set_exn main ~info [ "foo" ] "foo" >>= fun () -> + let* items = ls main in + Alcotest.(check (list string)) "Sort order" [ "foo"; "foo.c"; "foo1" ] items; + Lwt.return_unit + +module Ref (S : Irmin_git.G) = struct + module M = Irmin_git.Ref (S) (Git_unix.Sync (S)) + include M.Make (Irmin.Contents.String) +end + +let pp_reference ppf = function + | `Branch s -> Fmt.pf ppf "branch: %s" s + | `Remote s -> Fmt.pf ppf "remote: %s" s + | `Tag s -> Fmt.pf ppf "tag: %s" s + | `Other s -> Fmt.pf ppf "other: %s" s + +let reference = Alcotest.testable pp_reference ( = ) + +let test_list_refs (module S : G) = + let module R = Ref (S.Git) in + let config = Irmin_git.config test_db in + S.init ~config >>= fun () -> + let* repo = R.Repo.v config in + let* main = R.main repo in + R.set_exn main ~info:R.Info.none [ "test" ] "toto" >>= fun () -> + let* head = R.Head.get main in + R.Branch.set repo (`Remote "datakit/main") head >>= fun () -> + R.Branch.set repo (`Other "foo/bar/toto") head >>= fun () -> + R.Branch.set repo (`Branch "foo") head >>= fun () -> + let* bs = R.Repo.branches repo in + Alcotest.(check (slist reference compare)) + "raw branches" + [ + `Branch "foo"; + `Branch "main"; + `Other "foo/bar/toto"; + `Remote "datakit/main"; + ] + bs; + let* repo = S.Repo.v (Irmin_git.config test_db) in + let* bs = S.Repo.branches repo in + Alcotest.(check (slist string String.compare)) + "filtered branches" [ "main"; "foo" ] bs; + + (* XXX: re-add + if S.Git.kind = `Disk then + let i = Fmt.kstr Sys.command "cd %s && git gc" test_db in + if i <> 0 then Alcotest.fail "git gc failed"; + S.Repo.branches repo >|= fun bs -> + Alcotest.(check (slist string String.compare)) "filtered branches" + ["main";"foo"] bs + else *) + Lwt.return_unit + +let bin_string = Alcotest.testable (Fmt.fmt "%S") ( = ) + +let pre_hash t v = + let buf = Buffer.create 13 in + let pre_hash = Irmin.Type.(unstage (pre_hash t)) in + pre_hash v (Buffer.add_string buf); + Buffer.contents buf + +let test_blobs (module S : S) = + let str = pre_hash S.Contents.t "foo" in + Alcotest.(check bin_string) "blob foo" "blob 3\000foo" str; + let str = pre_hash S.Contents.t "" in + Alcotest.(check bin_string) "blob ''" "blob 0\000" str; + let module X = Mem (X) in + let str = pre_hash X.Contents.t (Y [ "foo"; "bar" ]) in + Alcotest.(check bin_string) + "blob foo" "blob 19\000{\"Y\":[\"foo\",\"bar\"]}" str; + let str = pre_hash X.Contents.t (X (1, 2)) in + Alcotest.(check bin_string) "blob ''" "blob 11\000{\"X\":[1,2]}" str; + let t = X.Tree.singleton [ "foo" ] (X (1, 2)) in + let k1 = X.Tree.hash t in + let* repo = X.Repo.v (Irmin_git.config test_db) in + let* k2 = + X.Backend.Repo.batch repo (fun x y _ -> X.save_tree ~clear:false repo x y t) + >|= function + | `Node k -> k + | `Contents k -> k + in + let hash = Irmin_test.testable X.Hash.t in + Alcotest.(check hash) "blob" k1 k2; + Lwt.return_unit + +let test_import_export (module S : S) = + let module Generic = Generic (Irmin.Contents.String) in + let module Sync = Irmin.Sync.Make (Generic) in + let config = Irmin_git.config test_db in + S.init ~config >>= fun () -> + let* _ = Generic.init ~config in + let* repo = S.Repo.v config in + let* t = S.main repo in + S.set_exn t ~info:S.Info.none [ "test" ] "toto" >>= fun () -> + let remote = Irmin.remote_store (module S) t in + let* repo = Generic.Repo.v (Irmin_mem.config ()) in + let* t = Generic.main repo in + let* _ = Sync.pull_exn t remote `Set in + let+ toto = Generic.get t [ "test" ] in + Alcotest.(check string) "import" toto "toto" + +let misc (module S : G) = + let s = (module S : S) in + let g = (module S : G) in + let generic = (module Generic (Irmin.Contents.String) : S) in + [ + ("Testing sort order", `Quick, fun () -> test_sort_order s); + ("Testing sort order (generic)", `Quick, fun () -> test_sort_order generic); + ("Testing listing refs", `Quick, fun () -> test_list_refs g); + ("git -> mem", `Quick, fun () -> test_import_export s); + ("git blobs", `Quick, fun () -> test_blobs s); + ("git blobs of generic", `Quick, fun () -> test_blobs s); + ] + +let mem = (module Mem (Irmin.Contents.String) : G) diff --git a/vendors/irmin/test/irmin-git/test_git.mli b/vendors/irmin/test/irmin-git/test_git.mli new file mode 100644 index 000000000000..6191323f9acb --- /dev/null +++ b/vendors/irmin/test/irmin-git/test_git.mli @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val suite : Irmin_test.Suite.t +val suite_generic : Irmin_test.Suite.t +val test_db : string + +module type S = sig + include Irmin_test.S + + val init : config:Irmin.config -> unit Lwt.t +end + +module type G = sig + include S + module Git : Irmin_git.G +end + +val misc : (module G) -> unit Alcotest_lwt.test_case list +val mem : (module G) diff --git a/vendors/irmin/test/irmin-git/test_git_unix.ml b/vendors/irmin/test/irmin-git/test_git_unix.ml new file mode 100644 index 000000000000..afeecf9ba8d6 --- /dev/null +++ b/vendors/irmin/test/irmin-git/test_git_unix.ml @@ -0,0 +1,55 @@ +include Irmin.Export_for_backends + +let stats () = + let stats = Irmin_watcher.stats () in + (stats.Irmin_watcher.watchdogs, Irmin.Backend.Watch.workers ()) + +let test_db = Test_git.test_db + +let init ~config = + let test_db = + Irmin.Backend.Conf.find_root config |> Option.value ~default:test_db + in + assert (test_db <> ".git"); + let+ () = + if Sys.file_exists test_db then + Git_unix.Store.v (Fpath.v test_db) >>= function + | Ok t -> Git_unix.Store.reset t >|= fun _ -> () + | Error _ -> Lwt.return_unit + else Lwt.return_unit + in + Irmin.Backend.Watch.set_listen_dir_hook Irmin_watcher.hook + +module S = struct + module G = Git_unix.Store + include Irmin_git_unix.FS.KV (Irmin.Contents.String) + + let init = init +end + +let store = (module S : Test_git.G) + +let clean ~config:_ = + Irmin.Backend.Watch.(set_listen_dir_hook none); + Lwt.return_unit + +let config = + let head = Git.Reference.v "refs/heads/test" in + Irmin_git.config ~head ~bare:true test_db + +let suite = + let store = (module S : Irmin_test.S) in + Irmin_test.Suite.create ~name:"GIT.UNIX" ~init ~store ~config ~clean ~stats () + +let test_non_bare () = + let config = Irmin_git.config ~bare:false test_db in + init ~config >>= fun () -> + let info = Irmin_git_unix.info in + let* repo = S.Repo.v config in + let* t = S.main repo in + S.set_exn t ~info:(info "fst one") [ "fst" ] "ok" >>= fun () -> + S.set_exn t ~info:(info "snd one") [ "fst"; "snd" ] "maybe?" >>= fun () -> + S.set_exn t ~info:(info "fst one") [ "fst" ] "hoho" + +let misc : unit Alcotest.test_case list = + [ ("non-bare", `Quick, fun () -> Lwt_main.run (test_non_bare ())) ] diff --git a/vendors/irmin/test/irmin-git/test_unix.ml b/vendors/irmin/test/irmin-git/test_unix.ml new file mode 100644 index 000000000000..9e3157ec8f41 --- /dev/null +++ b/vendors/irmin/test/irmin-git/test_unix.ml @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let misc = [ ("misc", Test_git.misc Test_git_unix.store) ] +let suites = [ (`Quick, Test_git_unix.suite) ] + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-git.unix" ~misc ~slow:false + ~sleep:Lwt_unix.sleep suites diff --git a/vendors/irmin/test/irmin-graphql/common.ml b/vendors/irmin/test/irmin-graphql/common.ml new file mode 100644 index 000000000000..b5e6109c5a5d --- /dev/null +++ b/vendors/irmin/test/irmin-graphql/common.ml @@ -0,0 +1,197 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Store = Irmin_mem.KV.Make (Irmin.Contents.String) + +let ( / ) = Filename.concat +let http_graphql_dir = "test-graphql" +let socket = http_graphql_dir / "irmin.sock" +let host = "irmin" + +let ctx = + let resolver = + let h = Hashtbl.create 1 in + Hashtbl.add h host (`Unix_domain_socket socket); + Resolver_lwt_unix.static h + in + Cohttp_lwt_unix.Client.custom_ctx ~resolver () + +module Server = + Irmin_graphql_unix.Server.Make + (Store) + (struct + let remote = None + end) + +let mkdir d = + Lwt.catch + (fun () -> Lwt_unix.mkdir d 0o755) + (function + | Unix.Unix_error (Unix.EEXIST, _, _) -> Lwt.return_unit | e -> Lwt.fail e) + +(** Create a GraphQL server over the supplied Irmin repository, returning the + event loop thread. *) +let server_of_repo : type a. Store.repo -> a Lwt.t = + fun repo -> + let server = Server.v repo in + let* () = + Lwt.catch + (fun () -> Lwt_unix.unlink socket) + (function Unix.Unix_error _ -> Lwt.return_unit | e -> Lwt.fail e) + in + mkdir http_graphql_dir >>= fun () -> + let on_exn = raise and mode = `Unix_domain_socket (`File socket) in + Cohttp_lwt_unix.Server.create ~on_exn ~mode server >>= fun () -> + Lwt.fail_with "GraphQL server terminated unexpectedly" + +type server = { event_loop : 'a. 'a Lwt.t; store : Store.t } + +let spawn_graphql_server () = + let config = Irmin_mem.config () in + let* repo = Store.Repo.v config in + let+ main = Store.main repo in + let event_loop = server_of_repo repo in + { event_loop; store = main } + +let rec retry n f = + let retries = ref 0 in + Lwt.catch f (fun e -> + if n = 0 then Lwt.fail e + else + Lwt_unix.sleep (0.1 *. float !retries) >>= fun () -> + incr retries; + retry (n + 1) f) + +type param = + | Var of string + | Raw of string + | String of string + | Int of int + | Float of float + +type query = + | Mutation of query + | Query of query + | List of query list + | Func of string * (string * param) list * query + | Field of string + +let rec string_of_query = function + | Query q -> Printf.sprintf "query { %s }" (string_of_query q) + | Mutation q -> Printf.sprintf "mutation { %s }" (string_of_query q) + | List ql -> String.concat "\n" (List.map string_of_query ql) + | Func (name, params, query) -> ( + match params with + | [] -> Printf.sprintf "%s { %s }" name (string_of_query query) + | args -> + Printf.sprintf "%s (%s) { %s }" name (string_of_args args) + (string_of_query query)) + | Field s -> s + +and string_of_args args = + List.map + (fun (k, v) -> + let v = + match v with + | Var s -> "$" ^ s + | String s -> "\"" ^ s ^ "\"" + | Raw s -> s + | Int i -> string_of_int i + | Float f -> string_of_float f + in + k ^ ": " ^ v) + args + |> String.concat ", " + +let query q = Query q +let mutation q = Mutation q +let list l = List l +let func name ?(params = []) q = Func (name, params, q) +let field s = Field s +let string s = String s +let raw s = Raw s +let var s = Var s +let int i = Int i +let float f = Float f + +let find_result res x = + let rec aux (res : Yojson.Safe.t) x = + match res with + | `List l -> `List (List.map (fun res -> aux res x) l) + | `Assoc _ -> ( + match x with + | Query q | Mutation q -> aux (Yojson.Safe.Util.member "data" res) q + | Func (name, _, q) -> aux (Yojson.Safe.Util.member name res) q + | Field name -> Yojson.Safe.Util.member name res + | List l -> + `Assoc + (List.map + (function + | Field name as item -> (name, aux res item) + | Func (name, _, _) as item -> (name, aux res item) + | _ -> assert false) + l)) + | x -> x + in + aux res x + +(** Issue a query to the localhost server and return the body of the response + message *) +let send_query : + ?vars:(string * Yojson.Safe.t) list -> + string -> + (string, [ `Msg of string ]) result Lwt.t = + fun ?(vars = []) query -> + let headers = Cohttp.Header.init_with "Content-Type" "application/json" + and body = + Yojson.Safe.to_string + (`Assoc [ ("query", `String query); ("variables", `Assoc vars) ]) + |> Cohttp_lwt.Body.of_string + in + let* response, body = + retry 10 (fun () -> + Cohttp_lwt_unix.Client.post ~headers ~body ~ctx + (Uri.make ~scheme:"http" ~host ~path:"graphql" ())) + in + let status = Cohttp_lwt.Response.status response in + let+ body = Cohttp_lwt.Body.to_string body in + match Cohttp.Code.(status |> code_of_status |> is_success) with + | true -> Ok body + | false -> + let msg = + Format.sprintf "Response: %s\nBody:\n%s" + (Cohttp.Code.string_of_status status) + body + in + Error (`Msg msg) + +let members keys json = + List.fold_left (fun key json -> Yojson.Safe.Util.member json key) json keys + +let parse_result k f res = f (members k res) + +(** Issue a query to the localhost server, parse the response object and convert + it using [f] *) +let exec ?vars query f = + let* res = send_query ?vars (string_of_query query) in + match res with + | Error (`Msg e) -> Alcotest.fail e + | Ok res -> + let res = Yojson.Safe.from_string res in + let value = find_result res query in + print_endline (Yojson.Safe.to_string value); + Lwt.return (f value) diff --git a/vendors/irmin/test/irmin-graphql/common.mli b/vendors/irmin/test/irmin-graphql/common.mli new file mode 100644 index 000000000000..59d6b3159a79 --- /dev/null +++ b/vendors/irmin/test/irmin-graphql/common.mli @@ -0,0 +1,141 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(** Default Irmin GraphQL store *) +module Store : + Irmin.S + with type Schema.Path.step = string + and type Schema.Path.t = string list + and type Schema.Contents.t = string + and type Schema.Metadata.t = unit + and type Schema.Branch.t = string + +type server = { + event_loop : 'a. 'a Lwt.t; + (** The server runtime. Cancelling this thread terminates the server. *) + store : Store.t; (** The store used by the server *) +} + +val spawn_graphql_server : unit -> server Lwt.t +(** Initialise a GraphQL server. At most one server may be running concurrently. *) + +type param +(** Parameter to GraphQL function *) + +val var : string -> param +(** Variable parameter *) + +val string : string -> param +(** String parameter, a string with quotation marks added *) + +val raw : string -> param +(** Raw parameter, will be sent without any modification *) + +val int : int -> param +(** Int parameter *) + +val float : float -> param +(** Float parameter *) + +type query +(** GraphQL query + + All queries will begin with either [query] or [mutation], and contain a + combination of [list], [func] and [field]. + + For example, the following query returns the latest commit hash for the + [main] branch: + + {[ + query (func "main" (field "hash")) + ]} + + To avoid nesting parenthesis, you can use the [@@] operator to chain + expressions: + + {[ + query @@ func "main" @@ field "hash" + ]} *) + +val query : query -> query +(** Start a query + + In GraphQL: [query { ... }] *) + +val mutation : query -> query +(** Start a mutation + + In GraphQL: [mutation { ... }] *) + +val list : query list -> query +(** List of [field] or [func] + + + In GraphQL: {[ + { + ... + } + ]} +*) + +val func : string -> ?params:(string * param) list -> query -> query +(** GraphQL method + + In GraphQL: {[ + func(params...) { + ... + } + ]} + + Without parameters: {[ + func { + ... + } + ]} + *) + +val field : string -> query +(** Named field/attribute + + In GraphQL: {[ + { + field + } + ]} + *) + +val string_of_query : query -> string +(** Convert [query] to [string] *) + +val send_query : + ?vars:(string * Yojson.Safe.t) list -> + string -> + (string, [ `Msg of string ]) result Lwt.t +(** Send a GraphQL query string to the currently running test GraphQL instance. *) + +val members : string list -> Yojson.Safe.t -> Yojson.Safe.t +(** Get key from JSON object *) + +val parse_result : string list -> (Yojson.Safe.t -> 'a) -> Yojson.Safe.t -> 'a +(** Get key from JSON object and apply conversion function *) + +val exec : + ?vars:(string * Yojson.Safe.t) list -> + query -> + (Yojson.Safe.t -> 'a) -> + 'a Lwt.t +(** Send a [query] to the running GraphQL instance and parse the JSON results + using the provided conversion function *) diff --git a/vendors/irmin/test/irmin-graphql/dune b/vendors/irmin/test/irmin-graphql/dune new file mode 100644 index 000000000000..5f8d03744e67 --- /dev/null +++ b/vendors/irmin/test/irmin-graphql/dune @@ -0,0 +1,19 @@ +(executable + (name test) + (modules test common import) + (libraries + alcotest + alcotest-lwt + yojson + irmin + irmin-graphql.unix + irmin.mem + cohttp-lwt-unix + logs.fmt + logs)) + +(rule + (alias runtest) + (package irmin-graphql) + (action + (run ./test.exe -q --color=always))) diff --git a/vendors/irmin/test/irmin-graphql/import.ml b/vendors/irmin/test/irmin-graphql/import.ml new file mode 100644 index 000000000000..e6f13c7c2129 --- /dev/null +++ b/vendors/irmin/test/irmin-graphql/import.ml @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2021 Craig Ferguson + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/test/irmin-graphql/test.ml b/vendors/irmin/test/irmin-graphql/test.ml new file mode 100644 index 000000000000..057518343bcf --- /dev/null +++ b/vendors/irmin/test/irmin-graphql/test.ml @@ -0,0 +1,353 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +module Json = struct + include Yojson.Safe + include Yojson.Safe.Util +end + +type concrete = Store.Tree.concrete + +module Alcotest = struct + include Alcotest + + let yojson = testable Json.pp Json.equal +end + +(** Helpers for constructing data *) + +(** Tree with a single child *) +let stree only_key only_child = `Tree [ (only_key, only_child) ] + +(** Sequence of nested trees each with exactly one child *) +let strees : string list -> concrete -> concrete = List.fold_right stree + +let contents v = `Contents (v, ()) + +let set_tree store tree = + Store.Tree.of_concrete tree + |> Store.set_tree_exn ~info:Store.Info.none store [] + +type test_case = Store.t -> unit Lwt.t + +let test_get_contents_list : test_case = + fun store -> + let data = strees [ "a"; "b"; "c" ] (contents "data") + and query = + query + @@ func "main" + @@ func "tree" + @@ func "get_contents" + ~params:[ ("path", string "a/b/c") ] + (list [ field "path"; field "__typename" ]) + in + set_tree store data >>= fun () -> + let+ (result : (string * Json.t) list) = exec query Json.to_assoc in + Alcotest.(check (list (pair string yojson))) + "Returned entry data is valid" + [ ("path", `String "/a/b/c"); ("__typename", `String "Contents") ] + result; + () + +let test_list_contents_recursively : test_case = + fun store -> + let* () = + Store.set_exn store [ "a"; "b"; "c" ] "data" ~info:Store.Info.none + in + let* () = + Store.set_exn store [ "a"; "b"; "d" ] "data1" ~info:Store.Info.none + in + let q = + query + @@ func "main" + @@ func "tree" + @@ func "list_contents_recursively" (list [ field "path"; field "value" ]) + in + let+ contents = exec q Json.to_list >|= List.map Json.to_assoc in + Alcotest.(check (list (list (pair string yojson)))) + "Contents list matches" + [ + [ ("path", `String "/a/b/c"); ("value", `String "data") ]; + [ ("path", `String "/a/b/d"); ("value", `String "data1") ]; + ] + contents + +let test_get_tree_list : test_case = + fun store -> + let data = + strees [ "a"; "b"; "c" ] + (`Tree + [ ("leaf", contents "data1"); ("branch", stree "f" (contents "data2")) ]) + and query = + query + @@ func "main" + @@ func "tree" + @@ func "get_tree" ~params:[ ("path", string "a/b/c") ] + @@ func "list" (list [ field "path"; field "__typename" ]) + in + set_tree store data >>= fun () -> + let+ path_data = exec query Json.(fun x -> to_list x |> List.map to_assoc) in + Alcotest.(check (list (list (pair string yojson)))) + "Returned entry data is valid" + [ + [ ("path", `String "/a/b/c/branch"); ("__typename", `String "Tree") ]; + [ ("path", `String "/a/b/c/leaf"); ("__typename", `String "Contents") ]; + ] + path_data; + () + +let test_get_last_modified : test_case = + fun store -> + let data = stree "a" (contents "data") + and query = + query + @@ func "main" + @@ func "last_modified" + ~params:[ ("path", string "a"); ("n", int 1); ("depth", int 1) ] + @@ func "tree" + @@ func "get_contents" + ~params:[ ("path", string "a") ] + (list [ field "value"; field "__typename" ]) + in + set_tree store data >>= fun () -> + let+ result = exec query Json.(fun m -> to_list m |> List.map to_assoc) in + Alcotest.(check (list (list (pair string yojson)))) + "Returned entry data is valid " + [ [ ("value", `String "data"); ("__typename", `String "Contents") ] ] + result; + () + +let test_commit : test_case = + fun _ -> + let query0 = + query @@ func "main" @@ func "head" (list [ field "hash"; field "key" ]) + in + let* result = exec query0 Json.to_assoc in + let hash = List.assoc "hash" result |> Json.to_string in + let key = List.assoc "key" result |> Json.to_string in + let query1 = + query @@ func "commit_of_key" ~params:[ ("key", var "key") ] @@ field "hash" + in + let vars = [ ("key", `String key) ] in + let+ hash' = exec ~vars query1 Json.to_string in + Alcotest.(check string) "Hashes equal" hash hash' + +let test_mutation : test_case = + fun store -> + let m = + mutation + @@ func "set" ~params:[ ("path", string "foo"); ("value", string "bar") ] + @@ field "hash" + in + let* _hash = exec m Json.to_string in + let q = + query + @@ func "main" + @@ func "tree" + @@ func "get_contents" ~params:[ ("path", string "foo") ] + @@ field "value" + in + let* value = Store.get store [ "foo" ] in + let+ result' = exec q Json.to_string in + Alcotest.(check string) "Contents equal" "bar" result'; + Alcotest.(check string) "Contents equal stored value" "bar" value + +let test_mutation_test_set_and_get : test_case = + fun store -> + (* {parents: [], allow_empty: false, retries: 1, message: "Hello", author: "Me"} *) + let message = "A commit message" in + let vars = + [ + ( "info", + `Assoc + [ + ("parents", `List []); + ("allow_empty", `Bool false); + ("retries", `Int 1); + ("message", `String message); + ("author", `String "irmin-test-graphql"); + ] ); + ] + in + let m = + mutation + @@ func "test_set_and_get" + ~params: + [ + ("info", var "info"); + ("path", string "foo"); + ("test", string "bar"); + ("set", string "baz"); + ] + @@ func "info" + @@ field "message" + in + let* exec_message = exec ~vars m Json.to_string in + let q = + query + @@ func "main" + @@ func "tree" + @@ func "get_contents" ~params:[ ("path", string "foo") ] + @@ field "value" + in + let* value = Store.get store [ "foo" ] in + let+ result' = exec q Json.to_string in + Alcotest.(check string) "Contents equal" "baz" result'; + Alcotest.(check string) "Contents equal stored value" "baz" value; + Alcotest.(check string) "Same commit message" message exec_message + +let test_contents_hash : test_case = + fun _store -> + let v = "bar" in + let m = + query + @@ func "contents_hash" ~params:[ ("value", string v) ] + @@ field "hash" + in + let+ hash = exec m Json.to_string in + let actual_hash = + Store.Contents.hash v |> Irmin.Type.to_string Store.Hash.t + in + Alcotest.(check string) "Content hash equal" actual_hash hash + +let test_update_tree : test_case = + fun store -> + let* commit = Store.Head.get store in + let hash = Store.Commit.hash commit |> Irmin.Type.to_string Store.hash_t in + let m = + mutation + @@ func "update_tree" ~params:[ ("path", string "/"); ("tree", raw "[]") ] + @@ field "hash" + in + let* hash' = exec m Json.to_string in + Alcotest.(check string) "Hashes equal" hash hash'; + let m = + mutation + @@ func "update_tree" + ~params: + [ + ("path", string "/"); + ("tree", raw {| [{path: "foo", value: "bar1"}] |}); + ] + @@ field "hash" + in + let* hash' = exec m Json.to_string in + if String.equal hash hash' then + Alcotest.fail "Hashes should not be equal after update"; + let* contents = Store.get store [ "foo" ] in + Alcotest.(check string) "Contents at foo" contents "bar1"; + let m = + mutation + @@ func "update_tree" + ~params:[ ("path", string "/"); ("tree", raw {| [{path: "foo"}] |}) ] + @@ field "hash" + in + let* () = exec m ignore in + let+ contents = Store.find store [ "foo" ] in + Alcotest.(check (option string)) "Contents empty after update" contents None + +let test_remove : test_case = + fun store -> + let info () = Store.Info.v 0L in + let path_param = string "test/remove" in + let* () = Store.set_exn store [ "test"; "remove" ] "XXX" ~info in + let m = + mutation @@ func "remove" ~params:[ ("path", path_param) ] @@ field "hash" + in + let* () = exec m ignore in + let q = + query + @@ func "main" + @@ func "tree" + @@ func "get_contents" ~params:[ ("path", path_param) ] + @@ field "value" + in + let+ c = exec q Json.to_string_option in + Alcotest.(check (option string)) "Contents have been removed" c None + +let test_branch_list : test_case = + fun store -> + let repo = Store.repo store in + let* head = Store.Head.get store in + let* () = Store.Branch.set repo "A" head in + let* () = Store.Branch.set repo "B" head in + let q = query @@ func "branches" @@ list [ field "name" ] in + let+ branches = + exec q (fun x -> + Json.to_list x |> List.map Json.to_assoc |> List.map List.hd) + in + let branches = + List.sort + (fun (_, a) (_, b) -> + String.compare (Json.to_string a) (Json.to_string b)) + branches + in + Alcotest.(check (list (pair string yojson))) + "Check branch list" branches + [ ("name", `String "A"); ("name", `String "B"); ("name", `String "main") ] + +let test_revert store = + let* head = Store.Head.get store in + let parents = Store.Commit.parents head in + let parent = List.hd parents in + let parent_s = Irmin.Type.to_string Store.hash_t parent in + let q = + mutation + @@ func "revert" ~params:[ ("commit", string parent_s) ] + @@ field "hash" + in + let* hash = exec q Json.to_string in + Alcotest.(check string) "hash is parent hash" hash parent_s; + let+ new_head = Store.Head.get store in + let new_hash = + Store.Commit.hash new_head |> Irmin.Type.to_string Store.hash_t + in + Alcotest.(check string) "parent is new head" parent_s new_hash + +let suite store = + let test_case : string -> test_case -> unit Alcotest_lwt.test_case = + fun name f -> Alcotest_lwt.test_case name `Quick (fun _ () -> f store) + in + [ + ( "GRAPHQL", + [ + test_case "get_contents-list" test_get_contents_list; + test_case "list_contents_recursively" test_list_contents_recursively; + test_case "get_tree-list" test_get_tree_list; + test_case "get_last_modified" test_get_last_modified; + test_case "commit" test_commit; + test_case "contents_hash" test_contents_hash; + test_case "mutation" test_mutation; + test_case "mutation_test-set-and-get" test_mutation_test_set_and_get; + test_case "update_tree" test_update_tree; + test_case "remove" test_remove; + test_case "branches" test_branch_list; + test_case "revert" test_revert; + ] ); + ] + +let () = + Random.self_init (); + Logs.set_reporter (Logs_fmt.reporter ()); + Logs.set_level (Some Debug); + let main = + let* { event_loop; store } = spawn_graphql_server () in + Lwt.pick [ event_loop; Alcotest_lwt.run "irmin-graphql" (suite store) ] + in + Lwt_main.run main diff --git a/vendors/irmin/test/irmin-graphql/test.mli b/vendors/irmin/test/irmin-graphql/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-graphql/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-http/dune b/vendors/irmin/test/irmin-http/dune new file mode 100644 index 000000000000..72c03033ce78 --- /dev/null +++ b/vendors/irmin/test/irmin-http/dune @@ -0,0 +1,37 @@ +(library + (name test_http) + (modules test_http) + (libraries + alcotest + cohttp-lwt + cohttp-lwt-unix + conduit + conduit-lwt-unix + fmt + irmin-test + test_mem + test_git + test_fs_unix + test_git_unix + irmin + irmin-http.unix + logs + lwt + lwt.unix + uri) + (preprocess + (pps ppx_irmin.internal))) + +(executable + (name test) + (modules test) + (libraries irmin-test test_http)) + +(rule + (alias runtest) + (package irmin-http) + (locks ../http) + (action + (chdir + %{workspace_root} + (run %{exe:test.exe} -q --color=always)))) diff --git a/vendors/irmin/test/irmin-http/test.ml b/vendors/irmin/test/irmin-http/test.ml new file mode 100644 index 000000000000..7f7f4950e2bb --- /dev/null +++ b/vendors/irmin/test/irmin-http/test.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Test_http.(with_server servers) (fun () -> + Irmin_test.Store.run "irmin-http" ~misc:[] ~sleep:Lwt_unix.sleep + Test_http.(suites servers)) diff --git a/vendors/irmin/test/irmin-http/test.mli b/vendors/irmin/test/irmin-http/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-http/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-http/test_http.ml b/vendors/irmin/test/irmin-http/test_http.ml new file mode 100644 index 000000000000..999675740a75 --- /dev/null +++ b/vendors/irmin/test/irmin-http/test_http.ml @@ -0,0 +1,238 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends + +let () = Random.self_init () +let ( / ) = Filename.concat +let test_http_dir = "test-http" +let uri = Uri.of_string "http://irmin" + +type id = { name : string; id : int } + +let pp ppf t = Fmt.pf ppf "%s-%d" t.name t.id +let socket t = test_http_dir / Fmt.str "irmin-%a.sock" pp t +let pid_file t = test_http_dir / Fmt.str "irmin-test-%a.pid" pp t +let tmp_file file = file ^ ".tmp" + +module Client = Irmin_http_unix.Http_client + +module Sock (P : sig + val id : id +end) = +struct + let sock = socket P.id +end + +let http_store id (module S : Irmin_test.S) = + let module P = Sock (struct + let id = id + end) in + let module M = Irmin_http.Client (Client (P)) (S) in + (module M : Irmin_test.S) + +let remove file = try Unix.unlink file with _ -> () + +let check_connection id = + let module Client = Client (Sock (struct + let id = id + end)) in + let ctx = Client.ctx () in + let rec loop n = + let url = + Uri.of_string ("http://irmin/branch/CHECK-CONNECTION-" ^ string_of_int n) + in + if n > 10 then + Alcotest.failf "Cannot connect to server %a: too many retries" pp id + else + Lwt.try_bind + (fun () -> Client.get ?ctx url) + (fun _ -> Lwt.return ()) + (function + | Unix.Unix_error (Unix.ECONNREFUSED, _, _) -> + Lwt_unix.sleep (float n *. 0.1) >>= fun () -> loop (n + 1) + | e -> + Alcotest.failf "Cannot connect to server %a: %a" pp id Fmt.exn e) + in + loop 1 + +let wait_for_the_server_to_start id = + let rec aux n = + let pid_file = pid_file id in + let socket = socket id in + if Sys.file_exists pid_file && Sys.file_exists socket then ( + let ic = open_in pid_file in + let line = input_line ic in + close_in ic; + let pid = int_of_string line in + [%logs.debug "read PID %d from %s" pid pid_file]; + Unix.unlink pid_file; + check_connection id >|= fun () -> pid) + else ( + [%logs.debug "waiting for the server to start..."]; + Lwt_unix.sleep (float n *. 0.1) >>= fun () -> aux (n + 1)) + in + aux 1 + +let servers = + [ + (`Quick, Test_mem.suite); + (`Quick, Test_git.suite); + (`Quick, Test_fs_unix.suite); + (`Quick, Test_git_unix.suite); + ] + +module Conf = Irmin_http.Conf + +let root c = Irmin.Backend.Conf.(get c (root Irmin_http.Conf.spec)) + +let mkdir d = + Lwt.catch + (fun () -> Lwt_unix.mkdir d 0o755) + (function + | Unix.Unix_error (Unix.EEXIST, _, _) -> Lwt.return_unit | e -> Lwt.fail e) + +let rec lock id = + let pid = string_of_int (Unix.getpid ()) in + let pid_len = String.length pid in + let pid_file = pid_file id in + let pid_file_tmp = tmp_file pid_file in + (* [fd] is used to write the actual PID file; the file is renamed + bellow to ensure atomicity. *) + let* fd = + Lwt_unix.openfile pid_file_tmp [ Unix.O_CREAT; Unix.O_RDWR ] 0o600 + in + Lwt.catch + (fun () -> + Lwt_unix.lockf fd Unix.F_LOCK 0 >>= fun () -> + [%logs.debug "write PID %s in %s" pid pid_file]; + let* len = Lwt_unix.write fd (Bytes.of_string pid) 0 pid_len in + if len <> pid_len then + Lwt_unix.close fd >>= fun () -> + Lwt.fail_with "Unable to write PID to lock file" + else Lwt_unix.rename pid_file_tmp pid_file >|= fun () -> fd) + (function + | Unix.Unix_error (Unix.EAGAIN, _, _) -> + Lwt_unix.close fd >>= fun () -> lock id + | e -> Lwt_unix.close fd >>= fun () -> Lwt.fail e) + +let unlock fd = Lwt_unix.close fd + +let get_store suite = + match Irmin_test.Suite.store suite with + | Some x -> x + | None -> + failwith + "Cannot construct `irmin-http` test suite for non-content-addressable \ + backend. Pass a store of type `Irmin.S`." + +let serve servers n id = + Logs.set_level ~all:true (Some Logs.Debug); + [%logs.debug "pwd: %s" @@ Unix.getcwd ()]; + let _, (server : Irmin_test.Suite.t) = List.nth servers n in + [%logs.debug + "Got server: %s, root=%s" + (Irmin_test.Suite.name server) + (root (Irmin_test.Suite.config server))]; + let (module Server : Irmin_test.S) = get_store server in + let module HTTP = Irmin_http_unix.Server (Server) in + let test = { name = Irmin_test.Suite.name server; id } in + let socket = socket test in + let server () = + let config = Irmin_test.Suite.config server in + Irmin_test.Suite.init server ~config >>= fun () -> + let* repo = Server.Repo.v config in + let* lock = lock test in + let spec = HTTP.v repo ~strict:false in + let* () = + Lwt.catch + (fun () -> Lwt_unix.unlink socket) + (function Unix.Unix_error _ -> Lwt.return_unit | e -> Lwt.fail e) + in + let mode = `Unix_domain_socket (`File socket) in + Conduit_lwt_unix.set_max_active 100; + let* () = + Cohttp_lwt_unix.Server.create + ~on_exn:(Fmt.pr "Async exception caught: %a" Fmt.exn) + ~mode spec + in + unlock lock + in + Lwt_main.run (server ()) + +let kill_server socket pid = + let () = + try + Unix.kill pid Sys.sigkill; + try ignore (Unix.waitpid [ Unix.WUNTRACED ] pid) with _ -> () + with Unix.Unix_error (Unix.ESRCH, _, _) -> () + in + Unix.unlink socket; + Fmt.epr "Server [PID %d] is killed.\n%!" pid + +let suite i server = + let id = + { name = Irmin_test.Suite.name server; id = Random.int 0x3FFFFFFF } + in + let socket = socket id in + let server_pid = ref 0 in + let config = + Irmin_http.config uri (Irmin.Backend.Conf.empty Irmin_http.Conf.spec) + in + Irmin_test.Suite.create + ~name:(Printf.sprintf "HTTP.%s" (Irmin_test.Suite.name server)) + ~init:(fun ~config:_ -> + remove socket; + remove (pid_file id); + mkdir test_http_dir >>= fun () -> + Lwt_io.flush_all () >>= fun () -> + let pwd = Sys.getcwd () in + let root = + if Filename.basename pwd = "default" then ".." / ".." / "" else "" + in + let cmd = + root + ^ "_build" + / "default" + / Fmt.str "%s serve %d %d &" Sys.argv.(0) i id.id + in + Fmt.epr "pwd=%s\nExecuting: %S\n%!" pwd cmd; + let _ = Sys.command cmd in + let+ pid = wait_for_the_server_to_start id in + server_pid := pid) + ~clean:(fun ~config -> + kill_server socket !server_pid; + Irmin_test.Suite.clean server ~config) + ~config + ~store:(http_store id (get_store server)) + () + +let suites servers = + if Sys.os_type = "Win32" then + (* it's a bit hard to test client/server stuff on windows because + we can't fork. Can work around that later if needed. *) + [] + else List.mapi (fun i (s, server) -> (s, suite i server)) servers + +let with_server servers f = + if Array.length Sys.argv = 4 && Sys.argv.(1) = "serve" then ( + let n = int_of_string Sys.argv.(2) in + let id = int_of_string Sys.argv.(3) in + Logs.set_reporter (Irmin_test.reporter ~prefix:"S" ()); + serve servers n id) + else Lwt_main.run (f ()) + +type test = Alcotest.speed_level * Irmin_test.Suite.t diff --git a/vendors/irmin/test/irmin-http/test_http.mli b/vendors/irmin/test/irmin-http/test_http.mli new file mode 100644 index 000000000000..f9541ffbf1d3 --- /dev/null +++ b/vendors/irmin/test/irmin-http/test_http.mli @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +type test = Alcotest.speed_level * Irmin_test.Suite.t + +val servers : test list +val suites : test list -> test list +val with_server : test list -> (unit -> unit Lwt.t) -> unit diff --git a/vendors/irmin/test/irmin-mem/bench.ml b/vendors/irmin/test/irmin-mem/bench.ml new file mode 100644 index 000000000000..c4bc86d41e57 --- /dev/null +++ b/vendors/irmin/test/irmin-mem/bench.ml @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let config ~root:_ = Irmin_mem.config () + +module KV = Irmin_mem.KV.Make (Irmin.Contents.String) +module Bench = Irmin_bench.Make (KV) + +let size ~root:_ = 0 +let () = Bench.run ~config ~size diff --git a/vendors/irmin/test/irmin-mem/dune b/vendors/irmin/test/irmin-mem/dune new file mode 100644 index 000000000000..1f548b95c10d --- /dev/null +++ b/vendors/irmin/test/irmin-mem/dune @@ -0,0 +1,20 @@ +(library + (name test_mem) + (modules test_mem) + (libraries irmin irmin-test irmin.mem lwt)) + +(executable + (name test) + (modules test) + (libraries alcotest lwt.unix irmin-test test_mem)) + +(rule + (alias runtest) + (package irmin-test) + (action + (run ./test.exe -q --color=always))) + +(executable + (name bench) + (modules bench) + (libraries irmin.mem irmin-test.bench)) diff --git a/vendors/irmin/test/irmin-mem/test.ml b/vendors/irmin/test/irmin-mem/test.ml new file mode 100644 index 000000000000..e2d99e032ff9 --- /dev/null +++ b/vendors/irmin/test/irmin-mem/test.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-mem" ~slow:true ~misc:[] ~sleep:Lwt_unix.sleep + [ (`Quick, Test_mem.suite) ] diff --git a/vendors/irmin/test/irmin-mem/test.mli b/vendors/irmin/test/irmin-mem/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-mem/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-mem/test_mem.ml b/vendors/irmin/test/irmin-mem/test_mem.ml new file mode 100644 index 000000000000..bf8c5b13cd35 --- /dev/null +++ b/vendors/irmin/test/irmin-mem/test_mem.ml @@ -0,0 +1,20 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let store = Irmin_test.store (module Irmin_mem) (module Irmin.Metadata.None) +let config = Irmin_mem.config () +let init ~config:_ = Lwt.return_unit +let suite = Irmin_test.Suite.create ~name:"MEM" ~init ~store ~config () diff --git a/vendors/irmin/test/irmin-pack/_layered.mli b/vendors/irmin/test/irmin-pack/_layered.mli new file mode 100644 index 000000000000..2b40d2f8916f --- /dev/null +++ b/vendors/irmin/test/irmin-pack/_layered.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest.test_case list diff --git a/vendors/irmin/test/irmin-pack/common.ml b/vendors/irmin/test/irmin-pack/common.ml new file mode 100644 index 000000000000..705905a5dba1 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/common.ml @@ -0,0 +1,385 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends +module Int63 = Optint.Int63 + +let get = function Some x -> x | None -> Alcotest.fail "None" +let sha1 x = Irmin.Hash.SHA1.hash (fun f -> f x) +let sha1_contents x = sha1 ("B" ^ x) + +let rm_dir root = + if Sys.file_exists root then ( + let cmd = Printf.sprintf "rm -rf %s" root in + [%logs.info "exec: %s\n%!" cmd]; + let _ = Sys.command cmd in + ()) + +let index_log_size = Some 1_000 +let () = Random.self_init () +let random_char () = char_of_int (Random.int 256) +let random_string n = String.init n (fun _i -> random_char ()) +let random_letter () = char_of_int (Char.code 'a' + Random.int 26) +let random_letters n = String.init n (fun _i -> random_letter ()) + +module Conf = Irmin_tezos.Conf + +module Schema = struct + open Irmin + module Metadata = Metadata.None + module Contents = Contents.String_v2 + module Path = Path.String_list + module Branch = Branch.String + module Hash = Hash.SHA1 + module Node = Node.Generic_key.Make_v2 (Hash) (Path) (Metadata) + module Commit = Commit.Generic_key.Make_v2 (Hash) + module Info = Info.Default +end + +module Contents = struct + include Irmin.Contents.String + + let kind _ = Irmin_pack.Pack_value.Kind.Contents + + module H = Irmin.Hash.Typed (Irmin.Hash.SHA1) (Irmin.Contents.String) + + let hash = H.hash + let magic = 'B' + let weight _ = 1 + let encode_triple = Irmin.Type.(unstage (encode_bin (triple H.t char t))) + let decode_triple = Irmin.Type.(unstage (decode_bin (triple H.t char t))) + let length_header = Fun.const (Some `Varint) + let encode_bin ~dict:_ ~offset_of_key:_ k x = encode_triple (k, magic, x) + + let decode_bin ~dict:_ ~key_of_offset:_ ~key_of_hash:_ x pos_ref = + let _, _, v = decode_triple x pos_ref in + v + + let decode_bin_length = + match Irmin.Type.(Size.of_encoding (triple H.t char t)) with + | Dynamic f -> f + | _ -> assert false +end + +module I = Irmin_pack_unix.Index +module Index = Irmin_pack_unix.Index.Make (Schema.Hash) +module Key = Irmin_pack_unix.Pack_key.Make (Schema.Hash) +module Io = Irmin_pack_unix.Io.Unix +module Errs = Irmin_pack_unix.Io_errors.Make (Io) +module File_manager = Irmin_pack_unix.File_manager.Make (Io) (Index) (Errs) +module Dict = Irmin_pack_unix.Dict.Make (File_manager) +module Dispatcher = Irmin_pack_unix.Dispatcher.Make (File_manager) + +module Pack = + Irmin_pack_unix.Pack_store.Make (File_manager) (Dict) (Dispatcher) + (Schema.Hash) + (Contents) + (Errs) + +module Branch = + Irmin_pack_unix.Atomic_write.Make_persistent + (Irmin.Branch.String) + (Irmin_pack.Atomic_write.Value.Of_hash (Schema.Hash)) + +module Make_context (Config : sig + val root : string +end) = +struct + let fresh_name = + let c = ref 0 in + fun object_type -> + incr c; + + let name = Filename.concat Config.root ("pack_" ^ string_of_int !c) in + [%logs.info "Constructing %s context object: %s" object_type name]; + name + + let mkdir_dash_p dirname = Irmin_pack_unix.Io_legacy.Unix.mkdir dirname + + type d = { name : string; fm : File_manager.t; dict : Dict.t } + + (* TODO : test the indexing_strategy minimal. *) + let config ~readonly ~fresh name = + Irmin_pack.Conf.init ~fresh ~readonly + ~indexing_strategy:Irmin_pack.Indexing_strategy.always ~lru_size:0 name + + (* TODO : remove duplication with irmin_pack/ext.ml *) + let get_fm config = + let readonly = Irmin_pack.Conf.readonly config in + if readonly then File_manager.open_ro config |> Errs.raise_if_error + else + let fresh = Irmin_pack.Conf.fresh config in + if fresh then ( + let root = Irmin_pack.Conf.root config in + mkdir_dash_p root; + File_manager.create_rw ~overwrite:true config |> Errs.raise_if_error) + else File_manager.open_rw config |> Errs.raise_if_error + + let get_dict ?name ~readonly ~fresh () = + let name = Option.value name ~default:(fresh_name "dict") in + let fm = config ~readonly ~fresh name |> get_fm in + let dict = Dict.v fm |> Errs.raise_if_error in + { name; dict; fm } + + let close_dict d = File_manager.close d.fm |> Errs.raise_if_error + + type t = { + name : string; + fm : File_manager.t; + index : Index.t; + pack : read Pack.t; + dict : Pack.dict; + } + + let create ~readonly ~fresh name = + let f = ref (fun () -> ()) in + let config = config ~readonly ~fresh name in + let fm = get_fm config in + let dispatcher = Dispatcher.v fm |> Errs.raise_if_error in + (* open the index created by the fm. *) + let index = File_manager.index fm in + let dict = Dict.v fm |> Errs.raise_if_error in + let pack = Pack.v ~config ~fm ~dict ~dispatcher in + (f := fun () -> File_manager.flush fm |> Errs.raise_if_error); + { name; index; pack; dict; fm } |> Lwt.return + + let get_rw_pack () = + let name = fresh_name "" in + create ~readonly:false ~fresh:true name + + let get_ro_pack name = create ~readonly:true ~fresh:false name + let reopen_rw name = create ~readonly:false ~fresh:false name + + let close_pack t = + Index.close_exn t.index; + File_manager.close t.fm |> Errs.raise_if_error; + (* closes pack and dict *) + Lwt.return_unit +end + +module Alcotest = struct + include Alcotest + + let int63 = testable Int63.pp Int63.equal + + let check_raises_pack_error msg pass f = + Lwt.try_bind f + (fun _ -> + Alcotest.failf + "Fail %s: expected function to raise, but it returned instead." msg) + (function + | Irmin_pack_unix.Errors.Pack_error e as exn -> ( + match pass e with + | true -> Lwt.return_unit + | false -> + Alcotest.failf + "Fail %s: function raised unexpected exception %s" msg + (Printexc.to_string exn)) + | exn -> + Alcotest.failf + "Fail %s: expected function to raise Pack_error, but it raised \ + %s instead" + msg (Printexc.to_string exn)) + + (** TODO: upstream this to Alcotest *) + let check_raises_lwt msg exn (type a) (f : unit -> a Lwt.t) = + Lwt.try_bind f + (fun _ -> + Alcotest.failf + "Fail %s: expected function to raise %s, but it returned instead." msg + (Printexc.to_string exn)) + (function + | e when e = exn -> Lwt.return_unit + | e -> + Alcotest.failf + "Fail %s: expected function to raise %s, but it raised %s \ + instead." + msg (Printexc.to_string exn) (Printexc.to_string e)) + + let testable_repr t = + Alcotest.testable (Irmin.Type.pp t) Irmin.Type.(unstage (equal t)) + + let check_repr ?pos t = Alcotest.check ?pos (testable_repr t) + let kind = testable_repr Irmin_pack.Pack_value.Kind.t + let hash = testable_repr Schema.Hash.t +end + +module Alcotest_lwt = struct + include Alcotest_lwt + + let quick_tc name f = test_case name `Quick (fun _switch () -> f ()) +end + +module Filename = struct + include Filename + + (** Extraction from OCaml for pre-4.10 compatibility *) + + let generic_quote quotequote s = + let l = String.length s in + let b = Buffer.create (l + 20) in + Buffer.add_char b '\''; + for i = 0 to l - 1 do + if s.[i] = '\'' then Buffer.add_string b quotequote + else Buffer.add_char b s.[i] + done; + Buffer.add_char b '\''; + Buffer.contents b + + let quote_command = + match Sys.os_type with + | "Win32" -> + let quote s = + let l = String.length s in + let b = Buffer.create (l + 20) in + Buffer.add_char b '\"'; + let rec loop i = + if i = l then Buffer.add_char b '\"' + else + match s.[i] with + | '\"' -> loop_bs 0 i + | '\\' -> loop_bs 0 i + | c -> + Buffer.add_char b c; + loop (i + 1) + and loop_bs n i = + if i = l then ( + Buffer.add_char b '\"'; + add_bs n) + else + match s.[i] with + | '\"' -> + add_bs ((2 * n) + 1); + Buffer.add_char b '\"'; + loop (i + 1) + | '\\' -> loop_bs (n + 1) (i + 1) + | _ -> + add_bs n; + loop i + and add_bs n = + for _j = 1 to n do + Buffer.add_char b '\\' + done + in + loop 0; + Buffer.contents b + in + let quote_cmd s = + let b = Buffer.create (String.length s + 20) in + String.iter + (fun c -> + match c with + | '(' | ')' | '!' | '^' | '%' | '\"' | '<' | '>' | '&' | '|' -> + Buffer.add_char b '^'; + Buffer.add_char b c + | _ -> Buffer.add_char b c) + s; + Buffer.contents b + in + let quote_cmd_filename f = + if String.contains f '\"' || String.contains f '%' then + failwith ("Filename.quote_command: bad file name " ^ f) + else if String.contains f ' ' then "\"" ^ f ^ "\"" + else f + in + fun cmd ?stdin ?stdout ?stderr args -> + String.concat "" + [ + "\""; + quote_cmd_filename cmd; + " "; + quote_cmd (String.concat " " (List.map quote args)); + (match stdin with + | None -> "" + | Some f -> " <" ^ quote_cmd_filename f); + (match stdout with + | None -> "" + | Some f -> " >" ^ quote_cmd_filename f); + (match stderr with + | None -> "" + | Some f -> + if stderr = stdout then " 2>&1" + else " 2>" ^ quote_cmd_filename f); + "\""; + ] + | _ -> ( + let quote = generic_quote "'\\''" in + fun cmd ?stdin ?stdout ?stderr args -> + String.concat " " (List.map quote (cmd :: args)) + ^ (match stdin with None -> "" | Some f -> " <" ^ quote f) + ^ (match stdout with None -> "" | Some f -> " >" ^ quote f) + ^ + match stderr with + | None -> "" + | Some f -> if stderr = stdout then " 2>&1" else " 2>" ^ quote f) +end + +(** Exec a command, and return [Ok ()] or [Error n] if return code is n <> 0 *) +let exec_cmd cmd = + [%logs.info "exec: %s" cmd]; + match Sys.command cmd with 0 -> Ok () | n -> Error n + +let rec repeat = function + | 0 -> fun _f x -> x + | n -> fun f x -> f (repeat (n - 1) f x) + +(** The current working directory depends on whether the test binary is directly + run or is triggered with [dune exec], [dune runtest]. We normalise by + switching to the project root first. *) +let goto_project_root () = + let cwd = Fpath.v (Sys.getcwd ()) in + match cwd |> Fpath.segs |> List.rev with + | "irmin-pack" :: "test" :: "default" :: "_build" :: _ -> + let root = cwd |> repeat 4 Fpath.parent in + Unix.chdir (Fpath.to_string root) + | _ -> () + +let rec unlink_path path = + match Irmin_pack_unix.Io.Unix.classify_path path with + | `No_such_file_or_directory -> () + | `Directory -> + Sys.readdir path + |> Array.map (fun p -> Filename.concat path p) + |> Array.iter unlink_path; + Unix.rmdir path + | _ -> Unix.unlink path + +let create_lower_root = + let counter = ref 0 in + let ( let$ ) res f = f @@ Result.get_ok res in + fun ?(mkdir = true) () -> + let lower_root = "test_lower_" ^ string_of_int !counter in + incr counter; + let lower_path = Filename.concat "_build" lower_root in + unlink_path lower_path; + let$ _ = + if mkdir then Irmin_pack_unix.Io.Unix.mkdir lower_path else Result.ok () + in + lower_path + +let setup_test_env ~root_archive ~root_local_build = + goto_project_root (); + rm_dir root_local_build; + let cmd = + Filename.quote_command "cp" [ "-R"; "-p"; root_archive; root_local_build ] + in + exec_cmd cmd |> function + | Ok () -> () + | Error n -> + Fmt.failwith + "Failed to set up the test environment: command `%s' exited with \ + non-zero exit code %d" + cmd n diff --git a/vendors/irmin/test/irmin-pack/common.mli b/vendors/irmin/test/irmin-pack/common.mli new file mode 100644 index 000000000000..d5f95304568a --- /dev/null +++ b/vendors/irmin/test/irmin-pack/common.mli @@ -0,0 +1,134 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Perms +module Int63 = Optint.Int63 +module Dict : Irmin_pack_unix.Dict.S +module I = Irmin_pack_unix.Index +module Conf : Irmin_pack.Conf.S + +module File_manager : + Irmin_pack_unix.File_manager.S with module Io = Irmin_pack_unix.Io.Unix + +module Errs : + Irmin_pack_unix.Io_errors.S with module Io = Irmin_pack_unix.Io.Unix + +module Schema : + Irmin.Schema.Extended + with type Hash.t = Irmin.Hash.SHA1.t + and type Path.step = string + and type Path.t = string list + and type Branch.t = string + and type Contents.t = string + and type Metadata.t = unit + +module Filename : sig + include module type of Filename + + val quote_command : + string -> + ?stdin:string -> + ?stdout:string -> + ?stderr:string -> + string list -> + string +end + +module Alcotest : sig + include module type of Alcotest + + val int63 : Int63.t testable + val kind : Irmin_pack.Pack_value.Kind.t testable + val hash : Schema.Hash.t testable + + val check_raises_pack_error : + string -> + (Irmin_pack_unix.Errors.base_error -> bool) -> + (unit -> _ Lwt.t) -> + unit Lwt.t + + val check_raises_lwt : string -> exn -> (unit -> _ Lwt.t) -> unit Lwt.t + + val check_repr : + ?pos:Source_code_position.pos -> + 'a Irmin.Type.t -> + string -> + 'a -> + 'a -> + unit + + val testable_repr : 'a Irmin.Type.t -> 'a Alcotest.testable +end + +module Alcotest_lwt : sig + include module type of Alcotest_lwt + + val quick_tc : string -> (unit -> unit Lwt.t) -> unit test_case + (** Convenience to create a `Quick test_case that doesn't need to use a + switch. *) +end + +module Index : module type of Irmin_pack_unix.Index.Make (Schema.Hash) +module Key : Irmin_pack_unix.Pack_key.S with type hash = Schema.Hash.t + +module Pack : + Irmin_pack_unix.Pack_store.S + with type hash = Schema.Hash.t + and type key = Key.t + and type value = string + +(** Helper constructors for fresh pre-initialised dictionaries and packs *) +module Make_context (Config : sig + val root : string +end) : sig + val fresh_name : string -> string + (** [fresh_name typ] is a clean directory for a resource of type [typ]. *) + + type d = { name : string; fm : File_manager.t; dict : Dict.t } + + val get_dict : ?name:string -> readonly:bool -> fresh:bool -> unit -> d + val close_dict : d -> unit + + type t = { + name : string; + fm : File_manager.t; + index : Index.t; + pack : read Pack.t; + dict : Dict.t; + } + + val get_rw_pack : unit -> t Lwt.t + val get_ro_pack : string -> t Lwt.t + val reopen_rw : string -> t Lwt.t + val close_pack : t -> unit Lwt.t +end + +val get : 'a option -> 'a +val sha1 : string -> Schema.Hash.t +val sha1_contents : string -> Schema.Hash.t +val rm_dir : string -> unit +val index_log_size : int option +val random_string : int -> string +val random_letters : int -> string +val unlink_path : string -> unit +val create_lower_root : ?mkdir:bool -> unit -> string + +val exec_cmd : string -> (unit, int) result +(** Exec a command, and return [Ok ()] or [Error n] if return code is n <> 0 *) + +val setup_test_env : root_archive:string -> root_local_build:string -> unit +(** [setup_test_env ~root_archive ~root_local_build] copies an existing store to + a temporary location, to be used by the test. *) diff --git a/vendors/irmin/test/irmin-pack/data/corrupted/index/log b/vendors/irmin/test/irmin-pack/data/corrupted/index/log new file mode 100644 index 0000000000000000000000000000000000000000..3c08841e2e1a2ed8a382a2c48b17a6db72388409 GIT binary patch literal 428 zcmZPo1I8W$2rvY5kqE(WYx|CBX|}9h^|!`4FqOF?Mxh8vTHI+_%bav83+`X#4JKH((Du`xaU@&pEjQ#Qbs60b~=E}40;)Ie@Bpf25!)AW#C^-sq!wCik23MGObEWy&Ce^WF1sN i64;7kZ&m+uALK3+Iut&$hiCV5$)es3M5Y(D9CueXxWlI>6a5@ReSmM1)2I@ z56`VE4Q-vY%FZF>&_u9vl0ljn7#RA!H&>p07bldQBH<7b9X9h@N6FC&KL#ca#w4hU zWk_x}*zwrs${YQgN89XJbDCIWbA?XMLvi~Fkxggcd)>aqwI+I{=v9XoH*d?_|Lu%T J8`N|V1ppEadHw(Z literal 0 HcmV?d00001 diff --git a/vendors/irmin/test/irmin-pack/data/corrupted_inode/index/log b/vendors/irmin/test/irmin-pack/data/corrupted_inode/index/log new file mode 100644 index 0000000000000000000000000000000000000000..73803a19fcd76206e7c773816ce14199a527e72d GIT binary patch literal 824 zcmZPo17-;W2rvY5kqAxoEh%%p7}U>X;9Qt%ytwDxk`rl2(h^Q$SJp2o_&*^?amU*e zCjy_TN7>gdfhv$-U|^7N%6%wu<Q7GRQ9J&3Cz@p?zr~*)sOE`7EnYLUm?>g@SMJ4X(-%8h}tho{c zRZs^uL3o--o%l_oTU?h`%nez%?MGW@EYzEf)4-10y61cJm%skAmu~IxxMuxldVF~Q zBB%+6!QNDEc@q$~YF$tJ^nR7XbuZmr+2l4u6+8u-ATq_hA?#g>qKbj-jG2L4`7gOc zK#pTzU|b@*19T| z3b9YoAe|r+62So_EvGtX$@AU4hjohAzO-#@JT&L^GpGqI3=9k=&e1Dv=59Fu(>`dc z;&mrJ=WlNpRro^{>|kJE5ciWz@t)nfYW^wpW!GM=w0x&k?DX_4RKa<$8w~9ylpfdT z*&&w8e4y{gR8hV2Ib~1+RfGu6FZxDlbRR_D9kcH++S4@*oPBNgXDaHb2Q=vz%CdHsW$#f%gS#PX;D7#tN`Q7#Jkj7%QPn1B;W66aSe0 zn6gX1Ogr-61pYlbW+I*pjBJcmP!%5Wu1oype2>m)`@Q2N<09Mts`sw`^<-pXW`ZhU zU`SwuF?(+=Ti-f~Vy?q(eW8&?if!n8eTg?0lEVh`tX-M^lE_>x7C^bbkjtA$G@yLvJ*urR`v{9Agvfbab!3-;sR ze~Iol+dO3(<78DQrgDQTw~J?pQ7GRQ9J&3Cz@p?zC#Fh+?l;qx%jI3?U7)DM zJ^fqh+LSd{Vw{+&41}kN)QR6Ty2W*A#oUmE+kUil#{TtWVB&y<8lyHm)ELvY?)e`5 z<*)zjrCWPEu37(?9v|Mn2<%O0s4>DS%ca*fT_vc{47)dAIo9-kV*Lr_AE z@hQwWCLvy%a^0J{oMyKb0$S^;SSrLmMGK*X8k32%oa&q<&v*A8)+t{5(zdbj(45!L zoU!SHMH>SHL-b0Uxf{;^v=7>DWJF3I@CaqvVQ4?0^te9H4zXP31ARZHit3%uDf44wV1`F1)A`=co#kpbf2ZX#4JKH((Du`xaU@&pEjQ#Qbs60b~=E}40;)Ie@Bpf25!)AW#C^-sq!wCik23MGObEWy&Ce^WF1sN i64;7kZ&m+uALK3+Iut&$hiCV5$)e|5d;F zdBt`CKL$oN#uTuA1_p-k*&oz)|0^tFT>0b2|Axc*ZZiZc{1_NH7!#o?#4C=NMQBD^ z9ySruS>5{L#yPX#9lFlgv_Un1D9hL%-;c^O6iA*nP>}I_(Xu6b(k~~*s`m2h3o`Y+ z9-doS8rnK(m7PP%p^0GUB!e_DFfjCcZ>~K1E>0*pMZzH>I&9{*j*_Dlehf?;j7d-x z%aGh|u;a1Ml{fk~kG9#d<}|U$<_evhhvN1VBAd>>_qu(JYfbb@(W?$GZr+x;|Jxax zHmK string_of_int + +(* random path [0-2]/[0-99] *) +let random_key () = + let d x = Random.int x |> string_of_int in + [d 3; d 100] + +let random_commit repo tree parent = + let* tree = Store.Tree.add tree (random_key ()) (random_content ()) in + let hash = Store.Commit.hash parent in + let* c = Store.Commit.v repo ~info ~parents:[hash] tree in + Lwt.return (c, tree) + +let fill_repo repo = + let tree = Store.Tree.empty () in + let* origin = Store.Commit.v repo ~info ~parents:[] tree in + let rec add_commits n parent tree = + if n <= 0 then Lwt.return parent + else + let* c, tree = random_commit repo tree parent in + add_commits (n - 1) c tree + in + add_commits 10_000 origin tree + +let main () = + Random.self_init (); + rm_dir (); + let* repo = Store.Repo.v (config data_dir) in + let* head = fill_repo repo in + let* () = Store.Branch.set repo "main" head in + Store.Repo.close repo + +let () = Lwt_main.run (main ()) +``` diff --git a/vendors/irmin/test/irmin-pack/data/version_1_large/index/lock b/vendors/irmin/test/irmin-pack/data/version_1_large/index/lock new file mode 100644 index 000000000000..b8e7f0f5fc31 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/data/version_1_large/index/lock @@ -0,0 +1 @@ +241188 \ No newline at end of file diff --git a/vendors/irmin/test/irmin-pack/data/version_1_large/index/log b/vendors/irmin/test/irmin-pack/data/version_1_large/index/log new file mode 100644 index 0000000000000000000000000000000000000000..c8d82247815db2c1db338327b8c5afbd18512d08 GIT binary patch literal 1525292 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

uNzbP%-$G%IE8 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�a}4*;n%Y=SLFLCA@^c;u|F+AU$1a( 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 y4OqE( zE_PH-GHgqE=)qUD$|>M=PEvM1%ngsgj=XZTPke*#k>@5a97+yp1JajQ4!FJwQME0td^eDJIhkK zf_2@dhnbu987!SVg9|hi4l)6>;!MiPXUegiVb$v+6U{b>D^0519Cu;;K1f`YgXaI^ zJ=MY$S2Si7FXz4e!snz)0gJEYRZvyLz`#`w-2)OorKN3)lR(u0?M|Hc15mrC}ZaDC!SnR9EIKzm>q7`Q4ydqB!O=jr-LPm<_elzsHg zMlMh5sT<0*K(j9(1&|(!(3JZc3=2$nbtgqx*6=lEba@>Hja)D=a8*NkD1Y95>lEzQ z*?(=?{@Q01OWW;RW<$fF8kDL%oWCv>e_;AOAVzq`^FUug>9Wrr{-AY}AQM16lz7jb z!q-phgq&EtQS;Gnr8i}pABHx9T3`$eTs7R_*zEif`fkh8=p3;Mr_b--9G$w-dJ$xy zDOWAX3JX8)5;lIu+T+*iueUClS>CvTThIhF>BzvqRSQbA9?l2v-^_c}b7-4-t9tY) zi#2LOVUM82U@d61m$(!2|7n*l9y%uf%kF#h27`OsEmhuw5-Z3AP*A&ivPkA>a_)E} z(RlNr-^u&U649SmfO^Xe3|w`PDYK+68~FL}oT*G-?|;%(WZJu)EkdBw%)r1^4;tCB z@XPi66x627P>b@X8LthW9Q{xdq<4?#yb z8$dxW_dzt^pKj`kwyLE;Fnr+hpCT{kihP-%sto z&9*|;%W*X%fkSdb{R7Nu}a5aGfOv-7a-OkzK z31z2+OH7}#$m{M2+mit56@V0gCcc6_ZA1P>o>*&?VBBTjyf&_5=EU7j(1E)q$Oz}N zi%JW`?GDRSt@D`jctvpFmEG5%j%)!95?J^>-1Y9~;$NHXHQ%n@ZP&QZGm7yas48M$ z;A(-4aC&)d3Grak=PB-g`B*@tZ{h3uR>%e}t`^7$CvTEgYZt~%@YM?C#dHAamt65li)LpJe=>XsJywm z-$q)0O8o_qO(&OC)JQ`+Vr`%xmvUM+k6nYws`*I7{r=t4wGFgxzL+-|65VZ}-jcOv zVRganbqCdQ8#yga8D@QXvQAwLG(7`y1LRJ5@1qi)S1Q^(xNdkx*3F4o7NvCoIxg1% zYRg#oZ8PEef4jd>?by~S#n&3v&q%j>3R&CC)d5O+9?t)^KHYTfR=!l*v;0@M@V(OB0vZDXDFBVvdN}7z^oz`p zomg=EF~`FNWx|2iwq5}>G(ieLK`!OAz5n++&zZmXE)dk*#I*X$k(U!Qp{tv^K*O+Q zp8Y1FFK^xN*J?0X=5wpnXI)_CS7?IiE(OQtvMo1f_+)loYdYledE<{0A^dm$K!;&_ zK%?&#etKp54Sde)_HX4)FJP|Zn^P}033Aj1S1+hY_Hgd{QE$3SJZ1mCdopPxR z7arrO|IY7AVt_GpET|VUBW68++L>0#`w8s3H(gnIa++`5L|8cVgM4G*xBbh0iw!F; zey(RcwRYZHc>ch2j5IzgZLK07&aepl54HBA^8xF&)EOu}gaPtNYUZw-29 zwLkaSbkn5&Z-_2vhzFzq)N^(9>~+r(=3=d{ZnxTCKc7*Hi6O!sT1HKh2S<0V#jZ6> zrMn2ay{aQu_bm-AdT*mW_t-RO8)gRRY)=tj2iXQ5 z&_p`}R1`}&Jyt!_yJTZkKI_5#8xAbE&U;s~7!(H}6F_5Q`ko8#W^8Bqe5>um1o1YJ z=*haLU0#6t+aLvy3tPSZJ&yleceIuH>ehD)CPigEm@EbwxnN-6ngv?YZ{gQ@>h?pf z9nYVC=T3Mlk=$&Y`@R9xumCA21-AyZ5`qqI(%Wqs$h$mpZe9Oj+rONkh6P9gs3?|l znrP45_SEy{1mk&MkKMTcbbgZLBFM%iu36W?H+UwzSiTac`t$H z?%9wta@FjQuZYOf**v>0|VDwP-MA#a^73Xu(^eQ?TPN)RZ(9;xzd;0g9Zga3Lx!=ZU3j#wn<%y zFBL2`H}$P>TX*g~Xg3i91J^uA`@za%)0ecQPdzKUOk>V;tBbJ;ZiFV zt5xi3j3tTJmcFfy>YiZ@UF9_&(tg;znXz0XEke_3f$QW1cbl7qPgX*EYV$$u2W3w+ z-M2T)_eH&ETXavzXX4{I50bu{QSJ{=eO6XI2q+Pg64NYCV(0mWuCM0$|tDZS8esG zo0v7_Ypsy`&NrZh0#fi0?8td_@04C&WquR+;QlS~2L|`szi~o4Ad5jgH48t3%ndu- zHt4@U`Q^p&6*IIKe2UrvS{};4z_qvtoF>JxRDa%_yumqS{mQRP%O1RH-pvnM{smG1 z8g`O$`WhIcu{_Ct6|Wn^hvdx%UAIZ~f*RZ)1)xDxS5FScLK$5{=DgCtQ~I9gPc;Px z9)d3NTp|f}q@j5nYp1cwh2Vz@qNaC>r&b8OgHHS{1-Ze(kL&(M1KWw}hc}tLy8Son zh~;(WMCjDO(p6wbs!u6iGrL*qOZcDI&iHlLDioTJLkxX8>JMvy6v3)N8cx+cB?ffR3nfyNye7`T>$ zh9Nzim6Qt}R|fT5zam%s zaL!{EV%NIOtp;y&wq& z2Cg-rxCr!2=Ub_&*njCx=Ax--DF#N%bTnl_O?CzbuC;yG#7#O(LC4raRh*V0*oH&QGmSHs^nQa(0sOpavF50jQVY;rw-5Z%LBW z;=~k}8*A84vT7w5oQKXntOJd7N;-Yrs679_+~vH+SoWN>J)PTUI;cH{ln?7beZ5%E z;!hjg1P?tlwS21kd*g+RqAg|@K{<+nfopvPI3#uMvnR*wa0t0kEFv;%Lf_A6%j!T) z69xvZ4WKn^7JjGu+`sf6TcLVx;ibSc`_^lSopS>%N&qPU6-6G-H~xPq5xO;Dv9I9< zBcb#0^Qv{HgElNNFmP=IIabQ)rOJf@!xvF8PfqmSsX3s^D{No}YRiHYfL2-sdX^+f zPFr2NHfDx({Ej(muC_eToeIr*8zINf20h>67cL*9-N-6m?Aq{^>u7@^qQplVUd>D84*(oV%oxX#YbGS1w8a^=kf>d;}g&7du_)}H-AQLQ3(#46Tr{4ZA9 z_NHl#(j`zK4zdE$jY|BlJ7JOG4iB?jAL$7nwr)N#-}?n5F1CWICJR437L~)H0TWIh zzoaWaB}3FiXr?pBaSRMxTcg1x%&jGECnv>j5(=NUPIp7&mOa_`1)#$VTOr-3D~tNY zgpDVx&)qkF#h2w7&!-2Rf=)(n1r^D`o^#sg^cZ@4di-(fv>(fj7oC{EWCN;-7#O&= zK@QsL6;%0l>Z;I9>Gnk>=kHDI&QZGvDx(<~xVD4Vn_KubN60<6kl*>}$DxMy4cC)v zpZXqx&g*So2zKP=8=F_WoM6-+Za2GZUu2^5@)mhel?*ZglpX>-Qx)4KjV37)9w@R;y|jn@`xTX#Nzt{dD5s$ebrj+9le;`dDB zd7k-x!R}4A{i|jKK&NSTg33b==StR1QtKSuB|HVzUa8Lotz`(T| zRP$K)xrd+Uvi|-?^3t|r(;gjE(RL0>h8BanL47_C=lN&2>)RU-zMC;=!puC5M?5Xd zcYp@V7#O(rsDmq3Lw=jd)AelTK8#rE{B=^{p(9VFp^cn9piy^gPnLWAlV8gAg^Kj< zR+}Q-QP{(;1=<-7GNA?>P+tQj&7@~f3evBzO?vfdvFEfC&Ctxd7gV`f_|2Ji`(f=o zX_XV+!mHFd>>6XH?u7PO_kkvSJe*xiV@^0)3tEaD3*@@Y$6dI_@ja-FW?*HGeM(@AO)Zm+WMaHK4&@azMj!8E&HqM$Aq$*ma|=; z9guyHV=nf+S%3VpvG(MNA77lmG4olht?)wV5a@o;Vm1rEHO%i$$jCkLl;r7YShxP% z3Vx}l&|2>RXyVJmIem?(r}*)vw`VF>e`mJo3}D>_o5wi-syFmK@7AYtoIjktih1(v z-VaO;*G$qAL1~eJfeUnI5o4sEuRWvqi4%)vGpU~QTI^frXco5y>dk|olE%XCtHJV% zPfJ_`{(i03^#2*Veo=QmbgcLgXcWQ2Ikj%>yeZ!K8yC!XvZ!62**{g84YHk|3w$Jz zzUPMrfA9DHzxnCqo~M_;ew=ykohLtZN!}sIOwi(o!3P-jXs;8ipZ`7JUmed@ElrT! z3=CXHATvSE*8jM z&WBzfny;5uUkNY_V6JZkEVb_aFl*nDN$J0&p4gwBzhf6P*`ELvhZcUn><{?7kdW>^%d|9e_5&9_ z*S9vHS!xCbt`nfD$-}wnWbY@phE=amR9BvBiB4{B_n8VEk2(ojKPlz3D{u~vhVHA3 zDIKd>9&LEFY4NIK?;&ONNl@Yq_MFkddU$1DOYO%CnZ;Qu^E*yoo&=hnVPN1oSqFCH zS_6Cbug!cDU8nBev}c(c=cfx6ph}&Af$J2gmt^4=_%`@X(#F$TJ?Y1%oNc`EzisMAKI-x4a%eXo(~)fHZq*|yz}aLV!!-DUWp5To`dQt1_rLv3&4&PpPByV%Xgt? zlgwEvKDNyLVOJ0VTJFQZz;)&)xCP?#?fMa?2}|pn1Wu&qTr*GJ)$tm%q=12e>ny15 z_Hbr@EpxqU^VfZo-tiO!Tw>{8Xvqg^!+{ilx^$9GTh6SzZ>#u2c&gwP)5gE2oZCMg z03DVJQZNa8WxUm?KU@#(x&H||*0rjeHD6!OYyfJBGB9wR;{ZEyw{m8@_M~?EQ-_|F zpRW6VVEXzBXwEth>Q-9#&G=xphP~`#`QtNf#c>8!uI3$?kj=JS=Rw2K9?tI;mz(&0 zuATDaOi;yk;YWyL0{-`)2h>5uEJ+kTUh zp-q&FppKY_^Rm@NbIR5SPkSq5%6mUUyf3Y|2&&)`WW>9ul<)BTW*>vqvv2QPwYWz6 z#I@znS-DG~5pOHc_mA$1SiDMz+k0V!na(y|&m&WnpzViCx!{1hEcWQK^c>|A6|pP_ z4Hxaa{naxp5RzywgBrgUeyy6)9Fo~0zj}py-kv&X$iQ-b?{ugF(0Vx!=OwcH?=VIu zT*-(&@yTGZ1!v5RRiFkp0|VC;P_I$S$&KT?TIcVVlg~!1UdG8-xJ1;f8QL1W0@@^E z?RlB;_{z(ty*v91cXT?7I_PekdL26Qe`Pk|qrZ`f4CDOodZ0lf z1_rLHpwScyKLvA}3AZPCEL^?e^#6&`j+f3l-GZ8M4Kxem;aqa;;=EbyY~5uGJ_o#L zl5TC3RRh&k3=CY?Kdg zt-Z)#JvW;MiH*Sy`Z%Vqy`^}6TK9_vj;up{>+-QLc1;N!CbSJgBD)z6vS zU$;X8>K3TsY2mlzW2DHnDRVd;eL1p3;aywit=(*(JjuYobqkcUJe)J-IDWWh7oK>Q zS;@J=!!kMOmI8EO{}yQQP|E4}AD`IjDb>uY8yy&K>C8X7s2@DM0x|&<7qOmF7Ryx^ zD>PWX40c%k|Mq7G7ug8tFw5;gup@(htf=^-D*2h|z5W^Au!4{~cZ@+TFa`#$JD^Un zg>?oj1@Gn0G)u6c6V&+b7pEy*|H8bu61 z19l7yTz5gMyd<5NGVWHq4|y5!q|=pOJLug@IT23K+ANR)P}OAZ>0)&B^3E4k`(69K z@7}oJj{LUcD$ogzyO5&z;9~!EFVqjMJ=wZeOZ?xVsJhq8poGG}z;zE&6nh`Ei}n4$ zC>wC|>!rHcVs#-h=Rmzg1_rMCkfKuDEl{M^aRYfbVOWa<6^{W~*``?EY#gqQm zSXlP0+oz`b@rb{j?cFUE+n|dy?t_YAYfpyiqdby+U1ye^J^kwR%&pcdzeGYiLH8lI zy2MnRm+D%)M|-}-F}IVqJdfX5$^j~y7#O%7f<`(m{Hk@&WGkk1gllcPyY)m)iA`K% zB(#t75Hzyq;mommN=2pFBXQq_3hW{9T9ge zRkd^s5;6~&LbCru(5AXFPYZ*JtbcQF^TqM@GPx&D+I;TZHRu${BT;a4-*3?0RQzq3 z|ARgE^{hg^dTdp-29+!f3|x;v)0h^1JO3=+a9l0W_?Tc#{==w5JHED^ptdYX0ce$z zhjX1cXJKvQw+EVRJ$y?t#F&@w4+TvsfE0kngruC_`W{aB#D94od+Rex{s&*OYbQEG zi=ZbQ;1yO^zr5YrBzeSvSwi^0oGCMpI19Hy)58|E~bmoR@etq%h zWOblDl&7G9Obb7al)7xT1|bo#EKBj{?vYssr*(r$SOx~Jr=Y%=gAH?EFZ zU!J-Ce-fb8F&DJGgn@zU87SJNobn&dI%AnxqLcnT*GzKi2a88ar=bJ;&p=hQo9C3> zW&4d}RaR|{y<$7_fl}+7_(RYc(r1vS`}w!eo6SyJZR30Qbd#czoo);7U1+oUIi%_S zGHk0}8CxN1^bCu)M$EUl8&Bp!_g}n#G~L^#Go-u<-gYg!CiwJ8nTRbP@{d7#NiRUf zp`??o{*5P7^nDuGYT{owWquX0xN;Xd9`yngS<0Rl(&V>nR;YRIshp=(^gxKQcH<9d z<^EzKIJ#@CK1o~^Xtmm9c9gUG)HI9ajh~>={Sp-97Ji1x8aW$$1bOdH&OJ8Yz4he! zmtCOb&cML+3e?Z=aAsIGF<$%f)TQw|qTZ$ySUwTXGliB9uRtSwl1{;Kl3({L>#Tom z^r7s7q4d#3EM3rA?-j_g)}BXY&rZ9v=g*?HOzXcJuL&J>WYPnb(I6`zx4K-8nz(^c z=Fy>_R`0E*)>mIy^>saTYr`AR`K%Ux`5V)hpBA0q)%iZE)^nYqRMRQBWsqe51~mNU z;k@#Be!Y87^<$le&%3#64&*WDs)9y%85p?UfC_afCu;*W?(6rOHyh96>?~2Td;UR2 z9GWlQfW|E5X+@7{!$(I*v1flc(??45Khja3lpE5r_ z-}$UX;s&}A{h@{gIyY=(8Z-2YLC_7!<&6M4vl=~aBYyS?^(6IL8 zY<|me_;%Emty~LKzy8@i=VI6=P=(6C!1W$71iFCvuFwmsCyiYJPjj}qpWkyqNDNx* zeE?OD7JeHn*}s;TuCh4q%%ip+>T zw{!`cs0VaR>;q&7boH^4_BG8_TDMo|ZF^s7BrYY>18t&w1Py_@din>Lt~+-E~f$I~b#z_+Uu{{3jZrgaJZ9k{>+`DIgpbgrF`3$LX(lgGV z{l*zw{_B@wB}>iyiEIaVfQn!S2CmPb8Yj@x===KT9FIHnoF2z;iD>vS#+{l38u14y zm;%l?rMVn40}tOjd2oGRa*c{z+Vj{DXdmYbsEcpmxAMl`+Cs+o_#Y<=XP^8z)6;*C z2(+yJ3W|0Q=ho8LTBeYtPbV-7hun#5`TzbqFLXiOSI~%#l+&603Kj*rU78o!N+zw` z@Ml}xquZdJ8w?CwUqPM0GSALy3lzT`cvBH4R&%nU-9Te>regYjWA0IE*ahzhjN%&@$b*HO71GKOA9kfN# z!@163<_@R4`gulcuFt%_YI3)=nmBZ!$oFgDA&!Ttnd`rX&a}DoOZ4h`JNLIX>^nf? zFCZ&Gqbc#8Op#3A3@w|yuJU)41w6=JIobR6afWI9)+oCnrE_)IbVA1*(Vh_bsvt+h&^I z63IUv{oiMLVyICBXx@T>f$JBj$0q6YO3Cq8&O=%Lr%z^l3Mi^qUiCu|I=}e~RCif> zy6Y|7Vk!Urm6Z{P=F2YG&pD<7&;jjVkiy)nG_58wqjKuzgS7#L4FZDO-$j7R1qKGL z-;lyQ$2l(Mf#LOJL5bYwXCAK8=)M;MU90v7QkZ{heNZ(u{n+ZPNo?N_g{2xE5ncuw zuw!80`U5J=rJTBI4_Cb3-Cgjkq_XKpTFoEbL*k&BQIG=2IE++2!xnK9<&8E;3TgAZ zzVtf8SwQ>Ue<0&9(ytdk`15s2#24n?1zZ1E37+NR;DQu`e<9;A8&X-`Tt99+@0!^L z;a171U+-vvZwF*x;Q9v{hdHzU!#}&#m!e`f$V}Vxxa66kPbR301}Omb{iU3kql3SE zoRB`L>TmdzwUy7h@;l~&3NMfXP{&-~Q+3+6$J4F2V?y7&y!M=JnUXaC0Y30F-{T6nz~EEEUdxWbBSoOuUZCV zJ03R!s37rhwrN{pzPCrSCh%6fjRu=_u+hJ6(8vYI1W-@S%`@Nt&#QH6vrhf`K4Jc; zj?22nwfiB_&CPHh?1nZs*+0i_{yHmt&*{jE)T-*t7kfb)5*Qe`nLr&=3%~E*%NP6n zo4G7A;hW#JEhg>3#u=b;0i*ylIq%{8NkQrAwp%Z2A8z!X^S|K#jb5?CkbvT50!bXH{&W}|-Q298;U+1k1nxA0!&(dPDj&Vd5XOdHqVpFBUR-zzsT3h{3{7 zG~BB3NBw@qhhp8@ca0<)msM>7bzK-3xYsGW_{Z=asew|TZjW$KC}8U>## zA&z7Rg@=?=!$z(TJ3Xh)T(#!jS$kWlh@Gd>pl)CX)!k*D1&><(pL>z+WF%_nWOppD zM8Gl#(p%(ahs*?RDKuKvqF!2bwf+3Ir;CNP=RcnUshYVtL2Y~szogHK4br+yKMG{C zco#Q5{kdbOBWSjsfq|P7R1A7JKl{~QXS%t0f}NhuAFicVtvn5dkezPaoS@20%Bkw` zMA=l`X&s3#6F&BM`Zg_o!2k+DkO`pZ4)$E$C&O!G6;@H%zey(M(XS%~UAdqf#lXPL z1zGhsp(uG>>XYYc;_50{tvmi-Dbt<=sS@U-7 zJMJjR7zj5vs7>qP{N&r)>W-MCa6{*(@4p#F)J(|@hb%4N=6(V$io;^O%E~(ahn`e? zZMlwXTTr%C4rIKVn;X>kxAt6rw07%GQ|@3=Icf z(7Iv|=b**AEPnKNa5w#%{^aWNmH$rJ{DO?jar1$?wo*$c(sCA%v3>RM#%SL z9p|n=9mxl3s#tq2+hDfdBgbQ}RR2bX;4SYLF)ZqaH1@dpAh*KZP}gf6|SIw2Ha;LE&NHcgTJn7ngOCjL?Y|>&rEJWJ7dqA)R7we$Z+b59grG(H0z+ zk1lU(_~V(Oa_r}Zk0GFTBm)Dt0I2UP<)kAVZn1K~Bgvq&+p=(pV2mKN00Gq-jFEnipU#?e#ir_cME#Kpwz)Fj4l_&# z1rP%Rw;-q!WZ`!v_jQTs4dI4_-`NeuCaRlfbMb=8Xa)vuAyB>H;atSjpw!!}v*c!8 z`~~5?w=FwoKo;CFa0`Jlv6NG6*RuW3m5W~Uo7pxWe_(!f+7EuvU>V2+&`A=(o-yYG zt)%m9-=s&B&;0Cem3--dB4~RFNCD(Das{R-n~yOsUw*26TLb^`HL}cgQ$eem7#O%k zKqan)Us_#dz-8`lCog@R@#F5<>02vVZ-EAhKng&IxOh0P=xY`2*mM3@$3v?r?pv3h zmH7yr@8%W(^_HZZCdcpjYjo|_*|i&|UUTz$Q<45i5Y&BQVBi)3Ek#rId~&A$E4$M- zmnUhg?ERcePN=!-LmC*|B9Lp!nKP%UJ(+*a`Sz}|O-$MGi}|?!K^C)di-8uRTlifJ zV$YcR=7Z<0L$UsMPp9Q^hkJpVCJYSRVxW~)9?r4Bvz>N*kKTX0l}C}^O6JIE<2wTU-;Iakz82eJ}2Ke#hg(xkFcL#5PVpVB|w8k9?n)AvC>C>IU3sdaSA*)k@}vv;X7#81Oo%NB&e|? z>7?mV<;}C~r}VUffCaxh7T)sbRe{VDb4yAyFfaspuJ=)h30r^KDtX44q}1PuOD!_a zg6b-e36R0VqxM-xyqvy>8cj0|%Q|?xwd2-%$mk-s6ex9D`1#EL{6{=7R82ltD}%4I z#_iNP=)H2>QlJ9F!#TvlXj8@lrhWM`Vy@xo?=rr41cO45fq`2ZlrE&4Tv*@wXV1yL zESsF<)RMHMaG%C}P}>Eh05o`5=J{l!SLO#3^YuSX=dJcSyVq3gwLEB`3Z&o~I3zjt zWO(=Y*b>{Js zr`sPN)Mq;gnQP{j2f4w*FHY*>cg4t0nL8)iI7a?_#~=><+@gJvs{9O-H(Mqw}Tc;6BK|}?h2r} zR%_2$wu|_;rCRC5u|}lsdvJ!wATtfprR7$z0Xy>i!a74E)}2CXU*1NF`pn;;b*uxj zX^2}9)V8(oW1DljZ^`~T3)Kg#o0tvf2_8Lv1C%Ej7`PQdXS8@Yd&r#e@+^0mug;fq zqp1Fp%qDIJXhTa0wBc3CiT4xl4XO10MA!RjZ&w`1oKsd+3R=X*z`(5piYzxzzs$E5 z=AY)2YMMGub)CDzVq(vE$owX^5@e~W@b?41zJ7PVw##Atr;{D0YEOt-L5pH#kXtPL z{w>(zbNR@;_%Ap1SMtu^DUq^u31~cyfq`2EG^*s`te>X$cMa!O!MEG(?K9ohU9&H) zg{iDxJZ4j9CT>Xu!(CZ+nN4Xv+To zj<)~vcCRRTyRG}~R!||%z`(5rs!%+fvpBA)?Fo%y{;rl405vTJ$f@&I&382A}U{B^A|4VOXTyO4pXmRt`k{i=k*3O2E z!*HuX4uAXJ$Tj7^>z`SD=g&xKA6~Rz2kS(r6&j#&!op8gT5W2oXzf+DS*Nn!)*St9 z?|&K8on~O*)&OKqpl5zE|j1$M&FqF7TG98gaEmx>wO^fmYEuhYx5Oq|B%G7-{+;no6KVc~b`{A{nA z&Vds@uP_dnR4F9JC726pCNeN^Yk?LBcsQ?Uf40O?D4O$Fn1{iN%~(ts_j-w$ie__ZBV4?dmdc1J5=StoelZ75*iY7_CKE? z)(GiUv&Xe5&|Y zzTUj1|HV*m>OlIN-xO!P@|;n7m?cNAG}OH5o5d1S(AsVW25wzYe^bgSK`U3eQEu9V z>b)~RlyhwOmd6kPO)$Ek3bxEsDNDOidExF1>2Y)Yf-p$AqRa+#rE@E zW%K_bdu)QGQ{5p`s|kysmAgJ@`qIL$&wVcNl8d>_F zW`ecnpBGoxBxoN#C)*T0{dn0|=03|qpz@J{fm`X8N^p+EuN$4ilD# ze~&eJxNqkrNVl5X5LACkIW;qfxVF1|k3D^!Yx#_SHY(1Awb1&)5Hyus=Gm(jpZV+G zH}lvvLOq|q-i}%*x*A%L8bPAFKI+=U&QlK;*v=D`Q56dO_#p{=_#FcSw=pET_uD^S zm-M&TGN@V7$#K$~+4FL5gGRDI3Lw!PAjiGy|K`qp520nX z31oQT;>E)B*C{WV?{iCWr98f9U3E3K?F|c767d-6rPlB!?4M_xE3m5G!2; z8YE(1;5GyGo;{o^CD#ScpSCO|D$L<<^W665F~ihp!5oRz%k(0h)XTM==Rw2446^XpR6s(NTd6I? zPxppSYuI|18z)~vMmV`GK+_WzezP;O#1#>EmYkTc+Eb*Wcgue?QaQL zykxp~O5kBLy-(q(RR=a@z4Ujon*lB5tU&7^Ec|57t~*k5=ZDR)C;6Rw_WyLve{gL* zq_JlOS|H)!T=Y0!LDf9v*{;Y?NsIqq!+(A|2N`zbwgN3)l5+Z3a-z!Xl(6@?kH@3E z52h_XulOA@io$IT>J%z_avxZ5$!UI$#LX$)aq{dAUsP^>gT{q5*4I~ z_Dha)-pzuAY~7DF7A{pRyZ0Y7PR+o;Z39|SBIVS~+2?#+L+9$NY!~T8lEpl_TjfFL zPBJiX+k!?>$~-%l3CS?J8hlwi@!Nr#q&?mIhOnyHwjW$p%dwV79@NkHHv6rI#l^pO zi#aEEfm(qK4BU30R-uKT_MeCSl3G8QjS>zo*J@tm_;|KEWCaDcJ*cGhaL!CSw%JZ1 zO+~Nfpxj2^L*CKCryxV1-1Zp^pz9RR%+;JL6XiZ3O8CCH{;rnuA77t`tY+c1hg7UQ zUMn}mww?^&Y3Mh!*I8>+wde#W+cPk5JA#U23%~XT?O;idFQ+^niS#XAtM{#Xs{yFK z1Sx=2ta0MZ;IX$i{c1pI6c-vq!wKHbQ7M2TE zUqF2ukOEM}YVDc)g}u_%Rxv<-#fA5(&Tlxf^|nLXw2pVd0k!G+QNDZK8$Pyqf2%wl zusYsV;S$Ju3=G`PpstLCpH{c3wS(G^Z)W=rGFq6_$o4Hu0kz>k3P3r_!};lCiOU>k z+t-Q~9&!{*{`tLQT@bWja0YeytUVbv zAGjR;#8t3G#YswkmuN|kU=nDH3j+hU3uJiV7~`zWOruZtnuMh0<%U0buQ4SP+Cy;# zt^K#~)9)*cce{3~I<)G*4daeOKUJ6Kf>vHKFmSs@@sCVG*S-Zt59jR6^hw-$i~D}Bthjn%v%5xm)y1Wd-0cBs z!b>@2x5%?xbN*ppuX8NgprHEU;xI30#_<4+?74YfSZ@)S@=Uejxb4M#y?hrp2v0l@ z8Ukiu;07H@#2D$`z{{p`@(>wEYaE0MvAi^(<4dXg^+l zYEr3*Qa;ab}sp!9k%Dn z@z+w&a?%H~GrIcolb_xW@88Z**Xa8ne^cpYW*ey8z`(%m2bz_#@KbH(+P}Nz+R0x! z^SAA6t8p=7iUs8dkOI(5sfV+|7q;&)I-5L>KE7#r;KRi}g9s1M`f`v0Q1z(qS!bMN ze$ImVrpp>-H64$d82<-C&~}vHD{w$r&#n9z2J1)P3D$7usVw1pq1 zkz||i#1l^(yL9KTJ@G)~k536?9)~*sv>4pOd25*=m-d~9#y{eEWgRYk3e=p(0y@%> zfq^>!)ZdbF>iZC;zp?gzOWo_2MeCleEXr+p3X%XR0QEb|JU<9FtvL1jliSX2@joV< zmu{54w}bXK1B1bil=yzVPi^l<@2vG}o-KGAxq6MWEp(_S2(%u=!tauc+iLZ-?d8&2 z_dZVlwL0Q|!*QrLgFso&!+Bd=`KDcePkc-dI<#49>Q!(18?!;JVFm{7V9=nMlv8DU z>AjCVbF`1|`4`e$*TbsZaSK!>gA{-|=4GA+tFBI-zUfh9M(zItS!x@$-1OQBEgym* z_pv_C@c%XKmWcWP32sao9~mb${!xOas8CSCvGChzHSf^WBW7K)dm^3G9angW3uHqp z)=*Ho@Ni!9kza>vE`v#oe)jX`KLr{8va&&S6$1lzD5$?F>9mad)fSKTRr}*z7w3dAmQQs zXnu7JXTnumhdt?5**a$~SA6n=7K7oSKCh(HD#^pVcMOdlEUA~!)lZW>_15z^Xu1w$ z1<0|=p5O1qY`qqD>_p`Wp5HTLgr9b*q(Tdj2*{fMt|{Wvesd?@6=eL~VficGbVc!F zP{F~#z#R!%9%$h=UtM{{)YOXt`U&@p)qm|snt1CBC>?+lfZ9_Y&b(QB#pjv|mTx$d zeCyp|t+tdq>7Wno-*_XPMHS7@P+*+D}x8l=#| zukvt0<3_Pb(stPr+&8~>M1Gv32AUyeVBn61te`mbN#psWU08_w4?qu_&;aaUSE*4ZcMM z{OT88YMqBfR!k~5y7@d3Jof$CJ2~I)hsdpsCO)%cSfHaxv7oBS!tX}$y`z5V2G8o8 z6TO?}`I-wC34!WM1_tg}&=MpM=c37Hr{8kpH(nFB>1O4N>5W}FC!r?9ftFfGIccA> zF*04w-|jy1_tBgKE-(eF zz>e(hS|N~-qf_R~x|Z=Tx3KB#100~`fD8=W;M4Lf{C@4$F`H%d+jNg@Xj!Gg_N7*y z4Iux66oAS}59iA4Ez5tu@NSzFCFgxW$ZV&^$5hA!D0f0Lc))6%-;|sB1-eDjQxsMG zmi=or(fk0JLgh{X^*fb4%Qd3EC-c7u&RUeUch2(sdlf=0pcU#MD$>O^dRI-2+KqlQX zpBK7&FD;1MX3v-9zoNA?s4@gpXM+@gW~HQ@J{;e)H}2G*XoF8bDm^~7*@_4qfo#~} zP6FLxq3n6RUF5#H)%#a>I-HktOX!^Z%^|H$%YXW421JXhD1Oo$i3TW8P!&&{UVcFz|rCE#< zr4M~oe3LOZt`wRkQ$S^vl#`8*+BE)0C%7tq@VJ*5o4-z&<ZP7}c5=-I)XmAO;5RR7l%?L$z(Z1k0JKNhf`cZgU+xy=Bov&~jl02JSRa zQ^mrsDlg!IcAWE^gzKS6uhdU9AN(ZfK>goCU#*rc9 zAdmu3c`501&LXn>lXU3rNomvgV^6b|hbw#p^_CeJxYI#H9 zE>9%vr_5mEF|PmUG#5JJodKzFocAOjYsh=FN$Q4CjrT_*(aoyPpo)ZnfjbkFE~K1l z);DskKDtSbPsA%@k9K1H>8eeTMZescAcfYR&i%T6i;n#AfAL6+Ve<2n_x`o41|7iz zGNBQiaqfjZO!HddG;3?(*9A{jeVIQ~SQN6_jXMj}#kcUgZD{9t>7nQv_hq{))9xm5 z%U;d~b!8bCxU)fXNgmEixmp5duGoG*@2J6&~_OFw0$9$z9Tv4Rv#2RpJR zWtOhp1%}PfW8P}W{Zq|9Xi^3`%Z!16I|sD9!NTwN(k1@4qV7I(y6*H~+Ub0UoIjo* z2?hr4T+rZvhx1#lKG#{xcj&LNP}p{kmFYv!v@@Xo6-WVScwWj$kzXOBt0;7uf0xp& zG@tZKwGQ_|{Y;Po&|Is#r}o;gQ;FxkRa|uuX0MfzlsB8P2sEq!Qg9LM$m9Ui&U}Zi zd#C>>F&g-2nEud6fadOeP(fnh7xH@dm)rZ&imwE`ojo^r-11Hw z&Ihf;)c0%>Jaw({%dKFKd8(_HtA3gndd3A*6@e6d20K#4tF1K4NdD#Z){+IH$0Zwk z8Y7|2q(abgatpuNER8XtbM7RpXR|x?YKiGrQSPnK!Jvs)4jz_3szrA5 zs^(Q|nX5ldHoEqp*yiyD#RO zQVR}AwVaJy?;7J-G#5%P&1?wJ==-V$%Crm&+@+ue)t_U)o0JAGeB5#HF0fT;en93xs+C z|GgJHs>$&A+o2uM>8dhNq7CvCR4|OS46mDzthZK@DK$h$l(P~vw+b==vX%bVZ=r-d zLybLJPR|P$evR}@?Mwh|fn#9ct^iF}S@_8vd-iX?yA|IBy+*zkiEW%a6}CgmhYHZ- zyod9N=TkpN@|~?suJpV8@X<#bQ8O-3^9W=DWGj8^G%4o)sikFSEH5t1yX1d(%CKT(r@BPj*U2TkWggQk7a%S|X#~q4;`l3<@9FoE19Fe`=ruMdzJWpiT{@;Fk z|6ypQR+SCj9N|6tT&$_du{--_Kb7qeIC{Exi85$YB?AL@6=*x2hco-jQ%iTPH~727 zZQ}KdDiV9S&Ig0KPap-LW8|cqR%aaMcbp*|x2?szXQRsEZSu?Gp>a_ST5+cDx&8W? zq+`E@zO0?JUd)egdCk??;?RNIY7?*{Ps{eH+z49n?fH%e3DQDO-keKn02RRu4BR!K zuAGG*+ty#Z_Xxjw^~GuD$N3ytS#9zb(1unGs7>eLyz#``sSMedJ)bM6cJrz!zU_&h z2uiFB4BWM#?xd8{1=FyiO${9BSEgl#=X)xdq+ad-)e|5Epp9%+p39n}BhLu+q-{x7 z`@W!^C!^aIybvFxAQ9|HmZz_maBA5ciMOkk`s|kR++=q$=Ggy@jUgdeHVn zDW^t>kDqTV{4b0C`9k3CZq3Fp#Zc%-PCaN%Ypkc+rHqb4P8)UDT%JpO*O7~y5w#n% z;*f!XyB>0guEcC7?>9{q(tJ)QKF<^W(j~rnGH7aqfq}abG{R@$Ct6b5>c#1Bfi3Ke z>m{bFa_83%phG>4pc2=^Iq&-%#k;1j0^$TO980(EQtkMa3Y{5j1eMiNPCa|Hk1Jbl z2o^2UkcyPtY3P4;F|_I42&y-NJxh8guix-o^m%si;+Js&e_kgr?1UDijo-l`+4y(s zaYJrBefb9yCdF<{S$~c3i?&*_L_ zFXRwB?q<-av%BYf-4kbj7gW3N+wlqlhTMWUD3}cm>Zn;xpeneb| z`}}40T|W~4f)@KSFmShm!okAtX#DBGt&x0p*UmEixZEs(iRVTNw3*ZjT8Zi5+_>I{ zUofRFnKAX~V=EiWMVk5L&?MIeiVJH`nM!xoW=oUQLif4P?o3`ZvBsSn>V`JRXp&`~ z(v+G4yCuK*O_YM%BhGJK*bgo3+d-Mw!f%yo6O;F+V+Ypmkyi-_OqwxWX(gzU$H2hd z4k{--ocGUBSay0v!RZ}lz6ae|7Ozo!dlEF)&cMLk0UAvT@?7>$THf+j$ZnCNdQ#af z4_dNB{h&2YM*%n-9359JJ!TV=5>mQV-2X^P{dLhOXerkTvdY5G{LLYQOwo%w6ujs9 zmMBJMxOE9bmPc}Tfu?aioPSh_E)%o39DG6Xl2MseM9BQ6I_QX27pR{h<#g-Tg#@j= zZVUOvbNpwPaiw;e89=8HcvGSMx(Vq+K_`j!b8M z^3}4brzz#cq*YIy4PUx#lLK|17#O&FK;v^3etu1_?!P^FH6!la$A;iL1{)QB@PH;) zKng&y>f!8bY^8lef0OsU?K3q}PE3w}B>o9B{0dS4nlh4d%I{R07whL`l*skRWR196 z$)iOVptW8PsA_igG)gG!_W!_Zl*4kwVMq3~4~uf2fLi1X4BWkfU`O^RGFM45?K$Gx z`=fp7!GO%!wq78+85p?xK(vM5_lAD{$TTm zX1lJ(QgZOq+#dVdj=vC*ZxnrFL6gxp*lZo6J*;F z_XN=KNEUt@^yVI)ETi0|l~m1R*EZj#;?XW>dYAyJU_G2~vzBa`q~7-CK!aQAuQ+oa z)8a}{*M)(Bdm`uz1}Uezj*osk-r_M~%A#{mGUq4+?+TRJ198JdP#$&ljGZj$DrVNE z)v?%P^Vdt-I#1%lpasZ8$dtNfq2!C*$JWgCw%PIbm%z5tN4ndf6FrkaZm{rE$+Ywo zsW~)1uSs~}sS0y@mh*vm5Gy8wMwL9AC(mlRaR1A_;MG;)b1%=;oi;z%4BAu!mzPpb zoNS&hT{q6n=lJadao=!25JJRyo~kSDA=~#;`Nb^izjxc?`iP%a{iSFDnJ<+ zxF^TTtC&e2!gssxM_Fs6FY*+&cYosT)o@;mXV;|}TQi|aZYHP|Amud2c(b+Eozp+(f9~@L z+Aq`_{O~R`Ma=}QRSWW*Wmw9(IzVE>ywZPjlMkJ~ooqh`G!DhUzHck;DU$K=~P zg}sx))Vd|7T-`C*=`yH?#=yWm8#Fjz;TLigkXqg?k@XX!C|GlN_Klnax zfY$zVKs$S^J=X;}vv;4>`EZ~rD5Jh%ZCq3JCun1D4&*)*qg|^)mxcK~(hfeYI!8e- zL$}u#Iutw?v@6%buUu49m+3^TKU3tg!>Z}GPHo*-3mu@C3+kAAIP>lg;ZsWu4?wP=2ob{rr zgo$nA*M6b5f2}u_{D5Y?d63fr|8-6;{hI$NYnl}QUpw*iyk!bYKy6tD2JQu*`ohBR zxSCMd2a|@|yiCjQYs9Tsuie!FT|uz`bo7XaGvn8a?Q$VPcXk}i)L*vCx^44(@bD|h z1klM#QclYcIzIjv%%pRb?Q4bH=P5$st7k(yg9||I>R8YEJ=&_yn%c+CsVI2J)xAG( zkQtJo7`PWe4&rkvDve}*FCCy%Z))F|yPG}8V*_YW0s{m0BG6!wh2Nok0oU1gZZ$k< znJEi$Li?%E_laHzUHd z(nrUsddu>i-&;0Tyn*)I7lGQ}b%m2@U0m~uILN+5?$w|!jJ4;IOr7kaXYcv`oft+=A6s|C03Av zG;qfGTQL9nrR5y&FL}lNeUvmQcPGOJP+DYQ;9d`!rL^!%R+#p-bz8rVe>;z*i)85x z%X_<^UAgt3c`Xm;f{Cv@7Swv&c<1`z<$`HPF6rLf30n2Yz`(r$v@S@>>5IOIFuQYL z=x4@@r}Z+y=_zF#I``jK(@_)^z_Fy<+l>26*lsPPjUaeHVZoWxCJr>vR9So)nIO|@;1LG_J$%p$*E{JEHgeQ(=j?mene7doITNw$HS2_DYx zq$E`wLTB&?9N4aY`QPQvoXc|1LTnqT39s*2nOs-c`tiYeFKY(RDcAhBEpT%J^;8)c zxVPN{rzok~FRh-R=K5TGvUK0IzWlA}hjKx#XJFvo0Xl=h!f$EZ+um-&klTm+8SE_g ztmQ6Q!Vi)FDFD^L9?srXU-#+?s0G$5*qhHw<9}paWe2MDK?*>F>QYYU)+#e5lT>Q{n4C&jG=Z7*S9;NA(ja)t4* z*_}BolYhFsW>puscKG6IrZDKZ{Vq`2wD7CcjAHw|@0P-a>0)&!ir0P?xt9t$sgQwz zdlzVy(!=>tyQoA_)1z+w#p^jDIlOY`^Ynn)vLFSZAz>*eq42_cU#t$tU6q!wJhLdc z^RJvCXbPEufqOTo&+G1)yTm4ZzBNO%Yga|%^`%?Voy_Gx%jiK0AX_7^-L&woKiuei z+Ify^f_34ozx9`(ZJ0fvaas$%3fmPnD|tI^Nj#qGuAjpee&MGlC^a)MaPI*%**u)v zmk2NzXcRhcK7K-0M&#Z}!Jl8D)7g7LW5q$9Is5ClkJUV@sz0cCutmDiyO14GgTa0ZEtNiOXJL!-`smaogW4U?tP%8Hx_;y@9T!l(%QO}b&=Tf|MtoU zEv&deMl&#Q?*}zqJ)C`aHrJJ((Q&m@oqO;9m5H9e-P;a8(&T>7*qD@4)Sa;8drW-d z(Z(EicAMKD^u9e8v{?vb0w_Hwd)m5mi9Q!OboqK_-tx8wd`*vD&45m4@1F!tatlN! zO_`?nG_{YV=P{RQ?xL4po`9w$7#O$@fZ7ihev1@Mz4ocU^Ko-A+GcOf?Kzjf66AUY z2JVBP3f9B9rP44io-2j3bIPGJb{dZ__W$&8;i|Kw~VWeca1eV~yGkOEL=$iumn zKQ{Hv&s@f5X?#xWpKGM=r?8ygdw%0K5wSA4 z6QJbIz`%VJ)NHiyTj$V~Gu1>qdf63@Iq_4z6>j;P4o$R2K}&BuoZDaA_E)ypmAPx- z@hi_bGf#c_kPGUeflL6+Qc5`qPL^51Tk(Ud`Oof@A~pY|6I1W zouzj{>47CvpT2Oq@^isY$Tn5(V~{aY!7r=BI-QilIjnDO-nie=`BB|AXs`J=sD*Cf zx38~ntzgcyHNG~*4D73$nU+l10ZK^>4BW>dW286I9$nK`%RZLURX{%~K$g$~<38*Z;fDc$d@TvM-7W+Hr2GVe6nv(M~~b z`1Q#uG4t&#nXI~Z$J*@EcP7d?L62qTJ_Bm1Soj6Lv-7vi>^~OoaxQhpO}0l5PWwT< zc?MMKdpJ*@E;~i@5cBRfo_S*N3y!?FcjpvHCj$fb8PFPMDW{spt5%&dx%+}^_Nj+o zOAmTZowpm>eK-T^H3xalWInw|^{S1>iamKfVpo-&|Gg=_35kodEZ~s*!7_cB;Mx%O z&TQw0Ps?xreKG3-bd>cR=pq0Mzxtxdg4HbYuf|z1RWro+TVH{;`YFd6i zS>&bmJa@J^0ri{3ZDLDX4@6DF^~@T#8(G!kBlZ{bjNHOWJ*Q zK59&Q;{y%q%S*tH^uM&3dlg&d%yp0CX51Dl^i$fD2|9v@fr0x9s7q(zXZl9E>b}{% z4)ITXCeKBF6}SI%02RRu4BS^i^@fM@&Ru%GM~ZbOikxPSf2H)>@%HTtpvDbI0ciWO zl+({n6(OUi`}WT|?Ja#-anrU%kNu(Jv{ylen6;;ajz|5K-1*WH{l8|0*ezZkefkbG zvaVhNJCb8j>~cfv=$OKv1@CPezBn)469H;@Ffedm2aSAN_;vd(oAX>*Y1T4*k-4*e zG3@Bg-v^z~x(*u1^>8i=$)A-XcTfA(R<@nFA2WJ8<|V-tfJU|?ob)Hw`J63tF|%#- zEXfYwiZZ^w5i|}3vI10x$9tB4Wifemdy)LPONYd6DlaX4Re1?o?iD?CSD+>3^u^3F7T@}4N#AFsP)CAJJz|XXOH0$6#kD*)eoEezhwC}GW=?Gp z0(D&&7`ShP++gANuS!Q(Fu*s>(@I#yAUNl3NT&#NYr}0&i%4r# zG0PYGMg4Km=)MDLHcB})#%r+p{5-SOGvmDGg1N8%Eb#XQbsHEMxbJ`(eXgFTi|01% z^^ExuVe@V8Z?}fyZ&~I+JLY#F4UB^ig*H6g7-yQk^H!+2<&Mvn5`IHlL3crJu<-k_ zdBHO4*<1N~)~$Z!Gk+>)>GW)9m-Zeg`Fl8<-%ZH;a`48&6-Svm&-c9a)wgniuKK$N zX<)p1IcHwNkqdin_w!nCc5Js35<3T)J7Hkpz6VO(`kuQdKlv?d^JNiVtK{-qYYSKR zdBs9Ir1!RfqdOpNU$W001HnnzM+;7^JTap~;stb8?g6M$v+&bmyeO0FELEq+_lPs+ z-J)M@PD0Ry=np`>XAfsXSxMy}QHL$tXmONY*>4G`i%M$ZqO>}0cavr-;<$G-civ{Xd+LTfnmt%gPt8f z1Rb}31e&H%_FSA%v~m8*3Dec|CwMNNV0iY{-wx<3%p=I@F3;^;nabC0x-(UVp_Z*# zohPPx545ND1Qbvfeli6MCd?0t+p*$;d#ahQiG#()L{I~Zfr0x8sD$xw?&>?z>Z!fc zMbEP%uzP=W(%V)>XvTR0YJo^Ox%cciA#tQm%D~om_0)=JA$QR?&{X{d)J)L#ypzrB zV3~H;Ol>otbMBv~+rDW&fmVx8A=?rq7ucuM{|pa25{_cKsH zS@=07d|9jCQ1>LJR#1!*Bxit?zpnP(?bKA zH=lu8AW}|OSHHEo(-+L~_`IE-M#{~Q=}O(8Wep4r+|NPdlggfnyK~EaD5f`5`KX0H z;yP8xvQGrs-+ZnDPLsw5D`Y%aME`HRtRF z+l4>wU-0GjE5q-Fpk>nx4BRh3L!lnd@5Np^Ib218hH#1+^;|-t%cu-h6TEln=Z>7NQ@6; zT~wMJ^8P1uK>HP_81!)7yJo}XX{WR^pMBf8%#Yj6CU*8OXvTRB3J)o#3sqm&&&aqt z&+GfM31W8&9R!vrLKj%R2DM?VJ)b^NDEOM5{Nv!Yr+ER*%ePPSt^^I>GB9wzo&gTY zj^ojZO0M@7_RdQ6EtU5FoBl=;S}nc-?MAimTbJUS|5;}7```EUJ_-C=U1o3l4jNEz zL2I=7u8{M(PKA?q-E z04Sj_FmS&Gl@rRIOy_ED9WO8MRCc;8`eRY4eba0w(3(Y%f^}d=I;HK`(0ck&*Y4oP zt>n5^tdUSU-t@9r^CW`kE;_E-3%1jCkH&tN-cRG$v>X^En?JlEqs6949xs z?>Rc-@RAMr1z}n{)Imv&fr0xos3`Vu{%YatWIk_t9napG-^@C4mab<2kG6vpfL8xW zIaOHwcv-VY?Lf?dJ&ejX9#^kA+YVh(^93|@=IXg^hW_kjpZ!)HH(B7gbV=K{t9c2~ zZuJ+)p~@}n8_Ju?`>!~xe&-mR(&X{HLmJvl`U-M`h2OQQ;(iUYmdt(-!nNDr%!L^* z3Ob=}n6IFs$irF7VTNIYc&EIOMnLR#g()Vh9a|+K(ftjS1+6_*L*Bot5ti)GcZ=Ed zFyzfrsl_6oNMc~%{sy_$;gtG!)^o47di>rtx2BxkE`$Bhe`tU6J7_r8!tdCOsXcq# zdon)0S@$yW!M87W&!&RP1qKH0@1W5X59j*sbe@!Hwo?Bk=Jy^s{Oz00>tfLGD+2@f z576+Nl+%XOtbP0yU*~B*%qo;y5|Ey1&I*zMDFBUNSbO>!cjdhj7hD#^p|s&)tI6HB zO?l8%{bK?+Hut}B3;Ef8M6pxJSRadQIH9sJgV_w+rG6Y{zLfR?>j_(d*UaEEodKCeZ}dtJHWm8pk);z4PV zfr0xEDCv1P+e+DTzjnH#A)j^s@Spz=yBKpDpi`)SKm~}Kr%L9L%bm|TvyE~O@D*_h z%)hc=6==Z_$OOpZMyH<}D)S!fxYEpPf9$T(p@jw0Km!vD3=G`=K%+_)ewj9^x7a^5 z^BybDXL=BRMpw5y1G+u)A7}{B!`bNh1o`5wH68{~tI)%l!`>&K?}J$TeBJ-nQTrsToc>vXyvM-6!vIPv*zZ~KU{2MgriC zQ#Ex+tC)wm1MJ8u)|hGQa$MdhPEgo#FVg2u$FG-=2~Zvu&{>!kek$y;QXQvU*Y!CV zly~q=pR&xj6EfP&!wM<}Je&{hv}(AmxaZkr{)p!FYrmg(xn(6JZ}PB$=2+c4Z|d>0 z>T~bvf7#67PS7JIZg_n0R)o*yTwqDksnKh^cm_-1U33W3Qm9>dGw)tzth_c`^xi08P(;hk|I_-1=-EOz{3g3{uX{u1my3@ zNmec5h~cVoR0!d0y~hs8-8`J2SoLteSm1w6ZN0v(En~qwr%l&|8La|9=>TK`s9JRQ zT=rUlXI0zeTgh807$p8HePjQ17qV%HhZAyXtp4t4dxLl9PxUdEU_ZT1ZLD!wuR9?%^z}SuQ*0%|Ver44YyE z&ra0}Z3TD8K_);hjjhVFopsOV!)Mkh+ikwTy79^Jsy?V(04V^CIxBldhfY0Yzg)@R zzxdO+q&!`NzhZ|$9S@L#f8c<+Ft^v_!UJ_zvswRbKE60sJ|*NXC@nHD@bH3~jTU|~ zB@>=Cp5)@ceYZz!O84h=$GWRQV?ZDUprf)u=ZRH5=1(hm$al<~A@jBA>O1DPpph() zg6rUQ#gZBBiP_c>-%KymGyKZ={yq8ubafLCFQ}nq?YTa@@kp}kvhxQ|wyRhA_XBJMe8 zER2DH2YP0aQdQ{*S(frQnty-=dKR8E)c%o>^3Ds4rfdvE9;TH_zb%50#iZ ze$N2~F~|haL~xnsoT(ccs#=fQNzAOT+;Jy_k2xgM9a2UKL8AM&X@TXw;Glhr7O;!i z9w=tlZ@SwDQ6K_|?v-V&k*eh?0V@~XD>{;WbmQ6k?vT*~9uY`%v*$%w88P>AFS`EX z*U@iFRc2*82aSy~Fz|?g+#>1pt8<3bLbE^TtKxJ-YZMG7KUWKcmM|iqAuoMTk>0Ca z8QU&zTAtasv6fj9CAl+?x8i`JXJLxE?j+VZSUNjGuj^-Li!gx5}=-nh2IkU3u#hD zcFD#6|MlK`r`OkTs2S3x5^H~w(c-mQFdZK$a^3YKnX|6sdJ76)AKOT z^vaDpmL)sSefjp|UeGEQkOI&|hr4HSFuU^Y3aba(OTK>Im*VaIrM3Yw1j-}*9_&ai z^VN|T{(Nfwf9%_dwFfMk?mTh@Z6;)3;E@GY(H4H{9kN?K7$iAM$7ISTbIzM%5E2Ml za{y8RsxLg8Pv^&nE%TqMyzfh>8vo3;l~Gsnps^_nI`3b~X|nOZF1NPRPh`6O>P+DY z*)pZrAJX6Ckp<1`xqE(olt1^-6+eUNZFgtPBi1a*!jcOm;a_=(phC-h8?Ta<08!+w(Cs)h8u6`(xHz`!HFi-Cc` z!&$PdnPZ~nziO+KhFhbJBg*azDS}3s85npJK)GDX>7YjmOT?ptLf_K(v%??Xe%`0K z8`9|IQ2-4RlzH|fxXHL|Gr89;)D_OZQGMaOzR#c*ImiUasM^lZO>FO$rKg#zo%_*Z zAae2Ph0~C}9*-iZiDKdR;_0_lIlhKL&)auB#NkBs9{T&WCure@X$YN9bP@Th^N?esnM_9R>on|rO-O#bNXLdAOa zsM)ii3e+LD1a=7MD@vuzs61kr+v%95cQSa+NoX;s0V;|t{3blGDq5uKbk}J`yi=6Y zyi(4~3n9Hl9u1IVJ)8s1%6!|Dyr_gFv(rL9`+ z#u<0tztVduM)UO+Q0s?*fkzXx2E*O+zuVjn1=}adxjJTln@m1$^D{pH8ixWYfOIEk zd=4w(bX~`rby(?&iMr=)?GOXd01X2Jj}|ELTKI*EnjAl-A9DKqCew$^3PyiRJV2dc z29N?scTypD>8Ec;W4Aj6YwvR74B{*_w+AhpVqoCW2K5?aJ)cd!nacX@P{I#p5t-(9 z2j+U7KLOeK$fFGz>QVl^kYDEDw_iyM7MXwNdS>c2VKuZ>tOII+SorDsFESUq`g2C| zcZof0`{$f%%kYLKdtJy-&u3#XzHEhE<{7ywX77t%UDQ=;3ptpPM;A2IBk6RQKWLB1 zn%L=Q<#$}YSMxKgdF^Uw+g=y6q(9bkQMAo1d7&S>k}8@!MK0H@pIa^g?V;#C2N#2f z<~+5WWvWrY^=@*9VWndP5U(ZSEto_E4KC!3xcer_~D~tMR$OH$E zJ}7^9I8U~Z3_m0rSROKaY4eIdhF?z|;DZLWKB%mca>`f}eoOb%O3n>a3g=twFa4Jr zp$O_ifq};uvII-v+Ad~>D{Jfuh4(Gn$o1!E^ZebA9xIPAs72=CEdSm9?n%F&*#hP5 zo4TW7CQI9tfs#7|1CI%){*-dc+RNvdES=8%_~-BS2O@MmJD>P~&gcOt0CgXfJzK5C z&uyx;`yO3&Q>#nvpEQGj4`@RpNC9LWNcTUrY_=_io0llueiHWHY8Bh-AD{*n0|SpK zXeEV(pGM*l^(n`Ee!VRzvhA6?gL$4u8fYUQ0|O8A%%TTpstaH4Pud>QF@J^Ca^v8l z?{guOEIiONi@x`*4CY)J*c-Mvs_DZi^#GEbZZ`=H6*f)_k!#JF4)ItC%0S!p7N8+7H&31XozhPtW2(F@In};uhdnU59|F4R8Dzp+ zaK_>En7$#%to)$$rs{cqmx2}Nz0i$#BZUXdiK_RZmB1BWrR zzOVwVSod&VnRadp`*ADVn3JMM-#gvP{;6>Zlr^v;uXx33B4}WOfq};cG*x2ZSCD%8 z(Fd39t|8O%W;^CdJ}AhT0xE(*3P39mJ)BEUUpgdu=%9^vqQKgfxi31UO=F=M#|GqG zNvG)UU#Asvudw!CY+A5vhSr}QNeqygVjdgN0W$HP`S<>nD8#&Vp1MDWbH$^IKdFeZ^x7kt%kTg-;61L3g)t>v`vGk>9}mU$xKw%^Ok zQM&XBDQtT(DHnyze@ zo|xccXs5%ey{=*vv>0>-Rj?k;_a}?W$~(L;nfGV)Nw4pnBJ=ehfpRqi1CKLkk%pAh zWPXk-x6Vy%ty#RScAHDWnF|f!kU>-)XVBILYtL!Fo^#HRGT+K78yy}VcwDVJyBeD0 zT-d<@C1o*rrFSO7G>rg-+T#5mavNSJd<+k>bhgxlR9?LJ6KApNb>*qFTY`TI95-F#|Q2q~sH^2VB;q}iT zZrwcru2*fK(RKy~9#>GkVD0HO@9e{0?^c*q)*R&WSAKqE|IXu(O~*WLreH^2?76gz zW1=C)#)R0QmvI`mj6x$p<1Y*hJno?Cz{2mU{GRB$3$?0Nb7}_c@BYQUd!_@lRqPJR zdLGW*Tk9Xr{8bp;s(A3f;N>>GHpvXobUp(Ej|U(4PS_HrsPao+D*xzTk(a7Jc->80^XGF9Slo6Q z2)&V5mXona0AE;XNaCUfb zu4_-4){Se+w|>01;L-HW%$cAr9LNMvyHe6=vJh{Vtny>4sJr^fZ)Z=hG+3(u>Y;%Y zfFdj2bKROpyU$Iuyn7@f;*bA~quf6qD1$~W7#Mi`A(wP~3r&4{eZjQfi=%kX=4n-{ zZM1&^jm-ei455WzwnB5{`ho-@xr|@dVorDeA4#49T2aKnz!Lx((DrZ+K57%Ioy@~K zQ7L8jy!$=hKCE8^%26N%p!6W=#F(?tM|F;0lg+OEVs)=Cxr9D0fR@#Ppn-jT&rMAC zW2gT(#%5_*Jaf+ROvYtAGa-9vc>*Cfc;@-V{rGwM-o&|!ueIu%INn_Oivv1}5(Fxe zE&M72=51%5_u$RtrBBO$RhD(?P0)bW{z0HFjED2ghZ|qB&l8XN7H+q#>t*RanfNxy z22Y+~&}6KX(`S1P{%uoAHcxAK_3iKB^{&jbw?e}q7!)UNo*93Be@YLJJACQlRrcBI zZo16A zZCILmz-G?+tU74T8wy(X;^DkA_Qsb;{Q#94j7#|T7DoFd-L-<2w4tC=3#6Pp&+f?R zxEkd2G(DxA$+#=?{k=9&Br!1Xgo4&$SbN?H^E5Czy?oNI#j=(wPE05~`jj0s!2?pT z5S(#@7EQ}7l6uSMFe%LH^6$vqQ(DSEO%nzNo-j}uW#M;Q_k-r$J%3r1dR6m;KCR1Xe6>7sy7bJxW z0do`UPlkOk5QD~MG^jge;dgRIK<46yeocz!dqM^3d4jIr-2*M}!e>AM z#K6E43knAdzn-P5Y>x<)-8vo`bY?e`$Go4@w?i9yaiAu=hqF!Qk!@m*3f&xc=B(V# zeSgc9=HDrhR2>J33n{0Kep92{ZSTcC`uJz+UfubQFW7jXX)+GfwRQ8HoqeZa=fdzu zPDuvl+&x#OexA4i)W2e2;E6j7b|ll^U#l;1clI!53mIAcf2GZMV>e_II!^+qnPA~J zwdeGTJtbitu_=2LYQDeo&?w9X_3;=OcoIPMg@^O~k5w~kI2u{?O8lf6^UgjuR*-;> z1toyml~PVWKEE+B{C_|9(z&vrB|HyqSSwtI=8FVSTh7|^3Hz;268;G*dtN;^I{3oU zOe~QN+8RuNoD8q*%XnX6jl9IQ!=G4_=X4jysqKc2!z6)*A1(Z5$<7gK;kqg9`rEU8 zL!I>h2~z?f3ubtdKto<0&J*h5ReN)P-kPeH7`tuX{Qlcl+#%c0c#=S4gvy@Z`nWGl zeR^@WKWAop{@p4YiI&OWIU)w0BuLYJBhz8|*(vWH{jHIaH{SR;_fGcA8<4n2fi&HH zUwXW{VSleU<(Ku5W~~M4=F@I~`V|ZeJSmW-yLIOMsnWJS5{FM`h)(~#bN7ngN>BiS z6oA?fl1?k5{=WV4w%WEwZL#qD8&el{3rfSR0FA@AdK%VFdBV4$_sD^)`B(YpuAR|! z_&am}GZnJrX73w`R_4m6v$9N~&RS-!GwL3xfEJiCFz}>-(u0K`=ajaY4`UjRt$(gE z@qb|3Bi^_K&?;Dv0?_IO59i*uOIHZiw9EAGY!fuU8*tlgyJ!Z)n`xlDDdp5t))d^d z`sP3F%$}PIU)iKjHhn*kb!u<+yiQ~tOskgeoK*1>ht5A{AR)GY-S!3+#M z8K82~!`VXeY3}4_p4O)WZ|$4Rf zjL_YXosB%1Ace}FS{>6a2rO7MA#!z;WnK3I(K1h2=+IwgJ=l?!o01P)W&3M-jfwGy zSKrxZr^NY0Zu$?+{@I{?YEn*0%inChuhhLyjIsQ}0UMjhyWOXub$2!>6T5n{ z{ae3&>51rVP36rW;+S1mUp~3S6cQKN+rf_H-6<&*P&)mvPNevy5a&M|eacfoBYF%B zJh>n@Sorx%_Z5b%H_TSoi&r&%%9V6ZEd$!%%ms~CdpM_+8O{kZsTAXq43f}!_~V@B zmTpid5M%;q+*-`cs9 zpvk@nGW;lIP}G^gwn5i=!QbwC9>s^}D=h_WXk=jEDFPMdv7UTJ#=ML-r5S(a>|6Rm zGw0)NhGLir72w#c?t8DZ_qjZuxB7>$$!!zTELeM>9nxaZ`eF+|wP#xk?3ZuozGd#m z`e*T%VA(?<&~PXLE!y#LUh`|NuEB(hImzq3{nPfJEGqaq8q^|ZVBjeMl@n4D1cw2 z1loQm1GPjvoOjlBiQAn>F1K7`b?esjHF7nAGSJD#GEm!A%E{%@^YV9Pf2T-2Ibo>e*9zJ`loBZDffWopO+6NcJX#5564#nj-=_Bwhhp!zksnA#+Q3+bk>npEn&%UoKy>BBc8jw7*#a z+GDQo*`X8@<;k_Q)74Ys75AIR+iQDwLJN?JZ(v8-ir1`9O1(SJAXMU2_@z@;8ZL`K zIf{XSrwX)R&BAZSmM4omj_1$M^U&^ov$yNOt|$SqP%JJU7J9rdz5dw%Z4`9U+7xgrGifT{tI37{I--P1@(Vo9W| z?Y0N(NgR$h%^TC!D}Z`v3=BNg24F|>+jM`g>Qd8hPf6Ik(!Z|3MMV?Z0;vHNBo=-K zuVn}t?sJ49ZNeiVn{gM4u^OkR!J1M3a+Q_K| zr7S6@wN}2W<#KsBli%`fnIGD4GWql!=;DN0&_qwL=f?-{7TwN}F;H`=VtOyLZPw*| z&!8(7EPDkQ*%g7QeXLAKV+7b&^%z#wplY@=$RSsDZ`6 zz|#oo40$*&d(bqaE2=GGV%ps)^2@ePP<<*1El3+d=|RdV=tSZ5yuw0#5xX5*g3ku5 zwVfIOie``rpdPEW=Z0@V4cRA`@Rk+dSzBZ}{n+JSF3`!xM#%EWC6+2e4Gbx#0HgAP#uuFdLD_+Zta*0=nGe4OjR}GjfFdi< zQ$;1+{e@*DL!@KD>Ld1^UHt1BK#e>G2A&oLaGF$}Ig>B4{LqtD&6e2$c2_=muP6oO zY6b?LR?u1$3%^rSC;gcG`xguI{h|xfQH#tpoz+3pR3HVQNjDGY-B#yC=5Cpszw1<{ zRpQm`7n4|TLhH>|kU}XZ|LNOZcbXhuedE^GRY?mZg;k>BKy&R33_NY19;=(@PuGW2 znrHECUHN31^tRUS69VBT7jjCDr zJz+nvJFWl7t4r@w8sB{X@mO%hG-yk#9n|OZaL%3dH1Jf?x%SzSch+fEvCVttSO6M^ zW?@d}7D(*MiI5MXEX4f|d(|W}`YP!EV^$QST}BBEZ{XrBv_7 z+GwGr&srb{(D8I$0uPCM9;|p8Hkmcr@#nO~yDvuGe6z>}s-O!rVB_H&&2v;xaIX%uc&@HV}{pG&&hrI`ajmrfG$Pr0(H>KJT+qY zU;8JYkt>P0f2ieACjW%H`=B|i3v#%$#O;g0Lhn^2Ub$EPuV-Dids)E?$ihON9?+DT zh2JclWzY5-H%m&|t34}-nmQr%+-Xp9XJFvz0Sy*;I5)j~bz;xPscAPA{N{4a+%_%N zWhZnQSPy90PRi-{Ln+o{v4hvG%x3E zy}agkmy?2f??O8uz3SkQY;JiVdnvu*$pz+TAzdAr^=AS$Koe~rXiUh$&sNu%yLsQk zYf_Ki{Nr8J>2u@$VrYWt0}beUIJ2|Ay>sz^{*raCLW8UW%0e_w>O&U}fu~ZWoHPzh ze6V}Xj<kGOPumxKD53=BN|QVa|X`kwz?)^4y)TX5n^?;JggB{Pp54)BH6 z7yX`KM=mvMlYD&O^2s8P_gO(_f^RR`G7psP85npbfLbCJes4C+KF>K<_V6ixt@pwY zZ!XZ)z6$M_PXLVxc{mG{=ZNf&i8`TtbN1YiQTHX;;?tpHK@&l>pOh2#w^R4Cd0(Dc zY&$JVsZsB4g8&04H8U{qOayh%-8>IGx%_e3#=26j{;GEkpTiC&E|7#yfKF@zJ97Tq z!y>cTp3SgL-<5bK`efTVNhPI<7gU+Ima@uiVY4pK2pN}cd*z5QF^DkF* z$@@?%CWA&9tvwyK7*6MFE77(4^hTtM=1Nd&n1O+3@&>RY)z`g!bS_v~apmP; ztyAkZ@RZETg6yT`nF^}2Ec^@|Qh(lhWxtZ4oLRGD6UWVu3woec(o|5&@^HShti^|O z&cjoCGbTLxYRH(jQQQEO4j34Crh@8CDW_9Ug_$=P{obsy;(?p0MqmBHu+5+`Vvqt* zGr`SMQNrZhs%>Uc0bEaNBf7=Uvgns*>PxUA7sa^LXp7$WV0rAH(!Z{K)pGqD zPyjJ7@Jt7_0xbM^f9`tOytX{2EbiTcH%xbQ>&{LBwIe|aK!Zgd&ZfR!g$gpB)TCuq zy?a>kNG{JFHcLAl)De?%y8q)$uKKd|r`B(n{`Zvp7qi2A!a*SjG69r{l|6$!+>c-5 z;0iUen5um0W%#bI7ZyTO^>oN#9f=zXy%oLQt4g|iM>VNd!JOQl^ z!2NG2r!}<_5ua|Y4G4Udx9aD7!&e&}>Oq|!kO`nsr9e-CqY?iYXDVAsZa$|q(feX; zl*AoqYj76iEYMe9;(Ai;4Z<UfTIzSq8dpaP}NwFNHg#oxH|ewb{37JUAwH#>APJCyPH=SR z*sgezbYdDOch9GNuW!|v-nwZ6UHv#0WR-!OTI^M77bzI5!* z`6lZpTP;Dknt_350jSQh@atmN-~RoanV4S8)l*CUEp>U_%n#Xx%Ci768}(4+h{u=J zts!eg-haN9`)~8Km=~bAG>{3Pl19==&ibah;qK$#cUfszA7WtSo3J(-G{gf^02*!9 z_xyjNMCV2D6}`(lgc3|nMQB?8y#|^}2Pyak4#^|u=kWd#UX$9KbK(!{$Hm`Nr*}bT zqZWbA;;`_0?sGx+=;uW)YyN%S7r=F2BE)$jG|?^sEm`$&W?T7d)q{i$@6}K3JN7)L zJpTKlgb+Q?Y~s@yF6+{Ip& zv#?$&pBo_mwD6h9MAKhuK#SNI7d7)s!`nTtt>QgXl>4$$^$cSNRKapksqf*uT>fUmL(>)qj?U*R z>UIR&{FdPl8jfdR;8`93UU18`cZ22jr_v%01=Bup{!s9k7;pFsl4zHM(u2O|+ewkP zwT=n=Y4m$*-eo)aamYedEvSN-U`L+zJ8{m2ZD{P%#45qOz*XH`b z2`b${3P9s9Qcm|fY{SjDUaZ*eP{jXhKG(5zTu(ve0!Tp*1L*pjG_Cj3d-#7S7)LT# zwi!7dE~{&Xu3lJq8SKczk6q-vp0K{uOIX>hbR{-8**ptc+OGx;mRR_m|G)6l?2R2K zUo1Rwbm61Ta_6NNK|95(LH#Wc=gAMIKbAanTlnpVeAgrQzkGMJ1YZ!sz`(N_v<5-a z>8OUJ`%RJf$gh99#D4e5Xz6f2g*LobgG#%2&$q!-Zma2Cay;l0ClJ+jSe?UsIkX+M z1~Pcqz2Osggjk;I$HsXX2iL4=c9awYt+Quf;8_dmHCp%;gc&~D$?s5I_&on+!g-;c zCAXGAmmaMJwe3BeueG%q)>|$JFhb~^9nye!Sog!Hm1P;kVo+k_i zZxwHBSGX4R^@TzEwYQ9*78nBq&w9{YtA(G8(n1N>m~N53C9B^%?U3}_uxA;xr?wt6 z>h9s3vLWrb^3q0b*Ml20R_;)8t3Bli8cb(k;MoA``${?WHzZ$mip>6+zD1TLOp<)9I*zG9{IRjXFeFf>TP zB(NLYZ-*GX@z&;Q)W4stZF0>lOzbl>95zE1SiUcQzQkpb$)z}{c^^5dG`~#Q91R)^ zV_@Lf0_t~rI2TGsbnRtc{z%}qCC}`Zt9Lz?Cqq}%Yyk}xNjbg0#_V@l*{3)(z*E=6 zUw!3fpKOr#Kqi1z)&zN0J=34^fW7(SwWUXPJ}s7YUH{zy+P~Ox9qh;==8%u9KVHA} z-`?{l+C}1M-m+3?bZ-My3l@Ij-C~!VH_KSx%sQYe{q{~{qTzq&IPEsju(XHsa%*;x z#P0g^0$F~$n~OHc^}V_d$}kKJJljBNQ_87iAD7aBmwF7-jOEOa25GoSyx|2+0D}}j zM*a_*F}S|5I?VSnK|b;F=ZY5Vo^7BpVvqvJ$iItW#b?{+_N(>woH+XJl3H$Z=q;!> zcYuQ2!Y@HD=Ac^QvgNr~_cSI8C&}bV8bBvNcYq3Y59iaubHk#4?ksxmXfkuY!6v>V zTA%zNh1d?z$iI}+E%tSL-X}`wB;D%Bl`B%WixHX$YLPQA@azCJ6ZAb#{#o_fWc%%^ z6~z@CuU+Q+JOAhysO!SOz_XJd9FiVO<|W2FYfsLLT^pY6P-r}(>NC`eU7&!n@XK;> zJ1O^=>G7Q8C_U+ADl27=ZiVK}U7#J19?nPiEjV&F;oPRZUt+J`napxY^!0Sm^b7+7 z&n{54Amya4*cW47)j7}Y+J)o(>+bQ)R8%|x@x^Y?s$hN3^3t`T_I||-VhSe(I$|aY zI(!KO)piUFJi86SjxK-9m9Lluo*OZ!oa|@7t~{w za_aJSlX%3xs)K#@j~CWI@4w92c?g>1_JR_xo99lqA73YbuZRgVTDar7ypH{H+qt0n z5@Z5oN3hneviP61_5YGgiWc{8oX=UzHyyIKnr9zqsKdf<>9IZh+jYg4e0yPOlxFdG zqSEn?ApbKk@a+2y&b(8m@CAFlz5MOw?($yJs8U_ZQ{h%(Lq|?7Z&mF0Y zw@m)%5P4hPo~ztR+y`0&?FS`2YtK#1nu;A8+LWIi&}h3hy&_Ly^L;Z&Q16G_R`BOS z*WKf3IuDPsZ93`s_Z0t>sZF49Y6b?L1E40Gh2NIvX|_ksr<@B&3sgG%Pj+s6Q-wOj zgoB`}$-{ZCL6zNM&4*k%|ND28G&I>R6!`%Shl8L~uq2$;*!yo~QckJcb!7dS(pV#% z_G^WpStteuo`W3>3=Hv}t&$~6t?OsE=`810R{V13ZQ`*x@1a&emWf`--|btHy#Jw6 z$2HmX1FO73>m;Fx_AqD)(ZX+U+$A5^^ws-HeFVPGG(2f0=kOaetiZs)a~QHrRDIQ> zpQ7BGLo{5awrW2)nY&HsG-%Z$NWlRH1_mjo*-s}3_SHC=@_s70_vt%(YMz%ms1OG! z0A-+9&s8b!XItlfWnS=Jcx~+GnP0z`E(CQv7#Mhtn1j<~XW$z1Hw&jOe6ufh!`AnQ z3|AM3g4)vz3_M3c9S{q@j2)Le58UhCVR~-f-UEJ;KF{C11FcB{DF7vZ59hM;PZ?Rx zZ7xZ6Hd(d&2!r#t(`BIIkAZ>b7^ov6<)nX`a~r?9s%`>@gY*LC=9$+Fj)HmxAO)aw z;qKYiFZGz`k>}g|mQOFTTW{*M9-0h_1CWA3up?#6KFg;tJooH%%4ZAdU)k65ULRD5 zGcfQR2Nhx#etUaOjQ`Vln=RXIfwU_s}YMr_mS9f^*)x2q_Xf9eDPhYxMDH8VC0)@Ir?dPJyNfq@1=@_=gu~PCFg#8Qm(xrWs^nd=k`^ z1(^U!5AL3EJKLrC%S;T`3YUHhbuX2BG~E)^AqOeg4|e3spFB%mT(iqfdEs|WMSPaz zwRh0N0C}K?8vSgslS$5czpg1a?CAN~duBOk?u9lup@$l+vs-xf$0eQ9Qr>QEcc1da z%wsYEHMkiVc%X+GEeTj^u(xq)!UIQTh2P0XclZUZg-)`74>i*FoD=w~y8gok?Tm)F zl4SW)MNcv~pmq0|hhRtgCDb37ar}Bp#uc+8Mo(XV{{6oNI$M1X6loTIrC%bVg=Vg9 zYd$9>>HFpU!=7`spvDaY1J5~7i`2uJea5rv4%1ikeLY|KcvGh{+mzJb(A<3v)G?KE zI`w1k$x!15$JVtaH#6j&%Fq)~0xkCenE>jsx_e%TGMVk2lfBz^znPmt?7}qhb|Fw( zmVtriyfoO6(}KJ#3Jfh%zkRT??k}C|T7kX!2`? zc*}>QFGF`hyOS3{Em99>-e2X`mh68Fv!le`ma%nDtvoXU8V(mgC5^u4kNcq^+dDu1 zI(PZzJ|WSAyxEx%pt)5B2A+$`U^jIB+dRd|{^Etwny=PQX1P)yjBP-b83O~)B~W|H z!f#7K%IC>-Uvze!SoLvUpU}1*bvI~PeF=2hjfeAr1CQ-eP74;D%l&fCKi8fs#Aq*c zdBY`8w^GXK-LfQ>ZDQNbpIasMj;~YoR`8l%(8;FDphO$!>3m&#e#4`yhK%3MkB1!I z=Hi#zunbblT}}r(vO($5cW#H!8JcXKk9ihOFP>gj3+?k>0R@nnudXa=PIb24E8ki zSt|EHbW7a1&{Vq{)w5Hd_|-tmhpUspZg`yHb=2bPA9t0onGV}J4rnx&*h0sGu7MhT z7JkwxS*aJ()TQDooqIo6A2Vu7d`0rJT;}<(p``HpI(8AgJ&dXV1^*9T%ZR@paJJ-XPC2JQj`r4hi4BxJ%b5 zPVlkq|M&vXs%Vf2kli%T9e&PsbuqNOU0D|(P_jhGS2-WD5uWEJXj#35U*gQKGnx`p z6F+|6*E2crcjG}1J5cGyz`%18G|A%O9AzqfJSQO~{<_!Ehg-AlCvYb4fQI})3P1z< zQcld%68l;wN7nA&9o6mIogQ`mH4CUZ1StR|J!{YGyFcZaI@7#w?UIF7JggTZD@?Jxp2)PFV-<{ zach0&As@&=89cW^a|j;JHY%UOe?Rn&5Ru~Ae*3D2k8GH{4kW?c2GyTZPHhtv+e531 zuRa$3Tkje9gX2r#i63!VytHpbea}R=^J$kZr0m~C( z(PsoB zu(U4l$lDK^M+}6o6V}QcmX%swB?18Re|N?)^8f?Cs)i?IutQ45R=wSfuZ% z$enRHPUl_5^p@-yb3U!8S zx9~HN_jaFQ>#^&DuxyIzqW^cUuY3pH=l%pVnCjuIk+AlvR>iB%sG@jc_|Go8t zrpYIuvP#NH&$nsjU3Ld!y*0CRPPU%6Y0}dK#Q_5Y&lAv~QM{+sl2xJYwym?<)jitp zD6WY1nd1jtS@bjn?8qNazy1+ce3gBb@!Qd94%1~;pPK>dB{DGZJOfQ3TKEODW%Rk3SdeYeQQY<3VxXPxlm z<9~=1&&$A$v{f`WV9&W9Yp}k-F16zPT*i{$(2Vl}H2G-Z7g18T`mmd$%$;P@Ejz^~ z`1PMZ&<8Q$C8(d_;XJ|X?)&53&##4P2~{N=+=-={gH8 z9~Voy4z07^f_f?zeh(h#gt+IZy-!#gR~WchVYPX|Qc#V{z`*ksw4=wv*>`3i*Ho|S zowZi`Qupu8J0bsj9cYmXNCBwdDdqIWE$D_Lqw|R?D?R!YYJxb=Y`X`Y=y?koz_a$8 zw;A! z?7asK5?J{4&0at6#e~`h;j*1`A6#Roc?JfakD%_9hcjoK?IN}0#pyq*jBUhMt8Y|2RSpg6 zPoTc9lvB4sqWL5Lt(`}I8S}O$ym^_O{A z)8;)>+-!USIz90PGW&4GJ-kVkPxAYn!|Nw(IDJlJt)D5h=KTVheR#Km?^{ObPS@PU zSMThXIeuG&Q61FiXJFv@0&48(dnO4!Ik0sV+>@CCZC@XKm&NJgxm zcCzSIfjDpb`l#shcaLl{3j{SZ85nrJf!26i_`No8;rOM!QG2zowQWk<(f@z_44{qP zZ=fM@59hKAR<-x$3;laNH+)0q%(tm8rtyIq+#nM`BRWz}jl%EWOIF)}GqixQ(|Y?lfmJu$tJ|cT7M?$Q#r=0x5t@k*L|#cS>#UXZ&6y zaiTdipzyqyjR_>l{eVo7tT8ONSmC_8u5^NXy4do`b3RX)1#OA_01b(II4`}sXGbp6 zwpFi$y;PjM-+e23^&2$W&cML)15`ChIXS&*>%Qah_>fa+(;Le@*V0dKiG|J-{{RKK zwWs{U2eVvsT5HsvZP#pNaOg~m5ro#8KOq}-ST}N{PD%S0eBytr?d9uShu%%v4hkR! z2A*FD;E{j3iiZ3aGvCNpC6B)u$4nB2N6ol!E2 zdnXdH>Boob&TGjwchBd(;u1dExGrPLR*9XL2)7F)DiM}`3$!8 zD-yQ^SNE6aTv~3K0-c5V51Qw7_k5Vac|M<{zbJZKiT9D1z?j`F{}XNP!;L zy5GAl=lINZ_pXZ1<9Jq32bu5YWdvnj3%?2Niy~caG+yIswDMpQnH9CjI0lqy85npO zK?61(&dkmg|Gs_G%s+l5$-?9P-dkElpCL2Fyo{igR#HwSJ!d|?37l~IhW6p(CRGlu z*XuhVJ$GJ4P*2U>Q;N;#`)m6rS#|-ZDvoEq`*Qn|5M)T4ml1M5PWj|ZUoLL=JGb8H z>ZT{&)&fhG>;@$i1_oZ{5OA8bGI-Cu^tGal=Ix*HwH&Pb&I&g|3J_jqP%igyR!#h+ z8n!~~z@wj6-M-lVfB5s|T*&YOFEgkWAmtPj();`IQG4U++NHNny!`xYsmggs_UB~= z#j3t1uj7he36FN1J{NFGXB}^T#iSnaf%KnQxk9?*N}t`GrMhYRCrp1D07^*=47_ZhCGGK^ zimzMBu9WR9sMoGuuE|@un_ndhG9Jat2Du;Sp5E8eS*1@d%;Lr zu;_=@+!mEbUTz;iL%<*fo53O3yKF|unVO$Q@_tJ1(-~^IwS4kHH4Os;FBhmKV&S)= z^Y6E}62Buho_x)_>1mkZs{IMjaNq(RUFPAOdp`Lhr%iK#w@9_%8TK;^pB+^IEqel) z07?&1PP!kLr#!me>iW9es7|V6!|yt|3{W=`qyW^#*Z2HAf9{K~wzH4VTgB=1Mj_Wq zY)LU>{DGJ2D%g>=m&>YFb6!4K>1O)PKXQMf$;Bwh)FCeq=)@fhzlvjBwb9*w@>b4P ztFtiJt?VQ7WZfVy4=7~?d#-=$QMlA2#NpV#|8apeGmh?=r~tVNnU@zb zlJj<+?B)(nzTmH4c7B=7T+{#U1`A{~iI)#Dl5?%?gZRt?6Q(An%eq#SXRVi?e+aZ> znSp_q4>FQt@AoFhsN!1H6-7UjinNFG-=t^ZpA}&*wlUbV3%-rq!f$_PjRISUlHi$jZcG+YS$0?1&p_%6USUub?cw~Vc@|Ik zrMvb^3d1Cyw~6P22vV`~ zih@oKu<(2S@Il9-yNLo;y#MBZ+kWp*0$UiU9m&AJD+-#8@o@J2zN+}?x!tD?=XC!t zvAY-Bt*8cC6%A4_1zdMu472?4|Ne3Z(d9Gu8>!6q-+6Q;q&3JZ3QDwYo|b%H!uFk6 z*K{)Cg0=gdO|_!V`H=ByUePaLM?THFCXkk4YW3Com6mSZmZxtujzdPYc*Q}@Mhica z1?FATE___tf5hnX>>Ks>*L($!Y%(zLih~L>4`*v`@BTpc)O?TmCp2C7ef6#=7=cES zKng&!wNg%cY7whM`>ekmDABPhxnZ`j&8Y#>A>|bZop7t~`SZz?8K1sbv?lEA^w9AL zdjIB7at>#bS2<&tVdta_q3y4yi7rcX%`1UgAqiTdXyK>cbzf_hpU^^w z1-oy5oqf6HrB?%}70AHAD+wC<@^EfC>C>3>*jZG;~_2}-Yy>!F$1ifV}7X`nZcec3oz_;fwr032n z1=$Mc^ZUq^p0LeR8#J!;)UC^z)cfZGwAPb`Y=t|O(EL;WSc6xUujYrHm-tsFh~9+E z4Dw1tw!(dBsH;A(x^s%^-ce7xl`*riOXpv>! z&Q~8nM>u(9Kz$u|&xh>|pFVVCnx`c=SFV0CWB+=M0Lb_QuMA`>oa@o~Ve6G|H0Y`7 z2LAY^ekZqc5hyh?F!0KPCgm;s#FhuJ9;lEt{dPaPBisAC(w+5s+I=FMscC`a2kIP4If)g{ma6kO)gRh;>}WdE{BXMlDNwlp zG6B@*)%WbP$Xqq!?`{{N|JAbpmhIG#J#7xs2~w~IoF)zZ8c*y?xR!FQ&S!b$)t|eL z{?Y(7O&Az>6+q(<7JjF~516%vP5W0mdG4t*7i;CFe@z4RuRsbwE7m=nonQK~yc6HO zd4G#{fpm=ELvhu$zae$E0w~c+IT^nyc{^jp-o{6>cigNGdn+m9I~|l*K_-9(5raL~ z2;BGDedv`{=^Np1IbZIVy}3OB)Qtow_yl(3jo7?rQ+FBs+PSF7j_Hd^{Tb-i2L@gx zP|C9KTXyuF1ACL*)3cLAdwq9oT^Kln9Wsx@s{|So^KkBcFy(vC)WA#cUe=jQsm#7E za;F(IPR+o;s{|S&m2y&uy38Gy@!*2=TK8$bB9D1o_soEd4e~0125PK5k2qC&iHH~O z+x{#V;9iLH=i8;8ljK(6-9^YW3yZ>Q1ir!aBMeW-i#bU@ByggjWT!Li=B5 zFGu>VwW@RF`Zs+rKc1i@x)0RQWMJS`0oA}B&ij0)&->ZX=eTU`=iTp*7z=s4XajZO zKng&4RMKg4`RU)A&IjfkRypEWzX^ss2rZ)K#7%sfmcTW>`0eCZ&z}!VxG0& zr->fdA&-EK?E0XI4F(2YUC_9kg`e4)vrps9lFMJm&Y!IP;^kVQDNmtIR^5dRpi|NO zPH%GhZssa*AS&pS`zxOM+eVw9C9N)KKwHWwM#yenme(=GonKe&UcTAzSMT(9pybZL zz^eyp1q6D2y?_32M1{iy(>D`B86sFW{K~2WMG{B>WDr#%!ZCB_Ek~8de?Pwn?oMB^ z|3wREIG%xlS06Hn%JuE`8$-Utc(?4gOu@UaojmrT3o;4Is}J(7hqK;aw!{l}8C(`W z?Ui=RsOUJJmjbG*7#MgBAcLsql9#3Z?Y#PP%Co(uDGG}wg$Xc#`V}Arpr(7g=dM&{ zD_^TPrcD0tEv3)aRZXaU4I1hKDOd&$$+t(%{+i2FI>cY+^(6Oa`aej0*lQCF_639oos)cok+@-LrLdO<}n0|T!KC_Frzn~mqI z=f}Ulvoyx1+I-Gqf7z6`(3ZIgXkc5)slb>qETO{ua9Lv!n?{n%t@TnHKnn^%CV)Do zuAb#yw#hOr)6Mb<_Dp&uCk9!7&1(*7Kj?dwY>?Qj{L|s2 zu-J>dDCN^JxrbXou4iE2HMaoAruajbwaR<-t$a9-d_6JKcEXcub{>%O0erW-gAoco|Mnt_4W0+jVUoSP4B@=2b#L&ICpf0O-^m8mYd>X6|_ zUQ5tzKT=NVd?z#?Yz(&&J#td_*6P2-9{tCmC5$C#u|}Y0#{a=gMuJOt61kaMs|135@ z&cWcd1!X-C=Y=MV<9_TqYSBD-L1(O8f}_1+7i2h^*A_IuAMY9Fo@fxehxdNLRI6$R zo9Hc3W&t1xkQML1Zdj)rGAlys7el7fa#fWFMH0KGHb4f=c-0D267^#fk1LwKUMlDfXcmfr zf!7gI6o=QZ7Mpu_c4C%mL_b%Nz|%SEtDrTGBcv$aeEI#79u3vwJi9kte{aa%fAPfv z(4r*<23{vnQS9bDh$D^6t}%Z?dGtO_0rJm1p?Ee2g69a87K=W!-1S5-|bH{^<3{HdH$!2w#K z&cMLy3YsFZ@OxRf?);YEe~$H^gCxZq5>GGY-3w~6GcfSFK{}+4m5t|^Z#m3qZhky3 z{kY(S>Bqt6kb)FII;5|2o<51J%&!S8&EJ1&+Ute7#&4l1$_>_LZH4b0|T#@1$cCEUSRrBK5r%l{!j&x_Tlgi&o|w10?*!+YOOl=Ms_U0ZAL@dpC_m81w}-Q5&o&YD zNgvJD$vkLTksNyN;%2q9*RF_c~$jy6Q991mA}6_ZYM$8lm4K{ z3iQ0SWA-|!b?Z`fKNYPj+2+R|n=lcwiHz4DGM}}Z_v@ba7g-yAMvAHE$R_=kIs>#DS#WJk>uYeEV>{T0%r7pEd zJF!lQ50ZHUL8)8HsUd06*XF-6@8q(xvo`Xsussx623cRt8wi@ua`Qa6)L{BtnG0(s zeK}LI;QBF*y^flofhq1@&ey zXz{OR&+{umf|Bj$h|sZz-t zt)la~WjUXWfLLtv>+qM_q7V}zLA9TSpUl6s2Ui2Pw{>m~;f~Art@xju zaQ>>V#yR_#nAwt9r7P`bMy_d&4To$@;Ee)ByOdMg44%s>p2tfCrTrp8U)HG0+L}Qo zqj{r1?FfBOp=Yl1?*#oQwl?XQeC1?K_M-$_(D4=w47^eMz>b{l+vq0e_P}-BeiqsA zU>?)Wjf|j`*$fQ4F`ykB7JeM>g!@B&NgT}l@ko1yW55losezECN4znh1ri?47BQBl z%NMV_uHn8=Y42r&H`k%56X4y4e+FQoY6YY5MRWBx>JFkLhMGX zO%EO~ST3Nhb=J>R!t9JSw2>3<4tC^a#TDMaHfM1!^O>Xff%iF2n!6LUOPc`dh*0XWhp7?ZB528v4(Y|m6ssk!U2xCy-4JM6UIHC{Oa;Y-lvAR`tB!|%tlM^JXYNl~ zW5;j7yBj)qmGaTYK~Ju?)=y*j)U$PuakxVpIq9IjzrLsB-7TAJjrR3E{A0j5>%N-}XUIRuygzS- z2soe?+RjNTb}LWba-eWU%CF;jx70g9IvE&vGeHaMEc^~?r#|}pK)vSs4b}b6%y(Q9 z(Y*{RVL=K&od6H#M(5%yN84I+7B1ixF>9VsqiQ<=G}HxB09v~z<+MUZNdLT+S^e4c zvYVoNrxvVO+yxyR$O0{(3iMP_jDVy?24I3ABXC1~vXY zoKO1&acnu;uGX#4=jp03P3Fpeb4Lv_Z9J_*ge&k4LWml}3lK|*wa}MOJp3|j&lq4I?nFC6gr+D}$EQzn9oeZ%{OsTn8PF&I5JKJ)BQ2*)dsbCu?}O z(?0KjcMtlvbyz{xXz}KOmO)86saaNh`19~B-&&5FTsuB%zM8FK3LPuX12w#@J((}? zU*bOda?_d%uWC=s;)`C^E(dDlF);AvEd_^Uz*$v^oPR5FzH)nh>fjb$6VjXu%{cj> zL1hcSPdln+cOKl=^fe&0kXNx%=*6QtP!Y_)z*_+7XLvZ9C&ujXn;Ox>;(Nr|- z|G#a}Bv%01*(Bvu>T*56Bg*-{R@1@b>xB~dpLjKaA_-&yXdOtbr%t$FcJXbtj*HAk zjk0}L3d?+a1KH8TTksX^$Xl!Azb{_y&ZJr^;I~lj@o(0DZO|@E5onsi!cVU%PS$7N zFZsP{zpABIzWN|8od&HIi$GH)9?owvu78$al6L#cQm>!O|IH2#5N3i79u|Ru+|~1? z&5;j}vvtp<>{;0)EV|FkQ4@UPGXn!}u`t*T>mvfsZ>pE(FAVu||6lT<;O0n9Xznfn zjS*V-&9sd^BFYiT!*nF&5!2(J6Q;0kgbpv1fC@7Y=dzf`Cd;C|gFB*Z^#U$;u`^y- z4;r{+VBiH8BvMZ7kGp$s(t z_U`D~1l5XfMn`R1r*5x22`Yja77e0@r_Y+C}@V5fq}OiR89tY-jB~-yttc{A$u#g`HTN% z=XoD&0!{dV6s!U}QndQxsZ+%kuYFd`(67E?@~(Y7Y%Zx1)bF$|7sKx>>z&~YCg&JTp_tUfpgxNvQ)+Uh4hE$(iLH*^rS5;T9|=4oI*p}zmk zyNO-e_wAOd&kx*edt2_yI!{%_!55AAXoR3}$lFmDQPkQak0%-T48q}4s@Vh+Y zMyC7KkMW^4*0wr7TRhaW5B-OPLp7+G;Ng5hDSw{nt*rqHe-;&eyPE&CQOy`y^Hzf@ zc}b@Y=TB$~?|6S;?nS;uuf*M47We%Ebpja}c&kBcIb%H!cX0-abJf@j*X5KxxW~pL zZrTjlf5BTL0e0k3hK+N#Oq-$JXUi9nV$gW<;e#vC*sKMmEDOJgmvz%DBjbJ*yt^3n z&}rhwo(vaIeaXPUTML@k^Kf2#Wo39n;?IoA$3iW4dQum?doKqXr~)Yf9bTgEd41yo z_mvKJH+El*i+VJLBe&Gj5Y$9tVBoD&0K1{VWt*B?#EPTu^2Bz|oB8KMwfTQ&IMjoJ z+`{k3dC{0BOxJX7DIHK!D_xS2Su_EfFX}wF$H2T-Gm14fh{kJ-6a`P?G|* zw66zsM65lfGkYcVo^-2hH9w-}lzK&B&5Vhlegy*qZ-WWg4bNpW>U*}b2kiF0bv10u znWq0y$3O)r0|RekFSy@bvUE37(z!R81s@m=M>>T4>WH2X?T9skhMhc|Mb}?f)7vZY z?fXFod0~|~T7OGQplc7BKtq30PA!gdQ=1knH1a*P{K+m3y(FZ zv#vT!ws?lqd|TT~Cyv>vtdx-Z0c|!nwSgUZ!t>Xx#M`S3wAXg8Uiwbhu|K&El&&jWCjM_R#2o_`1vFjn8}|z-yOzTWWO|F_LoyR;Ipe37TUu(4Cz2WU!(D}_a(9oZhlX*;pMu+y4hf`i9+ifgezivnOH_#*# z$OKUBXYFZFTIO}~=1*S9l&N>BMD_kPEj|s}WD8ONIe4wr{dUHom*o#VBHlzBs%Na7 zpRvaPlCwH=!Lj+Woc(aJ;kn!iLQiTYo^^>6DJTQArx_S{J3y@<59cFM?V0oJMHDi3 z2d;8oQe&ohKmjx`0a5^}qNSWdqE;U+^V|@6+-bf_`-{ALv1gc}1xN>|39s+z-Ev!J z(@Q1)NuMUltn!wg)VMwf+V}5(9K6QNbp4r0;Da?^ZNI7y1PI<6bnBc zxhwboDo)*1vSj6}nMcJh-_O_y&AeTpey4|XX_xBvyJE(I8}$ChKAdW5s9z%lou=sm zEhCq7O4o1bQR2QQ0C+vxmU zJ8k1)&?qwl18>iMaGN$(A}sloX}n zcROw|@8SD2m0=ls=<+0{>G7gtW(;a}_QG6Y!9LzDePP+>F0nm&_J2GFbeV24}%R|1# z<_4cd z;{R-aX?PTLvS~6XJp_8n3m*`;<35vDK$#)Wv*OV0b%LiM2dD5(feg#r{;2o5x$EJl zGxrm|2yA6gvI$@Ujixa$@JTNNa$4NVolythz0GNvab3!i zYrmPIGH8yOfq{2As6}ewckIiC6X$FB9Y6p0pP4V@!tyC)1?bcUkOI)GwTH9b@_nbg zHvY{#ud09vN zId|LsJ5xcb=7cH}meKMxdlE#1lSTcngh z|8(cJIf2mZKMyqYXW_TsC|k#UR$r^pHM93@{nMYX49) zXcm4t6SgSqeQ|k_SLy0}nW&Ht%&zXg=F!Ch zY7H|m@GbxqgHleRHqoNK|BVa{pD5hBSQ~oQn(-rO^B4mI??O;nt?%ixZruWlNg8q= z%DAPO<|Xpz3o?SHEkO#*z#&-{Ah;wehHurqTo1oUE4}NIXc)oOR&7(UMrn>X}$_|{ww1*HR! zf@-iMIYkTI?<=Rii@R3&`Ru({=1W?_L9(Coi-F4&QmpDIT1 z1b;rex=dGM)|+jI%C4zHliV^;H_F0Ks$v%RwVy6>DRz8wPQ}ch=WXB#9iUhaTJ-DT zy!T=`#Fy@!Ro`yo*jqnpUXqL_RAqlZhWex8jpKV$upi^b#sF2fyXyK z+Cqo^R)UH{3%{H&+2*Ck_r^~?7jA8uma*tNKlFAR-j$$9X%FXn#=q~+VY=lvlOd4Z zBRTw%ZcsS1HMkPgbCq)1|8_A?^abmAhcCs~EI#`9>6ynrp(`j>g67_pJ#U=PmAv=z zIe)X_#B)Z)Zx#N@y@IBwm2bcydAhCBM1MZN$@6%9!*}U^x%O_$p!LOSP?2omceqh~ z`un=IHpdF<-p`z7?4>L)2Nc8%47{sBYxX>x^-Csob?vac{bt`~uYws~UN0hUK?7>_ zQSfxt$2&`|UQD^EyXwRg)noEgtY^;_hqgdggIea+o=cT=<0eg(v0tyd;djW6v!Wc{ z0-)-Ufq{386xfmT)f6rpys^}Coo{$WuPV<;=zI^TWMN?7T??AtxA5bCFB({pDl9g^ zCGKMDh4xb$7brrflGm;Vr^y+1OYQvc{JwPD!^D{P&40FIg+HNHGx%Ttch7HkBKDv8 zc|GV=fbGWV@h9uu{^b0IME5$#6&v$Y-}gA>U(LCb_v+o&xl>n&r?`RA0Rsc?de9uB zg`c3fpJ~pG$t>B=(k)%4%N*Mvw|Xzcg!P~`dmheTCj3bEv5i{2)%DF)3kACwrT^Wb zvkx0UW9L#%vGNJz z^L10%Ezkl=Y77j#+d$1`3%`Kpt!wKxGACYn9CKOtq>6BdWg2t|_cl=N=i$7%-6ehb z#sBfgrM&L7-{IrzcI|?WqHF`T0;HT+g6a!%PQ7_ypVjf;WY*TQNw-!($K|$xh8NsC zH~lKN|9bp5Av497&7MUkaO>3=VL)`#R}aiTtv)4ei188<(?z#y&tM zG=QVqSS@>R z1WmMi1;OQm^YWH68$_`a%?dt|901f$Adv-QIoR-ov?S zR^{VeC8y^9o@|`>=YMAXgi{BgCCq+Mn^ww6aK-LLnm<1TB#eXlxz^bqs1NEtr0eu1Z@l#OMaHZ5&?OefK(njN$)G9kw}oiEf+DSwr*1G0+5uyXS${HTgk&slj_cMZQv7m6pt0rVT0=7#Mhu zK~8VDcC4v#acSg-BP-e;?iS3uE>{)>ni*wa;5`nCRSUmRAMImb+P6;^7LB=C^X3mz zPN@{MC_Vuy20fhjEE4!pac?_6Yw639=PCS0x3GKxm2M0SyeB~2NhzmIek(E-Y-5a( zvk0+cy=ZnZ*R(356&WCjM_Qy@23_<1;_etX>Pet))5L2$$4Kg+o9W`KGHAO)bT z=iyv3^Tg8vn;WsoD<52(TCU6!`n`u>D8O%PT!!7-ZP+41Z&U0CzE_ZR!%x(WEo~z;1|Gwf${C zs9WusN1I<>=a&1?<{1Xf{^vk7uZ3S>DvR!Q6ZgsbYO{N0Ke4>5aHSlSqZk-?&w;uR z9?m(|=Og}C7&WOni=YyST#&lauKjE#>wQh)KK@Na>phfAO#aSK1U zi_VX@67F2>^~zXz()dG;(1atP5|)91_tHynbr2Bj-srK|^-qe!<%H#j-4#WiFAjiM zaTzo_Ddpt$BGmucb~*MVs%)7@c3jkI5zzzf6=Y!Gy$q`4-963oYu8ze>mJ_P)%miG z+cR2be;;TU4M@QxaCCd#3N~7Jbg}*Vo3|fG-2B5GwzCveMl&$*UIFD%&=sGDw(q+Y z_UfgbvGhuVHUCp|SwN0sVBoz9no9L>_V7-4S1I=VwAG)drY?1QPyQRP05uCh3P8is zQckr27x&pJF_hM!2A@4`-QQ$^5J3`V+J+o_sl(*DFmss~egouY<;`rJSUD*O^X{lufhq zKK_x{Ge#%SHWf4m#K6FN9W*4Y@2M!+sg+Ue>F2`v{?O-uJe7j(7U*i0>yXpwmG&s7 zNG=g`*s@+PK7+^lDDyXPXPAM3_a>-4Y2mkKmcg5yVO;rI`IRM-yvnf`CU1fcKi&kT zO%LbwY=%9?C!WX@aM(Sv-6!dkFFyxbx!(j8Ad*f@t32+^5S_7XYS86XRofpy~hc596KA{AL`UkpG3+^e}wM{wY>lqdI5mb?YOaLX?cu$AjrowZNG;Fl~(-XXi`QsX)8- z&@+n;PkiBddQH#j2zfz4%fOV{mP{vT_J^KXwChV-=QMeJllnJ)Z1d7h>^h>#e?uJk zs1O{IiFvYjuH?Qm4K!Wx^yD5!qXJVYP?Md3f%nl)aAEFqxh>;N><^{!{p1fF z#%*5}Arhn=oc-l;AZW;sfr0lam06J-Y#Pv& zsLw%(HpugH@Djhp7TZ3_98b5h4Z3(Yau*+TGu`uOaFWyhmK=X)cgm(vwS`A`zki>> z>--uzK=A@J9%JFR&3y*%C#II~7n=TsbpBe`^?5q?| z|Ge^$$rbI@51|#xOVAPnDW|IkZ+-i|=5mFC7U%tUUoG$NnqmfW90LRIOHdYc_59dy zPIUccyS(6yHJe^mr=ApJPTK7ZenqPxDAhDiVHfj-tifxas>IvMszIv1RRX(s;|a} zx)|RtKJei5+_}{q(13aiTIS&4tQOd!q8z>MIUDQCnuR)vQ|1M}2bJ;+47_haB~7fS zmCn)Y0-H4I7B1eMQ}h35ynoOIXh^<;+~``_+{kFhQpRc0ZNB!_{OZ}-eMg~IyazQj zEc^n(*6O~oh>(oDDssD@Gvz&Ze>8N8WcPR{QZUG#FLE|)KK znB_gFdX#i}=e8%>_FvW9!yitaI(YPQ((!-Gpe5}GP>@@D=JSVaPu~&TDcI^A6uD=~ znZKtdLVJrJ+`s|VI$c6(Pubahd#bp2w)&YwX{Gmo#zq+!ct3&`N?7>inu$)A`sUm! zI_1*6w_$hBhh4G)h82~GY0w7eCs2b+%IV!U zCao*KHcYmvn>WGxT#_7r@oH#-`29lPq`ypZYWxnlM?!eUSMsl6B8C+A!-V+o`f`~q6dBIP8f_cv2cDqwA@<=QYi z*O~v{35J8((;yQ-Ch2>oF|H^$dPHnLZ-$(!kiK`JY}iR?OAOSNVT|;%II^x#>vV~= zpUYcIRzW_#Cn-+Q4#-!~0z(VG32tf60{$`0W~;u)*3>TeqxbO!XyyJ5v~JGBx#z8@ z)ln}e#g7|#JUZjUx_sn(tL&+f zE`3RxOVxMo$@V-SXhZ8K06u57h z;2J!+L;0_U^`V0*TLPfT{ud~1dN{M%#C?45&^*_iIcHC2_I6d%GZLW6jDdmo7igiS zl#_bs;oz^KFOB*nt5-G@WV+3|c>%hr=ND)xx4!4K+EgFq?`_=u)qAt(s9X2 zmus5TWc_KYV~>Lt(lIdb{sk2SZk~k~BMa{?P?5a%jxG3nX#_XJOLu6+`Zom}-Mh9< z`t`izjgI2(rnL{|xEH3peFf?aGcfS}12r%#{8pRg8=h%z3gv8SoL@APY0JVAdFUdI zf1r_04`)S&a5=w9e{1HLd!P2GE|h!pA|1Lk@js|7BjxnGmxV>YDdPV!-^7v%Jx`Cc z^WcFA1_s{$pypDLCl}8ieuiJ+XRL1jo4rPfWj@=bc~D3GUkP@k-j8`*vu@kmQlF6c zsiWKYp56p@$Y>HDBWSwD!f$)^{}pdjCw^8nF)1?gaFploIssYI&&Oy5Zo{0N3Yi(?V+8em zgFG!?=O|QWfBhA@?t`CHE_3l&-$KYnS3X9_W;%)Mo91r(Z}P4E^WLJX50XsHl8hj+ z$;S*@ykp^)p4PF`Rs1Gj#Sg~N+Xnnyo2+sm3r+c$K`UxJob%ZaC`~fCe(XlvvdTk@ z3M%q$PLOhvj~NsmQcm@`i+#nH=DnJ$rswqZ(LI@212%0-#VBli~m3AJ^#{1_BT-&)`|7!YdX*-wXL)K5EK?{x< z82H#g6^fKo_|y3oKeyVJ9c!q6JUcAD^NoiGXmuAz0jTb>_GHb|xph+gg6r~kYj2s0 zsRqCCPlxo}`PdS`j{LCvv}5XnwOUJ8PwVkn_AO5}V#P6VQOw5<%A*#3-<f}klwcxVg(0iT3gxE{HfByU;kHWSsQ=9JL%MY*NFcQAY~LE zM;X|W6F>GX+#p-EH9h?;zbwoBiu1n{+aV@!f>!ld_^oqM*(9MArN8>#a#<5)rqw%c z*h40I__#oWh#t=6Cz~cbcRsP=V|njh&m@-0$=f18dx;qs__#oW>rzg^)Bim=#dPNI z2QF>aRlj80w2$ROhNJnoKx1NVp1#&Ibr>2WYq}@Ku3?MIl8{UA24#DY3G2a*oZ%+) zYA?rGm;2{gW$KcT2em%Vg7o$HctFGR7JdPvzfbSxmmUe7-z?9_#j* zh8>{h5d#As52&;Y_GA+gbK~x;n0vl(Qmwy5kpdbaHMC`!mjp53XtI@K2cB})%O&WlWc#J%u|{FxV804L)HCE*E5jr1D_~l zcXrO#-0--Fl1m|0a|G&&F7r+g+64+h1_nNH(Ac1b-=#QZD<$(>@n2CD`(4&;N`A$* z0W`q_QUEILJ)93UOkbliS zL_*Nq;JjcMs4@d70L_dAdp7DBhhH3gu9_gJ-g0*eNe5>z`!R78cmXPnr|@a`YVsGlbS8>2p8SR=ehSI z7;<6&pCl-8-opj@q1`WGe`1$2r$h!1@T4Ti7yA6>duU`sZOa>J_3=DkIprIZQ=c>%< zTnoPjJr>aonzG5`2BwN!SB9rzT8XhGY9yS3R4aoIs#es$0rA>^*o%XdnDiaect-Cpo4Aj zagEwYw@Y(CJyiwc@BIR_1?ag)8fJ{HHGp0LhOJph{&ujsm69iHKO0=<_E)(1D z28EZ!q)7K4--#IHja!zxDoFwSvN(Kf#1;}ty ztl~+nd0TzIK9W=My|TNs$0V5vn(P%I!%cio6$FH)9ZQTY+aG3DEwfYQ|3px`0b~MX zxG6v@)%>)@^Mjo;PO!Vb(o|6`egrDrKng%^Df9feeBH(i;(gNHOS7J=jxJr_=p+vr z1L0FN28ZO^_{fPu)tlO%?02=1JT}!H%6vm~FHy8AM`|dG$ON z`FCH3^t1Ssj(`jEiO0VeuRic*(K6Xbb}Da{#{T@i2Q>W3z`&;rTGb=v^jP*W*YDeD zPj&6Z^?hXL#~e2P1{tsBQw9y_>U%~_cKN^@;XkkYp`zGKk8j z0_sM1IJbLB*?g52{kGGh^|RQkeT%1*y$AJm85sCfLAhMYNzz|GWxlo4@H;!h z$NS$N*WCR7y`0M+nO7aOO5DQl1Cz}~bswp>%^!X28{7V9YJ8K1%-Zv*gNkAg=cAv_ zE_ch?zUbGpjZyioeTG*qE`?0n@u`Cr2uL|eO+C=nY`k;fT%L3LpU+cmy4A`Ds;d|n z_|!r5Mxdt%`;C{nKZ-VUIGxy9_n$5QVNe`oY>-a_a@hE-drX?%5pG%6-)=khXHB?~ z%DP36bs&72pd@GEH(_Fs=*o|G?reOeJ@>Ht*$vz3Wuc86P0*~phqH!wE6rM z{|^GiA_D`T4yeHu?Aa|YS$QquKkZu&r70)C|;1WMJUa162zi&WmdG zxYk{^pXzD!d8*ZSubBs^R{e0rd^t(22!K!sOQa6-cZ@wyG!%BnlH7OsIz{PF35 znr!->txJ-5KD{Y@TcP}Z#nsEPJ6`^ahgR--kbyfLO`)UDx!McPTWnpT*mQOOKZ{l& zNRrcs4BV~gbeX$AcWG!utLMBqGH)X!vK;4=c{Q47BkpBKxo zv~SulzvT3Wsk0;As$6D+y1@uEvgP6Y^VruVa`PlLWO$Cmzne3Q^UJ{|P_qDJ0%&ku z%IRPFCJVn+8Vgk9!~XKBi88C$1cHnPDR|Goz!2-n?A14|pZVOzJTbQ^=N}vVa`+5g zU(II>xpTqQQlOwlLO?gjT)(d5f9Qcn5%)ktzzht0CZK4y@H2Yhcv5nsvO=M+;X6B% zxAuGFc00jjS2R z?F#qHUGK84=Ra3m1sPQ5GxY!mlul@N?Pp4z%S4CxOZl?LdLI)OKUkF*= zz-JB`ByjW8I%@q(G^O{>;lEd%b~tNBZdq1brXJFv71T_=lJsX$q;rb(U=lq$)nik6bkxv*u$$_dvkb?Q(a9|Nw zRHNu$cH_!UnSTC#HB4u9??D}D1+v1zZ<&Y4^>$ay>wO0#*4SP#+9uvM1GL11fq~B& zG}PhYd~l_p)p}8%RGyP1^L6+2#MbutjX>mR?>oR;W;nnw%_ zeDj+OF6A6Sj#WkX3O-m-B?h||Hs_syZ<3m>U{Q~7MZf=!PIsBkw(JK zdqfgFeNy?hby!{p7f}p+pxXi&BmM5jJbGAK6}(*KY-{e}zi+1Rt$78qn}LDP5fo4s zepAlGr*ul~m;K~jz2MT~Q<1NJCP7;uj-cA#!&yC1?}F0Shc2e;FFe)z&@$u50ek2` zjU%Z49q1Xxar=ose7g8(=84q;JGQ)7mjvn+Ffi~rgW|%&`D!DV#}l>O zU#}+QOyP1a{cO593);4K0ab3+o)(W~y3U=v#=y1vM$Sxz5)Yp8V{G7n;B$dY746z{ z+4TJVz_Kl81YiH%X8!A~`D|!+(iK$6Tll@%DE5eX-jC2ZeT)}RY)sI2((@MT23JsN z@8LXShQ1nSnM%$3ePY*ArcRO;`m+#fg&Sn5sJbcl*~z;rg{q(bH(jZG^YDL0Soz=v z>bbjlPVg#gNH1!14WDTluTpMlA67jV+5vHcbOtp_`m>by+0v5k+`Yf^&oWty<{8l1 z-yPJyu<&c%w)fZC@Bfc_$FJ_(X?RZ3;{PMaFf5-3s2KEcekJfi;Aj4+jEKkew`Lfv zdFcM`2DHiQ0cuxEIVo{;)H>*WJo?M@htF+>1Hlhin?c@VVBqrrmHMupuD<--ej-}G zsya=II9J++oiwR|%;WHRK=$Lz7B}SL`&Y|Ww<~vnV%l_-53A0A(g6blpBKmt7JdmW zOG0!eR`qHc3tmh=eY;x9`Yg1h^#b|E!#PB7Z}0on?@x-hoa*5;tlj?0s0wsWF~|f^ z!U^=$S+7^5Hsjcp74HkrAMH8c@HAp6D2PD{AluN`XT|kAI;Q;op#18fjqS{NZhkzV zl7)eR&j-}lv+!%Wn>u+$l7i-h4aOx?yUJ_d>g@uBAV>kon;y=6(Sfg0CQYjKoIAO@ zh%I3CTZ8wYk#3Lz(14Ycllu!M*EN5F-rs997BXGyIe(wn6zJHX52!G+_FSGb&3=8+ z?(mLdUyf`u+4`K5rwr6~VPN3%h1?12Cw@@s{BpC~LLT0_Evp0s7WXkj3sOJO3T+F& zhNKIYPD{fw9y5LUY`ohbh~>mq=s=AhsC(_&G4sFHq}; zfq~Bt6zx(@Yv)AP{fvt%^^j${t@vkQ&B7auAPEKrK7UZFSl{#1{GSt^)t_a_*wX&k zFY4^!xc7{pmMBO8WIjvv{rs23274DcUES84y58}Lk5>t(dBniL7XX>hn%0w8`{TLn zt_6Y&noR3<9+>VM0P0496o85v59gHS+4)CS&M)K3SpBu($5Nd+p}o+idmzX+)}GvX zZhL;eoN0C7=QsVbN_TGa!%fiProbq0X>Y!2;;&XdHM_aSd!B7MH0fg1nT4PcJq89o z@a{tkzp4qF-Z=Nozf*Bj*pz$CcEPv;L1?ND0D z$3W!*0|OtpgD&Ot?=E{2)86Z1hctLQYv0vrcsy}{7RAA!;}y$1xkE206^NGPq$EYZ z*&}Oe_PFQ*sC)#Oa2V{!PCmUt7N&1^t=2H6n&)o(F{y$r08+w)g4$CSelM37t54&d zI9c5?qqMc@M?+M71*pf)z`z#@8h`L`zIeo{%qM;FR+g~yn|Z&un3&F&h87^9ph0yh zC%Y!jq>v+S67O72H{EAbj5scr09p?OG6B@axArWaqt({yc=WQRxNPK&%|Bk&K5GY! zDuNVz1UvG;UMWQM8*2T4~3?z!wf0eGl@SwDo_RzQM6QXJl7gDvsga6>gLT+GNYXz!w2otH!o~ zNj!AR8A-1VN@9OktPNgNbn+i0BqKp3u7zLlgo@lB&Q`w`S8+<^N$WM9{GkOM9Eb#s z{ChYHR2I~?ytwR={K>|lK-qTwj6oUA7?maHqXHeH*%o`X$*87DZhmDlPBp{)HaHA zZ8;bCBsD)2I`SXm3BIqH(eK(~uIX>;KUTMXbuXcZOzQ1(ejowPgOfg>^s3>;xJa_Q^uN?}}+rz>SIbOATm(|Hu4Q(#Q zEe5+`y6C?4uQx20p11g7$+FKNT=!4|beJU`G)`;bcc{hx$GoJr|4UaNOO*P*@x-UY zXWSsMnE)!YJ)A2Jls_^*{-o<%J6A$}^f$KUt8_t=@eB-n37||Y<@8YNT7A%Grj^3; zdJpL*Rm`rbw+0Q4fE0kLg;>uNqs{wo*;a4<8K{4R^MSL2R`4finoRf%c4SokXZv;S zKC3<*tl?X^%(pDzh74$6f`NfA3A9$r!Y`q$=it>n6;Hm%N9i12x$$th_HXDIND`=9 z>ERq6=Jt8;E?|e70$}nEv?HUYO zyu_CVs`Wgazkg?V_D>>3`gZB*lsG@U2wwg)?fov@iMv)m-li)R_ihDW z-nBn=pw=)017AAGq+rj3s^=~%=={HWQCq1@N^MVl@X83tl3l*^dEk(|S**0u{u5K$ z_A7I;CO1y0yFAARI(m=+S|x7bcd~dQ-|Huz{JB?&e|T|r$%KZL2cbn!CTM!!!+Fti z6@FX0)__Mnxivi*>ymAvQbFfFFfj0Cf>x?aIX#{6UfsH8^O-Y~D^&7*k}}^%w>^dg zR3>PNft#lmKU-?P*&D6<#~yun_wz>D>+QjRpbD;o9r;`{)qa!wF0L}82@XGv`YJX~ zd9VheARE+6vhZ6v#~_yDpwuqy7fES;6aJt5#eN^u@?c=#%Ldgv9?sSqduMGmy!VAG z@R|7{vy3STKQ4n-J%SW~(u1VawbhlA-~XNKTKMe7pUEO^tzVb!0hQ4p1)w6x%~SF| zYwhZLt;Y-6`tweH(DI(gC=Zzs=gZ*-J5u}7kMlP_8hkbp+_UhEwbkCls;AIOEf?el z3%^2f{au9`btThtxSAP@7k})&4n3)lFBjA@_i)aiFwyA6)0l(Gl^m&Nt#=QY-gbfZ zadJUrm6X%hcJ-nkch2cGgv5QA+!C6=#rqVRdGnYU7#LhVJ7njqIT6XtCmEr6n#03k zqMx7Fen>#&xq}_qvhI(T>b_&|PwF|E9BKAA{?6Ro45A<(eIJd#qd^TFT`^dI!4_ZRHQ#G+-=ElrucD{QUf&fH3I1UID0_kaT)b;AzF0)bw=L zg5;*FleIs&ck@8Uf(k$rpw^xYT&rKDUr@>a$J3)4+7f9t(>#+I;)a3}up_7K`uT5P z3(LA9JKk{C-Fgcrho(S>Sqee>n=Sk_7@722&VTrSt|#f`lwGg0S4FdeHpwtB@D+jT zE)VD6r@!CcJz>CW-^HQq{*gA?19xZKw0sz~!g9 zZu(|Hx9jqifEpSWe)bPEf5=(mtBa#>@d+6 z%C{L=!gj3O)d;F_85sCVK;uzTPFdli>nBx(9#L;|HSOlS@}RqMF(|o%6o4Wt*t4bm zOYhevz6SaI1qUM4%`UtvXosfB5=dE{EPH41+yp+oX^KqD-Mf|Zc4q8`c7ny!i9qwT0rVlxLNzcSdk}1%VDLVPN1Z z1C`bKp0#dQ=M-oqscL8gj49rS|g%Isr(TxNZ;u99zZ-+CK5 zWmW-ds#*9szg#vcJ@Z?_`l}xW_220IS$L=qRJt)R@Ku0Pw}-P%@Zs`9T=qI5+vit* z))t>1{&)hksa64+Dw1-tbUPpQ^{_+Ssf38)AU)=5@jo;`qevhVK-VF;d#1B$9Ne<3 zXu7bU>hk^K7kw4i`GOjG3=DjgkSn^*U+PZvG!C;VtrXze^hW7iI(r{v4JTg}s0Oz1 zD|9l9QJpT*b9Kt<(q%!4FE^f)00j^O178(rfq;jzhQZG3=L?=h>^mVjX^GWOi;b@% zp@SsVpk3-xPI@_iXXJ!-=Ej6AjN9uXps)3x4_eYzYk-?5?w^>ZCS}!F2yeb*YJwp!yPI0;ou~_EfX*2wgT^{^TDUitOD;@ZnuJzLN{(t`rmjy z2Q-HSGT}AYkq54KUOIL5cIfSAMd_1U^V}|Y-+`>iCW5Do5 zsN~8eWoNELi=V50gHBUrVBl*8t?mi(%saB$&^$*d{VPg3u2$jpN03kN2nTc|rxjGeTKJ`F+RrsMe6QvGv2uY%`Ah$Lp<|%Y zGzJE~*8SjymeV;ch4hxhivj+=3XjaKFU?>%4qCj$z`)lAT8kp(bi>%<>hi<&zZD)n zoBePe>xG@Qur(NMppjm8PdC}hm1;NCjb6>ROr5yb`sa>E3D9Z%whVAcmdq=Dx~YFs zi^gX+Y5qTDp$y6sp<^KJpq`3_-x8OdGwr;ds_}-_I;+mvD*EmX=p=Lo1_r)%P%pv5 z`6!#U1$Vu6?BQMiav?8=y`1 z4p5<9=J~=zI^oCG8;5j))^RUZKCz~+?IvV1K3~U0up{SA*(P2rV6?IN^ijczD^G0I zkL5zwiFJWib6EHlK3jHVY5fnWb(P_7X7qhz&{%r_Gz-PRz}E#@Sm@zw&AwtYlcBHR zE4i}3_eln&+1Ixp_`2x)b!hJH0j)%} z@QY$d+NxdUrgd(YcKjxj(+X@&rjT8zd_ACz;2zF#7f^RMI%1wwui;4 zSL+`|BtJO`S*ps{s|a@Fy8T*d+4d*aYgA2sK2=_O4VTmw(5?vv2EIPfN>mHKGYaRG zu9evdd0zg$)Bm6o&-$qj&|#K7(6(I<=Nqa{4U%2c8CFUMCrCVev>`aZ9kg-+WCCcU zSIQ|;uHe{PW)bf8TQ+jIB)s;V? z9gu!!up^(UnjHxgd$8a4#i_&6bM70gn|=XWUrYdvKUnzLFLS%NSn^!JtZ3yIPvc*( z#22?fyAKmUm70gMSM&U~jY=Z?x1v4ngg^T5N1T@#x}a_%XbeQsX+Doz8LP+d-eUn8 zDmV6=>Hqd)0W|YY1kEw(d-CK7Zh!RWwuI*)Tc*ezj&F=6JcFEjzz4eCficqW-=Ep- z=iAw)&3L=|_lqsnM@^2NT?1)}O#;oiTlmGv{GGkNK85AKH)HvXlzXnGZ;nAbVv|6b z*u(k4%&^42|Bi4rKmMKYc#cHV-?dku^Lmp(O*Sbf$wT?mwzHg{_ha9T`1d!~S5YxkPFF&E2U9_HmxW)go&Nc`R)xX_A-nikS+8j4vJ^o_-KRoUU?zQYpA~n?vM7AU z#&-tXH?H2Z@`83irh+OIDW}DP%l#V;J-B!%u(xu_x#K3+o)v+{1Q{6krh+0X*3)cf zrJV-rqM~=dt1Zkl!n3ApMnR_zr~U*-chtMhC32d~jz}Ej@-usWr_S}e*FuAOI;foRa8~M$deg+QvO6vBkb1!s#}$X4y@pnc z(?KJAQcfkab#;#<25r8vXw!v2qZFeC4{=ahWMJT%4jK#5_dMPZ^{a969M5%%mwOBg zyh}F*g%{9K9A^Q@tY`lOtpWit1%<5bs>gq=zP$0qr#?`#fPsN; zRyH^!Ev5C7KPW#kU+!SBW38o&D2twm93)N71{Go!eh2QZHgbA=>9J;b%QC)WDJLv` zbAd+N85sCxgVKeE^SQsDXU$dpouS&QRiF%JCgNILy(TW z@$Qh{3Yk+_oL92t&4>0c=IMe5toD39tsSy+lhWCKt?d>+SiAdrq1OQM%>%7C^KjlD zSTL(s%4MG1E6(>_u6r+iHv(^xVPN2!2da6boWyQPUai${yR!73y35S%(_)R4Z-E-z zAO)aU4fO06x}ds;A$fM<@s)S9eSF-@U8A5y@qEb1jk?A>n}yTQ@8Sp$6P;flR^7AD z1(cc@82A=|$|?)LjMcrlr*|0VJ`pOvzxhgj(;*dIXuY`r)PwhMUi5#9!JXU%rboT2 z&r42x__;~J9-8bIfEK$-IlVqStH~we;!+LQWQjj(|CBtp5CAoo85sB$a)aBGZb#?4 zgkRed)J5vs_qla%1Xt9Qc zpVHH6Z@=^&@2$HovPep9KElB^4?2aq2sC}?;an)4F1*bm=ibK`rHrDvx7_mH>O(d* z@+}4(Cn)74o~ux>bmxp4*~uq9`kZ3u5RDRpw(S>#X05F~Uo10ukv`}69c$xb@@Myl zZ_B-*2^wu@VBlNa19s%)BXzSq%JV*X2NrZ0+s9Lb_n-_U|(lhhx zMSpe|wnzC^pEA*92DKX)82FZg=A1p8vwo}GQ>fL;4BF-V;prysvmYXJKsrGRKtR;DFBV%yL%=vKL6)?t;=hTK$h~XwcIUt_I-wC z-lfODj_k0_UjB9OFJ6s3x>51-V&!Ef&x4k7%Ry5E7Jg0Aox6DR9~58RkyDes<)=h* zp@9b^XDtU6#U9Sx*Qfe89DF)!0)OEvE46f^gqfnyhWB#N^n|3-^BFNtExE-%_BIDx z4UGF4`jtBZIvced)bMokv`YH(|8D*(;Ul}%K2Kg3ak=+4Bj^Af1_r+6kp11$C+&M^ z=#>}dRJy3}>ed$r&Mv(VO708{d@Dh2u<*;}G-^I}J@dJMxSv1Vy;m@9 zwnvR;?OW@22Rfh%)__`MQch1AZ1f*8oL$6tZ{w=J4K)bRkB06Br`xX@g`sJOV+ zDDivSo~305R;Z_dM%x(}_|}8cg@vEJ*Oahj|5-L&anec*y2Bc?r~f~w`^3P&w?Plw zJ5cf3z3;bj(tVB|BL%*jFLx{QFoLQgkOI))nUqth^K*l1T{rf`sk}ZZF=MM$;%RG8 zUl*hR)ZldYyl`J7#AfFm>*d=IK3dFTb=PmEJG2nn02w@d^w?B_ag&zVna5wA2nGLV z>t44T+NIqDDvB)p*p5qX%IYs_zOXLqY^+ME|EldFpo)Znfo~J2L+atoleOxSVM9#{ zQ`A)Vf_rnfdY(E7ot@kS>g!24dCY0Lzr$iG>;0cL{tjQ9?_CU*fu^WUpm`iu&tIvR zU+R@`adjweJ;nVi>bZN?4QRgD3>iFJ^^>vZv(D}bKdMsCoY6Wjab`glsNi5=;M)Rn zgN5G)R?dSrgFc)!Sf{DfJ(-tf$&C4+CK^ZqXe`LX*;Y&cSo1nb1BJr4j=aU2R2n^W zpkp9gKpk@_rz_Kfw`VRfci^A7-Sugms@UqCJ3c|O|5i{tO5gL!cAe^S!#~sae)#`6 zuV>2FJLR6B*;xh#zO9DfB-iz4w@&?HKIbcG6J>rGZZF*GQv+?}Yy-7nEc|M%OJ#Tc z@|>{ZU37lR>+b0*JFh^_P2$@IQt09QO6SNIQ;ka9>uT<{-=w(a-WHw;8boGb;M)#r z^hr6H`z<%WtFHYvI_=fdCu=?^250lv=l9PuW*Nt}=JA+=vZtT0paL3=DjGK?9f`&a$uEo84#2 z_v=S~Ph8qL`S9Np3!tU_UdZMMxf6LmQyyN*HoWa$DXf$hD0MR&+Lqf3O0;F3GKp6i zDq55yyk_nBe&=6k+m#g?Kd<=fE4rn5WWw_0iNTRY^vFuY+oR1_r+U zkoLosRkC_K!c0s-{CAeWie!7VcB(rl(}EO0+7I9R-U?n_lb{~3Y{}Pjuc$RE{k}n4 zAO}DuNjWi^9k$%JrlX)&RwicBcjLgDN$)|+#~B#-4uIMZ?w+O1kuy5a81Hh-6nzu# zR4=pIFa_E&KQIHFCU2})%9`Y^@$B?vY44a#vrau-Ck7gSVPN1p2&$4S{DOjd9$RKi zeXvo->_i1GdrpnqdQf%9z`%D1G==Kne0=`7(v1`?ebX#EwZ(!zGL{LK+CsN@90E3e!;ynAq}Z+B7jU&cl3tFpb>-kyXG zfgaigcI4efrxc1^`;IkO)FiJ{jXAU{ej2pCI08DN%EGV4GV?%K>0d$KY}IaV{$;b> zg496^0vH(hj)3}|9?t*6XWX$3XAWasu)V{7rR>v-;@QwNc?7iJR^Ri+k}Ri=uo&g1 z6M3ggUAStJ+WiJvH6MXoB(x)T#|8U0sajqgKa@6ci?tk^(+$nM$3Pj#!teQ=(#e~p z?#;FO^?9;+vqgRQf~}yY2?GP)v0!k8V*MoDVC(dn4)1HX<5nznV`I#N-nhhf3^ep5 zB($C-??j*66Gb?@a(0?xnt@TcTCR^M*V*=OD+EuzoIlj4qC+@MAOaBBOX!&qb5bVf_w%Xha zzJBQ{ez>}H_1kibdF+1BT?3~;tz!$nJqHi7XtAp4)UwJ)u49py!YywPss-;(UH{*e09`{2j$rGk3 zkOlbR7GXcMJ>L0pri==ohJvf{t&(>R&;jkUp#GMm)3&P{k}lP<4RrPS}ADD{2XX?kA>gcO$F0>6|4LE@25|zaevfxw)Qp1^$ZMr=Rw0P z9?qLH#h3ytvaZVdxZVA>XXS^a)F;q-^E_zjk(AS#*B%SFqY6|xHi*yR*{A0hcEuZ- z?9YRWWPMK`S#3#)uP3L!XJVA~JZz_QD(((wL=R*Iq;3BwqbKF+llG{a-*2C3X|l}U z#A^atSjoV^cM;TFwD5ZoE?s!&$!CGNo3z@*1V79w*Pje++g}6~Bp%MSnV}v(w5E10 z-7t4$fWz8MgLB=WG8$w8C<943#qU|DzBF*zgXnd${>IGHpC~6N2JM(%1bMg2)1_BF zWyXq}??)qJmj_Bd4^fkYt*5=D4-UznVdlbzOlDq4_`}a8x`<)@1Wr3p!NI`5cNw%_ z&%$r=l{=PezkIT?uwN)PeSN~gj=tld78pnYXhp7vv!YPh^F0rrY~$cxvi|ty_m)~; zSfFj%E1*4tQckLB|5`F~VrR3qxIbT}8Eh`Sa1nHg#T8JQt?#*a&k?sh$wHd06B!rx zg(iH@J9ZP)*kxegyAlX?NZ7vF1G>5LDk#V;{7#*k@Nd1R z(B$v7YhV7=^u2sWt^qn=brlq89?m=0US~B7oTHl97Cu*DPtBWv+1}7u+H0VJTq&pU zOS!dwv?C7g*6~{v*{!`3M#Qx+>uSo9-&@+4ku9{b2iOLajt4Fdz;^Q_A|{r&F3*ZssmugmV)&{(>&CxB)6@B%KuOHg{XezZScg z->Lj1{~gn!W%1DA#~Yxs+Rc;m`eS~H`nPX;k4n8*_3^$r+Z!cN%Y%V|@5W8ABkhCA z_mr^Q-Q4zRPRyocsr>g&k)Y8u1_r)cAU9a}eRjFLF?pu8ol)pQxt(|W_FatJ1a0Kp z0u@0X&a1rDuZBM9*bzR}**$4nvW?=gZcq^nG66JBE9srQ5$xY&x23+%|Nn|tf*A77T^o$^Sx zW&Vll`{XWw_FXVA@ZA9gn1$cjFV-u+q-lSfsQl{XZO$^L52;%~i4~*(RAzfPH%0UM zGKQ7M%I|EA|Ml{-X;$?-XaRB;G;1y8v~>UGW8RZ)MP2gO(dw+RDV@vr7CPd67u1B0 z_0)XcP;=b)y2aX=al#l!h-u2Sc2!{nWp z5AO3iZnK(+aYjD01#%x$En0iNYjOYd(^aHv&(m{Sn@u7%83s%R)m0!9`oM13KRxZy zgJ%~771r^6s4L&SNqf%+XaVv7v>DyP@AJZQFK^vb?>xz*{nfVjNWXQ!eCQa+Lr@Xq z;jEtYNP%(sG^H5zuX`rWTh)=6p>hI}CLe+_v6PeK0?AYDVpXaiwp;MLl<5B_@c$Wf z9Ofa24)zS&!g=wolS^IMq8Y6J%{DD}UcVUBxM5)6dk7hJ)0g<8x%5Ru$)Q=>4}ZI2 zp7cnx2$Y%`82BDThTWzlDxnDoI(FV^#sTSP|H-x$+k=+`N%gP^(l>8(@*Yx^~1s~0GjM z{A+n|?|+*X2M*^IU2lFHY=y2Qc??-DYhB+^yU2!l<*_p*t3!8wl=MFfUIxd&!1ol? z(6I2kDEQM%n)m0#t;!-|nhwui^W1+9?T|hN&8c}ff0<{d*i2{lm}8tqc;>&mh~54nKTk9=`hAxA&V}CKmqd z`S@izD`-%Ffr0NiDEV9X$!yp*w>@tg+sFS(ZoM7eU)hc|eSw(p9JIZ_!#O5S@mm$k zJ$t{~tLxpK%UZ1siUrjZ3=DiPKwVoYC!Y87#k*tvvsJxyH53s&RS zdcII*J}Gyw{{Bma{hcwJ^nS{I*#hdRf=qynV8leqMO^$-+K@b-qb>g0lT~Ur+MuoC zmmtSl_|03^?9s|UmHqR@iyDo5j7lv$lR(kTz`*wkRH%D6KMTCL`B2=1-(rW4o#Fq} zu{Ce~hwl(yyaJ72NICU;=UhJ>mvY33ZJlLMiQr|cD^sDPNv}Y;Jl=EBr*qGivVZE@ z&KdEwI{neQX)laHSq@|cxlOXKrRG7qv~NI5(L9_NM203+`N}Q5&gH8*`?!sz>922~h6Tt3 zP^}l_c_vEZN7)`T@9V*(QY;^Sr#AT|T0?yCRtTIoXT{Fvc{%%b+2M(b0e_eIo(fNG zbb=^&2b%b@@avNI&M380{uVsJq1`3)y>IW9SI{w#cc4<=!@091STnf1%kt~htUY@= z_nbU`(;GCYz`(%w4%CE~a!T3YK08;+=Zb6LBHL^^;WeHMCPKsEJ!rrx$Ww%eVfw*$ zxwaM4SEtx@YFXF{v4VQ43=Dkl!@-VR+OcWX$`wsBb2C$?Mjkx;s_V@u=qSnuP=Cw9 zFGf|uw{CTuh|1K}MzgMFL?wAMf#!D^82CPbYCjL>s+rAci#7=?2-DJjcc=YZQQCy1 zpbC|Nf$t-znIPrFoMpG6F^l~d!+f^KGk%GiB`|D!e|Fz|f_4N!PE_iit>RMs(5%$vOFpGZ)y*>oxB6+C>OK?RAF z)4t0GG8gtfzn!5Y>L^ve^8ma3KTw7NnE={`R_5vZU9g4iRMCm*oXjVs;Vg&u$1Q-4 z!+eGu<(Jtpb7ozoo3o)?`~OI>@4TmUETLl{UqR`@!q2b3Q@|qGxFqFcFkiTX$_o)K z@P0)G2EMPLqR7K}u44ShCDOS(2hV#X#2HxaXz1vHc45APDm5vm>x`!@RZSTk_jq63 zRk~*5gmZgSK>O1`CV&Rl<2~QWNnG>oOw{|h&tlX2+$&GMbee-YUZt77(?ebe?YE7lHT-^SL1%>YBO0$ ztrzC&@6EaP3fkEF3F@&~_+@K|8*9z|Id3Z`Uk2mTMRs8OGlSCXG5p;|Eh!Cu<`h-IalY1 zJO0+%apd5?89G_#JD~;0Kadp`esf#J&cu9<-M)?cL!EQY!Z?)^Ye4lS0|Vbb(8#}s z^N$&gH?ktQVbs=quNK!Rxjq zpppfo05tOL=GlJi@0L`z6Pec@@3`#7KZW^^aXzS@2~q&*PJS<*zu+aqzmvy&>;&f& zR{Qj|e1&u;`58bx6brv4uNY4c17#r70};y&}_Vn?0m_;AaH2qg*{- zo&M7PBui&D|F7#`uV~7-Z^)Ym>ErM-LWg>sUQLYp=XCYDUqWEF)Wyc&Fe`{R`I$g& zu<%>8L9}}AgRP~nwl_YXQo`u?sNp4~=g!XzY884orx`szWwJkYhs@dw2@L$pr`(x1 z88q|3z`)N8Y7I#`%`P@}oztPRwalWqd*N1Vy>0Dvp!O3;0cfzq+H>i{E{DmgoBcd= zpC`RE4@nI0Hi4A1{LDwe(S1{SmKE>5hFgD&`8V)?&;NgHhbGhtR!~`G;g=fnXTK$b z=5N7gA3xc9b=w^YdkN_j^Rt4w*B;LAit5j~e8^CG({gv^+|KLoF8baEWm*OXepXNe z!_9NUUpF%a`Tis2jMKAiHoP>sJi!X;NY*D{H{`AOpRs;YWS~ruo#&6P-iX5MM?l>M z1_pk1(8>V|KUMxcKYXWhFPg8XV;?=EuycO<49Gfjes<7$QV(a#J2x3aa(_&E>r?q= zlG^=s{`=J-tss7O(9pP)lYa7Ym0jzO9pBDwVsxuTYN?>>RLHhOes<7QQIKcJd_56^ zt+mE7w(sPY^=Z{B#w-J+W(Ed+4o$Elm-1xG#B3J+9AB^?xcR!=G3_u#$TkyxPEcRR z!cQ~(N<-{zf$R6W^)*thDs4ZOe*&!zXJFvx1nr^paPG?fUcI|bh2cr8Poblu;;X2g z&5(gRelAdRNy^Ehs{X`Vr{YrmdFzT27`1=s=066NZVU|kT%h5%SkLnd7PS1Ba=ZCe z-r5gAm7NDzo99CM{`_2!O08n=!O3y=bIWzkdry1ey*eo~xeapOAU`*xQoDE{p50*8 zOqoNIq(2@BNI0OvVE{^M3=I4{kV6LFZK?z<-3BRuRBHLr zMW@6X6pvqLQdwxk%b{`q$P-W#4Ws~4sTognYrWB*R2*>j;QqJ!dtABCu7*rL^7B9{ zHH+oem9=(v3s}UHHrTugFIc<86q<4PK-GeUA8TDwSnI)~+a@`5{(3*>`1~G|ZJ@ys z1_pjUNTudcdNQJt=j!>}JDpjUFW8i_V(J-Cy8)yCRH+4ehJ+n?_SPq-+y2{uIZmrN zUMnlfLV8L3{E(Y%r?hN|`?|CI|G$8R3vOv&nDMIOEhxD&Fz^e2dIuJM9)*R?sLKi7d`WlvK9dig@Y7;@`sdD z{yCp*hjT-OK0fXDJ>DDn>3`#TP(Kr-08|dTd7itZzhIYSjK)+Q_aN1@o-I{=cR{Ox z85sBlAx-ztUa$RU?Qc$(+;u)-k~Lo?jT`T`8wuYIV#;Et1jm zw4;(ZrWp2QE5}2#o-nBCuIyQ>>$~`Golo^{hRYXi_I}EkXnPRS@a7kWZ17ZeIs5k3 z;bTmEJhI$uO+~wGctt>G{4p@_i-0C$E&TrVRn2)Bz<4)pormUmF;>f~O$Q+}gZv_( z#VQ`om&A_0TRhReQ|0ZViDG&uf4rI}2^q=Z7X^7&%IWfdzuo7=*{$x2{H+mGyZBUm z=2B=;ED8#8Yfqu1CCA_Fc;IgBT=XS$p%v5bXqK-o5p)GxIjD`=I#HrXfeC zoY|pmGH3>ffq`EPG?HWC*RXD($(k_bWBOfu>x!ouMnCTj08O?rFz}0msw5BRWm%Va z%z`UUEBoxw<&#b?#ofe@bRp~uRM;5Yah+iC} zP~Y>g*YrISujU{6u6B2?gVW~j`5UxAyDmXiKrWUt2)y&kw3_|crSfGF5lej}LNS#=`M(tcrX z)}upz9*KcU7LWqaiZdyv{TAD%G(L5gIe&E*OTr}I>Kjp#`ZVC`DO&UcP8*8GRX#K#e>G27YN!kX!iq zS2+Jmw(FC7pY`*@3E>}a%NDNyRj42ZkfEL|S4k$W9i9n>>Zw}ywobMQy7(Tl2p)fm*z9AL{jlRH?g=;^t+pdbdB02);)^VEI! z*if=*=JwMMl@lxJb2?k|QPnCgzUkTJy@o@e! zyQC=R&f1BB=NRqHjD0(H{ka3Jl9V93Ckj5qaB0VFmYJ@n)@Gu%WTmq%+kS9Ai(d&e z)T8XV;lPH!5$3itZm)XsknOihXrzuKs8R=6(FG2uUAb@1r%24W?0Wn{v3c`?y?-Ze zftL2lpnAi?@0PM`$`iwLt;|}1T^j3s+(L>EfGSi527VP#N5sSVrLp~^s`Z^;1lB*l zGFQPzm0J(GubE#3bik67(`)|4la49o%087Am#BO3QTfZeg^3do<6y8j4 z?%WjqtiFHQvmmvU2(`IuMyHa;8z2A*Tb1{)>N>1Ut`Mgue}XW=*X;U4?N4L@G8a3-4^ zSg^W#anD`ItQ@}vsA}?X_DSWoeBZaiiZ844?8Y~Js=Dgu8zHf&0UBkMa?<^4d!NDk z*v!?|Hjbafm-=zDEr)cg`87bbp1!Al|C%QAvuQ@{pZADuQ)Ii$Bt8r322IG#bo-;1 zK4j_WT`H=2#%x;=@4P8lQIO##el5^^uZ3UlWv{rBg>8D17FU(7K6gIrn9D9`dH|P~ z9?rsgxgO;`Tl6ll^OvP7y?=r&8Kz?yt%!M&jQT?PhzZOB&Hl7rS}0s5I4w_i>_ zc`dx*z|$>(pqVfR27Vn->)67trE7MLs~#KIr#&&}S9^4wy^`JlS%}WB0~#CjaCVf_ ze4kgaOnzqBEwTH>KPu+`yaO5P;n#(1l@;7y9k}vRkDX^y{l3i;I)Y|2e1x{lbwMpM zeb2WM8B2R6@-->nPSO_6U8fwg{vBlKk6#yZt;2O`+r!RV*Dg%bsF1C9J2}-&QVuky z$iTp_2kPrs_?6$dJN4)V1~0aS36)WDhgpPmrhxW5fD}MB75?Nh*>f!~vMSb6fOWr| z$nxX-vO17}(gzI*OFCV*;op>GkplV&Wio;!@bqz6-pNK}>`F?0A zC=NghKoyFV)6G@9du}F#Ejp&38faR&>m@J4O~{GI{Dz=f&)U;%(k7%zXA>KG8fP3QYi$@=P@ww8%uy|-omX1*1uqo zzf+g7!foNbsWR2IcF-co7}W3daE|KH{8dyJ*tBGY_gQt0`z77mAA&{=Kqi1zQb;*f z&UIM*t@A*b%#DwwF;ikzFN-<@?Ijt5GO@L11*iNT1@8#6m`5Uu&$ZtR{eM*tlu$q> zKx)17B8MlIJ-bqE&Aa^K?ZK8W@`ZT5*Zly%|X#_;pY=JPotXsub-Bl(D~C7_V;d{^Z}G4M;71t>-fN_K5F*uS@#=2MGpf5 zzXhnNX6;$<`$nqrtGKm~xfJvA?;I*r>1_iY=nPT-Ie0C8kG|{v^V=IW)%&%$i=L$h zO7DYae@oEOD;9pyEgcMoUh|7SEL%J+-@^0vka7}#q@wT7zE}AA!nJN&rv_L)N_T?{lJHxBMsmtL?e1;p z*fsSy)5#*a8=86+%<1NPK@|xD1HTpI;I#+;80y}~_1qF!o*QA&Xm#V)!!3|0GkzOT z%Chjgk@0gT%aPZU+EY)oz8A1j`tqD!mA`fZ%?tkcz|L1hUw2zRTZv1u^ z7#JAJJVWMJMy0XJB)clwFP@f|CY0K78(QPoLr&7TaPNuA>`#$T^WVI_l9=)JSe}6l zv6i7@49=g<&kOK&v9da z{^#4g=QqcCnpwt^fRzybAAOxrm1%&L?mjmee$PgBx%ZMg%ABnAe4C(v-Lgv)To#;-*2fp^Xe@2V@aDOrgr3j3Qz_H zerHf`Ny;f`N7&;Vb*sYb{;z19-l|xs_rDn0esBi$n&Ukis&AHP+21%J63cUZx$m<* ztb*@Bvko8=E`c4X>Ab(;{HNtV7V*VD?hq4P&HM1ydq{QQ3K}c5@N=wtKY4Wzw_BRu z9dk*?keAVq`az5N7#R3nK@BYr=gm_Mz6O2?yd}<}`v1l$8>z~IaA*U=71V^6a=IM% z!u&ylSB9;zwYvSCn|x;@Rzb$?`CUOn!TO$;obI{&iux|jG_Ni9%wdE1_os1!c2$9_ z_yTt1&rSPpw@>+e$J#G_!bbLg0z3WfK@BVh27Y%?i`2sJvqRkP|MKgjwkpK*Ezhmx zSe*O>T1J6~Aw8V$D(vZuQf72ce!qx|n``Ca$V303JvDbwtJvD}sE_7_v@1)eeG`nC za69VPne$$1(5&ad0d_;%zs1uPf`oHsizj}ym-CM7Jiie#h|2E?Iz!sRPxE-;MD-tC zhwC&nGe3R(R{nH$H?$!21P#Y}IA6@RSopW_tL=FoDZ9z@-uh{{aY8l~@_T~%eAb?< z!4a$Ws27zvzq{A{PJM>lny~L6qZt_Zy=1^{U_L6Jd-78!V_lWU(VOC0KQ?G>0r{VS zf!`Z6CT8KcR=J?B;+33KyR0TlJ>E-tURZa1p!Y@OX|B#K` z6*SXh-^X544z^owL7hMb27aGBup^ang(07bW? z)1m(h&#rB$+-WySqH_b|iWBFBYM^N{095-2d-gpq3;S#|wNAliMSYz7?)ST+7ecG% zKvr-_vUgbUss`?j6o36|_kY#0fcl4Wpg3S);12?ARI%{;beZ|+)2ZJdroUJnwS7j? zn%pl7q18bUXq~l(^WF;gXC0@%=Kr3{`#ezRME8Vm7eNgykO`onP${R5`+Ijb$0%Y<__?-C`xQ@gD@*5by38R1oQtVX#rdT4}+1eol6$*`lBdmw|zSKiD4Z$o{ww zJNxGsxw5_wKl$K*oq|re2xMgue+Z}*WZ~zmTx8P|7?f~qx^}`=^^GqSmasr;{}51V z@8KM$)!A@abdAu^>WiSjqT<>@zXp5*MD{1ydD$>3=I6?)4&0x z8OONDYntKDqqpv#k#ah>`r1ZSXbBSma)X6m<3-ucf?oP}4m+uNnHQ<6ZBzaW8lPog z;Ex3LzdfAA1FW)@)jrJM<7ZXF-0o9s%%A{nA2IMpf)2Zqbb7OSzT9K2#}lKzl*b%> z^2LQ)rwtmLk)WE_&2zDpsYczxV^wR7zDY)8L|j_ImkAn=16gqn>_|hKGjnFvuIHcr z^qo;}Sb_CY@4L_h6Af~Mh2QNKo$juyNADN>+GKpwC?NBQ@FJ)qqd_xb9?rKJp8P$r z?8cvxS;{GM=AAS#2z&#|vi=6=k4FZ%0~+l}J%w}K065B>%hLpSx`StJmJs_wQ9pxC1(Ah=GAWAq4EmDKAttg*W)8Y^V@5etG$n z=(+hb`yh@?1XTwXe)9q*#Ik0Zt=tpWqIxcCn&&fCTWDu65!Al+a6Wx3w2VG$btL^j@yIG2ZBqsE+CuVaqGG1NWOWLAEyVCxN2f%~SM3 zaF5clW{>NCdkuTpymze+_JJ0~Nxfi4o(eENar-=T_R>s0so8b@<(&fGp%qFpC|y|i z`G_~#-mv%l+^?y`A33Qf;=$piptQ)qz@Gvd(Drcto7(m*e5b9%jzfXk`=8lFso(T~ zY@Xsz0d)%XJ*RCnddkkTXNK{IMx8H<-umtox&#`h2AKd^i!y~hPJ?v^hbHI0y|x7} zw=B%+dIW8WrGh3pEd2IQOFFE^eJ&>JPCG>3@3MO|yEFI)JuPe zJ?HuxavoGqFfj0EfjZ_Eey2VtxcqXy;cm%te?w09ndS3kQy>dw__IKxDIU%NYbr`F z?q~GL6gw0sddPIswypZm9!eIdnGo#B!ZG)$-)H|A-ZeVws;f?Jx_ZqCG!DhUz@Kdk z4yckhPac2Cx>~KGu;unG%dJc^XMP5?T^Jbnb3i4oguVBjwV#fgRAWL=+A?|K_9UsK$}Z&rTX zQ%v{`bdseIR0DfBZ%%z>`tEYXi|^s-FDEwexx9$~4;o$pnE)C*lyaJWuCesyzwPT! z?lV2tu=WLmRdW?6(}EPt1s_Q?YwpC4n%_g;X&Y{zF0p?e_x;4{&~ma6GBc=}Z|a{P zy2&W2`wZ{ld2U}`Wvl`P5Ca2$F~|)Tei7e)Z@p=>?9)MZyV-{huhYL@2kUnigZelg z&X-=k-^lwk&FANx^QXSVyx20?CkwRk8)O2gGvw|W!@bN%&?dRpq=o&mf3(*GfiEne z9y&5Gz&Yn zKPC1hDUf5C`Ab3lP7mkaroQ8^X4&MgpZLM-@h7E&eY_{3&4W@l8u$XJFtj2h|rAejWmAp559zsYUo_+0#2$U9T)rKW51Q z0{rEmAop-~ijDMc3k>Hv+qv^&UWm$u#kwuf8m9tOXT^I8s}?SMv{vjyr^b&7)q*Jj zCk>Z@n(Pb={1uQB>Wm|wv8;P})#IwTc*x6V*_O`p_JBrD7#R2~K~`A!X`GI=-M?z% z>d!`w`zGJ)tu<;}4Vr9YVBoI;&FgtM8$MQz`1@(iuRQnl?-vzDurXXtf=*XefeJGz zrzzq)xK%VP&Q8B<@|*LDdZa*HH8kUZ2l%Z$9hfh?D1J9j-SLmUm8VqOlPxm)VJ1M1 z+7Q=V&85Zkb>0k#s`q~_D%UT0{27|6Yd{OiEc`lLJC4YjadI#EevfgN?7C*bd4`|? z8U_ab8qmC+hx4?|d8YSsv(MGtp1J>vdb_MgW(sJY8>9fVN<7#z?u?Y`74gR(xAi8P zvMhP5;jTCfT0YeL1(y%mxesjppYWUr-@B^h`%>{7M!6DDcbb8LzYa7uX5q(iJ#Xe+ z_cxjj!dq-BdZs-3{P+tf4nPV(RkVlm#fz49_uAw%(kgjYdY*6i#gOR>9fzsA25uhQ z+x1}cl&`*v9~s{eTV3c9x31<8s67ob0n`z(_GEr`dHyPCh8!uT-f+3)3<|%W$3fe2 z^^j}AdZ+5UIrb}S_WpYv`+H@3V*2mr&`J3QP%gLdQ@fRDR9wC{;89b`KQ`ILkCeV% z0qweEVBl{6HIqD?559S^n3w%UTKl^lb^F71=w_+?08Ml;Fz`2mGO?6X;|J4eD`&`d zU3=HD|LOXavSt5MK^X?5091GDd&)WZmHge@$NpXVgQ}pV^cBmsPe7evkOE(DNS4~X zetyO-`fA*d{mB8mX&?ZU~ zsF~#9ocE0FiOE#$N6Ysp{+3;^=NS9{I?xag0|S3EXdS7P)86C-+jE~Ze@lNpucznx zB+>u=VK4=txz;kzJ3XHr-E@=w=thMYa=tjtaQ1)*=sXmV36M)$c*N2Kk4$+W_rPiD zGUY3m&s{!z2-?4B1@+i0{0`}8&pz(kSN*A~zm(!QR{MT}OjOY&^Nv*4OA|n=fk6sD z!!635p_6havRoEkANM2o1DDM$?^-c6P`Ln7069$9Qhb)*oNVd!=U#P%PWDuMsv;Hx zo%m}9o$6uXH&fD1s3mlE+p8DKsV}E&^4)bv7CJ-P4r*6=IKOs$_PEreKX9SurS(E= zjY50br$Jlh?VxFGDW{KFHv50v_fLrpmR`yiQ0ln9?IUQ~l7WH09W*xP=Gp$gOgc~G zuKcW%^@Y1OKAE~vl^3$;m%jtj=WR>9w7B0;Z~6*@ua86dV!xZMp9*UIFfj0ULi)T@ zzeIn0tn};HkGDdi38z0&l`J3ypxWQV`PYo5=Ib>t6dgWXyw*8SM2DfM650~$ z1f>T_Cm!_!cR&8vqFNvGZtmS*k)B#_k|0NI@OOR(pIYEr=iKcX_-J40$G9qPjzv68 z$wr`)$QT&-yC4@C*D(CC{$XBqR+O{j>8<>hDUnSdKYV(DG~?yVx4#yg(-!YM3vJu?g3^VBp9t%=`PMvQ^Lia5_?xxc@^Vfp zKu7j^K_+=PUtD}=uZip7ydu7t!KW@79GSfpHq6ooDyyWN-o`0ppLhP59DT3ES`RcxxB5i)$PHO{Zpqvn@N2e!MR(t@{($ieZ1?! z^+ky~1#4%`)cgqfD z5Ba~>t2**3FVLWe1_R(Zbi{(SS_iQtD1tY$cx$U-7( z0;mBV?>T9oRPUE9YA#0;)s?fpPfX(2#R4sYCNhH^x%KmzEgVax&MjNA?U-PP_w&tt zq0r%lNuY6S3%{km`(2(ZzY}HL>F=MRelP!yY#wObfq{X45@=nFhjUyAFGH*0E3?c5 z1vBY+%fjU4gF&;BAO)c0FXf~rGx^JggNpofrrtX0^4(cmtzH?_EC4A0H52qb7x)S< ztT}uCtV62h9yj6d$rWp!L#>#s3U*|KX!&Me@0R2C?^dmEsoVSZFe4wdu{Wg-+#=1} z{QqiEgSq&_h>WDD-8#aL>fb@z_ESJX4jOHC%5Ym}s@LY}?DxC(uXv^cie~z}oybho#Lk0%^si1)xS5Fn0E43BoVKoo(O}Wie9%tH! z7lPJJf)vDp9of(tro%j2czVr*(&EgJoC;kXGicVE26BUi-~453-yd9P$MsCRV)B|f z-E0S9XMqhUbSe$Pf#_$z`#Epv_DD8DgA$k z-`lz)$~POM?807eVtb)32_0sc4w{~b_q_6F?cN8mxtcxSj5);5zo_uAn+56&gG_*2 zU1zgY({a{&AJ;=$>x0D?Yc>7K?g!1zGBEJZ1Z_jJ@T=C*a<7SzKUfy|_Eelno*l1> zJ~YA11l1QF&YIKpY94P`qvH(#KuGp43zgCysr`S(^ zxxIRXFm%*?E@;-;!})q}MyS_m?kP;|?tB5;>|V=h9s%_dK_-BPr2{=>)*rj9yC(8} zZt&6&Gl8h+B;P`4zL*DTy8oWKj{W6N-lrS?MzCBw6<%W>#RqD;Ffj1Xhcw-T)Si_& z)%?n56Lu6k!m-zW*Szo0cGP@OOT@!DdyYi8oba^=QL{cj-k9*YF8B9LXyra1R8~tl zNgA$MsQ5|x%3I^8=tjMh#akA^rg7(k+!E`#DScvfaeedr`|O*wqEofQtS7R8mg+Jv z@Gl4g2h?uw%}iWp-XD4HvN7&}plLKy05_<TXp?mrs5q2z3UsaU z)l&Ik)wU*H{#HG6_2WsC)GDth> zA5-36_OhR8>&{=?sma~a_OVwGT9~hZw4ycSn;qN?Jp6KG}`@ghMwq`hd$7r`znx09?r8>x^09x&fAB7QQ|wa zZqb34A(7Cf@%i-5=#a<4_C?{HsC33vQkf2lUF8 zJYOI;eL?WqTarbqc8PF+YFv;4Pp~61)@9AqyOtNF$-XV&#-$sn%Wfz@w%hQp0Tlxl zepAi|D=%H=v$!g2ci%V3U!UD?g+kkMYe3Wc9?laY`a0@Qi4+=&r)q5Txf^_P(gKhK z0|WnBP+v#NscMlVU+J}mUCSNXcKvP17F`-W8*+OE|5`{ps`KN_*d^0H9@TU!RroaP z!TaS7uF&q}T1Y!8%HU+ct&2C<3O@@jbyYBkxodJBRDd!t@UMfkqhf63#W*|Pcdom7 z`MHbDwQq-cdO<}GNCBu&_i)~%W|#FaVm+iCRdq+rChp<< zwO$^qZ>Gty+0MLr9hBu582HzNiUDiSuYZEWICcwbN6hR?u6)*}9@GV^4%W{Eha`hX z-(JRVqKd_0ZG}}I4<=cOT>>rtVqoCk0BV_9_}y>I-uv@e(dHM&{GzRr?#2GuZ3t?b zFfj0M1a*o%oSkpEYD)bpQ*tub7FoF6&_5`q7#flrL93jUJtt*;_w+F;HTuu6bZheG z^{@Z=xPe+fAQK>isL|aA-%iQPR*>_XX8EH{T~aH}2Gm<-VBp^bs=F=xegtJ|=KtQ~ z_A|U&RO;&g_Xj75K^wiBK^-v<=NrLNfwOIW|Lr@+6#0|eElc_RQBa;_VBp^j8v2rQ z`dEF)@{IV+J*t}~Exd8Qw0ZWMerV;s8B(!k%?N5_w!%y}{!wC@6B z0;FP146HMDoyz5}Q;@~|a8V4~VMc9es@@8zST8N9PO1rhRr5KlTe5!3x65ohpeK3q zZ-rE>*(Mjx?3_8z(#TmYr($m%zxuj6pdLE|1OHY~x{z`@owEC^`MK98)-nnFyz*5s z#o=l#XvHB&0jQCq@2MKo?CfRt$lasFz`jxKQms}isLc%1NC`^q|OnLzAa6tm2!W__;+ME`6ipygse)qb9 zr2*>5ouH*hQcidNcP?{$;U*_3VI=!8<~~o}D=%oG-3eODsqd*McxCdo%TMm5{0zT4 z_qkL6f7V6N3RDIL{#}qA9G8=BIekkv6OcZ&Y))rJ{QYQyCD0mYH;A_In`81McjGkU zN7t8};ho5zy!zfhVdzNC?p@#$MLsnAJ~30>PHD;#pLRLruq%6FGC++y1_u5;pmIXW zsrj?hrY(MNzI?NG(a%`2{>Zutbx^x{arQcsrjK z-=6D|+OaL10eXQi|2~j+<2`3*eO+_VIrGhn&ga|PzV=UD`z{OGmfHuJp6C=)*(dl^ zzUG}p_pL2UzUJM(_yt;!9sotVh2QLa^Lop3TXW6lp4|H&%i+hJ5I4|-9|Hsb0Z_Hz z;r!mrImYBipzP5U_bu6an35QJVM&%^PcHixf0u~Q^H+n0 zxa@M*#`KA|Jb<5|Uher3|YH)N5Z1P)Ms+smnW;?y5R_D zqo;+R)Sd3o+w2qk_RDWqHrkj|?{;Pjv`u>yREK*wN9~UeKAL#&#{W${9KQ^E_sd-b z??+-_;6Dl~qokZpTQ@&@E9Re)*788^;Je+ejg2or)ged$s33Lq>~wIK_xaV>;8W=B zByD?7&h*@D&=fLA!Dg@{b?^DO^HsmtrE;}3mZ9Ng%Y6j}=&amvkQ*%gKCe1C`%=>< zd#@?Sx4HlR{Hb(;Ca7t`z`%bTRH=D5Gs;YfH#n!W>yN9xWeY!3*kt25pdLF&0cbQu z%E{ZUqeD@3`)L);49mw>VqY9}^`RjN-nMJ)=@J;uHq)HNe?e{1`=A4bn?C!^0_7-> z2@k=J?4OsrNc;cOsWe(k4d;PLEx=eDwT=3lxjJrP=%p9E!pNhd?L$l}DPv{x~+t~Bpm zR#D#WSXGiT8TfLkrR~kdC=-{Z{E8(m%2lvuy9R zE)UrD>8KXSdkhTxXF+wAh2M{vMjpS8O;>+yb>R8Q;*R<2>f=C34Ws~6xqCPtX_>ZD zhH*yrzCUvX+c$N_2>fk@hU7Uj@S;AQT|2GyzI@H*e3bIU-rt2k;Aj#^Cj$fjImmkZ z(i?|go&Ee{-R5+M&DVQAoe5vC96Bj~0hF^W{3f0b7dR1G%Mmft{@AK@49_cnn1EJJ zFfj0602M(V&W4WnkN!B7nm4C?@!!sAasl&fg`nYZ0aVIKIUQ4o*52TMrjj>o(w6C( zM|yU>odC_77eGNB==tQ+PK6K8C8zivY08*0o1mS*AO)bc7#_}g zehIUiuim)xeRn0Z-#^Cxc?;i8gOo6rK(p3TPM?-0ERB=%l)D&~#4kPL(G}%sevtF4 z`7ePwgVvsQv+gUIZm{dFV6)#NasRrQPfs2@yNfZ%hRf=n zo*#7e!WGcQJ`2ASPkyl|60|8C zQm4n0F5h-q5*`BzVvqt*%T&tAezU?!k*9Y1dXH~jGi|=wmwQ{gK?#L{f&VIK?V_uv zSi`}IOXKU~SF><$yxe_W*J|x&P@5j40J2$zPw~x_Q|TF7SxTduR?U54ufBf`w5+}c za)X7RdU?XG&mB5F{>L5{3H-3x%49Pa8r0W7$=<_xS7Dt}K>cly0#IZHdYTob^DSDH!s_gy zb!&Cv;8k^;zJM6m0vkIwCgUU0e5SnJ}%pH4?nPK<9`tF!0|1jUrh1#k247 zXH1`7t|CK^=1s=XTGpyDpUa-U)g-CBRcWpkj(uCUm&zCTRLj z(&_ExhD9rdQaq(|d~cWZxm7ziM1#g(7#R3(g33vK&uQ}4#CY0tEOch957_VXi;+7R zyj~EbU^m#2;WxHA-b`oR+IUFsQ~S#+OVgfCgO;?nLC2q1`27igB>kn|a`nXCl`)n& zTwKk}0-z1>3=I6YLHWbOIsE1CX)fzm9Az!I+`GCu{^5ZsC!ub*4Js$3obFm?t@k^= z&i#Ip72C?vM?5})D$qjgHmLXP<~f0L#(K5eC)cgAf3SB)3Fm}O$1^}P#2_mmYd95T zeml>LT;b31k!NRZYNxW3)Ba!`SnJ;srnU^oVyL#p&NWQoW z%Df)V(`sb`)_aDxuxEj1_d>5)Gf^&q<$82Im5fzKB%!{;kP>DRJ(%RvV^=@afQm+!Kcz{?4hmV`=I8MhqF}8 zHiK@lwJnpylFzHO{r=nXeI2wd_W-mrSjvfUxyAPErsv z57ZYAK?@};{0hQ(R%KN_R|ztno*DgUbLR}UZcv@gz`*|q)G_yPzIeFl&G*W4&*Fur z9alcDCAH{IG&I3H0`(fDoNlCE+^>1-zgc8~;4P`O=8RzmIiP7vkO`o*2iBhRE=^6a zT+kAgD*N{mqn^2#NK65=srG0A*pVJ?zf#{xzAb7$#?usGxvO^i(`0B|JO<4GSorOH zQD`BfyvjV0XT|@Y0!5eGy)!c)(ftH8cF>lH6BvEW^tbAq-L%sbI@I$7G_n`$Imw+>zT#bNLhW=L{xf23C#KH) z1Z@R9c?NdmYQ713_AlD9Nn>k9bl0(I))yxVKvxz$1C3}|_?3&gpa1v$W{qP&;Jgb4 zvu5hf%wZ zI|erOI#x#Se@p@OR2dlfpMm;W!JZ~(O>_I_o9}onlK$WE|JPJjCh!rT3=I6wA+xkb zufL?*NSPE~<6wWzeN=Pu*I*OSA{7P({uiLOjD_Fvz;jJccbpgevBG_$T<6y>U)91v zXFh@yfM!ZPoNF>}{JFmTYPS&g9DT_P$7QyEJpx_-@Degh%V+TY&Z_jn*$o1Fn^tv+ zOU%4@05syyz`*|!G)o)odGyA;a@My=O9NxJsOVPR$ot{35wti1q@WNSlHcU-9y!U` z6sc7A{pX^6b7ooY{RbLeVPN2Y1c8|Y-yYbJ0% zYoWrwn6-f)E=|!wYa8R%szL_`-h!55c{r;jPIu+v+L?ZzKdip$ z2+IP6>o=fX`?sJ40#Z(8%4&uQFBD%M`EyagF=_tvE8kKl-DJ|Gsa*te z9LNOF=`QY`Ro{0vUwnqbXVi5cH2+ri1$ZO<>ukMnZxYHod>xg z^}Fre`Fq?BOqzeq2a>x#f?CH?PHz;}Si4^{wmolnXG#A&muYR=)S+e6C(w+!wdXg7 zg@>0F@&4s#Ub*XN%5+t>pB11Yn1O-+6J!#WwQt|=GF}1hmTBQPdN)h@`EC9L8Y5<4 z;QtKj%31go6V}y2RmrFjCACG#&?102%)r3^1=OuB^IW?}%Z`sts`Z|#($X*I-(USx6$@Qa^93^O7B1rbf}N{C z>*S}WJ%4VN^&2M1g32Za2L7**VYhgdY{5;U%iaHEu07CkGe4%HlN-8$>l%`z46~g54bJ(R4VjAH^?)yb63(~ zXgBHysEK0XXQRe5_x#>D!e5WwFwl7V)xv7Se&|xPACN5`IrDh~`4mdE0`(7weXG;l zzSqwcTDkuKwWp+<6zX*UE0-pSbf@jpUB3C&6^{lFP*;|Lf&T|+q*LFMH8OKqc-`z{ zYgtznAL}hzqqMyRv`QYN0Mb18v9m}vL+;7$@W*We(Nm8EP7=|8mQlYzm79g1Mc%zT zOIlncj?B*wT&mz3wki-*XM+aKenFZC)w5W4giiYEZ~nCY*~PQX6LQ?cpo=_zftm+W zPLW)x>~m$W2(RyrWZ(Eg?#ls%bD-lb7#R3}f!dR0o=a2MU5@=?FV#A|c+ZWSNBk%9 ztb^{~{0-?P`Ck2hXYxXuV&yr?9#2{l6<4{w1m#Hv2L3;w#;=7R|C6_-)j`$K^2HlP zg#wo-`bISYYJxqTjad#++TSw_qDaRfoeMj2L8XGUXqlPisRA6 zyPiaHe4X=@QNZX=)DIVCXqEIAGJSdD+sBKK@;-+d9N+eJX6%aeXYH?`J@>zm=}Uok zvtF%Tw$;j^F16>`e3$8|1@ECdIR1lr2^M~pOwBv&u4tICT{Ldm<@Ch0>rPQLB+2~; zjcj>1zYA63czOOR|JT*QoM8_|wTz$lLdORGgX%6<&kGZkw{7;@khMDPOz1Z|L%&#I zSz;GsE+X@3k^ZOhGvcqyRMEE9J!T zXRb<)y`x(XTNu;T(s}-2$98}k{U8OPW#sXmfjf67Z8N#f)6T))xovtrqe9wN(4Zj$ zg8&oc7E$(FDRbE_$gDprsmpor*Dd+`31=Zyk^plBc-YPA*2MXS_1i*tm%Ta~GKH_{ zKJZ|@&2c}^uzlsGZ|wECr@yT6Yz~36iUn9f&1Vni z)aeybi>LfFeX@aNPu{x~+aK;@flR^*uz^~pQcmx7ODOOg)Z~_#IAO-ngM=t2ec~Y`2I(V+DrkvU2 z>Gu1!c|mGD0d`RL+QP4)mSeAg_U8|2^%Xbm*BTyN{I3&|mf`&l8;zYo*`9$xfCJRNmU7ZaPO-X^7Q=sLx*kWPhg$Hx%veYxM}PygW-rz= z>d(I03{EqeB-70}-)aY+Vvx-RHEuvAKsNkduh{+g`mE+B3l1FYGLYo>t*XrqO;KE+ z5Vi0-x%7zT`QPp?SzZBsr&h02YiksNg8&bx0dC>vEt9x9VSYi-*L5!EZmRysmttKCO|(3qZJHj=^Ug>< zFP?F{!?gIa=Tm9F+mAD!g7%+)OaLWbDJRw<*9$%OrImwgKW_hFdi3Y7Esr5>7y+I; z3=9m)o?hEbV-#ny+*#*ud~cF8hoZ0ZV@N|wfagEhk+araDi`KRn|Wc*gp8$Avo>yB z2%d#vU=ZK~O^jRk<^NXNm>d;vU3vZOg^49`chbG@K;wcB)ByKz{w0+v#C=6nb8UjU z?1ponyjFXKLy8~)K2W1q(rHDEJ)5}5;zbQQ#)qBGf<%Qv;!`$&9d#`o5#NYhB z0JJR=qyV&xy3F(Wx(Q+2!jYN94?O-%(mS13{Hq<*=x1OM5KIOKROYP13=eRVT?(~U18!r9hYipKYT$uzJUJwuhoqyor{L(^TlQHL5GfyV>VS$q+C|83N zfWkxB^9c9trH||WbzI+^xYhJt#Ql%6WFZ|f0b$7TP?sAwo%Liaw)^s9iq`IXd+x=_ zZ3Z=V85jgaKqguEP1!VUwtv;BM-20(=BIPkc`k8(4OyBfAPQ<%dN?1-VhfVFa>2eP zpk+z&=3a@W-dK=M1_l99Q2i<8bo6Xs<0+T+{ePQyix23}y7uyeB4`W+X3Z%SrQ{ugDQt$hU=-J+0<&w9Gm!jIfm^RBpHc*uH%!mmb`O^}s`0^*R3 z&u>Fn7s(x6lj&SLCE{oDGS+N!ZO9%{0r2td9?rX?t})DYVZ2=$X}B#fRrNl>fM!tdq5iUV>#Y^#sh zC*D$8?Haac<9bLNMnDqOI`(ju4L@^RTx;3fC+1g|>MCeH`KHPX>B0y|f*dR9)EfKV z^7!&U^$)x(cT~j9H*5$~1PwDWFbGJ3f;`q!$m09XhbGP0zrPuA7A(G0R(yK~Xt6H? zgMbv|6z(mz&1P)?hh@K^MUV`rdu{FcI$Y)WL0QiQ*SPj8m*1bXM7+oZ)I(!n5RieiqYfy~ z>C<=Yn-v@VV(u8Uck#=dqKESFjeLJ?p@o<%q#fnC z{8wPmxf7Npo4XFh>rQYvE%^Y_*b|TgwWIVszkVsORy=L|^WpBv?=>C#eV<0>fX2cY z7zE@}!Liw~>W*ny(v7U+IUU(eta3kgY5Rc&CKwn5z$fuzWRNKocu*ln;xV9a{1k! zt((~N^^D6{1%2*F%9ze-&2@*g1_hKry=DtP#;1`Fs-DjDl-uIRqq|$OUbgfS)E7#i z84wTWu{F00hzTIPyrQU7JfFO?>W1>)(QRI&--ImUYTmBwGFhfrvllIXD*?1=~ruj zXTr}2nP0D-J!hT08qyIHPyrRBQcic4EftjV@R+a8ch#cj%ECWK9@v1g90P-Z3aGRT z^t`b0T~YkD`N1Z03xno7^qjC#|1e~LLO>OANX5D@H@X|@yYz~WUJWysyLSIvyb(Jj z$*F<%^;-Dp2_BEpWPXy?HDxmYzqXAmpB>ghmL3VHK@O?7HhYroHxVweb$>cTvMl^q zCZ~WC3IhXV%t+E{508y3>$&L%6&6o1Y(BV0Y58lj6W zyZ?$;D^$IjM1VCG2 znvmOdXZmh#RJ&cJ_2P5jf*DsFl_I9ZK~2yGjZ0bhy?fVoJ3jUHUW?*u+B+s+CdmdO?@ibieT_f|g&;%4f3=9I=pdn#v&*leGU#fQIRAq7> zWLR@NjQQX6C(x#vHe`#3AX9PR!s+L?yPThFzhliNwFs-5AlEZ62+riGv2OX1He z*NSszN9f+4-mo$1Pi6>Y##}%b)Lis%K3^0TtChr7=V$ydcV6S;w6z>}A@f-Rx}ZfX zQci0$!lT3#Pj41!%jVo1T)-&~;WZmua|5{R}D2Xio^l^K-TOVkM zhk-#r4{}kd-1oT$W^)H=-#nnMbGyMecGOUEMxAb=&5tlTjn$@V>e}d+lx8S%}>|9T(G`;4LAfD7zB(Q7#J90J%yi~@V?V9)rzq`B+@_q zv)~1b9B658G#Bg!yGcA%n{_=@lRi(cyf8tMZHN9c(C$+P1_5JGNo(PEqDy1_UGAM_ zu8lXYls*z`DzI1sswWs21WZ5`tcUZ;GX|IDYS-CC&amy&de_voxPA?^)-wUEhmmqR zR-{s8aiF1d_ng0bjsI>9h>6_+s`Wu8fSRoCo<6QS*0D6LIQKxig16$?4?T&O7NFJ- zNCD&?vFOPYn?I!N***8FXsl-Uy*+MDd7y?S1A~AWX#b*xU#_S6G{NM+Nj|%N|Ig;E%Fk}IhfEj3D+rxR&+QU{KBIa*dSGH`0fn7UW&jBe=;RP}Q)SZ-adOv;o+wVSM znKpa5cE5U>CZ8d>-$xZl~y$LGSAc$YUr_}#I9){j4+ zv1tLCo%3+sZhb2CtjFnFhLb)7|5FpMxhU@k8u1620P0p+d-8D{lV`P1jl3=D${Q&C zEp*wrD#+NNfF)!hdWw_AGwxQNxEoxG&ze@vV?8AG0#qe4FbG(ImU3J8^=p}YRF`3u z>)+zn-5)n?C6in)WC&Ei3KXjz&g*oJ2t|3~drBdbbfKBVCy_X8S7Bwf4Oz5m@rOJT@O0RrGH)cT$$=BHg|juH*r;Js@4 zlw{YcR{2u7;u?4B7I7*2FAEBdiCzhf3p-F-#=>v);@gHYR&TCs zjVe;{)qCteEA}pA_Cdf7)P(nNzUHR)uKv-{cjs+BNS=Jb{&UvK^U$1S59+x~Ih}I) zA=JWd_9&iVPx3bHPwcY4z=LHB3Y3M&MJ1>Kc#Y3hsNDK^*Y3^99^?*{Z69=TZ13(e`0*V4%B{PU=VPDOv>jnhRvQ`BhT4h zVRrpl&?U>6T@Rs^nk%SVY2hdFf3b3awD)(J!-rVQm-X*de{=xamU9J7h6xAE8PGnj8z}k5 zdLG*S_@7O?27>^j_v9F+e>X)}eS~%&+;YLuz3S2KGTm%}^Z$+0S&EO{XZ`G}K|?C$-ris`a%_@zJZ_wzzj_zu@M52kp|jgYu?_^ZieaS2xdkwB%C%tIVmJ zGOd5V`T!a|VPFvO03BH-mF!$7XfY zYC(8e%aYz{Kfb3tQ;gmVtrk7{!H%qJZ{OJ^Y&mKAlwJFzBF%&MFkXku!U%YRnrs$+ zS&ziiPOS1gT*@l-_R0kPRR!rj&}*0{%VoRx_a3!u^M16rZ&?rE`Q zsbzN9!n}Fb2RtIBALX})Ke-C_hJeotup9U#*A+Ilo>-Riq}8R)K2-ehMNg;#KhTDF z3qK)0&5&2UZ=c+*?PFmP&y;`o{u*e)kAXqJ4>XVA;rvI4;rQ}ZK>~BjwB|EJi_F^h zK?EcLQg9HwizH=V_jivQo6ba4${2oPnRWX?$Y0R-EJy*U_KWqDIdnI8_Y?Qs{OkEo zTQ5!dAz5Y(ZS47*gB`g<$WZy(rrp;k=1#2NAY1!5sD33hHUmIavxQ${_~*%~b)79w z;#AGAE)_Wa?WZkh@RWf;AOMs$J)9?Zss{b}&bo8`@gAA7ov;3{tiKLz4F-aey_C~x zkDq%@^w(7#ncC*>HE%j=a^w+cofQabE(UwvEqZvG^On!T4#%ZcZ#|#;hjnd)CYZol zup?#7bx)TTIG$AOzwqhc{nZ)MTXR7n$iN^F1ggU={J3t%gtYy0p4t7PZCi4x;rw$| zIiRYDfk7Y`REK*wm&`t#{&zwLzi#fn@V*%j-CQ?p0u_HC1)z}}Nv8r?i7fZ}hLi5= z3^(i&Wjz?Xa22%S9Sj=a5BB6;yztY}vaFlC3RqrGeEeZb^{I`}0juCcU`M`UVLEV# zrS-5>*yhs18-jxW1kM5F2L=X#P*7QA;TQUp+H_J*udi88-aTj$ zAd}GoQJ^&#QckKBYRiJRHr~jpyDxbrI!Ei)=0wogCFh=@i`Sqw*TX}M)f49Cd>!L>mFUwPC85O-0?8r;AKJYT+ zPCw7K?yN6w_e-bWE?%Im!VC-o(V)(dhw}o>PfW5LuZ3f)uF6eLy5OB8^bxdbfq_9F z22^)TInAG~=po_vU$Qa7+DedJbvM66IA~cUNC9ZZ*xK`J%xw(Mq$ z$`k=;%^L%`+-mmaCr-luyz=ID9elAeJ!VnrZ#_^_V_*=71uZbN@SFduBw0}{l4Bo3 zMx)6^*@7AD(V$3TU=WA{HFi9l&mDm25l?{9Bg;w6yE&(W#v{2US&aiAO)>?yYEnnqS#(T01I_BG3f91#*aF$G#@#T@{L z97C*bSz=c4DTj*0=8H_2(bE@-WrZmlqTV3=9HEpi^&=I4C-%#6o8tI9?lmoYo%vdIsbd}tSe=c(1NJb<&Qxj)mU@=j6%jZOoZ7R=@_e*EAi*Bn4%Q@YX6l+}qZGohK)@VsNr7)HqiTe>UpPT#Y zg{|Cir8-N6K*Np<4B$ih8LU08hgTnC5k23xL*|^+&FiXbrP}9%I^-Y))?i0I?W)#p zzv+F`DyGza{Pzy8>6_M#9_uYiF;ARW}LmU5Cvn5n^OxVS&L;PR}UCKHSt zR&zjBM+>Bb`dhA^a~#Vumn<$*FT0jBdudCEr>{g3v}2wQIY35W|E=o+hp*X+FR5|n z-h1Io&W$e6;!XwzfeervEd0)TmM>E|H@j)uz1e@S`ph*9pOFTNMFs|eOwf>zhx4ZG z*-MfHl?Clz-?_O#{>!%hY<}pNc_yg&tnAr&M19{z$s9eQT$kO}|CYL2>P&tENt2n7 zX}bxMf4F$f*$yl0WPkh0*675`Yl}gyXJ8P>0#&RQejQSif>!%D^NK8rIB@Rdd2y-a zPtajEaIAYc3)Ivu-*@cvy=#_s+DqMb1%CLL0$GqRkPVr(n{Jhov}Z!1uyU8nJ~gA_ zH-Zi;LBsJ33snHD;WoGBd`PkM&646W6z(o(ThkKt5?pxQ=AWK{KtFhUc9(wnc3<+A&RTgZ(6KupJvbnZNn5m)|t;@{u9S*eB+bS z3*APCyR)aUht7nyf(k*)W-a_)T?sZ8ei{8&b<^9>6aCZHYs^)HcB2YGi=RE5`6N^P zOc!mJ{~RcK==!p*)W2otKs|N_27y9Qfhy%xn^q>Z=y%j4o#ed-b+h-G7VM6K_S}m= zNzdBzuxicYpHF=L%Kv;eWr}xp_?{(~K*b*egFulDI3z_cTx@=lHY4{$WXPYd@2bw` z))qm>X^TPOVBzQVaq?Vd4QHm)hc&iNf7O=~(f}!m83c+!t2jKIwIh$d*e~C)W!73r zUba6R7fe@O1r3%lFbI@@;v&#fZ28Y^%Vz(7y((nsCr6ve#e$&%pq>dx0c0oalgB^5 zxRgjfoNw`a?={g&7iO$)1~t(b7z9c|wV#FGs#LBS``Hf9a?st`aN1JuLj8#ukTVAa zN9Dgs) zs4ra0`MOzN4U&1wA%|pc3d(8Q-)8&9psMWm>zm&5PZwj;)>wKaO9tT*7wb zY&*26Rt0j4yQl6N_E}HYsq$q-g~xt&n!C;`xC6BNlz~B@3UWlY(aRMFRQFt0(|dX4 zkU=!V@~q6$&~mZ{)Zeu5+rm)mcYgD~r`2A&uKM5ndB9xGsAP^}L#0o1*Y z_3ZARYpQknV)PE)qme0wQ|E20Jp;}DwYK2s*6{a!xvD7l%a)njl!X5khxY{+f*QLF z3<7nawv2_}p>O*8M8h`4b!soSlvZAow|?Dbs5k3C0p{WS{IpvfyF>X!<2SQJ1zGxq z=53S&H8dF*1nNPpfHKd}{1-WOIsH6``|1>n%h19k(?jm|e~bZna{ z(&x4Pm6^N4==Tz6K?*)g+rsasaIEZl$(q$O_Fq%odOq0ugLeqDC~gF`NIje{mvqdE zQR;v9BhJ4l`TN@=s}?hAEmV}w#pueqN%3mp8bDp}glnS5E#W&VW?pv20+AkYZv zU%Pq=>}}$m67w^DszidxsY2$LYYX2%^F`wkup^ITMt3hh5afQ6clPvDH*tvk)kx^?ZBR`EQUF@4;omSRacNhe!G-Fm+Cmz1!f^KOS~$0<^Y&<;p5sD-ZY`HyjvRi^E; zwhK2GZTlQnC!Do41M0|T$g<(0`@Y4~LZ8~mtWtXTi^KiPANdW?Qmz%0vMl^6OB`i& zSN)84eE)=#-`*i+rgbW)fyKZe&P|(l7kB`p$f2lV9KKE*-VMQ*90H6t_W^XzpK^r*)>SZjREQ?H*0Znlruk?t+Fx zJ7`49!td+MZRak%v(ZwUX4rf#bM-lm-A6&QaSRLs?V#m>9?lV)*xJqZy_)6l^5FLz zwfD1JmdS(s4^jY{os)8!F`Z>=@46HJ{gvBU&z%*r)qb}C+Q;btEzyki)biYQg}ZNl zwO;hT*$($EE!p-+23iDl$gC?*#%j{xuD0}EF|dYWskd4lDhtDeOCPX1yq?aFbH&m#^)^j#4n^NyiDSJF6X0h zQ0BO=eDXGXsDd8Q=z)i`zaam`SC!i?|LfQyciK*Q#h&IK(6|EwgFp{t4JXUzvmf`m zSUl77bdO&9a`jh>rVr4CB0ZpDFxa!nXXoh!c#xKuR(sr)aUY85)+V??v2llO9^E}Tn>+Dxz_y5B+zryX%70~Pp1A{;x zC_Frzi*>l<50>1%{MGZm-n6B+orX!ZD+ZpDX$#;3g^xOO*%3#2=u#yqx(eVnlsNU{Pn&t z?~&LQD_*d1;Wr#l!=hF2mXIT?r#X)sJ_x`WlQ6Cg$d$o z0->#-Nub#W3qPU$`QHrhJ~+SkyV113Yc6?@9$te+)+ET<1ED*oGdjK)?Mt|!bouQj z_0$IUuO(sLm*>mLX2>ozmKeyH6^xS1H%X8TMSA$}afk9vjD9A1R zR`81J>Gh}HjB+Zh|7o$*_>P`GXg3i9gTPc!neE|RXBQ}w6rS?N$57*_pGNQel@$!2 zA{e9qG}6IG--HTsPC>+mFTWL6YY_9A5O#LkzT@7^DD{E~K0) z8pFl;q6N!V&-#9~vEliR1ZeinOs;NcqS&iqxv=e|fJL_sG&XM#r6Ec~+j#e4O4^i7uSHFryK_;hGP z=@HQCPX-2onV{{<9?t(hA2_vtc6d-g%W{jbmgC;$Z=@j0rv+w$(x#M?lo6k=-;0&? zC)tmOUAmqwroz|>9TS@cN}JZ6a^pa4@Zw@?`LRq&j!_57JmOG?FjmH^MHf9`FfYbhUK;4f1iO?e=;x# z%mxkUdN|v5J<>Wax;THKjbHYgp#73kYVyz}SaU%2rj%3uUN!cYU*>Pf{d0)%-1SrK zCv58>8yf}YfDX9U_dI8_|7P9Vhx2ahmndvqsdFpL^1>lVqMZY2Hdj7<6tH0VIh#M; z>)sdHRA{<~9DzpnTu_~5;iqaPP}!emxW{Vv~w*jUm(lK z1?GW<#H~FAi@veU)n^yJdhSz1S!DQXc2*|n1n4}-bd|Zh#+DTtuDNV`I2G2v_W!$U zZ!dK5(tOBt)hTB2Rl$qcf-01qS_G#YI<%li8#)fN0MzL7aQ@&nXTwU%(`OGoQ(kkK zcfr>8hYo_`fPq0^0cbQy%IU3VtM`uc%NNMBdcM!#_c)#wHUZkMUI3b|a`(I-C()*_ znSJx%qYKUQcjrrppX~xIg9DiWIb^%u;Z;p(;$r2C*-M$0YwTI|LHH}QW4;Kqy2rxr z1&h1cgpIm|t)eG##ia{=oQ-Y;%^5H-2rL3^{Pl3Q(phkhb3ZvG?e2umUn~K2Cq10CqqjOwnl4eJ z_hzTNQl3;?i?|RdSA$Fd^;o5xp1Zcp-Q;-gb5?c&lkttoOIADF2KDhk3P63GSWiXy zm3scUJ?w|-7>?YyP$1$pIT6~&S*iwh*@Rs%hwnBDmN6FPK}uH6+H03Ag~Nn zm|6H46(2kyqRo8b^3Ae;p5~74{|2-|ll?MKCGX*^-qxU9_VN_Vb!E#*XYDDlYwpR&lWrPTEtmNC zwmny0#rF_81iBn@$o7fQSgm?1&h5Oxf%hN8Irw&)@g4Zsd zX0}cWTr;cnxrV~iPiN+=4%^ZLt<+Y6`g(4jUxb+Uu0F6PV{gawd57{p#I{m8t8t4kR+ z-R#S}a{!X$R^I`~rpv?kHUD&W>{GYj)s|XtKg#$~A!ywL1B1X?(9KI0esaB+U1hF+ zf2a9PI#*i%4A}g5LgQ;lC3?LZ+#lOOI+`Kng%TR}bgu7Z1(eCKDf?zoqu#j_PZ*@)rw1&1H}R&2Ns!8X?)NER+L*0=0D4lTsCfM&!zoMQ!T1)nn6 zWxkau#VZUMDvl|2Kd zz5ANPKffU5*+*B)kYtzE^&dex85jh%+y;l_`l%8pKP`NyeEX%mfs2td&m^JmprI}X z27zs$c9ex*aDt6GBfrezoR?ym{ru*hn~nIPegAEsLfymp2(L!~qg`_#r?ANJO>_K= z=dLvX4W5Eb02KpLPGM1VovJG3^RhU%GM{R`wYZt#9%M*MU>m4wZ|x~u_07b~Rnu8X zCnI*=$?VoYHy=V9oZC6Uj%?&Vd8F5n@%0fK){t;NHMW4I&Y+eD1B1X0Pz7t@7r(vD zbX)Axq^j(fk50U*DOj7f4pifU6o8ru9?nT-`ujVS6y5nb=k{_5&i!fga0WE8c7TqW zkaUXr%DJJFXK{Pb|NVMF^Iq+=Ni~5^{OthEj9Gi;zLMI#I`iiJ!bCN5p$~hvv%JcM zwqbTcuFsR6H^t%5D*?~5VGpKn$@i*R&-?~*8KS^0&;hmXKMSCJAM{#%VGSHuDHanoG-{@+Lrl4 zaB0pKwVjFDP)F{CEb>fxJ|XkzVQJLX%JooL% z6MF3Pvf8(ItL=RRO_TdTjeiekXOSsN?+ews;*@zxqZ3!ok#)NZT2IWtAg~`a?B?eA zluNrKiGA71uZm|+im1A8PuX4!>R*8rKHxGiQl0BSHF#jrlC$LrL@^zc6A9Gf# z<*JH;7LYM82pj~JlTuEJD}z7IOP-hcG%4@Oa})bMOI8Qa_$){PXe2|~^Kt44lO4gf ziyDOEO78YJC52dKLDS?x$QJU6n}b8q+`f)<#96oA??9?q-3d$P)QGjO^cm(o+r3w^g`&KGD??IYO*sh2pk73xv}tz@%XhS$)`}#VyZcZP>;0d zu_r9hiJs%2olPFjT2bA?(ud`yoyzCf{%g{%mi;$apgVewgHpGYQ^>vEeY0yGSe{|v z+_!6C;-Y^xYS1?AaZvkO-_u0v`hus`KMt%r7F@VHc7^m)W*O*Y^a;pOT@%B;d+~)z zmy3K3t@!h|n(fDYW>AZqfkEITsMl!Ww|>6U%zMp0()OA2*2sn~^1QK33$!@|qyW?+ z^Kce7`RF{`$>C4cr!x-syXQQr_U!;o@Gvk4oB}PIwf2lCh?pc5ykO7j%Yw$u0vc;$ zEaRa~lv9v#TBdx3=KJ1z=FTx#mvGx=fu5G#OpyN>7z9p(I>i=#pK>n$50$GIn#&>7 za`sJL!@G7P$l(kEr$L3ehx56{mw)}(H*M!BLK^E^l!_)m~>kcG}6t$ zAaD*;^LjX6Ty(~G&7_zE>nDq9UwI;_7O!Xrk^m_HwdJIoQuYP2ZQG=;ziHRM>x}v@ z1FSE;ftGUTK!eKqo~Jhyh)6E&pZV6O>}t;CyG~ESSfNvg=ODXK75}{vc5M8*Zr+lO zYmeG({iwA3Bxs=w1B1W?P-$o3$7L}q=C0<3ilx~RuhddEZMm=Y8`{vi02;XRaK64@ zW6RZBtkT!?t&SX5k3Ge8Xf3pna{;uIMaqfghg8y%#DACOygb8n`PCnmd;7zobF3FY zMNye&i7K0U+63A6iiHeqWgXv2qc3d(jYBao2wao^=ZjUA8#I4J9Nc(5>rz;8%Za$< z34Wl`je$Yn5@^GYg&(VJy@g+s=;5mu+dkGU{2)~2SOz(uQsB}`aI09Vso6(+6IUmz z6>ofu-M@)_AN)b38^{FE%6%!PO`)mzYc?n79+z6%ylQ3f-~LyY(AlWV+~Bn+$EIbM zdwabPo%KvTS+l9+ilVtAv?F#o3+%|Ysg9~@Gx$`zW}V!o{5B#u{`Y@qfAb0`3tITC zO_+PwKJi_~UQP3osFIXxFK2HAbzK-31g?PUZV%_$C96Mg$e*}Gp!66^H`~>q{j**` zTVhv1s~`hCb=a0w*td1(Z27g|ipSnd^Gsy#f*N@Y3<6gn-D=AhmRlJPh3Gr9^3ILcI9+I7SF?F~?6#=szO9h8YZoM+oN z7cOxt{BnHm>MN>q-ZZV){t?;_*c*X+Bil%V7l_RKE_n?&POZi5_3b0*@0B8uRY3SnZGB=mD)a zZ-Sc77JkB>-eq<A`OV`!huRLEON}zzJvF`5JWvBVsQv)dt(J1Ck6@Bv`OM3>-lycW?ydgmEQ)W-!u&Ev4QCaiwPTK|HrO=l7BT&OT z-g8c!w9obAHGeXf6wO|jaqYsBmP4TYz`!8z=pERR6F2E@ai4ts+3xd?Zm@jzbf2bD z4cZybz##Ah6b=@Cx$`U}LiHz~nY)TRy!A%ZyOTYv&^F8yPzT+^+4_O_y!Twv)AUxS zcOR2pxqD-VD0EW(2`DatJS97?rRJyK?hH9lx!$!U{0P^%nV`CgfkEJ@B-jnEn^jv) z>(zK_Dg@M6@Eq}q9 zI{f$?)TRscZ1G+3qES<*^pJUMWt_sXTy4&4pym++gTQmh+`*$-(FotYIwB{nlv-9; zYb$0&7lYc73=9GctILPD3Z7UxA7u z3%@%~ZBD8?if>p8{4M?^wRORoKu^$eKn4bZ*PsDi59f0019}UzCm1zcbXEWsU@T z_&s@>tlY{BU1|1uE!dGhKEdW|179a^V4bjs@5faKb`~B`o@8JUcngYE3%`@S$`_dS zED_G+|6=s{=odCKrf%po&0EmsN)P9mhPmsO8Z42ov$?x&L6}tJr8~+WAjKf~q#a48 zDH}G3Ghg7}D9d^A$=yGDwCyJt&_qNxw^JH>lWCbxOFh0QsLQeZcrl+WCCcMR?3Nk+1~ct&jspMoo`w9 zHn6YDYlwrH0P6c%donW}dmor|ao+Dadl>kb)taO}oCK|d0hs_fFUV>l%g6H%zi)lo zx1od?+{LW~cy7G&ql0&ca6@$;p))zuXccCqikDz&P59erS zv4B^LzA1)p&v1Wm>F9bkpL5XhsE?q@1u3WPUtTod-m0-;iOHe8i%n8 zssVL=7#IXTgUToizn3`y7dB|VI}j^-*1n%*;aZ<1il7!4NCBt-@o>KLP3*I>)%qE` zB?A9gDO^*S_skGl41R$O4%Bbtx4f3L>{fN?x5wR@-_4~eJ)jxq3uthl%u`&~bDD+M zl{@>H{rt2fME)I?65)a*m@o6eX_DVNQDN4FBHpIzn92qg&8N{C*3bcpub`c77JlC* zpV2-uXOWOpsc*4VvC^ajzjDw-7XyR9H&Cp4I6rdV5YVjiX@+#V`?bmf`AoG(7eHe` zAO#iRf!tf?7W&>WvU_fSeCy6St6)dL**BmakZ+*vCi_`-kH1FNl)k9V8=+O`k6mh}gy%(n3Bx;ta{tvabKwIOV$ zcK?h{?cKZ?R97)D2>bvQs2;iERt z%=-&8A@1S4OL0qJ8-IN0g%46idP*^qTIve?5Kw*N-Nb)FwIj?SUq_KS#lhe@SZ- z^Oepe;nRyge_V0mLvy2IH)vpjfkEIesIepIWGIk+bICfld+%@jl~nLBI~zFnE2xPE zQUIFhaP>UYJ?GZsvc$!)Co|g&UEiF#@A(^A!u*8{7V)>%zl=Vzg2_nWDT}}_sh{PS zqd~PD1B1XnQ2W}#?^WsQ4;NO#Xx=H>DFDf^u#kL7KHy%p1-1itVNFvAx+J@%goc-4SnR$iN5_QQv>T`3<3JZjU zK||pT41$cHez%m<*OjsoCU3<~Kh*JGc4M*&BilVb(19r+1)%()?75z~<^IAW!MsVV zSCSq_y)258q_$1Eb;U zYG_C~c_v?LYP`Dr?8l1l8TVRvzW$5Z4cVw7$P8+_T6_BP*ecb9_UN`|^g6s<96HHK zFC4PaRFH)c>`3L0f2$)Mlhc#43(mXf&G=nsumRFM5M%}AatlALe%IUaa^KGGxw>!D zObH$JCnaj2>3jwTK~_)!;^AyHFG}pv)-M@XZ#?HN?c-X>8g~d(Hh~m?_Txx7wNB@ea!T& zuOe*k98Pyo7L{4tEcJdrXw(3t0F+=noWtZFaYQ;z%VPY#jVL#r6irYB~IsP1Fd96=vAj4Gl>? zQ28L`RMt0h&NYL&Eo?~=d`89R;*3A@U5A7NA1E#YJu{9>d1<_&t>sSW$E%N?m@ZPE z6b>5VVPFvCI|+8A(3JG0$u=85mf5uKRC7M}*y=zT$a@S7f&!o=+!lU)%eI~Q+RIwE zyyuVk)eq}E_N|BRYZep$ zz<01CFP#hjs*t7F{(R^3<%aB5(-fKPAPp@+AyCWQ!msZ0gInw7e4eV}y^VA08UD+A zmt6!kj~EyPg+Kx3;hdjh^T}iOn^t~dro3CG&(RjUoxX{#Y zq0U*GHfVdM&sviN8J80j<_5cAPg7{`KaIVHleaw6{^qL_)e^QHR2?!f2#SEpC=0*a zF`MH1w(sHPZ~1Pl9IU;fg2fI}cMFPuhI~An|DS&xxZ&@b*#2Gx2e&X^fr8x)iy@IE z@`QnbLCPsqwj?Xc*M-}n`SCvQO$|#G6_ zy*Vv!gTS2yrJyDnNC9YM%fos7I>QXf_CG8BvD>gzXto}&;Z}l{Fyf$grIeFrp()?P z;&7w4ak)CGR-2vIxc`SV7X`&ZO?Y=tamM&!y#7ukC!r2fO(}SqLr19IaWbQQ0mtA-1Iu;otWS4Z|&dj zMTuHht&6zu95nRFz#u3InT=ZA{{NUool3@pc*Q3v4*M6~TD2E42`eZC%ET6aJo*Pk zXU~2j;aY8aU`~Tk*)+LISx8)f#z+`EoP9ftzWsi%j&D=M4>~-;Fs6;VwoBt{%>GF-Eeaf$ttaDNNXXgdRgpv*T01_lei!`07{r+zZz zJ)-_3P#!cHYwh{BXJVCV z_hB989RXjA-uvyImDC04H4Dl^mT3CcsRe5v6IpB@enRZQ5Bt9}zk_cmWMB|f1QkUV zeksegT=JfKe6PCedVd9h`d!_zGa+YK2`Yl>O%LZSF}qGW#5_~KmptFa-c|0PX<;~M zG9F|CsKFKN$@{?k)#pFYr}E{kJgNNXno#j0jt!9Xpadx&&YL)%{>wB=F(=*Q&^n{M zKhrbRAk(;l%8>G5Y2Oav>Zf9glbL>bCxvcl{TuHC%@@j$@}c#W`o50Oa*}S=93lp*Cqk!5qR=}lMrwDJv|EDa0pPD=j^X|f6`|6^caaP!>odY`P_i@DR1 zVvcMKUEBVWTkjyWk)r}x?Y7VKwg2rt%h%0r=D$Vk-nh0Dvw&Kn3=D#*pg~j%KYiwp z@!gWaU$|_qC|E83yU-OpV3zJ7JGq&jF%6a#~x z8Yq8AIo;5Cw0X^@som>m>|0ayQ|Nh~dOE0-2Ppupc60YkcH&PE>tp`*IfG+)i9({_ z-Oy%eK&jP%Q`9?GkGJ>MOt@EeSNXH;|2v6_0vV8rU_o_I>bCIX7J9b-`H7FKSF#*o zxb~7a^xBeZpn`*eK~MwK*YR+!=6>VEbsthrv+wa9 zyyx)y6sN?;WoieUZv1Zy22J>ZOaK*Tfu8p-%H&Nu*y!{A!eho2Z?ZEMOFf1x`w`TD zZ1{cnQ7qW*mRnfY{0VJqOYIFAq#r|@2U?&4!oqLmyPTF%+4;_qHapEu*#5h(>>vZ_ zMhR*KgS#;E4lA#HeIfi@EvsNl*=^T4&O_bMCW;nlHA}qb9=XG1`J2A_?ppNv8=H;h zG&99ONOw|D>lZkn^0@eKPs>w~xSG{6MR#hzQ={*XLEd9v5Yz!#Vd3{IGa#t%yQ|H; z)8PkQR@aEXeYO>{l0;AkG}7teY}EfMTl`)8ivTTtx%;kCS{60BD#AWCdvU!P?Vgu9!)A*z0cATi+cuU#s5#+i(stzbU8- z8PJYR`X`n1^JeE{!)w*E*VesD=U)vfdKef4^&kV=dbtCf zCqW88jXn=&MlY$w-xnPV@3LRgXM4lHJW|yITKnsR2DBxeLNk{O?09XGc7*dtdo=6i zZwk}+px)F6bONTbHJ#Usy0^n{!YW?r3t7Y^Xb5VV277*Bn55>>aiuoGM(-Hc2DS4gmmDF}`huX*6vjxu zGk^DPoW1J#bc@=aCCfyrh0k2P39XWhK!d0jeyU7b%YLiLupHeew1M~3-f17B(xFwe zF=*u5!+A1uO)|&(Ka2Y!BKMiuHti_C+7BAAV_*<821S~bQ~KFML8(>8PH>;_4$Tt( zpf$(J0@@NY1~r@AJ-OmS_SiFdmE3H~IC=h;{f(#7)OrozE#R%^f$guI@Wwxlr*?Az$l3XcNUu37qUj z)lGd)%{clcYOhbPm&g4z^CusM_BYKzWtD}W@;0p{daLW>T9URZ_8;M$IpMA$D4{Sg z2%3X(xrZ~u1RsBa#>i93BDqmHnR|A3U5f_k1StSb+eta8Jbti#uK$fY%g!#yWemC0 z^0RjEYP|t{;kjKyzsf41yLJU`J;E^knpUH{oR2 zy5^dneMtgqjlMzV)C4U-ql*@P{~1poZQ6a}ZQsJXVJ}xZSnyY|gW4_(41$)Rkqi&# zN~JKV)}94Rt{wHXWL?_4a5ujIXn2KzLC^{`^ri1Brt-5kzP1Hw4-F^37SC;yM zViBaE0PKbnwvRr%nEd8P3d5!5rf*WbcjA4Z`NH}nxczX{|CxE=_U76DjngI_HklnF z;d2MtY_qxmMm$fKSH zcV&2VUj7ncf|&rCozwU9J9&8Kw94#L%_WIpH}ov7iy3Qz76dRb2--{nJM!{@je(Z^ zvpk}vO+GVa`GWJSUPypOa2OZ_Z9x-X7Jdn=(wmNV%oVq6UZxXwB2j1gq<_%rzz%d& zxQBDG=gs=_XTNOv=yI3AtLp8(#Y_G`%W6B&NT-xj%P9u-R+Y~?WY1YAetRu020=SepU>L!&!&B={1Z-w-ZQ)PZ^2C89O08@pyCgt0J2M+rHy6ESGV9=#{3oU zR{rZ~&fHN2ZL&Im=6fytdi&gTS}H$ZGCKT1c;=(0yRRQqhOCYjbO5bc^KkZNW8A#3 zL@lyqPH}vG$8oov83oYhq627TOUkKzxuaXh4O6E05BH~jzI)>+U&$d*u4Z5mbO0sV zGEeCvUz+WvyyWNYde+a-T%&%#aS^CWW?&F>gskHD@FKElQihGJZe;Hd4f((Iy>C8% z7O5~W2s%MlaY&qgHX+?W+jnyIx|zLy-*NbTbb_o37IXr&D?OZdP0Iagv(=6OzxihB(qi#P?HL6Iiq^wM;v_7N`ry08)?)j_%&Q;mnUNu3>x~sp!8p@o~@}3r)~$Jp+TF z3#gf3;n&ftf7$7+frhbsYp9>xhK^H8XQ1_k3uutU!+F7+qUy3kd2gtdvw48(R{eq(YnFXOtHze2YE@>5ym(5{?2s5KPi8S?m|kJn4(hf@TZS2XB}WhB>_ zfu@K+RzQ}KZ?%c|wBz>tbXLw8+RJPo1$&7pgO>X+FbH~rR&!YRDR)@aMV@(X@1l~> zX2%iCJmZ8hD6xVRK$ekzU8HQ9MBfh_dIUro-1G8>TH#F6k0vy=>yH{Obc`dP30i4LG{5p6RhV zbNAHrQ!{^F=bLd#;kW8S(6l83gP=Dk6I=MP*^B00+gf(YQj3%2JoC(J0y+wi*-1ff zP^@}5?=SeYcY9!s>-uQPsm<-qwH(j%p$#o>&`_|H(*{5Bxf^V4zsohbs1&YT@Je7= z7RYFj6`-4T$~-$oo0sS;U+ZD~DX+CTWyy2rdrhD?U|?$`*cXhQTY{LMsH$=n9BLF$7?b$2>O9KVu7B0b}ie5LcboddGFrwaMuLAAZ`)JoV%bO zWa_Y_`+VEehr$ddI;FQS?X=o&uJc|iHh{Y zpoS&`gJ1wCU3fUB%)VnG#v#vs@v#K^_sMc!jW08Tx=$bl5#ZSDbX+B|%<7}~w1-CQ z%^gP%PgHJz7GmHwU92ZV{PMWdN{i-xT6W##tGxBGJp1dAX&S+R^WcE$6RqFU7{R}) zH~jaK;&Xk{*57NO1xOI+fJO_y>G6+e8L$1WVOVM)r&TxcVb(<{Xq^=V>J)l7@6k_l zl~NHbimNs~zURID_xoZE{ z#IU!^^jV}+SH9a@vI;sB9Nq$UqdY9@I&=h}Q*zr19AXPhg;#mj%Bgp;bSgGN^w z7z86h^PEynueQy~if2B!V(;&YOO+EcKRH*lLVIeFpoV9#r{))x&1PB*wzu=YU)lOr zxz_9o_&{fn38%o03=!(^(sZnNRJd)&v%rv5RVGr2&=zSlsCi)Fx32DqljBqSXATSP zjyTFb+86(AIcNx&fk7}DGz;P3Y~OmF&)4katB|dersz1=7CUc z>OOCG_O;Ue?>61@Xtb!;u@}&gjJ^kU!!M@w_ii8jlJ=p+K43@g+MVu+PoT*@7S!jp z@cSJwqj1sUZHk#wb>Gcbbj_c3K@!^dj|ENFcsTQH`mn>_`)r%2A#;E zBo?%rM#@R*gpSpRHb(E_%0N2_k*D)^RkwrcO9lqPSWx~b^E|olWz2+W)*o}eAB}VW zxzh9ZX$equ$iN^N2iYR}-S6VPrTn?X_Hh2Pb5{f`kjjoG`CQuX!j zZMz?q1if5aFbOo_iihA8MTOEPHU&%)0+`$xjxbulNGm+}9*WHrZQ*OMF28Ycxb zt?l8Q7*VGrJw2`^Woz5>;@1v-YZP;!NiGF6rxfVUpZI(KdW^1LzpYu5JV|LHbQ~rPRG?b;b@Y`ta@AMn+>T087CHG% zzOpSD)GT0N5KIHj9e6l1)$Lem9~=8_uJ81fk&WyZa@PNDhm>+@pdgoW@;?&e$6{+X z)hEzm$(d%$bZ#D7X#XM&G~80=>5zH%MDg-lZ<*b<)@qVfQ~#qbv=GYx zB|Q&k@#*(JmGmt=C};HeUQ1Z<&K&7ZXd@>RRH#ciRXXx*p10c|a{VSdzx7M%}b2}6T7b?q$uTtEfvzcj|473%LSpbgB0~hqp2OQweE?*pQw6 z+lL}T(Ba1{P$S2}ul(y|?tK%NZR0=oqiluR0Sj^NO`rus3=D$VkY1AC9G_SGqL#b6 zYBV24U-wIBzA_8cg##%7wIigQel4gvaY3^A?rHw-%EE;#k9mImg{+?x%m($6f<5ij z4}|W}5l=p#rYZQq*+^|olLBbA9%RBcup`}t{wU^U-RfPwjy?3+?4mb0$LE16R0amY zTu?Yz_$`}${)*pwm+Gd)LVwQ`8r}SRI1Cz+xu7`&4`<S~d0e?PoaoMLk1 zX&$uUoePQ!DJQKP7Z*)7mzus(fyqe5Z*QII3~Ny92V?~(ms@)pOS|hno29Baf1|P> zPh&!fN%lt2#3x7rWE$7q^{EMB?mHB_lAJdD_mRLS$k%EPvp~befpECM4 zA5K^ixx@VFY1JG9P=A|&K`OTg{gr#dBOVI=iK|NL}C-dGf3uWK>@fjzJ zawLZK=Y_8j2Ce^KU=S=~WdPj+q9&5D`ML71SwAjENzZC8Wl@`S2UI?S6hH>e4hgda zvD`^JymhNh<&7P;Bl-Uw1Xbz`41&dwK{JyzHgh=>y6YVqu4f7UQp;WD$O~DjDp(8| zH0ubdekjZld7d-waC|41RPd``vq0@91_r?rP@s~^%zf!B=2}p}0aD-z4#|o?i>$V-Jn%v3tK7}W zH4&Tcb9{xS>QYd<(!!5r*7ZFWMHzPl#eOsBnk{k9y~PA=PnLoTa}Q^AH+HSxXWKIF zo>KYI*_g3fY?}yZT?zCFS%qv^Y<}$NNy2))c`Bn#Em{ih@9n11SJiZb6=l zfTw7Q*~_^}0K+#U9?``^>ocz2zim-@hER zLfOLap}~>E%o)N3EX(<7whLTM<$Y2KbwdSco2G|zu_{|%1N*;wJbybmADnWKe%2lZ z4XBEA1_lO6C-*YGzzE@koe2f~Rqw7ZULN&o56E#041yJ)g2c`9;dX&pYwS0)Mz~hL zil6yrtIwfo$ng$>701AiwBO)7JOAm-N~h=;k0g14k7f5ep?%&ekQ*%gu17W}AM9Q) zwK3G&$2D#5xlIwapd7`(AXo(&@%3=-%kC=P^W4Z!JJ0J^@jEBcoqbcF;ZOw{E0uJT zJIA%d_xsY{Q+ekx37UMIo6Wou+5)KpWuPF>&X>2(eL1&S{y?DOw55Ti$IG_}K(l`} zWP7Gp>}Ij;D(Nx@POg>q`e z&mMxha3BSs0c{WG|9d{X%zu8>?NpWAzR9PbJ9r-~gjPv4pw-b*PIWUm`qVWWf@F3j zl!nZz@9X}$BodPKYCvmJ+&pKzU&Cm2UsEXCtyK2cVqUSlpDm!2#K0g}>kJOb@RwVZ zboP`sdwso{E}OMIvwKM)Xni>YgJ2zKlEuQWepZ}pbhKi+%tPV#RX5d-@CN^fhGZS6 zYVvTNs~#>V{L+#k?HOyV){Py-Yv(-$b;ubQ1nWUV98yka9OJ(1*0SMIu0EvQb~^I< z;~QrnOW6hMLDhnrr-sFpk9#ZQR@QE8- zp0=g)%x|+?yZQ6Nr6tgIbt7mfRLbe^{)}32fsWiy9C^(Q%H|LF_~oFbeIuyB8SME; z-I04gW6ov%uY%$AJBzbSCdfmZNsW*Rju}_kEpz7;ukR?=%}iNde;}h-8#D&Qz#!NR zYU5k@h3QXwdQn-1d#HIEn=1Y03(`;WRe76=~PuXv4r--M1AX>XrO{)L**3TfNBN>nHN-JBhu`hk_9 zI)U%+fkF%D=s_!}Fpu^0u~;|JmglL%n<^i*;w$&g%=#=2ZNq@#j4{%0-FlNRhN~18 z?c=$2&d=gpW8d1>AQ=V*!FEvEwD4OL?(SqGe&R~|&wWQVZPUA3zE~6^n=S zJtl+Y6_sjVE+pPH%MsT4yz(9RY<-Xd(1LU+r?V{)dt9@^p3j*dQu9!jUugdGKIl+z zJE#-j?s@cy=GXS_j6GYXKi`>_a`@*S)#o7pGcX8tSbrPFbhnUUbasl@zEQ2~q%QM@2X`7flgp z=a#gNVP(#p(7g9yEOhX&57Lf$+9ddsooTJoqelJ0GaRZ%nEc*C*Manb+EMzR1xdC) z&fokqb5(|}_ail()hEAB1y#u)DyL%s^oaJ^v!{eyFPX7##_cCl58JsefqHWSXnUfE^XuQ+%mTg7EtU3-`Ew;qO??x? zKhQ`w$OKT$BjvPRH>xBu*?Id+z7J=Zw)^efwOs|;znB0@4`rS=?v=(Z+e=FRKZ3SlCV{+b;diPt_#5xq z$?r5xpPq_jbSgL5_zcv@V_*=R1ZpODIGenBSwCk(SaIf`tq;F9eeHU*nH%JK1_r^& zph{lKDfr;N_~SnAle=E-x3*#a`Z>p$6;$+q6o9%>L7o+COH&%X;$N(t@a(GJfzmmD zYh6I&4j=_>;3T(GyPQYI`O-=MWRs>FJlVHS^JWUI2&_*MSZ}(1J)}yS3L3DHbo%(XXV>rP zzg@Q}>F}=)^sn8W5eeC-A~+Sa1WVsDXY>1%75c{8Jbh&)j+NKHGnmZ_8h>G65S+Rk z?8yC@jGg-`6K)k=UsL?$)S>fsu42%3HF%wbh2Q!*X9HW`Zeg~~-KRIlMIBa65CF|m zGcX8F2Q6>#a9*Vpz<<=xu0RvY_Mk(?PjB(DQIIhq~BGwN;%5yApc2-W8x)LDhnVpNH)G%3TaoO0T?_ zZ1Dcu;k&H+!=ZU|CTKN_hjY`ylHHfzb6IVgbamy?S!X5mf@MJ~^%)ohXM$3elvCe( zwwDbH+@>l$db4}d>MQTnI<|twMnMWd<1yBre|W=G?p;ax{q69C(kVCDCY!|_hpeX+ zoC&!d@7jvqGJm6G-4ESAueoqGrn~u=ASkIZFbK{Dxy8cI_@CB2iT$-9mpOb|d$&x^ zaJdx(>e7Q0fMV6d`GCsu?NNN~J>nbBXn8*m<6bI%98{r#6o7^}q?~k@{INOfyw1(g z`&FI4nZH1-!yjm5%?1s>#e2Ry&&&MdKthXHDf0!R(2FU227%C^o)ZX;&4f4A=S$oF z3oYtUK6*dswwH!;Bd7pnU=W-O3I_|nc}s+Ev=?uD*Uudn#xuET+ z9?qJj-`5?Di>>GEe{s}C-=JgZ)<2-82?K-RJWyOnIk7seyxy~6AIGOn(?V2NO=;QO z+yPAw^FXUPtUZ_3y-hsb+;nU5DTdha!wUCYUTgt1c0ndUMw`X9h4b3YtN1pvUroq~ ztLdF{rYLAn6a$0cd{8)8_v%1o7wE_$(ncG8-c1K1_r?ekkMwR6t47D zFTb2$)9bL^hxbABkM)9mkbJQK6c7A!bp(7ZJK&>DTXQvaQtv@O}KR$W5z?A*-<8ElHcnK&y zNI69<_%LVPyxzQm&hQ+ri!I3}>9;|niXam}!%e}S`DeGZ=BK4S-Pq`o*pMpGvW5dP zD$gLe)E}HC`xhwZKAI%5HcC?V{`AsV_N#mDL0dt~K%?#!e*fle7qfn?TeSC}1otPu zy~~bFnhy$M1_r@ppoXW1^MRG~zHRy)oMWEeDPKOF4OD?Ui-U z+r8`UGRtbKjp+eWTPh%q5L^ygEpF}kfW2c&hMDuJM=ol&md(5*CR~^X>Mb)c2rh@5 z^UrcfB<#V-m+}iM));Zx3kW7~Dqn;I^$O4!fQ27dgD`3P5enYg?PqYyYeDJ$3cDd-@X@r zgF@xnpcM-E`WJoALiMEYd**i>syi31s>j9Vpcp0#_2x>*MwP}x78mQb+|z6oP}ys# zeK;_mC;Sk^k*h#U6D|DaH!qI9ZhgP)Zro{u=lnXd+KR!@dEV8al{FsD3R`S)PH3em zFZ$j0FTA6nXCq@2w5PTjQeU(@e(w{XUYxgj4jV&uw(G<)jt!vpGy{X+YDj%imc8ah z+qSQ3Zgv^FyUm{#6-%&ye3C8=z}2)`ApDIh9PDzU!~u->i4)6Mg3YIS}{E?E+}> z6=VV^(Uy5GINULN$*cdKd#9Xwk!A2LP5SLa=yJGq0^lUKV$-o75lLpZ!+A;!?#Tsn z&&k^e8lYid5L^$c0$M4|0=P;>Fm$e5KB+c;0Q{Z zMo{0^!tdd`NWVXf@(i840h@N)EiJUNo(D>c3=D!BL1X70&NBNRP4y1c<-f3!|HImM zGp#R#Yz6fa85jgNfhspCr)Hm$H@s}~6@;FCWr%h762bB3D5$RsQUF>e8tnNyHFRM& zo9Nj_@3S2jBAxFuRH{My7n^2-LsIkdvOKn#%E#0?o;8~O+EegXF%Z-lW?&H942lyA zzb?Cr4#^clvnS^7-7DGBSbOUfxDaPx5ZnSM8ThkL&bbEdMPB z9W2@c@@|>uQ8t!<**~77t#7&X-q7^+E1~zg&N{9xquXaR@QhpZ<>&>qur!= z_VV0acQ!uNKk0M%GPK{l4OA3KIc;a(@#j9XyX*#C`=xueN$)TNhXZ%=A`VSW9VDb)76W+u5giHS04hQz&#?PD|*be&eM*e7o zF51}%3P~v^>)1nA^)s(5H(u;zyw5R0;qi_Y&?TBXL94u!J)ip|NYq`l)GwRWv8#ja zV`GQRDVPbF;EM8~X!QG&eR>H~qX3xD1 zEl)mdUT^<=Ltftc==8lHogf9EqDbG<-+s3JjO_1!lK5V}S2H;LF~aygH1qE61UoWQ zsF~+T(lb_r%)8zmoV!ELKB@#|S_THeJ)kPd!Y`+CGw<2keRJid))yWP`*C>t9BF7- zy%*GU_i$cX9{*Kyqqw@F@$(mvZ2SJbE!+m35!(x@7Rx-3PtLM=H@UIGE^CHK*pwf#$a4)12bSHlA>>_jf&t1!G^j#LIZg<{-mSb zrPhxx{o%T#bP=>`0;B-sSP$n*>0#m9noYYRZb_yJY5uOvU7`wY!|aE2f^yF5n#ru8ut|bgmrK$75g+JfH;* zsG#o+k`>-=F#_vsHhu4X%$WXVCUltPAZT5Tg&#*quT|zg7gO!Lt4f#ST@QXebROCf zI|!QI_i)}bNpk(!>6*vmHJrAD<^HzbB3K9wDDX~kWzRUqKku1y`lMK#ujMva*33P9 z=K-juVPFtE1UacMHGpBw-p{-{y_$Aj$~x?}^6x&_;J{(fQVR>e{BtkM)=8c(y?bG< z{)Jm7?kvB*8*0K~P{Q$Wp3$W;xutJmgJtMZr|F_LE4Hrc0+sR%41$M2EmJ9{uWr}3 zhA*zJ-FjbD)7H=Xbp5A8(1P>`XfDOtv*W_Wn(kFQOO6@O=Q{5C)_s}%JkW3(1B2j^ z5O6@r&GFd9M=mR9t#=euX<7I+-}$cj?dSYO?fYJ|Z&&MO zQ2EHfAb1pVQlFalW_4TUbKkY|_m)ZQd2TYZ^A}_bx!^I7TO^&<{yTZxRQRaN-+Yh5 zWwnYYu6u8Rj^rEzoI&rcenY2{kAvJ`;TQhnbktHi&L7_*CLP)R?53*XQ+4PN#|cn#$-}vc zb-G2C!O{6ISKgYVU6%5{v7-i>CQpDGeb%0vbq;(IHwiklqkgXQgb7dWHKXo;=D8Ud z1Wzmg2h{hV?BqFd?@X65o;F-*lDxuf${o-GG6n|0lc2VYh2Ltu6C2Joi5G1>J8eT= z+mV2{iz}hE|0z(u@Nl-eoYI{lGOs@Fj{St+>v-~K*fK&Z_fwVNbs)UA`gcz?y8G18 z<%iiMZ~2+>8v4+d*eTFpQIIFYQV)xUEz>HC*QBoheD~~@$!83q<58!cf*mRG-{z`G zcD&c&Ic1B_oQ^!nU*rzWyk|fwtt|Z1eA#&G0vg2o_(D#sI<5P5`D0<|P!D)9mxuEW z9+}+zNB=at#{A>jc<9sxqi4*ZYJh=3@C;~sfs~W8B}ZVOo0dMMVOYWlj9+WFUr|47>5zV(dvZ(V&`(5wRkgWy@nI*`Wxuq`*PalSMDxHqpy zuzoG~wd>GQ?i^$t2i&(__@ZX{a(>B+w7T1!IcLQ|qpJ)Ig6E~d0hJjz zqio&2KW@{^b}fqOXuTlssSO=HxB#koE&MiDn_o}xh*WPlCvm;&wMMw!X%0|7lYv3- z0;taNaNgu({luYDGmiJYE1@fQH)z&fJ$+leZ+KWC=YnXvS z@G^*Y_q<-ob}y@KXO0D1!=p!AJocOF+Cis^E|-Htl2c)RMz*%*lCM&mBi=Hq{d%x> zHmFKwU=X|lN*5M>4%dVDUkE;Dow$AWN!`shKeg`1f!dJ_41!ldTYo&9+qVaDT;t~0 zo1({^;Am5QzBKzCv~7PCwB<$0$x1Hw@1HFVx(By+6{LmFoWmd31ReRm3Yxul^=z-Q zSMV2h{>@=ebJdb*H=je`~aHVza-n;$?6!bY$;3$PE^L zrrnoo7s#mj&Is|H%yix6$UjM5P+DYQ5WEh`VIIzxRgUG~mSz5uV$gS}Z__o)-)t<< zLhL$-mU4=+v~2jgZiBy^cICdtY@Yyz39u2)>!9SX?>YJ2PVXDr_6VG0I%e@LxT{L3{2uLBk6cex7qD7woxNQEpXUxz#E2 zr+&wS-_Z1M6I6G5I0rYMi&st&>XdbR8+Y}{OqH;0%b}x5H$g)jQcjyTHQrt`FKm~v zsQ#|g>XUpMCtE_N4sSw+dWscto^mfc5>O?oDPSpg{#Mx!H&84xFbLj+4E3~m{NM3Q zt3USQ0T(yPcimH*yWFA6U2cPh7cBfHG(_w&^9wCG-?S}s@6Kk1V_|jB8S~qap&nNo zzi-FP>Rx?~V_#MA)G~c%ZZ)XM&cGme8&rTuIaRpb3t5%BAl`k`-X9X{^!B(PRD*V_ zZ-cU+n`fHKPT%OQ(dW_*2wayqvY!2#-aAnDiGe}zjs-YPp7?jz~P#=J*Xb6 z-fQ)Y|9y`@r5nfu$h8jkQIe^b%d}o3PngQn^K*60KKGf>LhKP}_|3v^=e{d{?wCpn z3WTn=W!&^kf2XngaflU2Kl9{iUyHsU-PRsK=zT3rSzt-EU640L76Hvu!;diIWn(Nh!HS-t7MySNbY%tEL zWCE>PU|!rZE&((Q&A=e|46-ob47Y#O zN~KR3S(~~;def3NJt!#!jo^S3>;$hH+-%&w>4{2z;d;|Mi#n~?voE)6KnwHdpt4HJ zX~KSS&Ag(X-Fv&-1>N31KQ2H2CujiM-rCH$>V{lYh-IsF5^n&r#eYG_3Aci;L1mS`r(2AhUiG>|8$zxq+<7MDcY^1! zD6~WR`ZYL3?Pk3;;~3BU^<3L#J)PCP_EN6cO;EwXz##Y*G>~iICsFj|{;G37AHO!J z>o+pUR204K0vbF8DF97`dN>QOyE5TaZP8-^?(O?!YXc4_aA`mXa^HeV+Cb0ZBv1Aj z<(tp0%q`vaZ86u5h|V35BX9-ZiGtnGa`0@V>9QsZjoT{^iv^qhT&CshrAoxBH zyh-Gy*~eFU^75Mxr~Qdim(~z?9N7lyErS$*6nZ%CHb0PLlz+ugS>|fp&&-2$rMzFD zgCy@kT^T8-BYm#gYMVX0qM6;63v8;H{pn>BD9bT02z~%ni@~0mk4zO0h%-nSGk7ca z`~0##y;lU9nG4$l9ZD@ zli!c4KdsH9S`z*+RkU8I^NxYm{+~e8+HRgNnVo9FFJJ6);Nlkf@`0cIg`XT~pFxWpE&Q69p5Nj+Kdaeg>s-Gt_hYyJ zp1=m05oBNx`~q6tiL)SAZ0Nb{9!GS@pcX`?hR- zWkgWj-FvIfeyHazhfcbE0gZeIdA{-d_vG8_q8s{l$NADtyMz~QafEJT|8f)T$eXwH zI+-nxt(mZL>aFC2AG2*u96)Oh7#IYKQIH9n!2Jv7(A2f=QXKIX#}tm-5852o zBeoM%Hh~m?_M=#P-kTvlO(U3sQuV;3fffr4mmV6RN`gQ^U&CpzIlru zWk+4!D*P=NTA2R;jqq9cWxY+hn16WQi;me^^ZTf~Id77zBTS`Z^xY2g=SL zX+5z^zx?%auf{t!y$`<*fll=N02KpLPPGDe?MkG%BOdHs;4;&wXpX^?3((B_15_;r zd*&rap?p z-Y-zTu<*O-q;lP4{;IiB{Zq^;z30B?XWR-6>R+JqA3U7T-izbkUm{YzqI>tF_gf^- zxk(m7eeoMqhf6ti^l>WvJ+tHOc`1c=wRax(x=pWx79hVt%|&<5^?IvrJwIdph;3$Q zA=94~*$a+XgT_V~7z9CUIT<7UPOhnnWPYLP#ByWb^pl|4T zUr=0>dHOR-Cnfzfllpr@_NMfL<`l{Fh0yBY?=^5hDQ|Z?+iN(XK-{xxmrx&{#>*wS zpxTasLGVAwHx_;_Qm#$aU*&RV8{AmD?nBpv8}VGLA(i`o&XLX4mh3=ikE5{i9$H1&KY#a>>zfmirnOiMGU zWC57~Dw3s~z8($v`^lt2{GZCKTpmqF_BF!4d%@lmVgf~bndd5ra&~v_kC9&zuV{%n zN&Cpnt_O8Q85o3^ASa5f=e+PVe95mxe=o{(T+mhBDY3sBG>XK)AjAwxQ5JrFF0<7= zE-sU-KEwNKd6!o1!#c>=A%hSLs3Yd#eCTDB-lRQ(p$ulcw;xs7++A@k3er0eVgWTg zrJPKB7Fv3$+DS=l-xBv^uHx)@Pt+i#oDd6SdP3mBrKG^R$uBSeeavBR5+rDAvII2D z#K0iL0-2t;w9>LveddX|H?(&x_uNyNF*WcMC^a)M2!ZxSFj)BU&tPqmFnPs$D%a}! zt)lI1sx#w3O%sp;P|MWAxu(>*$RjaqkKl91WY(1@s&1(`L-M8&8>rNma{9UN=U%Vd z5o_d^-+E`m@MG4bt9w8#QIH9sfh#x9<_#O?&*wZ?RAaD`^Qzob7sp@@kWP?-2jDch zj<@LN8t(G7mtXAkJYJD>S@lC4Xu%KzgAfO(sbb;xyQwxIEiLBGH*3D+gj@#0(>eb@ zQ)M6pprLUO=RLCnU;7nZczt4_=aZ5G{^oqfX^@=@LL4C9NI9jR*u^lr{8jW@slFAz zmMYA=CRqk)^a^o+T0z#HR}KdJ3S{GA`gZ>S%ij-LZ{JP-3@SJn7=$<>*GlTkl{)?G zpLywrqE1oNyA45?vz~$4E({DpT%dem;rC%-sLRIHOV!i7yvqHi{ygz*%>hvH2T}m4 zKRui;yPru`*&6A8OXJQb%cz$X(N*U_t_LXq4Xy`zswfK`k^U<2DY6jf!2* zf$D4q1|e=pA4fWJo@~zXmN{iN`cHEy**p~!sDxCkLOh_RiiMxb>3q+)n&9A#9Ocd1 zfAg9*2=4&-pMgP$2bA?ZoLj#Z3(Iyd741Fed3qa5)tbwGN|5zYLcE|pjULJLvW`F5K@x?r-BY7d4WduJTzL397Xuo^ICDVPCvR2<1W(wWr`S2 z8sxd3PySo)`FHL1_RS@&TUJ4G79VKtz{7bJ-~0k^p+!}nB1`!zH|fuOe>(%RK1v9D z@R*cS`Df+RB|pM1YWuaX7cg2dFMq=%$X z^9PM8GB617L-w(z`D{5_qqu=*<4u|7IkIQ3^Ro4Twzx1b2nm2j*DU->0`9V?Z0t}p zR^!&2J1gT!s3r%fr^>(}BnVo}<>9<-5`WmSv#x8;eUi-o5!d~{^5}a=M@&c%H0&hh zR5r7&WnTY{yH$*j%jHZoOWbCyhSWGhf}o-(-qW#b(xl?QTCW?JKX17n^M3!c8UsiR zL`V>_Li@re;|)(IY}Gwzu;6Gi8>jcS+z3#6nt?$`*cRN_3qLoj=vVb+se>zcv|8RB zWlEN20<}az3P8o6hjY_fiyy6uLPmQ#k61pqKeOrDx)P`(g+YBCNvETCZ(i8eQ2fZu zYG1r$NL~EPaBfh+0Wty9Dh&2y<*qXkk`@j7m%h^5#ryQ0;Lb+SVFU~eLL!iTthVN- zjdQYH&qcYe_&M#-d-3z1!=U*>6x8>%@C$O5IsfBv*mM;i@uIU=^qxG=v;{5JVPFsv z1@*r@oF~m;lNeH zeP+WU>rRbClhfbhKUVjGf|!9p2)uDe%4uryJGPB)FaCaP@}SDP%3Zy0Y9zEuk^oI- z$9me#y;L7>VVSe{QHZlhQgv6<=8uqCPe@`jxRiUi-I{H}-Kpw zCgz~3soD6?&vx`{?)%@l*zB*|+Cv+?Awz#c;DdC^JngF7x6DcJ>@v8Unqc?& z`x}?JypT4GkSydn#j;ac>)djFE;F^g#PIHiS<%CZA3<@zz#t?CDo8B+y40sAB{*|W zZ2tP=-4|bt-wBc@A*0Pga-fc>hx6+((qx-!1GWA>JBD|eai>KYX{Pi)U zMJfb3CxT+0WE12KyI+`%W+*7ajNi22j~0r)V|El zS8_r3A={3G6hU>DhqKYqH)Z$#)g+nchJ4zfz<48~YYU{mDWnKm$}Q#8?$&uA`})%* zHphOhR2HlcobH(oEd~`qi`9ZXr@na18g{zjR6oQLMDJ+mX_cPXl&q>Jrh2n&Bkcl24RZu_6!tYf$r}e_ut!*#0txseL zWVNneAOji`WMB|d1=Tnn&K+W`*LZhZFe*rXJ}R29kzrHmeb5*XNCBv?C*?GuljZ&q z$w%LxRYyE8S@b(hxyTn(h%+zAE*Jy7Md(C?fh+3qf#lOMhDY3GG>qlDB!;}8~p#x@pOWh+#*qrb5fZo2p*j~HBHJxNPzM7@5Ipq_y z0MP>Fk225lSo4w_)A*+fbL(fB$Jv+8Fwuo{Cxx^iwcelemwrX*7#ZeFD=JjtzNDgf zHXB+c=|F0|w|wz_>ebWU%bYsRGVQeuqfPiyXuYWeD(yU+86U5lbG3i6dl@&Q{evud zr_J)hpuR2xgOCoW*0c7!=aiXp_E5$CTD70OT1HcqE(p4T@&ic04{$)WzA3#}!&0*L z|9_YL+ZUaSRQZ zaMS7X!s$&f?wdc>{>SI_sA4B%6^D=>XzpF#vmI5<{2pNDHdmhfAQiU7zZyf$Fa_M|Ub_&zR*Vku&=Gs9DKqES?p8BO~KFJ9U zn={whOnMN1$6tTazV7S?v8JML_whaungf~|VPFt40j>V?aL(nc$k=hW#KdZ5 zKKEs2(Tc09md@i#!nf5k~FP$YpAfT~9+r-@eism>eR+Q`A~7XT;!=?-l z)}XmX59b_K2i^T&X1-sjrujrEtgu`sR0lF>CS(mN2Be%8865HTD?GSsr%Xrn-9O(B z*k|iN28)EOL2a3M&r*T<;MeO#)}CLvCUa@IME(6IDxgLl1A~zDM{sNw9g{Y3%HC!7 z<3wD*w}VGRmmjZ&COKPB%Chj=;Sw8Z-ohxcDY9ZOb7XV*&-fV7C^G|tkS(Z9>*2hq z=3Mu0w(1{2o4TJR=FCs2zP$?C0kH-7M#|~xj`~Y%8AtB^et+YYs|e$6%?DGUBN(=z z;n+aW3cq^4Pybk-nPxgCywDApv;4|?$nt3+J5#VDQ{SHa{QKs!7B#`^Gl&#qy+iuTE@u!>t~8Q5qUq_Mm*>;kMo+6;1$p&T3)Vx27aTwdC*JcCyH4BsfJ(+x zh0^8nkJV#qBjlh>HHUVvBQqH-ERFn3eL_ti-}&^<&&l7|5fn)b3_^~O0V}=28S`sT znaj%0f5SZ`=6RV$*a2u4#tBqbc{o4(lKeGW%ZT|x-_<4a1ecedec1(?-(_GBasmxl zNjkYsT2OBKc-n=9(HGS&mM+?;d{GCoSVhPQREL*&rWqI>+#2h5PTE!R$N!3ocZm<* zL7ON}@4=4T9lFN&tGMi~>rH3HkH4J2<`EMFYP&En2)Td?GYdZh8^29;l^a&^z0bK+ z_uJ%!&HQPgAOnXo-PA$Q5!% zuHo!C4+7*0JOaN^41C6A^=o%$dwRO4z}Cd&^Q=@oJZ)!kA~8HcpfMEuV7v^_EEOKWnS z{l~i(w6%kQLC766aM$n#~BPBT4U)Ahm&RH=g$K-$$uW5jvhXtuuj zv~^{Eo;dF{#FJPFZNe+;?ckAF+qK%t6&5NCBu#>*1W# zwpHteluP68@>5?f2U?c-8C?K{AOnMtC#cydmF`_y^Y@#`PQvxxuck%F(+80s21AC@r5ik5s;5^ zc~SG8iz}-1Zfql?;s2vapjIFQgOD$1T*|}QJn)jcr-9|pl)IN)TPOR8uKFGfYTSSn zd;t&aUoP;gx+A#se%i8`F=YzsllEUI0gXd3FbMg9vcIzD#qG_?li69g+!^l`JJhU* z*frr8NCKq55FC;k32_I_Zc4r0bi#7)yw7HJvW+#MJjuWyDE-Mjm>16T^cbQmF*Lhi=T@Gy;yX`plS7P=tyrkxY3sC;~JwZsAvb`t`|zNS@ftb02s*JkBlByL$}k%?MDv;ogfy#y9MRAu~P% zEjQ&+I~WK$AOmE=6L7}a^Yqp9?6-fm<}#mKQt)+(`~J0xpjk3cVZ2^D5n796}49@hq0oFEhpI$5R6lkMn(yMNugn{4NN5(-$VUT>G0 z2kmc0cYqyf^Xl;9oiFM+cn{19&1&BFeaeg%pt_2IK`7=SxLy5!w}{DH`l}gvcy6t7StM&ayllM%6&1M z&!{v}VD*}Ai^WA{4UpMMp;%BJwf3A>s2JF+y7T&@hs>3mYS|MO&HD^$H!v^=#cl&T zaz@G#tz5;KEv2&^jh}Ug8nDi`f*dX_6weQKvr0?>S~o2QniA4iAN{?k8~ZCQW+JsXc$>L2I;W;~>UQT5}8I*U{F9l67O zcR5&@6PQ|0fod8C2BAbyE5O2U)!xPD)%@J=+s(TnYjgLY{KGRzpdK1X0Vr>JIGb2L zD#_)4ICuRQ^UMER>jW)1#X)UZkOENkDCJ~5OMOwF!-C3`cl%e~ymEsvgnJVxErJw) zBF)-;kv7cY=X!@WOpe|(mkSl*@X;zUH$Z-q|Ldl@r10K$=16bws9`rB1 z{YB9G!oCMO+nHWKy_x(CoN*ot?E2E6T)xnsx3nhj>%5;^bPb?sG6hrv$9hh%SD%+8 zd-5vNFddhdzZGId^t<&pVBV{m8d0eoS%alHw+9ysh~)+ z@H?P#uqU`y+MriC&xCbWS7hVwgOG&*LaCte@Nk|Me01*v&18jq>&~$G+6NqeGs4nj z8mO-)<&;(ZYk2 z+8-0@YoK*E=%gLSNI%JK42g#yzy7yO()`!DU%VIpt=b5x^%)q1(m@NbLAQA1udI0D zm#$EiS7q>Gk74xfE6`#v12p36;q2VZ9GJ@4tt4LPz0qk;-X2k@EKq7@U=Ydx&CW?V z-Cdu2d(PdD4pPk`-iw`^i?DkJSQGncRZUNL<_AEssO8FXwg%MzS%tVK4qoJ!Mkp0MG%AQjFi}A;wuHLfH3|b{+^MTW(g-SmE?gev`66M~m z+0C}7c~bDxf0Ata3@RTP7=&`>gB{r=J-fPO zqt*?(bfwf2hUxpw>uaIis2tFgnUqtAiNmXtFVYV^(S9&XcJ79TzYXl5)!_^bLb;#? zRLY*Nr@EW^FHBF!E%p^;;gaT5a0(PX~1;6NQF;Nx{j_+SK|FHDnJX#1j zq(UeUG+<-l$NFq>@yaQ?xj!=)pNahcgJVeo8?;@W2RdiY!`X4Uy>pNfd$eL&dBm+x zf3HQHX#$NRF)#?_fg(-Hsq^*LQxpFbEjcCiY!P#wURd7yCD1{$d{9Ya?fLD1^JTwp z`_*L62(RN^6FJLqF7(_aq5L4QBPYpfudJAJxOJ!A)OW3qSsZNjpMn||3=BdApqkgh zZ_R04`6Dr+^BorHDcw%@yU$~^D-Y6rC;;tn@^C(^mA)V@Tc*28+k|W+17dyi{-~7LM*1i8<#m7H~{r=wd}Xmw&jQyxOnl_8PKRA1A|a0sKI67C!e*KZ|S~i>7Me6v*$8JOk*}! z46T|=LFY$#IG^3Qq~ptsZE_zqn`a5=wRu-2YC(tHN&1rASlgxyF>n3)oK}*{p{`4Am7DPPXLL>jbGAEW@Z)y2bk zewlXrym-L{Cwi2{1M$+lG+4lT>H>du|*lY6S zZK+O;;odCBB2S?z(9B?&=aUd41@TVPU-vJX+b?Tj-MHugY}~%80vu3}y7x^ueR%rl=qm*x5lP&1K%L8uy(E-d_hsWU7+aE8sR+~iM%QI($rU-lztNY;STzlXEu zx|HvKW$in5FOd2B^Zfo<8663rLY#p?s0NgYrJUHeN}R2p6n`w)WaIxT^_53Mp3VbR zMIZ&BG2>v*Pmz|_M7{1yoMqV9w|2$CSXGZTps_HJf_-2|a{fJU)AYlrRQ+9u`I-s? z!5Xz*P&1K%L8uOt{Vn`h{{32{=i3wCFH?K)K6i|4hv*&1?n|LM(Dkz(&b<0B=9u^Y zsZqBwR*+BJATR#)5NMkX$OO>9wza3o<7d(b-9J}MT=3-_&^K$2V?r15Xk z{5ivEn*x`m(AH_T*I1kLe|CZ9^B5R}8bI0K!ml|dPX3L>t2qUsjVnV-BcAH^e+Koh zKng$s=Ha~X)-CyMJLdE0ynj~dpivyH?ywP>>>EI-TFS})wW!FyX?{PRf7SQCyY!Y! zvyUif3!+HOV zYtv*5FTU#3>3GVO!=ED6@)z2`XaaQx^*w9lH065O#pWrl+V+6)+|Tl}Tl7JTR2Ue9 znjse|h1|_wvz-4&!kduH4?&AN_P2Fz2aTREFbK7PhQ2KPe%PJ0dfI+ys&(3p2r=uI zvT|%apfO^Q0?-_zhx1z5HxX3}FY5B1GVFS?PJPbf^jlJpxM%^T3n?d|x(61)hlTh0 z<^IadclwyUdBI`GRyd(nNZWqyJ#ow0m#f!2wRrXU|I@DUD-T132%Usw^OZ-jVf;lFP6%$p?Lfp^}Y1?zv zUJU;7aC-6M*Xdo86g55`d9w#J_QAj))DCLf2YcpUUira*t@_$A*PB79CFUJpo;pI? zlkHo;sXF=V{x2oJ_ho#Sk_!CJuunC9>FoUwD>^~rwHAIqcUUa=Eg$1MBOsIe**Wfp z?^ka@``w+Ou^~`HJE;rjz61X^=Vcjv|8*0Eya>@YC9k1FkNk8!>!G? zWI4`ooQ|B;2U!Iw)VZ92fkEFhakT=c*^`O88e42`Cark;?qmC1P$!UqL8$W@*pY$T zT=}{79xBh=SXi=Av@h;a@*Ysx#K0f~-qvs7_sn90w_jQC)dqz>k1je@aA;pU2JNYJ zgPJHF&MHc-Uni}YR`%avKG!++##bw!zjcFnvl}$HF6ETE;C9Ec)FKmu4O~Ag47$Ba zV%*vWVPG*EpZ!P zb@T{ z_T-mkWm_L>yZqWl)$)&W9=fks9)p6IfkCLx2pp3A`GwP~Zl|!`&^~Vzkl*reWrGql zRriAuj)mW!@JMl|YauhPEt+tPH|D~%g{vMz3y^-$M6ic5ulu$o3LZDgJvnEd`5V^rRen!0Ku>~u8W0WskZ!m65*K=w6C-`k0sHw`pAT%Kh?1uX-&YdYH5j*qM zzsS56a`~sUe={f!7#M^mf~>Ic%kS-SsBoWTqM@I8PVu2n(D?#2Xn%7eXdJ@BS?~0> zoJ+S$KRoh%cwEt3?pW+iXK0-@2{hCZ?D;ljy7{L3=Z~v?YThl_;SLauZftIN+4%s9IU8c@?fd+ja!6kk?t{O&2X zL!z(Isvlii?|3+M&uX{!gVx>CAeEZooYa&#S=UTH9oD_m_2-~d!j0EZ1v4O( z+Rmq~8>(m9uFgPx9UOt42dDh?I)A!bOIs!4bWTP) z-`w=&(B9%qCU9iEnyG2@_RtG~%_lk+JvkI`b@RRzpxput3_`O&!%h}{!aokY{~7(l+&jTUUP$d1zz!G zcRfigHrV|r={0mzZ7%58Fn!NQna?cJvNn{vr~PlWE`OwQ{mn~IWd<@K0PIMGCE>Gd zZr>4mVRAK5>r^Q_(_}ADmSbQLng<$1vG8->8T@X>!N3Ul_UBoFRoA?>KjeZo7w3Vh zBoF6e$5O?4pHBT??falURYI-*Ee+|72LB=Zl7tpc0K4J;(T@squULKFWwZ14(d8WwrxO~=!s*7Ju>0hyhU(<~XG#dv}0GghVauN%7 zJA2SXe9ENWbS|~{({F^@8==eLmV!odVm*0zKlQy$?%R85qsrYFyUo*2vu*)pS_TH8 zWy;`?G}*@8DkZrb`c9KgtOWs1;%i3=Hv}iOat)T^%^JOz6^AWyiXEN0Q=tLE|qB3_>d)3j;LV zPe})Itvz+3@Yu`?xgt*)9LqtIZ43-TD?yDu3%{vH8mbkhX4Xj0HS^Wc4EB)Je*tY* zuL2FXcsPp+Jvy`Ef~u3yw)Jb;&uy&V96uG>_+JHD7$D_jQ_b+^U`6kj#E~*CAoY&j-ct z6L~{Rj^`M=IDz_j3=BeRKp7A1LL`G@JGJ##HVvdQH*p!LyP;6$!`$ zPlI1B1{y&{(mBU-+MW9B=$`SkIn&@}|__^U(_phoKG5b)YrQ9?q}a4PF%;J!>3T zvz*_z<>9}}N7qBcVI8P)mvV}KFn{m2r8Q>Cnjhwz+)^E~#@!Rt$75g+S`RviPT#ZM zfpd#M>(?(AFVA|_+pZ8kk^U5ZVaZJS64Roji3}_fy|ix6B*$ra3Nxvu;U&{0~w9>UX+%PMdUc4cE`J zZ)D?l=!Ts>DlUEf610i35wcJuVBcG*ck{(&J1z5HvTpm12M1#RLR(^+K!v)6UqofQ zy~(f2w;>1F|Ef5*d#!5q18wzTU=Z32ngH~0wk-MRv>`#MYNE>dld(@Ux?d<>2Q3Hy zDF6*BOF7vEIq%Ir$9Q>%ype|gk@fqU^sYcdaxg2*#x>V}>J^+j zBseJ)QdVzx#vK3c$?)kzMB$<0`l^@n)qLZLOaD zzWaA$^iv7`t_e9ijoO$`tObqFf=mES__%p46=9gwXj5=6E8JrB- zgtoDPGtT*?>o)L}ADr?1objQ{cQ5j#6fK43i|rt{Som$bmwAq{w8p8qv~1y)n`gcV zM7@K~m~RI)Q9PX2ROyFoWw5?`ym-}doA_XVK>@ZF2=zTgCH1#Jf{7}58<_kp)C(N83FuMleBj2q$Tol8 z=}XXN(k?e}Ks^plXfP=}r)?GbJ9m%b#mCzwbV9q;yFuf$7Jk83?gbv_X)qI<`sDOO z^@KAKWv8Gu@9yj1c9clb&NrLirCvSvVsFmr#$#pMeoO|pvb)A3QlIg8HTv}MJR6txG`opSe75$!0GDCSg>u6b`)QUH@{jXzA_p#3C+MD zv=21&=i&VOe@;V{iE!X6F+LTB?n9mN^L9d8V*5Z#@}!(rvuJdC`(E!8DBdC?z?gnT zn9UND4nQV=9P8$}McgU&^tV^hm$GjydiJ}K@BNx@AfrJFAZ2xtmCpO4o;!KhzP>+C zH7fh&o#e;Rdh-CJtY&&>S?O~8Zpa3X&x(?MoR4-1ZG?`A9e|Y8hf?=NGnCHx*jTl2 z{Ve;8ErRcNL0hB;KxMVEXJh5@!WD7aFWUb%hnehhvELza5L6X0FbEyk3XV;eG(!dk zLw1G}r3EZAXNMWHKimOrx*r0S4;FrQ_l{(JD7x}xQHko?wD5+Q(4L8)b|eFX&>>LY z*TcE?C?AXLvU4o$iri{Xj2fle!t|g66o)`7YowfHIKxB=YC^f@%sRz8ar&+oQf~i1 zX%S=sC`9!=-y0kkS;3%pX#S*@-0%m%B6jlwp@rC?>tIJVe=@(&^v=4s$N01J<~-Fy zr7Ps1HO>*xLNW`#C7d^y62Dyu>zs0Y^?dt{OOn6r1kGbHFbEw1)tes9n-dqSA3b%u z&?&H|S>^57N$OwZp^wciM?h7RyXVL6 zuZpg7*slqBXWX_90T=K zEc_fEm@Nnokq+n;|F~&k`;9X)3HP9bhsQuU%)>eFRgl;@vH90Z&C@pu^S!_C`cwpz z9~c;fj)9KCm2$ERpMBapS5UX}s#A$>AiMPJpP+Jsfq_BjIA|%in%$jW zYvaQV+ZdnEUn5m^3AFl?fkEg5sE^~}yzf|`w{p6M?j4g;mxJG4&-{4*3Uu+(Nzi1h zl+*TOXV$f&BZfcEZHO< zeHmIUo`jqX@65LA-)WDi)7`mKXRc#&W7ju)1sw}I1uCm7{A|>i`g6~$TT>MK(6WW& z@6Smywu7nx1_q(ipaAo5Zhs~|&wNU$s`HaakBi;QqEDQC3Q8y-1)z}}H_x!$ zZRE-lm;zlCLoYeJ@B`&)kbL6DvN$xBt=~;XF&5^kp7<^v0LTL4Z8Q*KS zF*n|V_HoYM20PMe@69#yXY&{9E^s(D{m~pjBM&|3D9U+IyJQXz1?f$d)U4)*}9 zoeH}vwBGKAE}uT119oJO?dzlc`*y3(DU<(L(JM1l4ci+u^ z#drDiW#KqB=%#>6pn}xeQ)K(}6(5o=pV4Qv;(2{;*2Y<#E}&DN7#M^u`GP~T@S?#v zGx1ZmXaAY&Vc}xL{4B^9GLfK_t!T*|7*nBQNHhC475VIq6QvzI~)JODt-O7XE$`qwbJg%MO=8m z2xN$hFBh67uY(FR3%^Mf!E&75y^@X})m<111NwV^HGujy z3=BdyK=c0|&OAQ@wm!M^`ufR=;|UY*o=Yri34<2JH$XcWq?|fWSv`HZ+|tzS<$c)} zrxi*^>>HrH#T%fNHNl=N8`z(AzrS}--s8sMzsK%`suoy5$7yf820OBE_R-XWQe$i9 z=`FMVUGHaKdGRZBr1uu6*J$DQPej_)T67N=bKSa}ypy#uI`?6z`WDE$9?tGZk9{^; zr8}vrfZfWOlXvFf`DdX`)?1*)j+E2hM<#VE#rI5FHS5$3yXP)fd?zM=W{4RWgl>V- zgTChxjl?$R=!5f)J-FyF<%gW*?vw&h5Hm0c-R1>5a$d97^SXJ_P9N@kRG!3rTIj^f z08oBlU=X?kTIFTo7aBOn&u`}&M$K<0cU3ObP1ZSQ3vC|U0To3a&OiFwjOr8n4yf{G zX7{bxc6E2xBTyj@G67VFOF2b%ziRpU>(o_!jZbPWD_j12b65>((=#v#fwQQar!LpD zd3#H1wfc3gud>az;)p-r401h40i?0FtHf-BU%bD`(JA|!%a6|g*3q;Enqclh8haZ& zQbZapMJuyAHPojGmVSI$+YOotV_*=v2g<}A&h9BuzpM4OUPxMFQ@pkI*7ZGBrOr%LT-@ynotBo9FO!@}>y#xK{aD=)jfR*p;V zn8p&$KF0()9`z8^jqq?jqJQ<*3?Z8nFS%sygmD=(g>3SKj)6P`r7UaD?e6O?cXe;u zu&z(OchT-LKe32!(EjE_$SllG|?a`cm72&q7_>FIR*5HXsu~y+(b{NqiUFg63rBZ&}P%RA6rU z@0@=aw7K{gGFI%j`})(>%k6DKR<8VaWu4f8WqviFh6MwI&{I%pXW_?b@Y;Q8_1s?> z->Ta~f3D$G`g{^Pm-H0W;PP;ur1-i<<8Q~O{=2#p85Z$rL~SkF0I9Q{g7Sxy)6|%r z70+)w{Phsp-W}=?sHd^s1~kC~vI5j=4)R>};cM3Rz>UgmLNdKv$1A57)m?!u(s&A4 zVZ|bP3TXR%tuo3@>|SuE5J zO)$?vis&4nGn0i}Sv=CGcFfa(cumdMKht(m~6Q3Gv zOV}m5m*+@=plbhI=&<}tP+?}_r{k$*>Q$d#w!K=QqkL!3PA&Q3=BfA zKr3skJ#&^UiB&edd}PaqJ&)5gdG<^=8wqNffE46_9VuO7*nX4$FrTt$y@2XmOa1)^ z6QK>Q*PtOl3%@V&PgY(!xqppO?m|huH5Hsb?)RY8;%m@i6%Xf|s@JENysy$uT%Gzh zHhI!Bhrg4dz2-NdSe0_h6^`9Wk%8yQht0cgN_>TmF1`hgnOpcR zsF!TZp7A+R-Qw`_nD2$tS^Bg^AxZ8X$Soeu*1g+76+T;8mGzP@LAoKy$uJmyJvvl|56UJ)`OVmp5+|l|z`?A;^=xo#nP}L;m6!_UM zi}QByEbfSy9TP&2a4qnN1(ot36F?_PSbIME`})KB(+~OWCO)5hF>mhDD1$}Nf&CBP zz>chZJ$uo%wi(?WHzL<9TRbPya^7K3%Y%VI=o4s?#lo-S;scYsyJ2ld7P@?`^Gv_g3nb9Bq=-tTp> zTbAwq?{IImuqh-YKY_-^f<5czihN~x9H_4N*ME-p8xe+6ZG1_q%opu*h4 z*?az!pIZ69-c^5eHC~rKN7gcLH*`hrS5Uf;a%vV?Jh{Ni&FPMIw7`8H)3=vCC4j`-6%RYYl zTaCchi_oFqZ=mj!g`e7-D6=0&uEbxsrg>D>=fTud!W*F#$~VyPqlYu&6RnroZ8Jk8 zSRJP?G(6$$)egPjTj)DzZc)lDet0?)UJpV;*GWoZ(Jkl-6RU+v5g4W$XAy*LzC1zDVy?@NaIx4DT z>GFM_U!MODE#-cLM&B*`OeRjhCAq87W!Z!;XMz?SzQHi#HK-zCU=aEZs-iud?dBd? z!+YZDu3f7B(_7aD?nzKhhIV0ogU>lyjDWp@E6n}weXW(ZsQl-{%l89#kULgZ>HZ}C3X+m z68j69`15cU+s9>dttO$8LBRE?j79vOnIiq59vTCK&|gq{O3KNzJ^4lE1Ob2Z>ci2$ z#IBuv#IzV%U;G74HYt0){9U?WUfD6PWscnoPP&G!Slem^9VGb+S)w`nTS|_n7h51> zOw)D%Qinlh%A)*7a20(Yw7Cx?=x7Xf#FAY3{a@%o2L>0!2I`lB-_M%-(${1X=|B z2hIPNc_yVS;4o&KQt~+DTL0}WhJtlY>7e|;z#z=v0ZviVH|6oyq@4d@*DX-|;Y=gb z{C#&IjXhyTP#I<6cgMEi$42&BANQxH2lrl;dyzg>6f*24%m^A)^KhQ`ME>sOJKk3m zu3yqVB6Z^PC56|J>OhzYR8C4c8GkvS^Z$Li_w%R^fge_$`6|n^64HJUW&))PYtOC? z!73`s&3Wn7(xOJWA=lR|J`Iv!U=U_113Pl^PGxcD%M+z6?JN}%{}dKgHSmItmSA8I zW(Ji}7Jd;Y&M-Z(mN@rKBX#f9-D&bnXP<-YW?&Fz0mX@j^Qs9C3luNCsX4EI`P2go zx#@EAWgv}SVHQw1Ddog*-jqFR*UQzf%O+0L zo+f$g`TZ4d|GX+V0GgHnS+NA{$ST>J<~Kii&e;3wRY|tclXtEyPn^KfEzAn4SS|cs zF~@j1oR~UAz^p#wO-OvXe`FP8yjqwIRG@k|yIp=d_d!+GnrwxN!%<5PW-(vn1yzR( z48m-neuk7&+jP%&Qk$pvgY8Pl=f`LJp z6LNo6@jf=rd6({r@Ak@l;`REd>D8%sAh}zZ3sgo~_~p+En%>Zjz$)X6_A zt04J8msAF=l>*0}h`-NJ8|*sAP#cN8_Yf!eYl1sUMz{@fn5 z&C4`#rCph3eE*G#9@dQIke0bH52yid;a6;W{xPYXcpCk6&# z9*}Q5oE6US@oe$_m#3mWcgM=zcbe?N44{$43o3D?oDv__zSOalTi7+@dRXXtb+741 z9zj~9!n~kD%+2#)W?=D$052YfphX-eE=d7t`P)I6mVrT-7joRFi*M+{h!2iGRw?+t zY?OK4xqRbo(1;!bgD@Xx6ve{t=gIvyUc9)(3P9?pq8 z%Nw!;>|&g3|J83@^-|IHt{T(?eo)U<%1QOwi3KHYhdEvyy6(~-Y09`t$^_C(66OaL z>TaHkUh)T6Pt}vYrevYAc9)}h@bhkHIPl*Bhon`cvCxwX+cgXwG>nz%_5bWSlMhNL z3=G18pryMOe%U;kKdY0rycKhJ_9Q>%*5wDk*FuI_guzGgcsR=^3av@Hxi?P#t?whw zr4?Tpzg~ija0&~8LR88rJ4H}*|4xKYxM&O4|cc*n7o}lhD1B0*-VS8*#p32kALKFrd0@-W z+f0!1K^T-Cq@3dCGHiZ-d0$oZ&9!O2#1&Hb7Ob-DV{zb@ zV#!Nq=e{g`Rsm_l2#c73L-OQBWy7`Gmqceyy1AJ>QS8Q~oo_)Mas~!rQP5r(3qO0` zm%0C@-p{?jQm+3XE%w>(tG7Uj6{G;P)WXAAq4jyV=oS@))u#6sI_>oBJsj@`8rfuE z5EcV1AC__omdtphX!Yam1IA>|+Y!c(mM?qDR_;$|heWy>)etDpr~vW12&%+N~Q|dAt$j7H6J(kZ;=z@*V?&uoP&-SIWujZM0gMgZ9Ul zHy_6besp47u_z8S{0dS4imX^qxqyBJ#b0{j!iBr<#jM?}xMk-{Xw@wB2JA>3r_*l* zrWh_e)RnVP;HfI7-AQ{;BaeYWSO%2CEc{-#?roZw|5mfm;Fg$9Hc!HWT15*;l9K^d zC?3ww*L?~;VjUotu9QAS_ka98DWmC-?t`!lsJB?=*={2FeP7kz6V1s9XP6@Xx?1dD zh9)^#Yp@%ZGB(XqcNV*~>yw9Xt=~8A;JZ_xZjb|Ie+$2K*^b$>GSzMG$1X`*{3+64 zUg~?ufkMJ^ph;;D=kTY`O2fn!+1)S?h}61uw(-P@jgYwmVR;d7Y+7t&-Tq_R-T7r3 zXKnR+t^M}lDbQgA3=9my@}SyJ-}AUy3iB0>Wrr2FuCI~h$Y$ZMT?}aj3CqWV9r?z) zp7+_5(62KR&I#8hoswGHW(?_83oC%ui&^;T8x*Q`0;AOWTD z4%~CMx}+ZF+4o@f{y&<_)So2j$*fd>wxbk5Bb-uBQE`{Fe)v?M;xgu0!?AjZJgd>4bTVmH{4h7W|=|18iu$szVp?&fO! z!!M@jgQkcW7=)ETqwf}er`G#rr%uW3D02AzNL0}(?#;^$kT$I_xLxVtT(rx89>!8WUdF-_c*QBrgi$O=Zw9Y`o`z zrKQUqUrq}a3rpS5GGBn_y5&)5y{UW`>_~l)S8}Etf!gmff>!O>wrEMq2}4lZg@Hj> z6%-B@ew*Ic#3ggB`NVz2=UHKs(X8N`uOVGpVO7wiw1>0s#KK?Kdw!R4Bwd_&l5z6n zp7#u(T@xS^Kye}Ev|~-w2ER{*8I}t&4vFaaA5arc1{LBU1)vgF-;>#$-N0JB?9Y*# zE}3b$JZjtS-vO;31u6IscI3iS*6Q79b{nSH-@KMN`%BET&3w?zs}9;lV&SK0r}Wvk zP9ptI>mKe)bM`--cj6SZk)sYe1kS@*=Z?(gh1&HiHiioe-#NtaD`}ntWWY*T9ki20 z%E{8pdKRO@aleafvyEiEKb?^^C;)YS7#M`rL9-A+o~P3|3OfoTD+o0 z3d)lV48j_ar6zSh7~=Ui`~NgC>Q7mxdava6q;$w~Sz%33L&L(a$5p#aV!@{;yN?A& zi6!)^pStG(844EG1f^~d=fxA!&M74L)pP4Ey=`=Y!#!Z>F;I(~fk9XcG|3?4QQTr%Pwd>ulhG=b@x~Lg*b@=Pl0l$YWMB~1 z0~KZ-&JF#pdyJaqZQR6A>aP8}HpwqHk_D14^gxxnl+&u4zE0Doz0Cf$oY8jOKkbd1 zc5Z@aZ=~#beUGM`}^&VUG8iKKQ*DXzX7N?^l*L~ZZgrr zHnt#0J@>-wcl#D5R~-WNR6!;z2bYuW?$;Z)6&LJ(XWMn}TlI9=H;cYNbCv<9lGpcq zn^cv3>(AEi>f*KRjaF-Zo;3>q4d8-I_yBffV^Q5Xm9Lkj3T!vDd!{>I*(9<6bd(_j zgRl{3>yw2a`|OF+5)5~$3kVo2&wujtfAhsd(0pM88Vm7oUbm{NU3c!wteXCM0g=CX z-h!xpTBsz(2sYE&IGSIRTj4$)EZ`B5H#^=0VtPyIG^u{+3tA7E7)zP&WhCQXB0C&?t_f{ z3!8#kWbU3X5}cGz@3=8%U*hXN{a<|#BWLo17P&Go2%ADKTW=HC(ei`;?ev>5{mh!l zGjhd5XG48q1}d{H{Bq^5%9pNr^Rx8foimeUj34dpWe2ro85o4kK*KE_&J)>m%MP61 zs(z`W{&s0_<;mQ1=pA0d=Ag!ol+(_>0O_sK9I8!a(fj8MbX&WIyn}|Mxea*l!@Xaf z57(CnFT8a6m{CjBhUL+$S3o113=G2N+2GiG=&3wOf$6eh>Jg5L=nea496hN3O_LU& z9A@FS%zp}t{!i1kORu&aC_8_0`_0bZpg3S)5VioVpY(9PwDx_{*EOr+7w%k;eDW^y zN|w-T(9CNInp4yFRPZ}%)LvvL$szXiP~PUoY>U_PAX^)REsMc!xc6jbu+E(u=34@q zqdf$pD>SDtLnh^gtw6QEh2QqTw`Zo-m3!&Rr!#Nea60HurygV#hp;s$3wk)q#>+2X z9scp_wb%CrubT!Rp27M9vZ_be8Z;p+<@CI%SGfJbng5|0`(nGwoacY+y$uZqYtWpU zwdbR&Z>A<@7=C(L^Sd7k{`@))p(Qxy9eQ2YgNtNCBvsb@!EbKPzlSxAZ!nsWbknI_#r;s$9%8(yZav*Jj@JB^=`93+mrU7 z3RcR=xU;2@sYWn*`i)C=iJ#oQ70(WUHZbf#y(Bl!$lJUZa*pj5&-=CSS4Q^D$$KA) zKnoBDVQ_SBezQKUTeWEY&uB#vcD03X=YOgO4J$A(2s?th_!fQ))~N!&=FB!h>hxR54-B96Qw_V+SDx}771?^MwaL%=REv0kh z^n};#s|A?eX76C!yb3f;#lRr!25Q1fIxXX!{(T;Q?o^()Z3gumET;uGPlArBxq&(& z)}BiZAH5g9uZwS~@yZ=O3CU`K6qXUp;)>+C7m9&PHYlff9Rf>%ZEpg{z~#O{r?F~QC^@^ZUR01P1l($O_DqN^GDQO z)}PUdmSx<~5l(MNvM*$4h~hiW(w6Fa)A5Me0zdWR@gV;*FbMlVlKr~8wb#5hsXBxy zowT)ej)0X54_z)OJo)-@wq(x=W^yt0hcCB0QD;v7=-;mJ0LCm=I|~N5oVan9llj9X5F>- z_w%BsLc0%sm%yDM?b&KZOIC=NMJ@^1@{h-*>$l8f$n1l#Kd4Xa0$?|JM^o&=T zVgDw4W__^2`ZRPD#UHdb$=!2<%TL3lA7aaH1Sa(}XSN>cQBHuING9wLIl*$}s-J<; zK1Ipxt{n`T&tqT^4gih5Tlo3C_qIBrmhbX5k2$pV=jHZ_Gb*6AECYjZ zAgHI};k=|{Rm}Q7|2;C}_#IfL{w*vtdkby+2ZEOFN;wsue|6ufbHc3aZja@DElKoP z<=hDxp9Pr!>Y=!KDxZ$!TQaxs^ka7eO^fGjUBM=Wpy7Cs0?5wCbmgUUUOqUohj-WC z*yr(kDhgNxAj<-UgF!nOEc|Tkb(UlrM{BWYA6;|wmhAo=x6Xp{Bm;vm_~rx;=lof- zcBe@^wPbvtlekW?LaF|OI&^R#7*ux!dDhwJEByPkP1T&o$+zXtwy%fPg&@+qNJI_N)m{3p|735-A3d(z zx&1Jx9m&8T90s|p#4h~7uFfFUAD;K0r&vf>31#G-fac9`P)J(%N^N;Xkxh90}^{S@?b1l6rYzV$IotDT?OtM)Re3cUFM* zGczyVm{Tpg9%h{Ffa&% zcbj-P-9dX4oWyIcD%8-F|dJ|{X0daH|Y3}`A<%E@!Z?$B9rD($MOtCua2e!S*4 z&q3(0d<>{t>E?OLDDOw?%FeE`CuPTVy6%aeR0W@W4YFbd*pW`03LWl8ie5~~tvxTU z=N!Lbz5-~nje$Wp4z%pW!tWMCO+d-&mFLes){cI8*>Cd6X>5=UeZp~|AwUo3$&W*g zUL2}ju2!4HZoA+n=Pkh{kV$#rI8gUN%89f7fp3p(tKfk8L{)Q#|PR*&9T$`@r+zf-C6k811F zHOD&lL5DySK>aO!&xMgIKX3d!!)Fom->m&F%1zJg-v_Pz6Ciu-oiZ7JtiCF*Izzl@ z+d&^=%lt>LKtp~E48lpE)e9DWPv4ZE(B8J<=iez=jYn_kFlx_O2r?R^0JO2s!};&z zHEtqd3neah^=A7@d@B)a`V1X3O9G`$DJPNgf|n=T*FCYFkW@VNc!c}Om=x$#Q4(n2 zF5WYKne^dI52X;lldT4mw!S*xs$U0f+b2VgJ(==SU2WeDOYzT=oidHz&j{^j2^E60 zKvF0Y9#Jk0yW&s0(a0=+42oL9l7Yz$swEKe9PHQZ` z7WUKaWvV>1MVbOCP^Fx1`!X1%a;=MfxF=$nczm{bgn%5hv`+;Mjk|mHYMA|=m}Q*3 z!1r8M`x=IM`7!H2DT#qWI5iHOWfS3KRdGLR`$;WW_vzlGoN z>bSTGQ@mbYxYZl7$Z%8=>`M>jEF}t38SSZ0=$(cR1UD+L!SV0OvWwyTORS(5L_sxsByc&HUNpz#GC9a3_m9hXHg=_t5ZbY{UAGyC-B=!gNfNSAwP&3KeQ)2V3=y^R=LbqC;-u$@u z+zq7*0gy9EgtPyG-Ecs7%2bcdw{x|ZpPiW_E?#9YR~)pqn}I<%7qmpt!Y{AtO#%Dq z>5D_A&P_VCZ+pN8xr3lC97q9ZTY-nO;8|y$bJgopq<*n1kV(0f>|x&pZS>||V_;y2 z_3TW|yK{S1!ZY8*d>)Cd?dwAPO`%QJJY%pMqDngX8|KVflqIpl*xBHg2L+`QwOoy^%z0}dzo``58U`r< z4KG-GZa4dsv!>^~>3cth9Y0c^e`4lb2^z2iDS(Wbw;h?d{LG9Sx(TmZ`xog+irsW= z1r@;z48p~raas#MRSuP{F`?e^%>3^q7H58{bZhvL0x3X>L3Ou>vj(%#KErK0WkYW$ zrUh(%HFZsn8c2eHLAV4ICsIzC4LN(xR9dR<)t##NASiiSN$GBA<}CsF#@bUtH$>4Y zX{z4iJxe>(FIFzwQW*m}R2pOgWXyc=qc$$}2iwYv&F@d)a=DW9CSfOZ(5w{Hwzcr% z-*Eb2?2;wT^KLpMeL1F*SgjTXP4;D=g2cnQTjAE@^X6B*OE?0){3@DY!N+nNRA)0V z2$z9;BjqGHfv=wXte=!aq4zBwr^U+XdPUyma56^8xLqnu!k| z`~8%F=FKw5wgRRfKYkqA?Wgm1-)?UjrX zr4P3Ba+u~A#zKq13Q*1C;anE$vhv=w()@3>c@eYkMm`Ytk%lJP3echzDJRjCCzE7K z&g!kI+mQKJlGDqg!~?R3OSobIc(5q@uIPa-LjgINApPZ6fBC0`-F*(q_8>Q$2dByU z%yO9%HoId@TI7Hm_`*u4rbz)6Mx&-vcoVlj%OD zkm#-govY^I+&D}3^V6(;mTQqAv+Z=wrvJWsE#bTRdk2%%e)X<@p|yVvXkD#`vv?EN!M_=s zR2{Y~&rxZaEcE>Q9B9Y92GkOfbjtk9t17s#cwd&lwxZm^oksIw9YHHd7#M_WL6PO^ zX}+f1b&*P_>h=rg!>;!`-rn@^1LSB0;aYF7BdylBEHa6=p1#pG#ZZIAdcxu(qL8JD z!gV0uSooFfV-(%Tn|+Z%sP^uv3D<-|q`)UfFfa($fd-X5obz{hy*2uER%qrsx$+Z# zwWX4S(x7uF^`Log38($jj23Y_ICL%jah}clz38?>!c##Z$iN_64;rWl_T&oMxK-o` z&;4z>*JKv2)ZPzhPSY+auw@|Cmw&1O;B8sc9)=PYAq^WKsyP*;|LLAVvv zt+ep#|2lW2A-~(^H4P6~Hxykl{B_F=v>Xtm092`YI4}8S;jviG=!uJndu`eGlHd~$ zxIisYkOEMwN;#!5EI4}MT=0?Ub_XxZ_sm@M-G3ISI}K6*>WGzjZYt%_nlf8cNkF_` z?`?ta!c$SUpvDaYgK!(<1PT6qn_JD;C#}|g<|E{$cBHoWFL;{`1A}loXpyId-;%4F zdMewOBwkGtUwH0c-2{(VYp5gJAty-e`V_p0zf;(K`41sY1B2P>x8*FLxw`|D{H2_( zHm=hPUVm!-p41x}OPalZZLx?29s9z-Al#wIz`)?<>HQ|y`nQJPss4)KqYLNloWAk5 z0JJ;Vkq!@ z`kq}a;{grOFfa&rf+|=KXS>9AMS6R)QpH=JKi=pqb=u2!KeS!l1?pBxIn8$aA-nH; zT!sGHJKqeRe=d10@E1DI+Xb5EwD$ZZ^!VhF>+40C1*h#3pU6Z=J}k=_j9GaXDoyxfAM!ZcyE2;b(m~sCTchyWtVBxhC&C%vSju-hy@?dO(Gl zhjY=S8>!iW$F)o5h5VkyX7#d3>m_trzX#MQmU2pV_j>5B^KwW1gM@WA-rq3_d^rg; z-_O7x+ykop^*yV1{F@=L!EBPN?nU8QZ!Za1^m{?esGjX$M>bc~v&biky;^I$ZMo|5 zC_R<+@}Ll8U=Z#DHTo?4e6(KQmwsQ|YkGVlgXNLul79dGL+4QXK%GGk=h$j7U3KHk@Nj0)IeY9H|DKkc2RB$|ZCG~C z{E0ZUH8=s(gqL&*T`qJm-|{6-b*!Vrc59({jR#DivI%4bXm(QH^X%ON`#r^6A6gvS z=KAVkN|@o#>#C3>H{lmJBz>0zRAl|-X1r-ycV})&@&*BCUQij$z#u#cv{co?FX8$A z5{ARywlka#GS-nr)Yt5IJ@sPw#VPtnLp(skD@TmJpb4awW%Sa1LP2_4y+ECF`Iik+XC_zq7iklFcZXF^88z2Yaw zp?$q6pkXHqKZdZ`FW)^5U-ij&&KZZeYcrQ0+YTCLVqg%S0!o`6&a3oKttyDw_v@R< zK84#~%P-o0YKBJl6j0S9<)puARdLt>HfP`5wKwmlq)v-CS_zt_Vqg%S3K|n~_Y~T1 z_TZkgP2W4$kY`N{k0Y*gmV#y_K?)$}PrjeFZL5>H*-o*NJ>osvCam{ASq7>v85o48 zfjXoXerl1c<*Fw}&ob3{p-@}ztEw%%0y?=c4b+bCaK6uTJ(n@r$+nsA`wD;70;3DJ zA!9`h!qY*WVmHsn4`VMKZGS)M>hU#ag%|X0oHO|kbV=UyLU2Ico3`V5@1r$G->zPG z^GCybYx8d&&}PyM&`5@b-&*UUiPk}Zg~y_+?F6s#-Y8q<0Ijn?#{n^TILmC54=LnI ztvw|4GvcgSnELj38&EaCz#u#mw9Z<}so|r#`TT8r_RP_ppY6YoFG`oE7Fxp01hodO zJx^QPS@vC)TKu^7ZH4-6bM^DTR>MqyT#&KCP5r&iEzi)G3%KrldY=4a;-XWKy|lu! zK!uovADard*3mUC^K(t-886u8|6#+uQcyx+U=W@SYRh;yAA7fo)$-MnbH?{~KH2i_ z;rRonzd?IRvq7BzNhglLqQHA+{w2Lz#azX(@9DO6CRU(11CR-z=5v|nwih~f{(CaB zKPL#WF*mkWFN@j<8n0(y5T3&h4$1T`ZNYu<(?o@K+t(ZHxLQ%rzXv)qI2Y8Gv+%nh z$EM7A{s*&V+(M6sTkUr0MohJO4fU;YI_*?kNtpJ zF&8voBjqIX``@ONTO|+HzFzd|jI5#LpE-u0qy{qK7r5p%k4hF*$vPjV`^VxN-_}V2 zui3tWhCUe>gy%u#d9Umcn)~(TgSFFU*Z!8`z4`Bl`c2SuJ_CdBe8@cSLe(|vIFieh zZ%VhGtzyl0Rc(v}l`J3yka^w@Q+D!lZI3H=lyXk1-7X_-zvn;Hn+re#Hg2Brtd3SM ze<(h-V+-Yfv*Gxwi;)S?2F3!&>S(rQUra;T-YSak{sCpuWF{v*F);=eBHaU2q_-Q`<5%(BS4=5zqn= z1_t3ppn6lvY1*!>F{U+K$JZ&}P}nEywtSP3Ds)b55oi%~pl7CdEN6K{SF+TS^=nqU z&6k_D=oU2lFM`bDu)HmPHTB)cCv&d|?ls_?ZK1ET3EIE_57=1vO__9};?04U9hw)V z&$fKN`t{)MQ_!GZ0*W*b=ZbC5uQp5;%sop##S5d(uT_`1sXfhJ-8+%682JJ+s;@>QM?SaRn)@oL-ohb<$v1GUEQ=#D1U$D@vcr6 z(6}T6gYdF8@a)6W)v>GEJImV=C%5u#;St&Pb|C|3J`bb-)MS%#$`t)D>pZ6!!_FsK zYkjy48y_y11s(EQ25QqptR z)ME?uToc>oS`fT$r`)X5m+hoQ$``KY1NBrH7=%|s+EEKFtb>D8HP7+e2(J!UVRd_t z{sK_R!oVQB3e*a)@XKD!zms=qvP+gorN(v}{%I3$cR**vR)G|HI4?MUdcX9SZ&5`( zUmK=b-(q&|yab(dUkz$US$hV4-u^qw-d!MJt5V6+Wh(#w2h~IN!U(U1Ow*VOEc`RA zG2>>@ROjjEq6Obfc^V9@P}V@EY0NHgw}wfHx4rr+j1B38d&>)G2 zbL-{U8H;DX>peKt<3pvX`Ld+F&!A~?Eoho1(DP!6x_<2?y`!S9Ov!S)#I?yf(3%?`ZkBCj*DbgPv*6Fl((W!-= zi4~A-Xu|739T5-bgoGE`jfDrkPyf3qqe>?$NKw)TRO2!*2(Jfq?WLUj&WG;Hy5)aR zuK${3J)cJZzw6DQ^*|s6pklDhQzv<93UBMmqhaF5T%y^cbD8g-2c3S!z#zNk1XT-CPMu4qC%-tu7TYBKIDW^n zr*l?pn+DR!z#zN{R6PcJHqHv)de@1k_9yrLto`u}??WAgLF;Hi3PQknGr64KCp*hK zWaAZGp6e+N+G+Q7p=%E|gX(Y#zi4mPW6qt54E*K`(=88nSY7a)0Wz9_L3lH0NZ7;q zq>1<`vz=Sf~ zWD97?uC?d$;G`=HU7}BNPc@o$QC$4M{!NO|VU{gTU`ICm5BgF0;ySm^##$Y&&%EE7Lv0wC2nV5%55@wrRN!<{Z?`{R^UokKUZv!o#_HbtZ?rC%SZ$<4% z^R-*9g+DT^mdx1%F<~2M?K?_6}7=(9$<`^yfJWU!Z zuI)Cvyn5va!+)=)s!3lkhKA%WP~+dj`NWonTl%37-M0&P8Lzu`(b%Ez?-xi&?gCYA zQcmYzBrd*caieDTV%FVDJvoj}bVvmqhs3}jyc?ALtv$umwG1MkU*QOk=#$(0d7Y1V z|16LMNP#=pku%Pvt}Jtuwzl4%_TZ92@~Uq^vqAlB1_t3hpa8S*bLgBW(w!2%?xU4M zj>o(FRaKHYlOb-{0~&twa8`QnG}U;wZK-kPRMe6gmXD7gTq-c|MLQF1t2S-c4!#)m{A3=-x7#M{2Lq`7RKh&F_cuI@uprJzE-zU0P zxEn)3Izb9R!!6dHVf$VkX|^}FJri|cvI_S}tq+M3(C)+jb>NV!RJxYD=61QtTE3kM zOB0lG()?vXWi$hW@Ig@5-omf9zBN#`V9|N=Orw*c#`gS8^&HR!#zA{<&HI1l%D=1B z%!=nQiaBk_(@Q#k5Oin@XaV*?(C|XM=cO}0!<`b7Ze2LPYG?VekPnw@AAm+KKvp~h zyJ71l=N_NN=$KulwhXUvZH%gz?i zdo5~ds3)`_Jq(HqeNW!1Yiv`K_KRz^{at=UOzTDG?C9^11apJ~?8tg+`5yhX1&@us z#2Q*McCZCJse~rlqo9=}7JiyddG~ZQ7H~68uwhu{7=P((a{{PRXJ8OM3aTDGoZA>z zOjkItNw`*`o<%l$!L*N=Y@iw!qyRJ)BIR^SlXI=mod+&4|PNVt9yUxyP397klIcFcJ zX~MuDd>j-|7Jij^AMPldPkX(l*h)-tpU1+Sl{=ty)^X55wjR!(BNzB?U*^4OS>dMY z39hfxiaofXgJ#D;;UVP|(!}3>BhRvA-m0Hok4`7?RV6!Y*T(fsb6|1V6tHOXO~serAC)|PuE`E{!%0x@z`}3Y zqpdgcf?O&DGp755@=RP+!LtyWXitIW|2>>D*g79;74TeiX*$leKS@F>?|mj{l^X+t z@F`FaMat>5k}KD8`yRcghr>UbzgrT6)gEo2@EH^j-@;?KE@EK6=z{1aU?W8+T=J$R3 zFY;u)SmlmQ&L2KO9eD;+K6p6qk&=&-D1AIJWzy!YoL_scD7;<>UHp6o)I*VSnz5NZ zarv@eCAkaJo^knY*2!KDI*lEaan68x31yzUmqdoViF?;@jAd@>wP&8oa(X{O+fiqQ zz>eIrVQRcfflCahM`H4thl?1uUr~b=#pggpk%iyQ3kJtBI(ZAt8`#W+lVye9F~Yi& z=Rnnghx5mTUAvzAN^|##w<>K&s?Lfno-R6R z-phNve?W_U85o4mgIcCRo>{I7Rz-UJ)m$lBc;JWpE#rrt^`J@}q#zvZ$d4;eU0Jq+ z^_0k$3vM%WZ<^Qqum*L=85o2wfcoDSesv3M-uH?!t!KWH+de0i)kAc-5-2}_6o6Xh z9?p-pt#r{2omVh<<-{zp*dJDL?(WbObrIAlmU5DMt-kE&G5d#_tW9ms;%k?ttpd7a_Y!EUhlQWTR>S%YXR@W|#BS@AT~bo__5iqfn(@@#A!8P+tWt z0=Mw{&R}?R&3>(lt_AC__gwBd~$F#c|>}NfA{*8T(XKGT^#6{~k zKn)892H~rq!c59(^1Gl?yBYOwTvqRomJHRo6U@K_-M@Ji)V(hAEY;llYbDRibsoCW zC*SeAR0TY|2ueu|48qqSi&Z4~*RBq}Se1FmNyfhJTPMq&HL9Q;ZVU{<*CC5l=626M z=;*4D;K=twN8$YY<=gXppb9`WGlPfo*Y>5CJJ!ks{cx4^&wtspO-bVt=)4042H_i^ z@kuGCP~Dp%*YC#Ny}eORT~h5S!|g@M&~owys8gu#x%Z%>{>Ji33 z1Qbai6DESwq|c*H{;awKvs6!SDY)MfBkQN4q75nSZ-Ro{!cUERv)PQ3SHh$wnay}% zhhEp5e5X3wV!|H@=mM(yka<16o%xlydT) zs=cf}Qhfc6D{Hp=UHdQSZ&ewztbPb;1;u(Uv){L~>)nTV1MUeIf88suNS+f0-68%E za{BZ=ORj9`C3^Rt)m+WkX!JvJnOKG$B%mIFIwBT+QW*ztw8jNA275oKoWEhgX0b_% z(4c+<+B4|ktd>}wmdZUZO#-7_Xc+JAd` zc&lc4xtj1s(H<*5(BvxvgYXkj_P6lcT~x{yx^>ExLx&e@wN2V_O+m&OnsJ_j*5r6N zTmG*yIZ@;nX*Rtq(9BTK$DIj1)%g0>#3ZPxcIZWQP|v5s$vq~H6nk@J%YAKUqDWV{}%h~ zapL6i#FhS&Eo!#CX_mKTgw}d5L7hPhzg1D2_a^+6Ygm)J{de@ESFYobaQ_0${;xrk3>JP;+NG==-KmppXBSVI7s4{t_~;L4#rhf)?H*TtFQ#1_t4`Ah%ff$s7%nTJ0iNspeDQp zWgrjdmq$$_Z1>GJJ}myNqGp8y)LR(_*)EF2TB%Mkpczoe@bK`z|WAlEV^R1Qk z8`(hx2LprfJ5cW+(6f{!>rhtkEbXoZo9kS@ZPLtn@*lLk1Ec_QD*I3Iv@cD}o9_Ob zGxyFaX64wNH;SObi-AG-J?M-Y3%{Dv=@o13t{h!?`^A z=wUwf4^NW>V}uz5@w-!{wGB5~#$OJob|IhCJE%637Em!4T{Jlv0;Ea8(pz&Fd z0#IYG%yVj-9FwHZ%ivxfTg@3B9Pd}V6oLj%K?;6=L$Z5q%GQmwRw=Vq%s#=oJ8kcT zOY1?a9vK*fKY`WBFSNRs` za~8Y4b%YL*d?`QFsCTnidmgki_!TreSLP`aS+{miafzYi zJ*I|aamk5C5-mmUSNBw^D(b#{@*W`mMnYlSr{7K-#|Ib!Y^R` zv71vFn2coDz6l#VW0>~gRy}9|83TjxchLB~hx3k0>&34~tM2Q`DG+!*`A5#rtTyOa z(09<$L{d)DFPuN_d)25eV77Sk*}ZKNv+S>fI^-Y|KqgsxinWVd7&7MWR-PKpex{l6 zb@>ZE=&;-OlVC@Nvo;?S{ARSj@vEc!x7{o9SU>;Y1F0{5f*KeWerG)yK9{Kmx?EYv zC-y4EJ(nv|7Bn2sz##k+G+XWAT&Hrtu*7etjac;aTWjWqNB?Gd2#w93pk9KMQ^>;a zXC{iDvr?cu5GlF+3EpsgN^ zk$%r?Z>X;otW>|;>fkLfEvrCjvo$C+GcXAM2DJh#{8Wz|{k`9Ajm)A=hd!H!_D&L8 z;0P_ue}la1;oS4`N7;U!7oQk*b#dQLHs8KD*cCd6`WrGn$#Jrgp}PA@tdW$QqR8vr zE5FwVgSHbeFbMwv4I=7$+Q`=)=&-2J>q=eaeagOe@?GUm(8~Rf0XQW4^K+ld#A>^- zrVEzNeS9wa^d2=(eqdk_{tKcl{0!uEXU}*N?Yi-0wVJ!ph8W93>!9_;U(oQIhqH5z zhl!W{%nj;)e>_wE)n@XrBh(ubQ2#(Ju`*BhS-A@DOeHti=@#ygy?f>H5x+FhFf;>$ z@IT1icKahQxwlSPtt@P8xlBcJ$z}6z8=(cre^CCg@QdwW?|b-bcAcB(WA|$US6XIQ zl|c$I5e85zz{6RgQTTby0!xeIsp;|-|7W)x$e98f!C_z!VE|36W9pVz z**rI;i0cci{yhR^IgkR-xSX|T#P+^>%m3=H5!rD4YQFVS;q!A-Arn0!43L#(XT;vP zl?S-^EGuw~yT`uGGl5SF;!P1I(BdTvzdaHUe@UC!ly+xJEOPKk6mPt`7*vrkFo-aL z+AMgBu$Difg0e}p6684_g&u9vA6Tl9hoiv)Vgbb zE(eW$fJ`_Djx44-oNJ%#?Yn3$bV2$TYv%WVZ8M>cWC0~T3%_mhQ@n1w^ISri=7hEx{5n5et}eKB5a_^Hw!;Y!(;^!g`n#P)_&1&@c*K)$xjWk ztw4kg6zv|)7TYdW&nXdnx+vwuldn6kP0KwN290iZPz5XHw8%I3!~3mk<|T0bIC8o~ zviHWXT2R@=`b)hd?R;;IrnQ2=yq#Y%~4T)~a2i59=9~Ej=KQ8Rb z{XOTE-W@kcD@cSJ65YGmd*0TS#@`IyYH&MYcJ=bmC67TyGcbs7gQDBo(|(!D?f(a# zuiL!Vv197ny3+e?Pavx}M7SZxOI{1PvwzCjvrU_YWi2kB*^se%nJZ+%ON1BH-?Z?X zwRHI}!#p|Ni1I?kl?oNRBcAhvmisU;i130Y06m=5QVy}roL3?lSoe6Ic=`13tRU!K zS`l7QpI6E$U~$8SiGTeLZ@zWvNZXK^fKFovnE;xE4D`(G6V7RNuri7W5pCFN zC31a_$S+XihJitZ53({jZow7>_03H|JMT|0R?k>h9i{REs(>Ff3t{2+ZSuiO&c$7S zs`h?xJ2UBJ+P3$(pwSZs1`&S9%H&IClN{nVq{JGpwe2WylKnD6OcJ!6fPq0o05rHB z@A=H_Q|Ok%`KOl8j9a(FU=dr&AwS5Bn1}#m%PhzNl;PX>9ihNZ1}2iTsg+ZMLN5jHbPUi2xuv{l+$-}g{UZf6%O{$+}O9SabcHwHb5Hx zA|jv)CEjzw(y88sE5aXzD<_nk{(iDI*=~0$#G4{7z>XBwaj&X)!6!ReVTNw-?2UJknah zxL}p^gA)>LR}&xu6e41vVnE92)Z7i_GsAx{8*k;wFk3grTp@86v=9>m^)IYFgXXGy zJSk()l;`(kt~%cd!F%(gK#7%sK}1{(?8u_#W?Qz)%rl)n6xhGt%_=mfBoI{7FffQn zfWpDTZ_)`ds|n{!Yke!^{=H?sEF&Z41Zk>?NPtF_Je;{R-X?ec6`6l4@zb4!pMKoD z6ekZ^f+ZpWiVJPazc9|tHb*&JQfExCGigUYF|kd4nGl92IgC;nS+{%?1$_@up0 zFQdx*qQf0=$nqx{GoX>kY_SRuL)Cc&(I^f!WIw69z#!TDtcQv?!J~0SA=9m%Umuv{V-uP39MW&Tj90D&jh* zcf`OTA_JO~w(xs?yuxvIbIaQfC5zvosg8n&1NJ~hI7PtcO4;MMjj=mfgau`&pGcbtA zfrff4{I>qw)!OlWZqz#AUA4a1Cyu0@-3bk9IZ%S}a9$R>?@q?a++dML8;uNo;hW2O z4ufVL7#Kw4K~=P}r%s=H!Q$DR2Y3p-?4x@lWGZ$%-|u zY7>RqXYDuP0~yW0AffdibC2xcybp&2uM0`n)0v*TJ#5G^{@A zTvY$*gQY%pMPKA3j{moUY_}0n1QkV6P6dT`AJ3o1dwFg0vKXx%hf^EG>>#UpL=-^^ z^*y=2|I-m!8>y~&v2;s?YQp!coeMyznSnt>5ppuy=~suj`mS(Bn|d#|t(mWyo1gs? z()Slp0_7|VziPYi`e)JXnYFn^E@$56NVwJ>ftGSgpdnBX=l9|@%WfUA3XQ+#&RC+q zrdzH?3se;`Fo-CFa<`O|P2)k)JRL60*E}9Fm95F2)DBC6MsPq1K%)m`o>Fr?9CK1s zwP!Z72t`FFs<2sr6Dvr;MQ}(q{n-1mXLk6SE5EEW86S7o2Va^G>J>0Bh=6Y-v+%2b zUAi|qv2*%FQAg%bnO}U*4HTf|q$+6m&BIxKz2c96ezki$FLExlDma;xz6g3}lZYy4 zmR8D1G38?P2?|<;PPEXoaE*DvE+VPldg{uloM|tNcKFDW>jUKG!1n zL6sQ;gNT|q*pZc9#*=21GXFYKxu%%&6{quFj#ki`W(Eckbx^a>!Y_VV;g=nP>OE&9 z?}~BXnZEYH<&V&eqrL(h-KI0MPA-vpopk9`<8`@Soug;f--D7G$OMqWKu^CX{buo7 zYv!Ear5z!;+~27GsV-!8QbYr?ZTTmk#thD7j~BAuzqkIk*<9_^_kTgzo`FF`6BH*F zev!La?u4;~-wm37cG4P~&(7E4-h)ySNCBvy;o)4c$)CYu&06l$jF0wqOI3ev`O^$- zcx!>$5mHW@jNWJonsA)6vwUhBrSxq<%tp0+kkVcYwANeS^MZH9f*nhbNlazWHdl&G zSUvOg320<#C4&RX_e|vcLtot9%=q}9%k0UeMv0_X#~>zXgF0dse!1OGH8!69tK0GS zN5NHxzXp3nzJgW*Gcbr~gNh;#XSZXU|LKPP*y9q%X3!UV>5wktGf+Ljz#yUnnzfd4 zN>@mFRXwfRdUq15_34Lxfo6*rLL1&Xpg1Y>Jm!#neXFNu-SeEcOO}VTAsV&Bt>4_?C*s^Yy0gJee$dpcWVdgNPoe-)-S{ZUVctf^+ngc>z<~V4m4v~6zy8n3nR+gWwq z;9A3)kK835vWss0T59f=49c_&3?c@g(G(Bo>gJ+kE76#S?z?yOxo6k3t~quGvJ_3k z0JK;|%1JLX)pPMy{d0*orRvACG}S#0b(UeptF8~ry&$78lfqx$MihTMJjw6s0{})0n#bHpcu!{)^%(H z<7123_!zqyIw zpW~SqB5kv6_w}w>diH(!&M=Vo7#KuMK;dEGm*ja!e?rx)75c1?ny(2@i!qzt2wEQo zQUIDd^Kh2h;gPWT;rq}==I-)ob!UFhoU%0Tnj?yN=268wrja7_kHt}rl&m_jy@W$wO}m$c}A^z5TE zvr3ogeTbY3K1hgxLBtHy(6I2cPnc*K^V4N*k*5E&jM*!W)ry*cQW8i3r~&Tbd|X)m zkiE8d$lN@8xvw8SUf+9o!kJ(C)dmOzjC6tM<1;mbVD7pERwy0veK@wMmk zoc{Q4KbFo2>Q^u@h}b~x&Xz9GGkL|xUjE&V>tjzp+tbEb)}YgE7#KusL5&>?Kh1?# zlzn)v1n757E|zyW^Xb&2DWFqjK?*=K#U9RWZ+1M{ujKvE_?+6`D{1@QxAHpiLGq?8 zXeEV|)84}~DsnxwL_9X7JbAgv$~QPI1e&VtKr_Z=o|8M*-#!}j~D{__U@M_*_3qDdVJk(p7)IgtuO9fVkJH`r@U|JuU)0vxi!@HT%=@{# zWEQ&zXrKzD;1M{WHtMj8&s5f(QtutDAKhR7iv9PxuaLNK0S!xA`0=t%%ebie%R2Ie z_1cz0hfmixF9EH+U|F4fkDI#n&H z-%6#=ppu1wLBt(0K6%7#MT3N2obe`MRm`LX)lf zMC3!4uAi8=rdoZ!FeuZ46o4u>59cKxRD~1PzMZhe_`8-<>yE%9wYNZ3G6RDM_y$WU zr;cw=emx0TH))QHtlGw{99l2zxS=B$o}eN*$TQPogTGtXgUmVRZ5?bUPp@P&xD8D( zo{*bNm&M-~-MjeA-O}#6QZv16mTteU1DS;p@j3^dl@r{XXlc%)EVkMr|HqU&M;RpD zR6)bg3=AUPpnisjbEQ~f#6{x;>`K4uGj4Us-al~73DipjDFDqONI9Kdd_T;1&Ah7L z%+oJ!DUx~{t|JUhlir{l7VNpicE`4qOUmXF0nAa7{}%oAb+`ZxYVY0P*u2R6cao!c z&xL*FbvGC@PCjv;HW#%1gMmTB7u1!p@LOQL?%_;(xmPOZFTS3q$IR_3`3su$d_kvy zc{ne;d?K$i`^}$amCpNb-^^p${5BMt^?X4^k(86YbS`U?%FQWWUMrf7b#(1FEUyQ} z0muqahz5EVEKYxTez}g6h*a7+5gX@kd08sZwwy2Ic*zo;-k^+4N%FkjXCEZLYnEm+ zafLRU{XyMp3qMJ#z+;|ryJHP|W(!q_N_aLH-tmWI9DmR{5D#aS89#LA{fxi8KKpD! zVehgFZ(8&~9S;Tu5r0raL&|BAlv{V1i2JLzHv@%+q(u&OUHZ!FlD{!_e3aump#s2$TEo{=2FSQ{(OLYipZ7@c4HKvCdDUTTgD)ypzWK;+gqjJ^QEOplSf50MxbhaBj)kl=`ywjl+J4v{(N^nSSVY z$bfbNGcbq*fl68_r&D~I`%+@IZxnIyl3Kal#L(o3GiWLuqyRL@qU`zcIG3?;fM4zW z(YZ?m`WtGQV#3XIs;ZbH^zhy;VW4;Fr5(d~*i zt{#}k5z=z0V%~~}>aP?b(-R`WpoL@}&OvuwPxIfIqV?CoM=t!D);j<4`H=NdA|W8h zN;%#6vVlEBnEU!c1O6XZ?N5s&ZO;NNy<%Vx2>}h*SbN$E%naF;aDCV9NLQa#_SadD zuVRIk4^iGl~09bWp1oi>0h>JteAHQlA0^sYt4 zRe!s~Tl+gy<<32iNq=u{f)0s?6)-R`D0@D5F1zaMvuozZGC%$OW$E(5SP!Co^xEfA$iEN3p-A%&R~CrS5cZ38;?;QUJLVR_ICD z94$wk>sOyF?7poz=PC0^9>|(rktonau!Y~$2YTH(>t#+qIxKx9u0|;5f=x20reRZ=k9vv8N!p9*u#G$IPi7ezqkEeCn(c0Fo;A$_C`f--Di|PyZ-DF zuS;zQBX6!Szby-zon>GUi2D&k91zCTrBfK`9*|Ot1w5*N;%@lh$KMFJZ7ofJqm@m3G zBH-wstv6FPL-S@lsF5S(bp6qu?{%+u&E@hVbbaRPWq$5`2x`kRFo?v1@@Ty0qHi(D ze|V2`sOE`ncRjhS<7m7GsEGzrFbV9)SOe+1`{uaaywWs9&Yk6;uu0AmP<~)w5J>=a z3N8F5dgZ_HQ7|$oeBdq_!t`=Wyq7n~aSRM1iJ(f&!};2D&6njfgO=O%eS9tvv7u|y zf?v=Xu|!Z4UdrhbluLX9cBHQLw|MtgwGa0!+xk^IKwRTo> zK+0#9*&&SIl0$QpFZ{cmVGs*%KFR2KuDGtDi|*6+5kY|9;~GA)IAJ?~iW<@2X;85Xk^7 z4AA%deQW*pnS}?74@zyb&{g#5zWJ&VayX<&2IOK0oAv$@oEQJb+FtIPa8P&ty&Y{8hu>xw`*6rZc^6mRj^4G*t#t0BVVNI49X1+OzOl$ED!> zUD{`~68&tRwShXK3=AS!pm{ARCv~G6tWul*XB_zMtR$e_CMv{t6dICQpaBYfPl+VO z#(=NKH+|NFJyTxA60*-D(mS zYT{5`Cefy8d3{IC*%s&=N*-ts(Zl)F<5QE>Kc;2qPH$u?C{^T(Dm?=#I6x+Vy0q?| zN(*n~Z~h#9C~D_Uj*_eYS<)Fbp|xJ#IdDMDnlk&j;BQYQUdDZoH2T&p@_Ne%sz?|Z zL<&INY74*Hk`7;VZ7h$NsioePxVb-psZ|bCE`St(29-UW*?HHW4(*Uj-~Q);&+jR} z7Moe_01Xm>6o5)QDJQdt6$0#@I!UXf6Ej;*dDS^+Zh)rh0#KvR+H;BbmE#`8_W%Dp z_)z+NVzPVZ5*^5LdXa)ZU`N(om0W5*!AG>Vpz+mfhOc$EPke_gcM&NH1vi^x{+^hg z_whoypt$wohhdAJtrBAdHLw^MM2bLj2OiF$pXAKf$F)0&SoLLYdKe*iS?nHYoTc+uRZep9wr_l=J5!W4kUAM`y{|7iL=FS@qCHvHb(`3l#VLUyc$ zCYWN#B+F@EQ6q&Xfhta~|Hg(zuMN0+lb;uoc}pOZEM1eBd)6B3Ka4nZL(r=*=P1w3 z{m==o5>R+}IQt0bb4092ZM@{5bl~!vC(Dhm)IiJ063{4ul+z-GNcW1h44z$n58~G_ zt1#^4xC{;IQqUxewWmV7X6y9%-`PCPSlf6W>0g?x{1`OK%)lU0>H`i*iB0>-;UYu{qIob$PVELo;a0JQ=c7(~h;%Z6Q(l5T8!As%Sy%)@oqIe*8Y zTr<#YJp+SC1*lbM;TMwHcgcWdwi36c%~EF7-I>ofSwl^z1dR!KIM;Tm|EkQC%>40r z3QPPApI@!)tQu*zDtZD6_Dw%;nq#Cq) z!osgb_3DF(H@<34-@>|Y_EMGb#Wu&Gm0C5Z=j!1cJliin;Zx?(n+GO2Kebl))v0_E zG;aYi0n~<(auQlDufqN3Pv@(dy&r$S2xQ)+bqX{D3{n89H}pL(+)R78^g-jJ))`Bt zb=`kDMQ80o&;oRjf`?#7GDWWAC|hXKkRr9=`jKvrzHEnGputlH29a9OK&FM?lliYw zCHCBAb`Dm$!ScZKet0CdTJqup7q&0Y+gU3SAui$vXg)FpKU6!j)2ag z)Po|;!f#vj+AWbzUl~udp4gXMDR=04#AE2tUwsw0Rm`&Dtx>K``>Y4fN4<>J9p11? zAPMAu1_qIO(2|pQ&y0e3tdBdccZ#2>*RM;TwCg~a0W|A1D1yV`^_R2TRIECjr!5l+ zeU#z4|K77cP*;|LL8K96g@s?&zIqkygImvRjyhnXxY{x4NW)oZebETA%EQ_IAJ^fS z)Y+;wrsWx*KF;tBKD!%KnSo3I6-D}&ZWri(e-ZC3l}amF@n+-zz{}7X}8AW>9y^!tbAqs>{6_a(|{M?KDuy<;oJD z1?#CbgM!+_S?BT9QrCZXQ-XtT#dXE4-M7GH4KzKpfHuoWIZc)H_@m{&?NHAve%=>% z*pmv9grF_b7SQfPYfrYM3jLWgqStY~;QjW^{#Z>D=SOH8rUkN##B%fV{XM^*+OLW0 zlUx1Yady?*+n|0X1A|B_Xl&5JuU8_4ze0FX?3U7`jip-4jIwrALCeWj&^ibY=d*tW z{q$C?W0c*!)UV){z%I{eYe3P=z#!5F8bxsTobY+xviEVZKVwtUg&(A77XBzTg(kVS za&SQHoF{Nte%EiW?$6tN1y`Om_|wq^s&N?@MA|`jPgwZn^vw|y6J5iz>vz3s{qyUY z_ctkn58z}F=>Q$P=Hbk9=HKe)TwLr9O@}s?@Ruc?-L3#_KXibyo|Mz=+mEB)UHRa& zF7YJ=2F!yF3?f~Sjn7+EG`;zM|7@RZSkw zOZbD&_CE1k(#NXY6c%vt@|nIbps_HJ36QG!=^GW}xA9@V7w@bJHk-n#*{2!`N{b8( zBK?r6d8uI3wV!uo*K+AJJy?!4%%eDLzxf}znuje4A9*Il_wTh*j z=HIKTE-P6bFTB~l;)zz|i&LHcxe#wo1_gPUXR@5hi-TziyT9haMP4r`}!u z`6EZnZ_ua#1B1v^(D0*&^W6D&@2d8jZ%9@Rd^b@@=4DFPU(m<}NWnC4&1;)e|Gm<` z#qP`68i^YvTC28Qump|If)s#C7&p(j&6=XjdvqE4J^@spRRP zRP@^x<^HNOo+>pe6_2u(cdVas8A$II`BPb3S7(`}3dP$m>l-F8He4TMx zr2o%tNj8@0(^o*}FJ?k|NkU0a9XFh>l6Mt&w|l|os)^bhdgnXpqFiIpnUZ$R6u!hVBC2 zl8rAuYF0ZK2@T0PkVP7IPky>Nd2*!mg@ubR{>rZW-+gu>w3M3zYU~7iPH<-XbLOGd zOv5XirZazEAhv?10W@{Wz#uXQ(o1U4Z&MLZ_}QTPkM~#VZ{8rc4T{k6VIHKHbSde; zG3GV5-v~~bDV3WS+P(JQTo*{Pp9gAidN{|;G)e4JUNWoFLgE#JiA~`G=l9T5Jr9%~ zq@3bseW|u%TfJ|h)~o#$$vrphBbuP&lk-4b+cM7-9o=c|YkkfJ%7=29X5?;M~oxQ@6&L!!JzAp=Yn= z95dz_*2h873{n6ZW%Y1w(72+#deXKvay^b4j+EtjPPuFhDx*OPKrIm|r-=JUri)eg zGsRxMDI%g3x5{iP12no9a)B>pSaIjd)uYx^p9S5^3*TJ4J>#H~EKGqbICtBAD0m!J z`S9{@mWZR-F<5(9(C5|Bw2e&?DO&)x1l&ArL?0q4KP zano~UilJ$831pFmdZeh4`%^X}3#px6n)VB1*01k|4lgW)EYhexa4e8xqk^wp+Lkw& z3g6?Jt&dKDq=%)TkzQrbxHB2M-%5OXCy^PTcC^2&aQ)ghpg{o!29c$e;DG9~lAr7S z^@zoilG+K`d%qrJ^ZEoi=U-$QXbix@PkX_!D;NJ+xt_Z`Z?*m5waTiJNr@0EmV@HL z!`Vt`>#fG8%B8CoviDr$l&NiPnhmY}mxD5pl+&hjf2Ns4q{TU>9$|D{bogn5$|7i* zTn;KP-8>ITc2->V-7w|cjWX@I(E*3|sULza$y*ND;ni5S$XjShuvE>t#Y=PF)@DA;E^XQ^^E63ss-ZHww=lH!U+E04P<+fC?`wxkX4mpb-#`As z_WQxoKsOhcf^fBalvI@E!ZY8L)Ml~ERc z{%&a&C)>l$a4xX?x?mQMM%bPDvGR@%eG?xiX^M`-7du;p{4 zzj>BHdr4~`hreCafBs0Rt?Qk0!9{`3r;RU&XwLy13&p@7vKF+9!ou&L`2^+im!CrI z4zVfREt=5v|LX$ixcyqt#FvNjdQHb=d}@n*lvbVaGE7}qy2JD%v?aC{v<^bbX@gp( zZctCn4raOYz4O)Mc;;|bL9_olP-F#rIu<^fe$puI!A4mt=4C5Fr(Qc%0&PdFgPg*B z?d!|UUP6CPt@_fq&O37bf&NvWpqY35c5n$}xT|s2th2u|)PF6z&%}GwAs8K z)J*blmPpxt<^^}1)9knW^VjV8@3--mIkaWI0dfj=?!x0)v&Ek+Hg}DFB6R;=;@kx~ zpqX+829XV*gj43}J*Q>X#EX`54hwZI&iJ%)=lg6AP}2mY;5azru#49vsV)qOUcGa& z@PhslcZ&xCpoGG}AhHRx5!}L0>1W-VE4<%3S!chMI~yl%X}dud+C##yq&;LDdIT#KGRF9vy! zfk9*oC_F6uf=V?WPuz3aYyFu&(JI-UiA5^GP%E~8dW#;;xn?GnCrd1MDz4Q&y&zrzHV=69pwIqW30spYb?)`u&ZN+0Yiq7SK{nH_wTme+%m@y)&2l z{>x7uUV9g+ZFGV*7q>!stcivX6~Z;0!+Z~{DmeboSoGPQaOh0XHjo=E{H`ox`JxaL zZ@`#kWGc5}#{I;gSD@Vj3=AUMAU)PUo-Iv zEKFX1$ZiTfqoTFy8+0^j=RB|*G<&!vEPkY7-!n1Yb)Rg}jFY!sfGQFO29aH$mbrzW z(CQ1vFD#n);OE4^P;Q5q>#3=F(5d9zprKF?=VucF3?zTwcQ|!dOyG`SZp4Z2XFxSB z1B1wJQ12knlf^$S=Jw7j!R!4$nCebh;mOLo5xM|-_X)5Ym|bsgPXkDyHzYy(ID0{}_tu^l z4Sw<+nw2zHz4_JWo?S9d74lgy1(0U5UEDY2W#$d~mr!kbf>{ zA{?Xu(ri}zHL+K0N=!4~$Mtod+(!zcLxiOuzSs|HHphF4*S*h6Fa8*Gpq@imjY+)t zY1vm$m!5$^sg7G zYfmRQ2>+AvU^%`5G{Or~0Ge9&aK1I+TKAeA&zIeu=ICH|nC;lN^>WbBq(h*%2=a9O ze(lQ7RPT-TKbp>^wXS`?CQ=Gom>+^%m-cJBp8B7ztt$?zKD*(#iGAOtQ+q+JVFm_~ z!)L%H?L?^;E#J9W>by5+Of8yY{4Da{OX!%`5m3$J;jA!`^~;G%)4qNyVs%jbe);Al z8AWKL_XucANXlu#;hT42HU_qySn&VzbGAiOxNLWV8Ws!;B1b?eE8bJ}Y@O|@+waew zsCc5h{C3HLq_xYS$^HoBNM!EY@;8d^-2Bq}cq8A8y`FjJKBYjjKj@4a1`EG)jCT3yfY#oo9RT3fm%Tx&X*p_+`3n8zD0WOnMEf;`B`Q%#e>#|F))Z6 z1GNUFoJ?1#Jw1Q4YQhhP8MDP|A*Pfevewkd2vGjF-9C{{l3gjCP=M9!_^90Tq?R=fJ?!~IzDGMXaN}!FL z)1Z}iQcjO-Up4NqKmQ=%PK)_Erq{7X4B}8=hfV7Z+db ziP!{6%?u18ry*Av#%4;gJg~C4(3!BIPj83GnP2|1pu=uwKO=UwV%ZR}*@xa4(f?wcd+j?jYiENDnv(y8-$ zkHl#w_Y2%6b9OGYzq~E>{XsWK-aHEmurkm4Z_B#0X1=ulUzlb8?Y-p2jCDJqzBs!P zT*}?xchFXwbXA2tIIl6zvMH?CBnvc%%)lUW9@OZy@Y{R#)N}@6Z@-t0PCFDT1Xx?m zYM?#V^Pq~=!&yW0+s^JP`2+mNc5l0p+I&RdMi!`y2AKdF$&hrCU1O#{{gpCnN*&)^ z=H!oEAA;XQ>x=WC&at~^m{qfQ<};4F+M68Dt!Nb7eIev0)EDPpfgNdi-ej7-@~2x3 zoC>czO`ly&(wPgIzGYw#xd>|XTKLu1yI9_ky(c%n#OXa#!=zqW{Jk|!sq-~gEbnnIOwsueXau8Mx0eN6N94U_x_M^E<7g((0{ zk?4C?e2`o4M&+vhpG6YFC-T;4ySf-wGRHdpa5cE5V;QO(pmVe?E1HK;jT5Vg(=!D z+6&Gz#(cT}t^Kcq=CwSWH%T6Uzh7eY;W=N_?oG(cpMU+*WIOGtU)%UHFL!U-yvgT`<$-*y{?6nRpe1Mw3?er{HIIegnG;9tf1P=JeSfgqiB(%%cjo-6 zf%Z3VftDzGIJ;}J@BH)WkgHsK<4c$Q@#SY*!lA3(Zh_7uk#I76pqiG-qPgN;`2?{K zo3d|Cm@*$aCUy%{R>gb1w3ht5>TlXor+ZGkQx8TTzq{HCR1GjNh}?oq1dE+H>+(!= zg@9Yd)B4OkrJYCj@`ILlFffSR0hQSnejh#SE~P!t;Ml$K>ki+?^Bm^I9*1VVJD?#S z59fIYGbQ_OM$CTx#(M6AX)l)5-PeR}g}Vb9$dz(B?ES`e+P|KsC5t)zniThMdnUsU zI&2+e1*n46_q-D?^Y7Arg?~FsXGTpp!T9k;>3qY`UEXcQd4}m>JmdeD1aCkMD9m|qx++y~)(c0>cmeW1 z1B1u|P|MuH@8!Mfm?Njph+cIxVxO+MC%QiWE;L^}0L^cDIET+UvyVfCH7Y0Zj`qZi z5`%qjmO^*iJp^sTl5#RrG;ZvFTbx;Y)>tvu@X3Q(QDzw)nUI}Vz+U|k?6}e z&OQ<P7+gKgzDOn=(BsfHVcY!ly{OB? z(v;nxDj8(LX>dqtPCn*%mMbVck!!74oTvheIOhXUEHW^NJO#PI!tefXx3X*3e@BX# z@7(ocby0N0L?O_$1V{mBM##h2!7M%0WX65b*>{81XPo&^^fl!VXbBof0cb#1%IUlJ zHbnuE-2PL|9S3br9V<4qWQEpxPeDDlSkD7oPEiJO{PuJe=F|YF3G9o-JLoV||Ei=o!n_BSp~K|2b&LOUmiulu1j&ogLO&98uUB zxv%Nv^+n>)%=-egn9JI8xAx@DX{qk9r`_$7nSbUMKJ}XeIh#e~1*C!TlXVSe$Hjx{ znWx{K5`1C4cjYlVP`81BLF6T*ff2FN?v#)43I7GwzU+Uv{%@Pc7XXdTmyia=+k-p| zH=aGp`mVS6!Ycc=BfTMKL7A3;LF5&rfuZ?alQ*{NXxb!+18oYGt+V}Z{(&}fUV$1I zv7Tj{|1M5(soJ&YZG3R(CVjt?$6`U_4j>a|fJ5?V$m5xEv%A;*v$E@+ntRgYS zP(+c}pivYHKf~4(`xd<;y&HO6IoapOoU?Ym1KRM+z##GlR9<>G`$+Il=(uOtb+PTG z3H#LKxwAf4g34%+0?JbF(p*(4+rn%h3Tjw@ z6#NFeL0D_5+w$Oxi_(N*=A1a!vg?_fIq0MS1_qH2peDS9pYD|%)j~E!a{nFFY%TvU z`dYUm094z76o4|2hx0RS5tHXKi$4b0^&0G5pH=?LECafddtWx6IE)@onU|JVEijP^lZ)0EG&D>O*opsS536KKNc$9~8=iUW`W zPzyxL=`?rl$+nPLtX!+|kNDsIzFR~3J*Zj0z##G&w1~;tGh%|a)(fVId8ZGpNMb*m zAe+W|9Xd<<88WBlzwnNPHA|9ZaCM*X5%Z!;C9DUVAtlTgP;qGCH}_mb(`he>9-q6W z(tUh|ZfYIZpF$OYXbjZwqsxr`3VYg3%`mg1CJ|v4k&!SyX%?xYDGsD z)=X%3@+W9`-oyDvO45xht&&IT^IJNq*B^*+bo~MCfcylt2Bn;q*F-+t^5ECC#utr| zTUI{#x1%3cHU9(^1F@bAGygG5{B?YB_fW*|BW+*1LsNvH!wWzEfs-7oLyw}?!7nej zDBgAvj^E$BXZZ(EZO6bM@*C91vG6-}%|+ysT~*`;#nO9=PClM_vCRV1@c=0RrEU-B z#L5G6-#6CpuXpeMvW{!QuJEIRpk@I`0jQxR<#g@OWIMx*YhRK&xBPj0v2*()S6IjV zH>iYh^<-sUtkb*s%!I|rR?nUDu|q=s5zjNY!k>jH}B-la8p-`^}?0va@AU=aBa za)X7RoT>c3-Q2&lj(3DteyG)NKB-dz9m)9*%9|d}Yw~YjR48qBkh$`WBjj}6_L_a0 zAx&0M22i9)IkBk)&UHGlE>8AGQ^eMk|C(!aUPF?-CH zE~T}%mT$e6mHmh#98#EzGJ!IXhqHeEr$a`r2`-cG=T5FSQ*Ti%e+L@bWMB|w0u@D4 zPH(wCwtTx8#VWDAZ}*Ye59FSihC+tCM43P0$-Df|3{=V2Z1-`ajO z2)=ctEhF}{6)4MrOaN8U!Jd296qn6i{Gmv2#c?xL{d3ZWjLDGFUX&HG%wwUO!>=HZ z6rF>Ax_MKzN{m$Y9EV!L2I|UK_^ns0Y>U@gXxUuych^RtH(}FHUV_F28z^mhIB!~Y zre#lV?(WD(p2Artt)_}ND?w^KQ8rLXBjt4RNkQML^;>7gLx2#@@t@-y;N0tYX&5`NCkxTnuLk0&#IY4cE59brIGKO5Se?;eI zY<-{HqI1T2u_0(;gMmSm6ErL>+Gi%Gae}y-@H)j(iP`t@*R?SMY%yMFg=_#C6l&G*7tET9I3Rh zeE0!WB{MLHa)Z)Cu;)zfrH0Qu)H60;{n61czjm|fDhWv56y;t6c7sH9V1vHZ^xm?? z6|q%!GoDEW9tN!#U|>A}t|U*DVpjeUR=fW|4MoTe-{?bs>ua;cTxE9-g@k%arK8zAj! zQC?7baPy2XI%7ObkG(r+{k)so7y4|U#vu#oHH-2-1v^rUnNd52bwT^l^-E$NZwgo? zZ1ovbfHE+M@`KK>vhcg*Q=XkCVz7H(Zi5VkSITBDAdE*e2d9D_9an2 zgY3B@SJ`|kK7H;#q@)$)2Q|E` z!k-4~c-)I%uKzrF{=Z5aU4t^n$iJunWEaUj-ObF)UT-uy-gWSuWVhP;;;aXdTYf|Z zA-hQII9D<>i`@Gv#j*a4U(J@!g}xg=b4UyfqJp3mRvykp&%Cyu4E$U6D?V|l;>C@w z(KXeOW|F8NXbd3O({6=-{Ikr@ED7sddAxGf9AYy>AcG{LLXhFdcdM*!C|Zi$nS0r_ z%SBso{Wh0)$V9NHFeqJE_?bL4vY2u%lGk22lyne7B_2Dmw?&GwE?tuRYOXS9*VJN$Zb2(5xo`N_uXd9QG@F_Nl(*X=|F- z`zkR=?G40J*hm^kQZ8zNv4;XXXO(T+6->4icWRA z79$N=XD%uasyD4Y#W_pTvu7O?6O44aaHc7xPQFXt~c^UK=XH6#<&yVPFtd1g#eLaNZ@j za<^yg#1v!pzxiVCXTD1f>46Lmh$@28gPW&9szQ*+-7jl-&NxNhF8pR#n3M$>ED}|O z9R60oeaHFT9($1+&5O@zPYT<%1};%$(BzwipR?)JH&5fv6%`&n{qLvS)7@HA z8z2LBqRODPC?3w&zy6lE6rFr4<(pPd!UDyY0=vB+V`8Gppl#fNp5GHS^V1tc7K^3w zT$XY9d*X%M251?j{2Ck%26pj@lNnOfID~G;m&ILr^Il>lWb{B(6*O*b;pc6-r|hrr zs%!eY5?40wJSu$USwCo>KLdlPDk%ATIGdf&iF$bZm86hHblRmA2WKy;?1c1CM8W6e zlzCR~DU>V-Fskmpi{*Eh-RDuUknN2Jw?JLkX>~}> z(gHOwq@4E8>`x5w(TrHudNQ1~v+*-~d?9F&3Il_v7O3WN^*qIK;)&BYHS3q@bvaxq zbyqhAdO{YniE8Zt$L641(;lX8kM zzgNguELk!`LQ*p89_QaV586SEU62W&hNrdXqBTwW(glCCTqZ4^E-l*d>T0|hC=Ngh zo`D_t^}a;sF$TNyiu=!9=Ln1V@YJakl&cvSMD;+;XA8ebgI|)LnNR-ew!8VYn`b(o z{xLyl-qZt4>w7qF%yO+VX1adxOPKAa|0i?Ld@i2_ZE)&=N;yfVGm~QUzLjZuUEVc+ z&;0#MxgPR`-G&6U9;gMP>?xTL>?s^Cl9F-q#cjJz>nYh6pMqvaL2iJIutv8h_UcLWRQV6sont?&o05XyzuMoL5-8M($qigHW3%9D*ELRhRjChM0fSLy$ z&cBr7+~SUZw@7(hpT#7Y@$<`e8BkpXG6B>Qk#b`CawsZx(&mz@0&@43rgQy|oaOq?dQ%fZ_doI?U-HfNh z=G?7d4}>-_j6jpH7JkJwFSX(&!f!pFZ(DXGMEysMaVBWf6a#~(5va-L;XL2*)qR5( zuG@a<&%Jjd$1Q+s%3jC{3Q=QFJ3`9oL+CP=bKOdkhdd|BXiPXd+tSVivcOW*7&NM; z@A-md-;Y)2?L+!s_3g`aS@TdNV?JcCNYof|-$CWaJ5`gku3US*!0G<(V_llIVg=C3 z-2^lfV&NzBNo(6)i>+|{ zwogk`gEsa|L4~@MQ_0H1QLkzv9-IEV-l5UCv*dBxMbIJ@1_n`6(Ah<9o@-}s(umS~ zE1)*(zQ>(C&QoRu-GbKsrYpc{@>=6_p2cFtvP(bp9pm{hJz;On3TSMagL+98ep|lU z-{`pe{^(K36?qr-B?prLUOXGT-4-F`2B1@*_O1po5pT)KU?0jOL6 zDFC(5T|EV~|4ay|Of0v*`jf}A^}51G8|eMrqUOiIZYY%Uso-jHu<$?AyvXB69Jj=u zlOWeKFo;@$`g|6C&lX-h@$b_a$I0*4Rfzi;s0(vQf@&I&0#Kpu;e7P`@-(Xz?!xa| z&fD{Ew&UNwYBtDjkOENeAlUQEVb7D>J9@(}KS?^lEpaG&A7eJCTmUKf1a^Z+$fv1` zH+OrMY&1D{IU(w$orDiG^IC&Ol`Q-=9}{2UwsEs?iJ^Ydy7I0Q`-Bcd%Li-F=$eP~ zy2JDPrY@WJvazsRQs+nG1s?zTkRfqVYfxD&<#gU(>d;2>TerH3KWp#Vqc?5uj1Xuy z%K9k-1B1J#`K+F;R{n1OE_oL9%5Sr*%KscqXTy2-#15kt)5%Sc>0+AyW9}8 z&umczwAQl)^^z?7-gP7iT-W{aX{-4@_nzf8o(tKkpc%&&w5Qm^*{tvW-)ZmH=|=c{ zj1t{)VR5-@izK9cumiO~q@2W*gYH{R`n;m>&{K!I?a%!RZfJsPeFg?mJ5XH2dj34U zwk-O~ifWedPs=>+z3Wzt+zIL(ffUq$9qHXr#~_e+-SS~T&C8m-6L>stFNbzW?Lk@4 z!tb3_+NR?#y;MnnEo0pPh@q*7`pXGmUYFi6gI3(%->Q=^jzOpOcvgpCJN6jcI-U@HaP#+8o3)39K#pTz5Oo5rNVV`|t`Du) z$EbLGQc}UuH&@;N)NS7r2ni@B&;}+C=gOL%h;wZB;)ABlx_D!k&YQKdqR>R^1hPuX z>08N-`F&5O%-+9A?8k!VVw3!XnnDT-?v;Zj_3Sr)iVPk^nz7S zE0w=c1kGbHFo?QipoF9EdHC_wkBj0(E-FfNs~ohsB^x+J6B-w;kltdT-G$v7 zuT2l=m6e+P==76L72&U-*%t-|Q8!R^VBzQLb^Gh~klteQm$>TtE1Ii)+WT4WPh9)4tK<`8 z5LMJ2R90JiPFc-9|JU)UhXr_lo+x^^RlVX*EVLcvo(K*}M&FY=r`)T)TL9Orr6{r?|+N|$ZERNdxx5QoMsMSpF!aC!A(EfG?22l^tD5HmSMYI1gy`6QJ zP2Vs_pE`1uxw6a`I&kL+8mN(SI(EBZ(f;U}0l!YIeYV#;B&751CeV-{1B0k1sNRhA z6kGG}r0tV$-Z!rGebQOfoAZ47G-zq>30bVNBvDUa;bO7j6uqK~|2op5u9XR(5|)8M z)Eneo3%`nG?=G*IU)**vefgRO(YETTGh#qv#2^Kb#VTLsYp@)j`0^%yjEwN{n^IhY z*Bd}OK?*>NRivDp9Zh6(qr&c)H5#RbJPT}`wtP7>vb;f^A$`yN@jNVH7awdio3Uux z-#dS%O<8dXnzOtwgF{kaoj6N=`{oc*f97qUo0)E6@0b>Wsvdj2in74fBeTdy0lA9!t=4hmuh z22p=d)okH+TtYHlqUp)gZ7u%O-+CL@&Ht?lZMyqICcHdte>eZ*==5djo-se@KmS!* z%NA&=_6H>#DJNH+__x#6wYRddBXvwhH-=G+)kwOv;M}f+j*O{HA6nZV>0# z!pk^!tK(avSm5{FCzv+6f8-ZEcWp zs-MiHG5fEyirEjhS8u(ecCOy_8nSvpG!WF5(f6FY-EL}Z^vr!L|88eiE!GVa->eY? zDa3*x2e0k$5Pd9o^X~hHvc50O+fV=I{oD+#l7c}2W#QLx;$KP6f~s1xZVBQlBnE(|H1?{4+@GG#pf7kM$e#q-3NAs4bvuuC7wTKa7MJT8% zE&kddAT-d0+@k8Gz?T6N;!2sn|r&mnty$Vl*scY{&`Wq z%yvO5)-X`*@8)TI$4BI3P=~w9zAr&%yKEH1DtCcacY#cRYydx1?(4L=Y3Yk{k%f%2 zj$}pOQ?>(nkAXon98}U;_?cSlvArUz?r_H}=|V!OZ214&>(GJR2#{MmoE?@kJGvZ| z?REQK!{q+UY)P2Y187q%0#w>dIVoM~`|ijo(;xojYx89HMIWzSc@C|+BS0I#gFTsk zY;QSn#(DGNhUGgq%w?ZjIa>>6#dUC+%**m;*}#yh+;e;4zUK9ACN^frp(aFux>FW@ zX2(+&lrB4WzxQ1G2T=n}CAM_^B1lL^f!fy|&g!>U3)Nf9^ec_|a4kKy`Ilg`AZP@K zfk8A1lpds=CPMW+&9?h_UfTb^ZdH6(*x5r) ze|1Dof;vAS6Mljnx%cA!Rclr5-(TcV!RqE>DRN)*6SRjC14_IWe!aP|$Cj^uClXxr za`9tVpSU_UM`%kd22{#zu_F))b6fqJYKe%b|(@9$BX`#4#CgYMtuA0r>V0-sg@ zQUK~LdN?22DS0oN$@u(s-CGAHx=4l^JBLA=&2gYHAt|Tn4{yc)zV5_#s6}5;(4KcC z&zWbCrAMOipk`8;=SnLT%M4kTk1oenzTP7%n&Wus6X*y(1_sgiX0Rg@otCy59t$u# z>|6VNefYb~_hI)yy(0z&(FD-i91FjQMc4j@X1!V@@aywG@q^5<+wW?DjAmdEO$05c z_i$cfexmJSQ0C;An^p3+?VZ`uvo1nQxkS)(jg-^zFuPTs-xOF}@wres-GoEf^3pDl z1jqzXtI*nWwRocd!(v|zw^|`b8pgv1yfYB zog<{QAW1G6RCihUv8JCEby+me{)%PrN&){Fj-tyLN}viLwcffn?u+`B4?OFyja#|d zE@jmp8}OEC1_se&PPgG)SdepHeyd}0Y4at8_e6itTQLcXa+S>Ct(w5PhIIZtO-N^9Q!SZG0e%w@Yp9;Mef<9PqEtKDbUQD3R=VH;cO?D_~H1TpjBTKG>leObg$_sWrEDwi>89M z%t|@k*uFOO*<03AQzo1Cn{C$kvgCj(v~o`c)xhqa30E%Ki^a_3k$TZMgGtsX>(ssF z&~dpmeQvh{$R z$~*<9Z*s48*zBFO1lr%s02N}^o`n_vTrd6e3){R+wl7FrDUaX39GZDEASb&XQfFe6 zPPoS-cj(mb+oHCPnPqIyMsFr)T*|`lS8yQ*Z}_AcYom5T+9 zo-i+^?jymBDmMAdT{SB>jLLBJ^GrPCH!_UYz^t@UB{3+vuSzMPAF0gN!107x{1hucFoMuPd{i*ux z$D`#T{S*8yrE{OOkA?Q!3qb?h)}9-ZCloQAzMVxI30PSW4J@%G+KpFY+}jnH|$;#P2MwqJS6d92^aTQPmXQi-N3 z5B5CS3@V!#7(`1zogoXq$9?Oy_D-_>J3~QwPSVQjp^u;cgBC%hpw*xr&Z{o%p6Tkq zbm{ed)gJk|)rN0c%0M*@1A}NOXtY(|)7GkrQ*q9vC;bion=d%aXk0jc8Z?LuQqT)_ z1LF#lR#&A(DzXs|{mlDHt0GJHK}*^)P|MW9ul_g3uC0IWPguiU*;zQHrgY9aUT8^M z4%#Z~;T$fq_fCt4$Hwa-dJ#wcC-1GCEe)D|VPFs~2Ngw9P8I)+bMEYHv${NG^@+(^ zVp$1GFGAMCh?av|rh%Ta$7XEJe<>f{@$<5OW5MQ4OBdKwLNaeTS$R)QRB;g|Z9{bWbY2axMrK{XJ(Y@5-B+ItDd z8M0zuv>G%MV&NCRf8w>EqRam4QvRO2^XyTupOQ9o;;$OCCdI><;YuC%G}FTV+?s!N z5@Hi`&g_2(S`fg%AX*I?r6cKq}5-p<0~oS+4!3=E<*knMP1lG@DHhEMs^^Mc8-SazXTN;eO5{Gk@q z#<%cG>pwGnUzt;d==1Hq{;5@-ak=}UwSO&W!H9=*WWXm-!d-uJ!$o`32Pn`Si&-?x~w69kOYCpJn9-P@XC-(Q&V=_Nv z7X(j#q@})Z3TT3dfkCt`3Y;dR@_j6XcXTQQ?C`l*K8MB9^YtWX#;FILOKRa)BXVNm zt){)5A5RMHQ0&qD-#n=k{eO8?3qf5G zd;ji;pNi19XaXIqoxPE=&{1yUL#Fm#sJH=*0aH5SgPBnHd{4<-H@coNR*JQ+#kjuH(hH z=X}DEi<*v}%3o~E_y^j+Xa;oxEd2Zq_&O=EZEl>A==w?Si(K+jJy*~m5d(v03+N_K z59dZf-XA~dUv`H0u5wQQ~2Afp)=MB6~CoIIS*8U5U|Meaq> zVrxJC6$#7Ai+(Qy2x1Dzsi162oZo~zY0 zdG8;58JnskreAx;BGcf;Ine42kO|+xj{KRl&Y3K_|JOhWXOI!(GF1M?%{l?aK%0Umx9u>Ubg<57IDvOi)9L^ z4adMB+5yUfQch=&^?v*jbKW^%aoJjrijv<}?DnAk6-WW7x9ILUqiR(=X6EIR*yNZcxKp(kZv2 zllAE`>pPb>OkpgQOns14Rt0M0ffOh+FfaspW`|tf_2-fzo1oXB>YsufN&ou~fd)@O z3QEC_yykO-DLg7s-Lle4L$jw|$u++oT3_^l8od^NJbZgx=TA9Y_272k9mU*-2Gw4B zKr5>l7({zPLp~nP$x{_xfBSevY;{{x@8RMtZ#3D|Kzm?73P25SDW{NIv0Y4e<}g@o z)!44Y6MOf4aR{_9?*)aZwdbmi^D`FQ{=M*9{p2Ib*%3>^-zS1fSda;e!HyKoy&1Il zPs0b*`;&K>9+mj3f1Ux_@a_Y(BP{$((G z^Kjn4cD!6)W`!Fsx6(1!@5Qsljx<3|ZxHPV&6G+xJ-=7h=DXtfFP{J>g*V5!>nC63 zgAR%JgIYt%o(2T34+F7KvwJoJM!xiPr+r6J2ZMOJEUdL z&6s@hfiNgFGcbrw1Whtn_}z=F>of59_$5o6XX2&P*%?=#OGC?tiJ&HmhjYu^1s@Y; zf6#rPb*V7^W|FENTLLJ(%c$HvUh(tIG;1VL=K&1!|e6 z$zk7!sdrrFD6_qqJo!|i?y0kmpvEo(gXknBup=k7I7AohRS?KE<=-hAoUHvIsu`MK zCWEGHEd1uZYT|5+YfgN`VIJ$qkj8uH@ODt8&cGl#8C2SPIG?Crx3=oTtogyW%9qD9 zW=~>FUI*IR0a5^(t(9_G8y~rhn;ZQUn(U{57HgDw`rJ+Xv{yjz z8~e+O9qCPG(-u5h1v!mebV@hak-3+v9@Yf5pQ)AOn7_N_bers<9O$h5R8ZH}!q4JX zHP4RqBK{__!UlD3`z}S+_=0wRGBAiv1D#0b;e2SpWUWaJ7dFH-rLG9K-#mGq_iE7U zPmlu82&a_O|6f~V9aLTB9FRKf9iYp|JNaleXxss$02J-+o@GDU51w|P&B$Lk@om{O zql%bYO3-f9G{{!jFNxx9*B4i+CZC<0uzdcW7ZRoSp=HzzP)p3h&*003kVRP$D)TN@ zwRzpTBlz`UEOe}R2B^p8;oS6n>UPzd5a)nnb8l&XTosa?GY2$x!oVOp1Jvhp_q-YJ zV{h`HNo-%hvG_y#*qaWtdqF!vGoFG2>WsgZL2WPZ(Wi@Jx$49Am&tGJ0IlU^U=W=J zSuc0!YKZ6KiZw@tYjj`Ry^T^`$%~%Ie z^9W=D$Tw0>w||_OKWX*ilPk?NdJGxvP1SsB0vgEzDFEfsV9$zaqHA8RTmG-|@MhjM zvchMSKi`7Z-Ltj9j@)$ms(hf~E@P+O)K!+7SNbGrtANS{1_seNAd@Wo3=20_{!v=W zC?>P`f7$L}-E1p#_3HF*+{DYPcb3t*T@5$~~&G*>O@5}G?9STxxR-0Onf>u2- zfJ}hQR%f+vS4jOS$upX?^+;*sp$lR{e9+!4n3qGnxe&B1Ps-`qCh<>k(F#pbvFhpNtK7o_ z3r|9WdLd}~(#^9eXY2GMQ8y2+`64~@3#-r1jjIAcaR9Ocvb*Y-`?hTv_m=U-9sczC zqPeN}ln!2KFKIET!DZo>b*@93WpB>3x{^QU0w(W2q+gPN=8MIkaVZbytixy|sk7#md)m!)0(lPv!WY;sm7Cl&8`LXcU=UplO0?FV z)$xgK7vIgltnap4BGz=r`S^Fgp%v?5$N=WaOyy^ZKO2rd(YjJHRX}t9n!LNv#{W{t z0Osi_PQ3jO5|^BrCiROo?PBSpo&Q1AAp?WxQc&IP;XJh_Kxr9E`}JGteY|~2JEui` z)d%SWDF78DQcf!SLr-vXWv9Jg;&CQ3ZTV!Or!}CK2S@>^ytMXQnJu=q@8fn!-*0v| zuU>m8ws=AhsK3p?Ai7K)oN<=@*eSc9Kl#j=@NkX_VG*t+OshfB%)lVJ9Mn^@@XHM^ zy&<@1MKODhO5Ns7LGS&yzlAmrmV-ugJe=oszlr0|oqJQ2_wa_|cN-?iZTtk9d}Uw| zT>EpB#{4!tMR!kwauW34Uhs*Cm_}{)b;+;t8bF88lBp3DCztQ znTm~TpvzrWK#o;3ZuMf`Bzes}V@XJE>uVvAoS!$L9kG?5c9ex*b(d79`To+G`xRBA zO((f&98n!Hd2nHa<$Wu{$Ze%?VmHuK|@b9?m7XjFT5vW~(}>Pc?dxcxGwE=c7{+xh`r1ZNsdCG!L@)J8nBL80B?ysPHRf z-?-Sn;SY4R{5nYUz%VC6{cY*1T$XnR2UInu+$??L1YIbyUJ0D!v=+ZBpSx(HSQlH{ z?P;l%eeqZRLkrRkkmf;gQ&X?gR#UM)=e2C>zguxnn{*FaK5T$A4;Hn|w>0of{$kXZ z?3JFdCa>YwJ!sXu0n$8J^X}xLwGWp01Pe~)?Cp7`baUY=XnnB})I8Al6m*^{_UE5v z<9SV~{=IrujhT+}pt&>#2GNZ!U`MXnqmuo9`TRdU1@7}pCOa2r&Y23G8rTFHOttW9 zm2KF#{P(Slm}P3Vb1q(MGiz!UhNP%XpcMoj&KbEpPtueESLa)4v1Bnv2sgS|fLzbO zAi5bcqNS<9IVnjs;kilqg@~Cx8^0`KxE>8LVKZbzYeG<@%7xbIL%s(C1m}fCZLJJ^ z2@QuWpjfr=yVLvTM`6Q~)^*DnFC>{RSyy~+4`@>*1B2)m$cWa5tCay73h&xQcoocC zjm~8yFI@-f3^Oo@ZUv2KNja6g%k`NMUEC~~Uv{QI_G0O@U2&j_1f&2o;id0+PTBq9 zf^GIEd1Logvqc52i8xRIZIN!R0teLM)VDInrYLS+-l!w7{L4nR=UHZ;{J_8nC{u!Wf=KLG*qPQ_{5zj@>th}Lql>mC_F6u+%pWOPww#ueB;V+rda!p*x#R9 zK;thA45GUs^@UdDM@NMz5yc+b70RbpKl*d8r5)Pv-VLfRB%S6jT)jj4Igd@;A>Mvt z#t&Ehxx$knNp3f&)OYh-IzKek==GL!%BGk0I0gKQPklBMv>u3oL39tKziB4_?rM11 z(X`NCee)`M`dj}dDg1|+uovV83qQTN<;;~Q6F(h&`eZtfroGJM3L)s+;$BF9lkNYP z19>l|G0duL+vlSkxli(X5_GJ1AE>`6<;0!2@5)~Ft1rH=oiTdv>lXRO^e=SCYagg` zFY{bCnel6x#Pg2jY9XP==j@P^m@5G)-53}|_ss&Q$z;thO{p1mho!=+r_cW}XTx?T zA?V=Ye$bqng`fJ1-TO74aH_g(e7B=PD|6l~+iRe7z`!7S0JQAI!#Qe)MgJ=^u7l3^ zH~m@k?%*ZyyA05!1qVQ*t+Af_ola?W-&nWEbltuqx{nm6<(zm1ZPOmO0Coer*}qqZ znvHCoU6fQ`lqb(=(O3i73MYC9)O@z^^IC3gt>R;>uy9Ky-)xCbc^-S8fQB|07(@?& zwxM}A*QOo6QNGvzSHI2~FSU%)r%%^+gI1t|6o6L6N;!3J+AEc@QYAFJyYHsTG+Wjt zPjP4`=n$yo8SL59D>8H1o3qd2J|A_T=azqAqS|uk_`_ky3Ab-N9;q*$9$2~{IH-`@ zKxgT{W=M!Hj|Emrq=a6 zJ7g6~O`CdpMK;w$|5UK~#kKkxXcC%%LG-8vI3yYSZ*15c<#?!Sn(Cg)j#o}~dwrlI zy~jY|Vd3{BWkrkk#LSpqNv&Te*!{RH|3G~wBuyRzb?H2uCsriy6Xp`MDs(B<^UK_fa+PEW&cew!Ahd+GAOX*sQXrY5V|U4m~MeT6~(XJ8P$2x{Y7 z_v%Hz1zNW2*^#!0}W(@6oBfDU{4?O-^a79+tg!^tZjFa zlw4h*r~oa@FF{83X1?V}e6eV!+|AC^gY}2+**l)Mh0ac126bgD{0uh-JvvtSZ1v@f zjZBA2Bf=J}5C?Ui7#KvaKt}fV*w0h;n{j^K?(lop3o28yJ-)SoR{MbzfD*5y(-fyE zw`G3qEs0zlsBgmd)>~JR0n{`BDFAJCiS_)pulV0aCEs7Rp9S_Z_|?apPx=ULPhL3! zj!lDO2H!S(F|Tv7;@UX5=)i2|n?=w`mTRDvn1!E&_oG!W{j&Lfr^lt+l}bEtTlxo@ z?5}}3g&xk1Up&^IP; zmAn2z2i32E`rpc)hm*Tv*lqTUKC$e2%d+p;d6(%<(B<^kZh{>-d16D0pL5c_)d3sN zy3D_(uip0#+Q_*9nmV)ab5NZr?BChSB;CO^HONa^JM6V4sJ>)i5WN9f7v$lr%yj!h zS5oDZs@|LB`F)95oMKZzGhrYFpcaU=XT1MGlYcwDXw7=sUA-jj;a-#J%`hw8g5B_A zk*D+bu5}EB4<^d`o>Wk%Sk??0*<@f4y#-ovX5m+G{n-bdn%~d%iJyI)u~t@8PKXui z&0C-mEe~f=QS<#bUO2o~lx=XBvDfyE(Y1TfvicTiQd-I>z4+!W4%RCPE8lIc=>D7d z(0!I|f>r&A=df7c|Ez;WUZKXO*JwDXZNnfx_RfJbtzP{3_5& zeUJiB16<$JM^I+QW1UYi7nn5fef_@iN0p~FXlEBl0c3fD-*wFbzO_c*-aL)UeU|31 zw`hh8r~qYP5WNRV4;Fs<2X4RkcTMTU+0w6B&kvm8GL%q-mJjzJ%Ns;?&-@|ieyJcn zc;WS6^G$E;1TKLVm@+Vk-UlsjkaV&P(JRh9b4)K}29w8DX4^w0A_qWgSV0OvrJbAS z-7jM4Hzk3pE;w1XyWmkx=UJ`!9W=>nawgse&dI;(zcsNVlxBvG1bcVvj9ogG2yh;$* zEIt1|Q~{_%Cgo(%yn3?k#^jtLPWGL*RBrs)nm=C=ssL1o1$y@SDL$U(v+-0YW2CoU zqjGNHw0Ka%f`LKwAtYZ+XJcVLUZSu-C?kj8&ZI;`aLNLxBOgQZ1?z_63syE?h`s1~ z$gWD`o`bIbRcI;q7?Lj{ZJ*3~e_^-!+Z<2dM+erOGLb$EN{b8(qK`rOBG^--OE+0` z`iJ@5GgMYL$h(>a-7x@pkAXq-38Xr(Gw?X3eKb(aXH|vhM5z>+$=SO=NsWO)^eLn| z=+;bX;}Ac2jd7N$>nCsD@SiKVL0x)~0+2!v=jp$cd{#MR&f<{za`{vBm1-H*23$Xn&efjT(d^8ojd?zUWaN|5tHFxMR>~m24Y2kP4P2ho+vkyME))f8B zXW87VvF{ydbd`ZY^f_o`%fmUZscIqL4up;#KoK=mxGApa9eNl>M-gkKstd#xoT!_J5l7#OZ|B5zql!3=E<# zLcvMyT(3o(e}HA}o-NTTyx;U^mo3->YML-Gh`t2natpupJlox?#XF0P&h~6oDAMUN zyZj7vjR8mjXmNsv^OYs{ZWldbI!IDrSD?Hp<@ByX>2*Qfj5E;_ zc6s|tTUYH^@C}+CUV%2txO={5(o^wCnOW8F;5;8{}~uW-+(F> z59e~z#9IrNn18dVy?ft}tlcd;^+|l5)CzeCDe8V$00`np!NYH{8;&_}dTY z@~1bTJrJ&*SDyU6SpMw&SK|6b{Cwp6%(5ju+U26A5U>EM(N@iRA{+N7xUr{*$G zoa%KR(28UR2GMsQH(2*{&K^IYrdpAO00i>B*ZNd#`?IJFp*qZk-OKMH}}FpZ^q`_D-qHkbxz zn04HX>UiIG7wU^opy6l>zbg-|8pFffRI z2KAoHJUyjp z{I$K1(ZAh7Tvd@_%bnxh?z?%QfY$%XOncAso~umFU4~fllHZR9E6S@ ze20v>*ULS!d|WE_n`3)dS!DRN9<>h#p=0LYdoWx*Pwe8TwlqHKxue?~i<5H7zmdf8 zz}xp=oUF+E{|VdQ87EJH#>G$25({h3gEo%})i?5A&X1@$U|{N{e{8M`)P!GoaTRm-!DXQRX$%aazagV2EBKxqO}`%&7-cnuX_>>6j~6VxL4#!= z1&~pcI~jgyX)bJ;{G=wD?>mPgBLOS`%pV;2(6481L!Dcg_m#(eq;{{OO>3<7UTV=%Cqu&>*UX zUwT~Q)$pFkDF8Ly-8_r!bbra%D1QwQStqi9Yb*PH<3$iF#299S!+|M=l`SqmUhhY5%CLf!x1YY(0>7iXY1JaEWV*%B`7Jj@TyXEbUnl72w{iAZB$}2rF#w(!a zG6RDc3uqj|!`b7Y*R@+0QzsnfTv++?nWxzm&(ok-1StTOcJ7`_zgyNW*eu*Hd*R!; z9Ig10904)NjF=e9d9WLFaty74XCEur{^5toM}Ntkz0DSo1(srLpq`3_pMux+YK8FY z2iKb?ZCA{@EwD5^3N*~bz#zs3TD;`pd~KyG?}66PYj1vi7t;$$|HAm}E@U;V7#nCR zNXqGsR>kfj-AnvY%O!6=Yw>+jpmGZ``yj>!O4Z7qs$8KM?`Di3E1+=rr%o%>VPpYh;e|%r7ZkD9nvzHTee0`gxf1p zR?Xw?_b4x@FE}8R(H`crWPj8?Eou37$m4>?q3C5Z-++1rAQM0xQz@rU_tZG=pK9Fv ztWI{Kc)H2GS%PmsNe!d`)Le4&e9Zc=@>=Rkh1r+%Z#3;$vnJ<2E@b3ij1zKalfBlN zQycX3_}47(H2H0DS5!UOAJk-LU=ZU16-5?)Zd2ynFNlfo>n^dsz1;Mf*G>CykOW8p zsIlYW{Bqf!GkvEXJl9CtYiPJffb*y$v@0jZ1?qQ7If>m3y7no?@5G%TL-lyqMXQ`w zN<*5>V&KDkTs_}!75%n&b*0<_iIbDI2-!sH+4F-+c?JeC?l5q4uXk|a+xAw<`|{_q zj!#E76t9qB0j&mRU=ZU0xxvD3mcd77mHA7)+N)<;+x9H>+JvGigyxOpJP z3mH9VI1*c-{w7Uf5!5pzyjqoGfQ1q-Iv`SZH*w^6K(Q zpaEP41~Gof=t0~6kOse}Pm6E38a8Y-O=Z}?wHtJN9!LSGeJ$m5SvXROwJpTlDQRB! z^DVQPFFpPPTI~l?0BVUTduCb8nK;{FOHYS_mypk@)S6!t^&lNFF@DIzU&gVyCoBq1 zHnvwDT=6PQ&(DOZ2eSH6OaL@IZ{auR)UAmg=4*O{^VO723C%n(as6G$w4InBWa5wQ zm-CV>%dC_1%pRZh`x<}#4Ldhv$&HvGsFxt+w0pJsX88pg*LL4LoBS@)sZOlS12QQu zCJ5?QyLyJLe_6_0qp*%K26xxvCuF8Chf+K@9}*sl0Lb+k)cFZ<#LXm1z;gP1U=dEntJ-fa3@KtN8& zeXGOAs}((KzE=rC-5?BF1sU(zFrzD}f2P!#4U)`~A=iJazO-zH05D4D8n!?h>3!%u<+Y{K{ZH!m2q#K`O0}6bMns4mU|3oE{chQ zdMF;wN7?i}+K0STYJE?Nhd>jpIH+>7@Y~j@nX~QIr^42~r&;%{ zWzb5|Ukn;;XJ8N$2bGf^&if|SZqoX-ob#SM+a%Q;YDZt^9|uW*6o8ruQck(k@~&!q zeeJ(g zoQs1@+lfhn8oeIQZ)}%s=50)kIJneng4~UIo7uCgprxD?Xns@5$tSAnPUGxDIckE@ zrOnk>Rax3MLz>NEQlPx4@43)~-D1Iu&r>^o#<`}*s%>O$)P*!z#iSsYwmfYQEBBk& zHs7KwqCq3Z75k2S5C=~F5W8h2n| z5R(CIvxxN!YqGo}%Usm)7TIHUu~ejF?KqKd}zjEA4t<(OwJxWn7rldy~ux+i@sE^ zkcsb^mi8z(a}zX0$$^r;n`hT?p1-**2l)ju&qsYXeItJQ$W>64%)lT9I?RVL(r+{W z_i~%|U#cI~<*k=_-TnN(I1`%v6+mvW@ayI2W8?XK!am>QNzbd6%ksrh*Fhux3=Col zpwR;l=ZiX5ID}f)aYr{lo}|j=Z?WsKGpK|GDF99HOF4P1e8|K!VgB@~dnepy+th7w zd-)Ae0D%;MMtZG1cd!0+JXO{A+8jlv3Hm7#cenOgKvqABfe!OwjP&!@_OCkzZ?N|3zyYtFeX9OfmDAF&pF-EN+{>yFH;eGaOUK_-A= zHP(}TXN!!&4$d7c3zJuz|JGUSGeHN`uwY;iQ}zbui_#g4Tg)GAGVJ&!qOW$NIWyq# zQ_z$E1A~|fsCQuD$Cr@DHQT-U_UmTGeEBKfbLP$|1of6d3P3G$4`-8ylQeq^Cz>`~ zU!<^wKkIdM$zRCGo|r1Aha%-vC->3LY=wbY_>~Kq4L_|;IL@>OIgWurOcmr9q9-hN0=O-vQCgX7tudqp!h7Ee&$lWt~Z7O?NVQ4^>W$iN_` z2I_ZO_??~JduO$g#@@#q>khvvd0^46djWK;0|SGYI%ss!!(>h<9F}zi z6dj)bm=78b>Y(%><)nCAecR5|Wxu|?7mm9daYs-Cbbhayj9r zAJ?wHpR0Mh%N@C))q(m+a7gY|*IQw8bM+)^&h(j!V>lITA8mw|QJSEEeG5NTrbA1` z+b-}K>@?nXpEbh#<{B@^K#iCtC{{h37ZiRzKY_QciFL;rpSrB&9WiUnK&OB)Fo>9IzelV%pV4NoSf5p+u+36MDgu> zTnE3_we<0zDO_Z94gvoRQkK`)2nJAD2lsu4^Hi0>li? zfs@>Ic|m>c#BP_K!fX~f-^Zsn?JkAZdPblzLJPn8Gd&+4oa(aOzbZqtA)aGJ*Te6S z0SGZ8P}1{ou3OLc^4LPN)9XbSE%SXm!SH%;2V@>c%m~!Bm2zU;zTyAJTiilz{T;P;t!+%G<)yi z{8L(nTmSls%oks6ICDRJDGXdH0_~8RfEpT7P8P;8OAbmGG#lk6a{S?)+-DXt3tE7f zfU3n{Pvc9j6|%?opECX)9@P;e&t{n{3Yh>EGj#$x^8BR3TO{OEzD;Ddv@^9X&n{Hlj{>1%bvr;G0Kc7T=xGBAi) zfU0N4`88KwYjL`K=DLY{b2My zR?2BL_sR#i?I%qX;Id>ftPyR$wlWzq94%%ITHRyqnb!NpdE%QQHh-;a2TCf1m~=yA zL93b=7{owl1~W$bdFZ?q3sU}_X{r4D-ff*(OrFp0gErAIFo@ZLd}HBvz;TXr*oI=I zE0_P1*59i8h0;?+&&W8laDHYw<4!q_PQ~zGvCF8)@;2RIWDL ze_8&WMeuY%8#`ptub4gLfXYvQ0+b*9JmB&s^u@CUGW#yov)6p|GIsi zpv~tD3}Q}@wtZ0Z`J6+ntK9w+887rwn(<}DB{ygj#TnAJx7(3>-RkcpWoC=ne6YW%kLSDA0hzF%hO4ZoEpd{*hH2dz+NU=VYGwC&fh{ZZ3nDoI@* zJ~Lp2)(bP{cV*Wg$=(&z(6I2Ujph4z%T=)L#lrTC8wHt_LdP3G%_9Z|F;`F_=HYzN z&u?Wu?_=$!i#(pcb5r**DYy(R<=h}```5C!zBQfv*=`dwXGx-M^ohV3H=#WgH&D~n z+H*;#jebpo|Nk=wgm${>Xs_V&-U=#$85qPs=LIoF`dzzzEJ)x~bNG_KopU*IO`g4q z2!WQg?x6ORh2I)(>6)^_dUZ*Ahvxs$SH&~_{Dpec12nDg;r#i=t`cQ4?)Hnvk0~2X znOE~ihz+zVnt?&g1GGj-%E`Yh{gCV=2H}m%yDp!S+t0qXB?ek8dVsq4)}FrN)7<1z zJ6~O1X4G*#L}#!2))Syz6Ce|IflHX(Tg6XhuMN4o_l$FJh; z%7)K)=Pr3KENdRUJj)(({EHaq%pS%_znnd?e|}D6h$}d@Sv;VnD$2rI2QpnH<_9WB zE&R+6rTjh}f0{8e%U-W<#T1nZ$?DKb%?~tK;^Ex3=C{zovpm*a$C&4to#=U_cIgQy zS2Hk(`GGR2vL}=MQucf6o}M~xW+mLN7|K^Ctp=G~5c6jON7k*aagEuN&gB(y9h!H$ zFe%e$uOp}`Vqg#p0F_l1ep{5U$@OW;c`yCvw?wtjXW8_#Fo=2LveqrEV#wL|124PeEh7{o$B9di%oq+~bMwabsQZP>?Zcg1Z|f&p(>1SHvq zf>tj`IR&v>IBlCKJ|!+^w(pF;9$WkO&YT2QkO>aSFd-97#mQd^SER<4I@WA{$Sryf zTB(ID0XwpwZYulb*GcM^y}3Qz_m>(?U|0?9(uRRL#}lRECYjBBxuao!cXR$v?)(z$f_M?Q%k#;)-|PiZiVK}NYH?; zhqLpejms^?ZCA_7SSoKlRkD$dXF4cHflL6+#z;9masDpR=D6tLwQ~<5IE||IIcZ;l zmb8(e5iNI5n`=tv7hO5#^kG8B!rH%!7-C$XgT_7>7{sC=SA<*6n6`OOQ|G0Z#*BPX z$HXpvFkb^LC!;|Nh%Ed#vML{I)G!}j@_F*MyNA~`|4Y>dWf%qqv1m|l$-{X8)2A;! zeme^@EAzs|1D6D>3P=a(1StRwLrOWNTfVvZgyS9i#Cdm4Deqr9V~Nxo&~^d_2C*1W zSI*kAhGq4a6(I%@3PQ@U?F*)_EV&9j^19!eajVv%%m5}c>>V$brJ=7>L?7OADT>t;TI)_QTEJR0N~v+Jkt(%{24 zI_;Vy@2mS~r)+QD2uZYYo#5!+Q?DuhuV%{gRl5&AetVtcT=LYppyeG53}W%1?xcmE zl-3A=gGT%r7{n4ln`Jzlqm<@4FT4D`;XK2#Yiv=k_jlh? zgiQR2C4g3YNjdTD=!;R(oNC!*IPXEW*4nho^%|g-2gn3auhGp@W7Rgn?gu|7{#dln zI7>H_btlt&Xjd-b5ZIBs1!X6m+WhD|&$~DF=eoJ7UI%$Vw)2Z6fw~VCerHm&uFUF< z)6ekxvr*+RC;M%m7HF-P1ZvxQICn;f%ftv~DTlKC{C#QhEL)2ckD%U60(D`eoZ{YS zJ}aDd$CQuD=1I$=+<$oi58EICl>{1o3-*+E?tYu*x!CfuZ&j7&p{qvmH=01z00V^3Q@SXi%qs26Qd_j`PoJ$%x%@p6^Nb{NGOk3jR1+ zL8ef}Qa~LM59i(PsRgQkGyklfxpKSc3TfSyhLxZ(K?Vk~6wrP(DJPeekDh-_u1KE~ zcCGhU(E@cD&yUcomjaq&jQ6~AU+G~}NXF4eCZ3-YCb!-D%%u;_IH{0h4T@YB{*1QW zz^GGcZsVPD@$%!Pr=i`4G|*lU3%@;^Iv2iPDrw^Ew}w0Ek|yI8_QRkyJp+SS8fYxU z!&&lkup5sstH-mfS5MRuCD@qOX+T@W>7d~jDJMUnz=JBMp8VPn{6c4akj&)lHV;re z!N4Gv4q9U2>Y0<7X3@5-?V8##1w}IhgIEU04HkZy)+cV?zyHB$(<410o5f)aQ$nuZfkaj&sJ`%UmNI{~ysy@2r%IXQu}~j6CCU587PJ0}a@?dFBOdOnP$bwZ3hpyQRO%+eL97 zu7GMg1_rS_$P%oC^)bJK7ikO{wyd}_{i`7sesB$$DsvC5vXdGa*E`Q_5D5HCQZVq z|5iZNXO(pvOweXh5$FiJSkJh?>%xyX7`KTD@HV#3I`j5=81%kHv0`4ZBNs3KuR3di z`&+J_MzNpCn@6)%|SLqV#Ud-#^+Ay_tQ2#>-+}l z(laoC@1|g|_H5g@V4JkTWuewh>i%N-KO7u*^Pwh`T7w;_efDhnCf@nZch;;qEb&pD zo$2d8(6l83gIF18xr>FLo5}KuOh;y3j&r5iY<>O1l0Elkqt9VO*7@11$cS&NnD9>B6F>_DB%NNwvIH+N zHnP89$18k)jl0r~rClJ$ffRs7FqA!gce!}pP~0?ET*>19`QIT&&a#U^2a9SyfJ3tL z|DMik-|MVy-O-h}X3em+WYcp{@yEa*RuAfkSorM>%AO^bSp1ipKk>8Fu6qn;en*1F zK0pdUyK+68jZ`mu54`r*roM!y`Q^#>Z>bwypi`*zpy5X;C!@`)kG-$_U9fXJT zssJ`gRmmqU6S`}*r};2434G&*22>Mh%dC{srronQ+W4B(Hz)sekLx;g^yiZM(B?rC zsP1z23}C-2RAKD1=V8i2y?3R#A2(} z^DKmx)y<&2FcyB9%6F&S6xh3RYr4*xH?{(cH>{P1HZYn&tD8KWvQP*KXe~5QBQNr4sB&txR*{C)20gh><>BmK`LLCa|#vvQ1U26|^nU z!ml|c+*G#0?i!2ThbKb4M(4#WnV~K7Hc;c=!+E!$p~1$FI}VB;%6l+>`zyQXEw+#y ze`0N*)qhe>OXe+KI4$DBp8H`gUaTjhst?|p3H4?hC{^owo)d_7UD@uM{%mEwQ|84( zXV$1Of*P6(3}S7NWnhkvrU!exkT3o7-Mv7i`2_DZm06%6Ui2 zAl0JEC5CHUANDU-WXb#2a=obd+1e)PTyq!5Bn!XQ5qo6x*e5foE}4C$;#%Q~NLee; zm>>g#SQn&PyqUTrd5whCm!@W>jjl?&jSJ5mfvh|f>w;8^G5%JXX_DXX`q^54`Q#lY zD}P)c+W7ARRg3zbX{Tk?UhexiSEG7K*k7*%*3VyELGxH3EAE4%`-8$0hm^A_OBe0# z`x~qr+H$(X9n|1vU=RcE{Il?rXpm=~`kV9iBdzeiQ}#{ya4T*CsHOoa096Yf&f1A9 zS9q;BdVl86T~W3j_XF=4?FF@EK?*>V3{p;uE(j?9f3@_8g1ObIUUQ!ljT`kr1qVn0 zC`AQ%E{b@UnET7)4A<^m3(FXft4IW{hBh#IRltr^j4oWVa+62o*+9W>&Av4&d7Bo1 znu!byVtt^ly@lVteb+BG?%cY=K>q3D6CQ^7JJTdVEijM*P{Q$WUMmw~B+GtskF4{u zQqQA@goS@kgpQf_fzpMPlSA6xJ$|jXL*Go;SeB8Xm04yJ2-%+{)(=Wq)}HrV4{_-( zY+L?|?_*1R>tk818*I>)Sbq@Mk++=1+g@<4KUx&?j?cjC!5MuMH&AWIz#ujOba1m%it( zOErw2|MoVE7UmbT@XWo{5pkv*QkYMMEPv`t@CoV@Zn$%1Ek~N--VCo-VVs%SpE;)wIqwYT>{OqdF)!#$jrZoK|Te3epdw02j^B=&~$ z$(0G94mrpK&=8=MQ{!rGUYmUjvTO7*g(WId4q9HE02(v|DF8K50zErZPuD$*zQy6X zOC@PZQyLH57n|4)}lZXc!v!2a%6U*kU(9Am>jZpF3PS54;%w{%{bcl+wMszbqC(8k_$ zP(wq?NiBtG=4-Q6H>Eq(LsFLpyS%JG0-YchAWZNu&men&s+26u%r|_@aQnL*-I#y;MwCMY0 z>SXjA+C!NM+8p8GEbzGZ_r#8pyc>?1GZ{4Z=@qQ{2OYPc1!|E=Ic3{B$6BhU8{fNE z(vobW(Y#N17PJ*K3pD&z=E<1i8Pa61z*nI6=W;C-wZHGy*+Q#>SqH$5Tsr3fv+w!Z z%R4;oUCzDxmXEot2RfoP2eduW!Y_T2?mA~}|9d^c)k6AnTOU^0XFx}K=YZNW9?o0( z7DgL6Glw_N>iG93(9*9o)CM%M!N4E}K9yX`DQrd5UeW)Z={C#u?w`M1wC23&8|b+G z98ls__RM(iUT5nN)OT@B>26=o8>j5wgGbvzCR_tMvUR28DpRh5JD$Z$t_txht9w?J z1?{QL0~N^@ewWwCZ|=xAwdlyhjgya0e|K!w?a837ECYksJkaQxhx2un#K@m|SJGdI z-VIM;-(C_k>kOzO0Vx1Yt?PR(_OWQ0_3+0P``tSkzHX7>cUfl$ZNq@h3u27)({!C! z$5v;V-+Nl9U!d@!+wQ&Q&}6>=)O@z^6Z$Nj_4q^3qE%}jo-x*q5t={9#a{*Z`UuVPFtj0GcY2a_U%=DXv)@(XsvU(L5a@-riWh;Vilm(QCvS@X{pE#LfqzYg^TpHb3OpY{9WVw4u|=RM0&7nV zh7{)i?G2w!`LSvLXQ<1yFk%6%IbdKATWke(B>%a%&+%U;PA)&YEa$AxT%l_sKF~E< zOC~cgFj)98bDiN1oGkwO(AvHUsvGL$Zt#8w%>Xelh%Et4k$5<>-aPwq(+W?StzJIY zmoOX>F}l0}+FM)-QYhv0BidhP?%|i84!#r+^V@Y%>bXiDC`U0ch%E(85x9FQT`RwE zAzV|nrQ$WqE{^x9-fNpdRS`%5-S> z#()?Y#Fm3Ey78-49ZK77 z;8S~U&6~7Kpr#4P1V}f^J@JUu+&J@jx8n9+4QCO1cb;znwCBDO(v3=66U#Djhw`;0 zU$z+}&*GAqn;Zm+W(Eeam5^@Kq1hVGUaPv=uX=iF%KxL$UrQnlpp&pGLG^}|(_!Yr z!pqFkd3{cQTYGzROtb2RU!ZX)kO`ocX_;r|yoLLxf4wU!cimC%>v50rBaHr_DMJPZ zu~m?R5iWW+WO};!UVM`EYEH>&{#(h5H-j<^1B2LVP`^;Zl8x1I1<5zF{;AjsK7dY7tOk`dQch})S-wl{&(3u& zE&M8iS;ay;o_S-?`+WNuUjwOXL(oEw(BRfm$W7goF+G(*(~bz z&ur^civ^O0j!r-LMm`Vf&9$HbD+@o4&e;c+z0N>-I&u?aqNg*$;A+oBxg{cxHn1v7ytr)0TnAdc!N4H43Dg=4 z^o&3MxUKYD`KSKHAJg8nOWM0kT@TsUEVc=<{AmV*VWvh-zw*K<+xJJe^sasS>ppZv z%@)Y=C!r@d^UmFPWZL;q_)t%p{*7jqSI{oZ7ErW%IIC{(+3}p|&~LulxxsvKPP?RZ zWIzie7#PI1fKrr{Q`(l4_4^d%yfxpv=J|g?b;bVAM?r0RkOEMTP2clR;3LMq;I607 zZngZ559i66wCf3E1DDvA58%j(JlpzGo*~9{S!{noYg%tM_Q@6CXANVh@y-Lel_6r{YrZ<6Jm=On(|FTgx?>cu)XYsH6h0td6Hc*Q+-t+r}$g4M7<90nLvHLiG>BEU(lRttM zh%hjSZHFv>3Vrp|dV@->hDY0@{T&~h`__6}gC?OF7{qpfTBa6$pBxfgKL>4R{~BDK zVf|Kg_XD{zFa@Ae-@|#%`G~*Ec1?YgVfIooTT<@aj{|=}T{s2?v7MlSZFkR#cL{EH zH@uwlF52Gx-sSkuyJ}jXV?jHUzybB8>}h?dbI}~*j`N8ZLTC5HZL0w_EEpKXc7fu= z!Y?SP^;Q|v+1<^DZFt_V4BP%~@mlC$@-EN@1rO)XrGmxh9Sw|cO)LAnCZSEVfRz>0 zj$~jE+YOqPl5~pR%i7beS!^tuks9cCVxg(v6lKI&k^w zG6_%3Bj462J=+eAti6yP>%?7Ee=S+VS+=wGCG*Iqp6fOc2GukS3}SmhRdk@|q8lQz zpC2su*>E2yt-FHSAp&ajUIS7x6T)N`7%>`yPL_36@q*6w(qnyUb)Tech}!qjzqX`GL2S zA0)MarjQvJ#14Y2u<+ZwZ3E+M`x%0HfA#o!zeW8B=?VnxUj-=u^}9Ws4>USE??0if zt@9@P%70JwrRTL4Ks&_;K{JC=PJf?9#e8}2)MFyIftk&1w+qH@7oaVWgP`flSkG^q zo0Q(YiJuY0@vQT?WWC_Twq$61aR_qux$a@MStTQjG^Tuct^d5^D!ocQz7Bi=DU@YUB4gH`DDC!8b~JtgV-?-@T~p0 z8`}+yXHTv@28yy@*32j(^bbHmz5Yd{r}~@u6u%K1Mk~6Hz%{)WAlY>B0CNm z3$gGEK7CI+*SWW)r{;*%v$i(H)!HASS?>gBINHP6q%&ao?irq3h95uAyO=P|{dB=c zXw`fIv;$Pi=`hnQpD+6qj?T1UG8C)*7RU7b1ZdoWfkEs9C=2R)ZqZg|SS7(Lbl;%% zqLue7?YTm-pjB=l1xvx@Lq@^$z2EHjeR}&?Z1v9~asB|-I?zBB1B2K}(7rtjzwpb! z2lE3$8Oyi2K9;(8ebI*sSx}FifkEt)8F=5pgzHPzUau7Oo1s|Caz#l?aFF~jzWiRYP_A|_7AzUbQgZNcem8Jj^vp9~CQ=RnIn zEc}GZ>cxAWuU@Ar>C4g4-nQocp)63H4N?GVCU`h|@w2KqvRM~iZRCCFWF+z^zIuiL zr1n1t+Fc~&lyR!qNqzFIjZy8+nqAW;FPtoM800;W37~d_zGsU5iz1cn=b~BE)Xb#x zC%@X8{20{wVPFtD4>=(}o#ZQ9?nsdrr!AF%*%Y(r@zqkOQHDhDg4lpoC~0S zx1^I@y^w(6?SE(gOK#67KM}j_V9!cuulXXV@$cq2E%}Dv&%k}wHaR{2*VldXlOZ^JJY`tH+=Q76XIWC6F5|{LDU`d{V7{*hNM~ z=g0-78dWZb5XhNkVwXVsl02M!vUka^taao5q+c}qpnu?E`Km9_puP+ms0s2+c)OQ_ z-)nL$7fXh@j@7%b8@D`yI`VQ0*bUQC!fL*x9ekhnvim?EEx z4Ud6A>?&yZ&DxVCgz0J8%F2uWZq-VzPkh8Bh5kbq5RTgx|iJe%csqU4U# z{jxVR;HBI((9oBK-{IoBoF{(1I<@@3l)lHa5|!@6$3X{+u7euj9?o+;SSRht<_-|B z*}RqYz~_|u_CwHq)^*TGr<9XjuAK2}g9ZC4<#*3prLcR=+D+@AiS|0EJr(SERYmZ8 zfjfsjV^DtKq`UuZZ`K!p>TCuEvFrE1j$G1LygF=){EFG%ud{o2JiUD91S_=fe-l(K zSoj5UZcBNZQ}TN;U;4CH4@4@y9iIbjCfx+}FFc(8bltsm>sgt9{b{c`0hSwh-(1-Q zs!$mi#BM_R-EUqm(%$;;c#GBbUcMV!UdVqa-~>f8NCD`46lKr9MRVSsI{c_S^_=L} zO~rG!o!+`1+W5Z-Ih^61g6|Y>!#_El*F4!@UhWjK)Q$m75iu}`-3ImbEd2a$a0qP6 z-_JaS+r%MubE%;Xw>q?WaJv;;h>3FiX?n=%IK6ZA^#fOW*1h>;tOjjh+y?bG^*xKE zG~Oh6)x5aAaEsElpIYzrXH`QtXxxS@$PaEm{Bpi)sGw}$ort+POQVHiYCr?}3=Cp- zK_faAerv2#d*9Zj9Jascb5r(IZ*iRSL1?Xa7c>#-;oSH^bo$R7hf01N`MyMPLgIsK z(?Xz2P3}S#BD()+Z*=a>iuVh)Uwv|;_pyujqvGDwZ-Y+b-Ulr}w(#5ZW$*G_yD!bv zd3v*qSS>Q%olSyHc-;pz7d@P<1&)PkoG7HYvz;s$w^GI7t@ z!2G{_`HYa6JzVTNX7Bq1Y9=x;h&_PJ+Apg268dxAWyKQx%wO_bj(mxM{G_(*B(3sO(lCcU&zi0X|pojjg666?vu_vH>;o)pxnjgnAb>jl#qb%}meEXD7UCII-L(IS+_5{?n zm2%>l+rE!=kyNZld-=-5KoxgQM$k|gs2%kLG|8avsn-|xp)sHTh5Aa)U7|f>#otrZc?t1ke+TeT!>X2Ia)toSXm>#*bvFyp~N_MAz z_ov#&K)aLAK&=1|XRqifqLS$ccFX0gIJrXg)*sn@Z=fUI&p=%nDJLmT}7-jX+tiK{sk@C4MyV_*<__6_XFmG>65 z&-i1`_;s4SW~Z^?>;;?jK^;*B2C)~QwylLp!aw=(%Uh_m>yHU+dXtDb)m#6~^ zVQrWfpo*o;)B5k1t`772YhHD@&zz_?hk4SEXVA@4FXO?EOgT02yt#AU_KyOy&v^x1 z4t47<1roL1t8kPIjTb?QmFLVg09qeOcP5_>`C6X7t~`1DFB6}l+&gMQW^LBxVO2ci(Js1 zHE%`L!3of1U~fUu9powQC2`gNwV~McZxYERmy@Lyd2@k=nLs9d1_#tE2KgpqN!Kkx zkzV$4k27GHnP-n9G2c3&?s*WPczZB|>-80uf$0y%| z!o%IOM7nY+(}x>e;v(KMdN!4Bo!7EJE0hnqU`M`EaP$yj`DA)NJd!&{YwA>%PuHP~ zc0Phe)hzr1OfO%kTg8@E_}shRwAchsgH z-?ZQ=D8n!?h`6M+gvW;-czd<@{DwnsRtKxGeV%&^+HC#=TA3T~DSe=WZTYDS zzZ)i}-jd4x683kc6*T*QsslUn0CUP3dHvY7Jy-RG?`@mm@vFTa6bB3pVxK{o*urnO z;eyqvt9~BOyJNR){oWrzJ1cEKjeZ6Ou`m4KI_p{9uUdWa;5)kA?9;@8YG zx1OvqKKS<1a{HLmFClLD1`2WyXReuFyw5NG>K9@?d7jH!1`+S~KcRizZ=f*{DW@3% zS8lw0x9nZ=FKz4dH#XSx)ha-<|2NQ(aG7VG!K~tCvOA04ZnT)x_v1v9e&-`-KkGZ> z#)O|%=Ojxjb?4+O=l|3DJNL__`QgxMnjfGfXW=JdeeLZ6K@C~QxSZm+tMj>C|F(ga z6fiJ|{Q%J(&UZszyz-krr6Z#I-tBclOuKxKDuU*37#PHUf-0|hZi0VwHNdzK};w(`C&)nw;(|5<&@(qi`8RiLR6kOD}fw|uVb`7I_} z%AR)|bLy%&AbZ-c=QJdsenA?&T-&d2xUu(DqQVrBpFt-ylHTQhg08p!1!@g>INuIE zzSI1a{u8~ew>0HG^UHa16+xTszd?;&DW|Y=+Vzn->=q_EH{uUOwR%=~e1a~2`VGpP z?w;Wr?nW<=DHGN+IF@i~jo6d}6S$y_oZpkdX;Sp2NU60hzx&s}Y8Sp(`S%L5q(N7j z{Q)(8E&N)I&K+g=uK7!If2{xGe;SKYmrMf9=P@vd{RLIg9?rJ4+YjeR-em|X(|c~c zWZj>Z_}|br%-iW@2C7g&3LpyuemtMbv1HzsKb8X7e~Vx2xb!>lC8)Oy zQUID6RQ7am4S&-o6?Ss|1X^aBLQ-eQ7)8pL|dD>WN7o&s!FyPRM{K9xb$!Vq z`P|$ORNH|RfI6g7PHPk5&l63;fu-0uN($Qc;K z*+5-7DJOxBD3?Oh6I%VJj(olpF!eH%a4~4&6QlstT-5h`X!F%!tD4_o)o9zDeP&%&LBwXz8g~W;aSqTBhm=$I zwm&l0{5MVcc#vn|`O~2}frmCi60JA~Xi=ZOXV3ran-?qmo4?+CqT_X|(e8EsF;Kq( zWI{bSy61dUzSe2qcxir;!^Y4f?-U|J*J$T`M+_?|?nBH28yfk}t`*__Mm;z9UN;%0qRr;U0iRbRy zuq|`aFP&|*nh^nMvx;+pQk1pl?0mm{bF|WSwA-#~?Re7c8ui5;n&h}3Q)WyGliBtf zti3q*%=O)tX`-j^iB&-6FT{C36|05c!Gy4dx9)wbHD$5SKKOKAPK8A(XgHpML7WHF zLicbsIHJ;7o_*jJR|WI*OUrZ)oCTHOUw0IJ-joZe=u#TV*CoLOwSweoD%gonqS zav*IvaUM`xM&GksqFealsS@imtArGnid|kEyjvGEZvip^a()!A+4tFd_ZJ@RyeqlU z$zS5Zp*tp;Xb5EleRmYe5|$GKao zxmo9K33HO&`=NSrW0ez3fe+Y`Cf}u2oc>yF(e~fQ;b+3{e?OVtgW`aJL0o7l18A;U zdG?l0-Iu4IUz)4cxAa@t{@q^9APJBHP^Zwtxmof)!|zl^LGkB19-mqt{^aB4DWFQ7 zfk9jtw8X&ObKUo^n&xXtgM=QgW!x;K#(m=4DrlM%&H=ljpzQG8TkgwU{%kx`Y<%biLHiXM7{o=6g58ji|6${S|38(F?N@yAd1su%DqeADIEefO=ZpWYlRlowpV6Nd zG3$}aqCcf(tG^Ru@H!t@G5q37NJNmjq>h3%|oVFLrCa zzEP6LD0Kbx=boaj#gjl&Weg1BlAsZ959hT{R3fL(t$Ka8$45p^uhcYg>L*AmNL&&$ z!YSo+;%npEsn6f2$T3Q}+u?8t}JHzOk=H?Ch%vO2-y@62Z#XF`u05tjxHB3k&(6kQosd%9UMU)b~L zQL&5VGDhqsh~GL*TXZwQB@tOx<)q z9F*l47{p~kLmVE?Y`>>DPMCSm>?*&K^z-wL+5sN-q3J;u)O3|{VqSh_gZlNGg)wW2 zpEFcjJ(!{L7_xy&Tn-dj)}F7QO}_j6*DIA>OaF);Dn7CI-jZy{NRGH1Z^mOnjU;a>j9WgoPJkq4Dk z9?t5mexe(BFE3l{c3*6ATDsxUr8ZDED1aJ!QchRono|$^pFbWJC3OBt{9S&jb=RS7 z7zI#S9qVbJa%$Du4K{QCC9g{Gy)t!j^TQ@+5u^Z__`5QRp8a zDI&ya@dTb((A=#A%EYmrHQwD;W^bZCKX{X~cl%4tyF$l#K+8KA7{rwz_w&9Nlb#!+ zcly&En@3)c|5UEJHA?_gnK3YkgLi^j_=Vq`u(wzIf=r;6XzOO<)O#$SeL$TbkOEL0 z?%|vr_|?tqsNII3qKO>6@^#*?_^lv~UU3yrve)-K^Dfe@ja_Pg`WeZN`Ru3PZhUVC zYKekOfNXpYzIAKnE{lJW8S~wiGe#L4Z^+UFH47LR#MMA8G7G=Aled^n;G4UB@r#{h z_PJM@R8QJ~`k5dFkd4p3_e<(FJAYiivc78K6`wT*;op{khF?JnK>Z6zC$py|ev_G( zy>B~`87r;8!@Qqe8L});Tn*F_(f3^B9@kr#uz$^j(*DxjOgCjdU5SSb)QGG70w??b z4s}`DTMpQq^lTFs)ODG1!_^V8qDEW;lyEHkUhCF=$e+v-wCi4i*N2eZ*#iDepg98u z25}8g3*E!{yyNFL_vH7xEeNhMXxOV&Y$sC*nZ6X)05ub&oWj@gC9JGo^*a7~cwTxU z$5$C|InWp}$OO>nnzg5=(Tb3^2Tx06cUm1zQ?6O4wXzVDSQ!|^H8sGFoU`WB>$6E0 z4!m_eA-$u}_2TC;Q;_2r7{s+eg_(sP>&mn)4lY^s*=)@(MKvBCn05IKs1*oO0CJ0m z^V(p~tgNg*^A&fzifO)Qk+<7wKj^F?1_p6$&=6pd=iJnAro#%8RsUa9fA#C|O`DC1 z@sJTtaqVER8zwZW?^rE%GF@to&AtCFKN@4+PlYC09Z=ie!Y{zdYkgjl52M9N?+>Zh z)5G=6O+k%31_p5*(2f=l=PV<$ub+gc@jg8w`d9SW#nVx47yKZFm@X*UOF0FEem-7R z+u|tkTB-1zL}tK&Ug#}9;<})%Kdzn=R)oA>cw2*?XYczjF%|Cr^Cu=jy0qfDki!5a zT-{CYO=J}D)488vdihDmag8w0h#mujxE{z27Jj{x(}llZ?or>X`8j`Mzt6gtO9CMs zb8&spN>mT$f*l`us-|UaSoNUs9RIX)EL&LDgErAIFo^4e`Z!WfM#VIRlbMtiT zmdeW5trsni*X*u^%q@x=g6b{{KjxzI+_QG(KH^xtP-*2>n{R4&CW5j(1B19B$h#iS z6Td8cX;=Jkc4Mt&W2yO z^q@74F{s&W;U_SE?!JU?E8aM5P+8kMHzh{rX)|ORSKJs>Z+bXqiXMOAym+SAGw=G- zyn6&I*IFKi^m)aNK}~llr+b^k#U$d+S1NojOuXbc)vTd8A2L`ZZVc*(1$#;?anj|R z<=!NF;rf4rOR>Ld*yKP4ZVDQo zv+%q1x^J53p9cZ#f)DD={bWL+LkkiECXwvR5GEYjMJxO zX2hn2jk^RbjGCZbIdjlNsE4yOQ~m??_*v&GEqCk)QGW5edxIosJrDzfxCLm8RLbeG zO`ZKV|L&;AKU=?i+c^1=VX8K?ZEpb@;S2Uu)BhnbOF^Xaj8KpE#GlS`x7BK33f6#g zcQ@PN(+e#O`~A#T?oVGXsl&FS9Wu%)ZUtI-XyLb@Rnb%P%)6A-wLD#ph5zNv7c2lZ z3m6#0tw77DJ)AA2w2y86^Q4|vC+KQf^1H1UoxvlUAO)b=C@H6PUID*ymM=^Hp;EGA z$!_!Ny7@}8A=%#ww3;K)Y_?^&P3KvoWj+d@v4JvS{n<$(j|VU8?=RXhBg{%`ws zAKK`(1I=?<`0eA(YJ0Ek(f#Aaov`h7`SAyh4WJDSJ5ajta9%3KEW~Net-zL2y6oWYCR{?mwQQ z-Mkg=&uv|4QseLjlxZ0l#O)yqsJi#NEOeg4xmme6!rj%|+Na}JK4>bPfkE5>R9;&6 zt;tI``^xEb%EE&Jr*FGF_2Jp}1k}I+DS#}Xs`R;9wQG9gV!b0jS&BWP^7PCef(lRu z260DFy&>h)n%>~i`ZoQQ=&eRy?flZ!FQykmmgI>$f+9=bb7B_5_IZUL)lEv}p0Rp< zTGlGG43sB9CP1dM19ok#H{N9Zs6a&h)Q81S*!F%_geEyBP&dlLPdBEuCU4*Eq6-rY z*D<%ezIXg;KQvW4gIeew&gHik^{CC(IoiL7VVF3U-0>MVCXod~(oqpWOG1MaN1Vj$ThI1(gd74C1b! zg#i|R<{hai)7__-POe>cA^Q8x5ZRhAXrtE^)MWE;zE-E!`QWlSe_h$u-79~*D1D-( z2RYbT+!fTFl5+Zy^NG)R(j=yD%hulF2)_AcaisvXD0T&{C)M{nd+e6?qlQcCbe?>@ zc>QtKEk*jNO{&?mhC0QhGu(9(%$vhL6pavF50cg5P-&0|q`K7W@UaqOL>?-4mgs+6?nSx3; zkb-|;M~b?wNxysf*sh68z2z(O>Tb-8+X5ZQ@dWj^Ec|5S6SezXQs=SlntR9UjCSCr zH0UBOaZk|Uh#t---yG&;TkPg2H#_XSe*VViug}Lq%Slhr7V4O_%`8q zs%=^KPnM8Bkzo^!Ky5e%261oDSgD1d-T!_K{ni{^laq5j*X=Z(_oHROOh_T-4eGIZ zIM;rg71|PS-8oO(Y1-U2;f2>K^+Bt<7#PHTKwVoYr;Bkpm2FjhHD@F<*Uxxu6u-Xr zBIJ~QaUal*d412P)eR4WOG{kmZ8>ns=9#C_j?mN4qS&Vh?8tX|FU$oQ$}`&kt~$O> z_uiNGALpT67++AFSop0^*L>?Z>Bxy6UD8b+6R$jD7Oa8Bg&%0N)x+8Sz)frEmCoil z%XL4^x{~g-`C$;K70AFK?gvV=QckB&yH94=cJh&X{EF2Nryh;a5zd5}02-qo2hp2ia_x+a;Gk@e)Jyna; zE`p5wiwA%fwMjW?|0~~JamHQU*2V1q&zTFNO*bt84H7XhhzEdjmbK^Sy@7H$Z|Cf| zxRdp@|6JGYl2bo{I$$6LkX6Blx1X-~tH`mFhwrto(Z3xh3|VhOi=ZG-kX!imO)%WA z)&68o4r9dj-76+fzxvh?qPL;pT#s0*ZE zIRgWOyXS-c$bAbJ)VXA{hWz@rN%ZF8a#t-#f(d#D4k#0q)*F@cyPhRif4UsC}u&E{XS4{nSnt(3^dXTNvpOq%>oVpXo@`y5ao52OH8h%UbcH1e{j!Vr!8}#^=1U95c6=hXE}Z5s(eY< z7v;3@j|*Marzo9*Y%36t0F8-RdrHIxZvFoJmV3*Oh#px5!6)n;`k?VR1_tp+$X$o) zE{k=q(a~ahUKG1$!TG&ymrZ>jdmqH3K&8HgpM%j0%l2UNOM!1Wx_dml=k|B4hlWEG zXvEjUIi$ncdO=^mr&_L;{7k!zr)J8VLMK_GL3OvjCo}tD$Ev*gSMTp1cjr1LXe(SY z2{KbG9_;{5Fq1srZRr<0owj`L8xA*?ZADy%4MD>z3=HBiprXja?{m?0>)=ao6?QK9 zHz(I1L906G8)$L`qyRK#?BTq&Gtch4Te$!;r@hLKp6gnllmeiAoLJB@YAGj^%|aiI zUQOJ3eC;mD%ohi2Qa&t$_7-D7?Q2)hNd4oBJ$BFfbl>&c*JDef>w}srL0uOH2JzSm zup^&N<~GawQF?tXYuci^wMxFM>Mx+Z<~WcWEd17I%UW z{X;VUkC(XzZu{$fsS-K^k_ZY93%_&IEx61?7sf5`=Z~xZv;FKgIaTOLZz5Jn^sB9!7&du-OxO-B%u_*Q#Zpe88TZdmcI!@Y{i1kWQY@-wd(}*6 zbf?~CU|?|bg(^scEE8o~{z+BqytM6x$KUGB%+g)B z|L%jvMLMXtWZ@UUaOD4S$qbR7OFjJGIH(ou(7gg09ARJ(PX~=Ac{rcf^gpgrSHV0b zaGf`WQDU#2OF+iegou!3`{shG0R{%~OvsEmW9p}MRXR4G1nzE?y~?JuozX)c zI^>lFDruygJeZts8LJe8?LW$ABKFUJ+jh-U@tA&-;;vP-d7oJJO4otrxj_m* zb4k{oT&q%(k~!LDten!pTC0EQbeEDNWD%Em4rCDZ_mA+Ot~&j$yBPm<VL_?(ov?eCic8Ag%!C#}d7y%%%=6YkGrv2Q#~DR$ zW&Y}xpKD?FLmhIqym&qfIH1yH?O8+QSJpW-mD|`c#9e%}QWvtCMZ5sizp(HNjLg~M zl4d(gP_TQuWJ*?@@#ZXOQCt8z^vlCpf>FqGi-XKIv9=9q7JEF(=FH{+6&wr<;su~S zjPi8dbot*ck^lJ~aN-C59yFvCt-=nyR6}KiktuUXt%WeJFCv%~5 z%|)PLX$!wa|74%Ne^Ipc-eWU^*Y9;V37EZt7Uo5uHm!&Aa=AV4BX6o(BzkPQ5hcXF zTKX3cC^CmvT%egP!8HrAfMj`qn&8mqh=E?9k?7F=TsYaP0SaHs@TAAG8U0_%g74yU?DOppFLvgLnxjZCdy} z74co%#N}DEXvVY*sgN0vN$VBDU3v&N1 z+vdJVbioU*!{>XTjlD8Zd&5kyX!%eM>WE1>9X{x> z&*${V)Cb2l{PR8dc;fD4Zs-tbIcVLWzGtBLX6;{xu4TMzJaRGN%JUjVz0c4=)N;rQ zEB-m=kx_yHvB~@TW~)2gv+F-H8?+3LfkC_i)Csciv+ER_u4}&O{cJ(!+>0FVt-3#$ zLUuNZS3*`;Da_o+*R>;3+Awh8)5B77i=%&i1dX;cFo;)zI$~v>%g!C2^w^8{Y@z%% zOU>e>U0F{&prZ$skohbXTgTu_2N#%x-ecMKSgq$1V|Xv9Y+_&#uLd>QEc^=c_DNov zl4qBGFU4{8Kbg5wH`Ag0&1z7`)Wg|*`<+du(ajS#Of}EnR#WspG<`j&QU{p;na^^X zeq$N)V!kzX$8=A!o@V^7Q8fuV!dVTP&(inIn(pVStWZ<|EX@2_tM$~jqd9A z;MiQtR(HhXUH9QN5l0F;x|S_o{<92ZHv@xsEvVkG@T+QaZ4Hu5kajjF`Fqmk4OTgymw`r^85qPH=7Amg@|D?!+f&%?-Ozfgomz2` zSA!x}YY|6oH3xZR`3cf_`$A zf1O`$&GeXN>J{1vtrnZg!3Bs+|(0_sLdIo&yLvDJ}p&JUk``YEeTrk~-@Y5>*x zAQM3CYJE?xqeamb*TYy}R>peHj@b84VYeKplm{t*EM1;ckE2+5ZTU&JK z&DzS#cYAz)1YLRonsfvy0M&kho`Q@=^PMx_3U5fVpLlBLp}iU14?*oGkb+O($od~X zUr^BQb-uOt>E;H(ja%$D{DoFY9iZs8@bgMu`D6ye+Lh(amiKo3uxomFm=jtQcQk_+ z2FP({somb7cKJ;A^r-US+`^>ChHEVQ57 zZ}XR}H5dQrT-~#XrDjJRq$So3>e5L$)i|#F{VMiB>a{-~yg$r(6VdCD09{Dd4N4Ez zo(GMyz9&onF$~(V<i+2}+9eL~Ggu5R^JNpal+JC-FvvPi+sRx}Z z0xxp3@KZkgU2FIu+;yfIz$ z1C(JH7{q%)aUtcTe}9&>;V#=>DSOWSW}d~JzibW@s3HL=fDE(LT~HL5D-$ubIQq)W z*qAfP85j7V38oh^%p!i${Y=6au9r1_tpyP`lE??=nL~Q)>KK zsRHX-_IUwOi=-Y;1GUH*7{vQQ<%5Sa!(VS#&xM>`>n7!W)0?~3=FXufkZow<{UC)> zPN8i6b(*Xxw-UtIO_)Mcb~)ep4eBL=OaR46uxI6u+w2$G1C71^pK$PHQ>*&c{2F95 zNWn93NS^;(IQzn-g3X^^ntf23owOkF!d7Uio(P)1u<%=~t*bJb!AJh)$IFwBg%n<2 zCmIS<04g6moRv2=9Qc!$_|wcgiQ_qAyW-Y$f}mLk1_tqopoWH&(;}(zWz%AsUoZT* zuQ`b0F3U}ERnWWzNC9Znxy(~5_nVCPgDb(OGTL42w?9{DUUc&=B*9Gb2Rm}!2d5r` z-s%aF>`AM4oobP-K7ImJcrh@DPX?`SvhX`FKT~4Tqq~l>w_fL|ZxdbV9{CJ93o{wi zD)w-m_}}8irVDSwq8LET6O2JtDNLtFwq7f0ykC-$c|O=1eYxFV#q zqA0rtlny`&ASZF1ky@~F;XU)6ldel=XjM+xrgVHUD2N#t#HWI$DJ=Z#6R)Lb9np}7b_S<`R%&}Vhp2@tQ?B{3i#OVySJN{^<r(@eI zuN9jd?lx_Ies1=nWhSTpwtyzv7#PH-LH16*-ZDGaqv(8v{;sLh-~60iT;wGT>X0)q zh))Nt53=xUOldoMB}=rjRwL!&A~pFPtp8GO2;Uu~GWxJtA}G=uRJ$Y=%z@mZkGpojAx)t_hY%)I#NY;?dU`7KK~>d*cFEyQMl z+H_J*RvhQLqhB%{{Oa;y@=f)nj59JeLpwpUK$G*@dNH%gfL?srXF_K)wgYae+*M{?$X_On{}}mq<9TvT7q}oEoG6`7@>vVy8l+Z_c>3f zMAW7}*?6gHUG%zx(DGpcXqdsnSv72Z(d0&l|NTDmJ?z;<9@R;F1I?u|Fo-V%DU@>B zZ@)|Z;c2!jKJWMbi;vYjq*)~oN~|CSpth~D=ZvZSS@F7gnDyf zHQ14VQlh^J-k7Zw_h8oRKhe^qJ_-TQ!GT4fc?=7`Eg!aiHLRXGOQTgK`oxmzrt@zm zK{mRIF9vnUJe(Qkd_61aEb74Js37|Izwf-Mt97B{w2ML86Q!Iksr{XKCi+tMfmZ<< zepz$G4$d+Jm2M0S;)_8hm3bEI4nD^k0b|8_2AQiWWB{tz>fU=Jh+bk z_2On7?qjno&Yty~5g!1m)EOAWmx9Vm3%~Wt>Kd+_KmQ^4f5PEcCv{ZxUEe_a7fV3{ zxgO5J?>AoCApL|hD=gi+tx)6L$0vrMbq^pD_JRkKufMWaIF(*B#d)V*SxukV!CK|d z(60SbPzNN~bA^20=YO9WE3AcV9H(!Zqj^XLdWxp_GRS_ty68^FysUXar`F4-8*Tno znwum7oe^6Oa;$}4d`x|diPV!f+OEnfX$NhWv5T#Q*1XF>0~H?5lUa)AXs!rdUwd2T zj}y=K^WjCH@L^zJ5MKeRd8M3I6@NO>8y>+h&G+fa`=#~kH@L?__OXhu05uPSJliL# ze_k{(zpGiZEJ5MOljMUXvd~4IDoYeAAK3m$G5^G^t(u^LYz7ALRkOgc*=+SZl;0w_p+x;d zjeNiJ=Nqdtp?PyPXfDOVPebE|#Mb?-2RbF@pKOMDGzo2Hag-~9Pa4sKU={45OrQ~&6gtAhMjXg_NWXvW;# zbJ;PzGRIlT%{LTuA5>l!6|O2i0_txwFo>_Y0(K-%#QDOUclmYk2WFn!@y+l1uB$si zmIEmOHF7+h6RvJs^Qc^6ON`Q! z9Gjo!t2Hl5Kxcy1f#wdRoWv8R?Fw++UsDo6ards%)lVN2~^ry_&s5gVVL3k&E8J!;pzMg$%@;Y`=KSwCQy0l;r#AszRb?O zug~9#3x6Nx{$pWD}^_DCM+NHe&L(>3vEYb?aL4J+@9T;AI1l9Ts44_rR3=AI5N0%M^GTGpg*Mn0{z1t_%PFu04zzX7q?V!9V z<;36m%<))Z#SPyHr#HP>dFA9I0byu!aXV;vq`v2e%IL}FYNabe62Di+Z+14m{!YLd zYQjWtbVqnZnrvM^@nll0?4_coTW+73R{)*p*#T;iS@>lgNnwn>$6DqZw(#;avku#* zZ&g9PL!Npy$KJ_kpuR-_QU4K&r97ZM$H#VGA^%c0w|5eXsKlr?pG_ zeCIOVVdiZYxj)|$I+eT|l6h~;V(B~>SU*Ya*D>ECxvj5!_BeoQI|c^v-H^v$Jf8&iIz?9-$s)?8z0zggZN@MWc9-5 zB*TcqXB1w{kzQ}RF3P^@a?4EU_~c$ttI)!)(rrrw$7Yr(!jr#j-?dhE(uu6+pe`H( zgZN%h#_@2T6l^(RMn_(Mpt%$azh}x~ZaW;*Uv%7?Bh>oi=7Ckccc4S!`#~AU!&&I| zUHIX$ao(h5E^HGi|~Or!OM|66`)9)ONd zf)3JQaQBouap`?4ugG@4b-jk(muBa`6~6(RzhPhyKLF`g*DJ-(_$InWZPC*3O=ovp zJvb|1FKDujfkFHrv|H_Uw!^(|-CW_?lwEB>M>Q_KRX??qY0z{GNN@kNoZ$r zLE)^>R6?TyjIMJRzYAO(TiPVl7WM|zuwY;iKMWbs z(zw>+&+?`HtH^EJ&$?#c`3x_Wf)+J0Fo+)kbt|QurY&t;G(AOWc4XG=;LF>W9jKH& z0UftL0_sk=d1hQ%An@{)^jEK^e}4&yrk}HuIRI*4flPqp&F-_0a(ADcR(`hWpHOS? z49+c1%+NyYC?s#n@y28o+boc8UriA3dLT{+v1 zTdP!hu0YenF;L!=a$2@5ym4+^xbCXJ-QT{ker`MeaUQfYcnma15bW7}j6Y~{$MLR$ z&0I!HkHueIAiw~v+>c!cC%LI>^ zXx@T>LHrb`TCni*vaWDY{XQ*Z>Gj#n2M*7xbALDoIz@5{G~(;wT+z}bWW2@onS#&L zE4y@eSKc^z9yG!WGT{gV1B0Z~d6!z*-5Q+>7jJJ!{m)SRX!cY#s4q@|N?d)o|{}|XMHK_ zSeMa^d7y421B3Wk$P9>g6wmx+`-)y9q;3gmJ-C|VK$kXX%8-FU{2VChS@=D=D14x3 z(ciAA2R=+loF9Mu)(g-$6sS#m4pdHfIIrk5F^V(oLYu zK^xenc0zO3MRjoRKsrHrR^=?^Q(`XOPd+llIc*ib0__xE1kDudd-CpZ-LlNw{+n3O znOV~_UvSm@>H`fkF))Z~M{)_RvfD<~}dtc|_G zc26y56c#!nHvP_ZznRy*LYqmKL2Wt@=dEk6X|6e%YSFN9`U<8#!5n6zXVCKDGHAfY z-Sckag0i_U`5%aN3ES*GAC+w1cpH>Z7#PGaLrzURQ6Bx{V_etF%UOAUYFkaze;$}V zfdK@>uYk%Z3%}$9hNp9POSk{|uJocX?&l6Exm(bsXjefsu!pm3`a!-!&rOfp^>KVy zHSM77%(5tGlDi5zHL=X|QbStyg@w<1SF`lhbFaQM(Y){@Xo!b_LHz1{aAX-SyP%s? zskTO5)v5pL;U_7V#OFdggV#Z4FIf1^ojf-(PpLvAfBiodp{ai}IXSLDhk~zzYCjL> zl&MQwTntyg6?AIaCMGWI8Weg2T997f0bV9LzqmY}*I{omPgv}dZ=dx`cW!zNUF3O# z6YPfH+XNcD_V_Ff+5YGR`&4N~)7n(%>c^X)R*;2Xmt5}DM?F%T|Jwv6U-{njX!V`B zpcXj;gZNF*$~zBdA&Fml53?*?w<_4WUEdU}yRmZ(v|W7@G)3a>*}f$?;{dOLYG_hT zX@J<@D9JCAK~)h0gZM4TIseaphRhI@+fW<5HREL1&9~MHuZ5w>{x)dB$HFhz`uKq_ z+b`~BvhvrhTobZ7*#~+dqxfym`R*Rhx$KJm_UaP%w?5a(xv;~ZJ8NP6DNtlGh~EKK zO;S#O)@B7L75aT97k61ipJ-M6^Dc?l z`%MIzFYZ8&Wp)kXZV={lpPVzrLcc@qW6@=;R%oie3o2#>OQ0jxz zyLIC``#`Q|U=Y6xnkw;d4!o7LVzHt*_aRo4FQ0{EuEut< z(%5>a=st)L+D6dG6P1t20&AtIu(1tX{e-d7JBuOZqR-3g9G=IauAP(NH>fwB1(e$syDu2SK3m4nC#U*Yv zw6%ct7N3CDr09Fjep)B>{m&jgm!scBWcjYxo;x@ZTFO0vtjTH3_^h(`dw`JRqTZkl z4@~wN>qUa90R{%~XP}bS!f!)&_#6A@H@B?4P$Z<}BwbrS=?SRL1}OlgO%La9R|K>d zU3O!zFgsmqyY{b!SY|M&#sw(=6(q5q)0SxYl>c2_b6$7p{re{j_Wl$32^s=sU=V)} zS?lif@C=s+|85=YpMU1C{bo5*z9kk~HNOBww}qc#bej)n?zNY5J{e98|H?nfx&YQ9 zeE}Mu^KhQ@O(Oc_mxXq0o6Cz8^3Bi8{w)lhQ+olLDslIG>RP8M|4_*1aYj$&gpz6g zjZgnVhofKGf#bqtPP$>5nYp%CTKUJR+a&7x4xR-Kw=pn?zXG+$Ec_A+HY~ri_29x}Gfr#X{CH9eH2%WC zApREAWb<(Tp&U7xw{OnYkXh<)X7sZ?vhceJUH|YF6kzV2v!|(d%JF`g_h`$-Do(R) z$(sDipg|$NuW1HCzzSH0$uPMae9qetuX&*hPeLER??2Jv^Gfo%&vmQTh~h5ZlA zE}PiLy-3;rr}Cs3bob?ZP)E$e`6RRc0f_)3roPS>-ivmJTvU=b1MN;{U=V)~8n}{j zs-87LGUxnE_HP{ZTi*NDr)(DhUoZwz0E!DY&+hU`sVT48Zy%KJ{JUC= z_mEQ)?Q1Q)X5E;!W>WuG>-)NvF&2lWLsz1H1dZ2P_!*VmJHE$v{!7nA#Y^4@>TLaa zH3?LiF))aK1dRcDIDb14xMS|!^~xegyt(-=fB(+j@&`0%2vPv*cS+dHo9?>jo_PtuZ+$Iu|q)&cGo41=1Ou&mh5?>MOp1%P0N* z*S9*=>l*HZngt9D;$K0HUJJj@!=|l8mF(8j7M0~0OK&LflUWZP>HP|-fjyj``5n60 zwpyfp%0-QP3nQ{Jl;+%ruJQf`>I_Oby<63r6~*Du-D#lPm{G&=t)f+auX&)|hi_BBnYZQm`>l3ssw^XUe)Hclo5mMs7X_L# zU|UXZ7?$szNz>1DMDwEY5&t}-x){{kf(59hV-@5@Gg_iZ%iWYa!!LXG$9mR3;d22uc; z8Iy9_D|GRdxR)VA;$u^5kE73OezyJwWf+hG(3o+VXEI0W{XIR|+t?a52Fr-;ja3y-RtwvD@v7Un?{{p|SXx+XOoyXod0zH2z@WH~GZog{$`*7Ake?U(+;& z<)OTn1ax7*AIQL+rvKh^H|@M4X0EAgTA~`oeY%Giy4>Y2Xy8uDsbHF*Z>ZEZE9Rsn zBJvK`P8KMqgMyfWLHsYMe2DcdRC)R=Z_{1v8;tMec)p$erM)p2)OGBD*8kb;UfR6FR;K$Hv@Q4VH3R76g!i|aa^G)%&13g$_QPrM=N39dy@n>*|DfKp zhjYRSnIKb-+8S@Ge{C$qYS)ukGC{Q+1B3W~P%}Zw$t_@;#*4%1v+ik}S-(my>$&18 zY3Pc(|Df=&_OulUxHn~okcYn8=M{~zW<96=&4>0_K_^)GR(}Sx`AoYa=BPcz% zd-5(Vm63V&<5{y5=8Appb@Z-77lRxbKwsA7Eq~C#0J))q& z5e5bcX3#vZh2IJ9pOcS0jEQV`T+z78<#NWlEN{rhMhRw6f$HJBr9OLUuqapH>6t5R zBoqHW&fX&dYV3kc040BSPeDz-7mwz0v83NU+p|Wj+GMHN1V~p-f(3FEkMi{u8Q*4V zwQn(~kv(}zG%@`>H>6!H!3yekTKLIzNW573aYO&B{qb9t2WNXaez*n6-4d*zX!me# z*jslq>}A5+o%6muzA`!Fp}Fl&kWK~$306?!H`dc#LN<49g_-jL_3e)yua4fMbJsdrQD+b5&HMNwjdtu>bn@;TV}%^Uo$(d>ASJB?2dJcxbke`vbId$F z!fku+xp!;%l?4;FJ_Zf>F)&DQfRbLIXJ&TMfeD2xc3o-=UN2|tIsGpGT1XQ`f&-H5 zdtRJ-R&eoav|yF@+=M^DG7e0RkmXMjoRDOnw{riSgb^nKN=^1WIA z<}}D1e-d09!3oA&``nz?zQt#3f+4{KuWPy}X5`2(8uXxa2r@1CmK1;2yc<`fm3G0gesgO}t z2|iFc;o;nQ%eKo#<@V*LFZ1gyrnTkA#qEF$CQI;vnhBClUY&iuYz$f-eb^q}>-MvC z_#yIOEhKmIfyPQ>Js)%J&s=jvUqHNVX@=0`WGUCQ>*hAB!Bw8yc1L< zgA_oHppk#Q`&-aGcJ>=(_cR2{-o+}4uY)F9=n*t)uTOl-f9K2|_7(O{rllI^&*rK@ z`u-9^Ager_*EsXHE;`e4!L&?bf@%0R?=Ge~Kg=kR?WI*(pq0*#e3Fi41kwqFH%UQO|O%U3PA>+1hfc1>CB>qkB^LY7!a zh(fxPmDkEHr~X;OTh^DT{@`Zi;}4%$APcA@#39{DzlG~rKm9d}40b=&@Nw@=%}SR; zkRGdqIH;uYa86CE*mI+_D0Wpb$CC)>bjyE_q#<)j65^2VOK8>&qYqx z58f=t^Pmn1R z329JQ#=|+%m-Rx!FGYn&jhy#SiYpvLg118JO=(b*Ro`K zbFGCKM7~RG`@5$)Yt?bNrO<*@4%B;g^)xx!&2uf__?6>N&A8YsUo0^BePSNOk#dj; z4xvAdB6*L)8#XIn=#ls-9Txf?R75i{Fi6OQ++g9CvAKTsPvJ|?{1r+zbz0#tdHd0I zE${R4tmi)hHQ5;$Bosgs9PXaSmWWutc=Xb{Y1<#ZNzePeq}~-k)1(5V#xcM8kg-Hm zI81M+=W|VIYt!Q#(0fQF6d^Uv+WCS17x6BRT=D$N9^-n~v=`#Pp+&J0$U7d+dCyjL zEa&x$lzRO;BzCS~u@%p8Xi2LC3Q;MiIS;;@tk~+m$K}F?FHe8Du4uV*?<*vrlt2wF zcTXj+^Nrdsp8Q#^(-FETrk-z+mRMUaJ`{j--shYKFP?{!UmoZ8aep2u(()X-#LkWc~jc|DwkQ(QOsNGx1(Wk&jf zm7P3{XZnO8D+eT0Kv~b#)Ai6I^A}gQ>^r~eNuo*J*OWiu%IaU z`_+YdE1Z>A&p9kpIv>)dl~4m^e+$1&e-BNLlv-2M5t6)k_NvRb@)h1eM!Y4|Kx3N)Wlh0rKqqw=4g*Qw1J@kvckgezW0T7%kpK;-Qe!bn=EtaQD5m% zP%n{zK|%vG>g?g{vS|`;-JI#XXgbrv)nuXtSp(AfjpE%}eJ=w=3eHqrJlQ>K-nF_9 zu^M;7nHZo2sUc{r)WXkW)zfHxwFZp@=dg{Li2=cqd2Q<;x!Vwwa6FvTR>|yKlKI^~ zA-uiI_tg5iyY^1igem})a#BufmmQvN`(lf=1N)8J3XVMi8 zXu6JpLBa%7`%5`_-dC==Qt-thJqyW+iQraCiuPw7pcGX$gJp!vwNmQ5J1l8FL3=*cGy34{Zv~a#_ zYPzK2pM!yaCi1kF&9UhJ3JEAvNGs^I;63jhkCq+fXK~nScELd`QvC>MLjnVXgc)ds zk(876k~czc%Fbx8t?k{puxO{g%IZjHFUbtl3Uc#QH|z26X9)3Qc zK|_!UkTty$+uqMr&8_BAns2tA{pyhqjH0~IL~9Nj(6#V$esi<-%gM=x0e`N4zNRuU zAoW}i)SDKdVK)!w@7XK4bTr#EF0V0)l4VT%#`fzjXuTidtUz&1-D{cH}=vmT#&{J;J9+b}sy^ zeo8IZz#Os~Dn3u}av02Gu>BpUmCAe^uKS zE2mQCMEtP!A2H08}*x zd9F?IG)!ymtICyLdgS~9zU;Z`tdMaS3ENVzBL%p2H*Y>Y@5@?^^`AKUeikcft_0;t z1_lW`Q1xix_sz>->h|NypD;|jtn0D6bwcBe2FST6684}{-^00giYm(w3tn7D#N`gMvKXGyb}0qwlq? zo$8&8^Bx}){eAZKGtenN3=9(X$H9)g6X1Pf{aLpXwmqGlcifIUy>)x?4Pt_$0yre! z*}U4j;n0k{T}rQNPK?ZoJ9Y$Yu3G&2{6}V9vF$syuLI3Wf=mFV?qE-g{~(HmvK1qKnIqKAP&!WqBEWh^d9KX|75xeF4KuAm7H3%}X1M<#rfYrOxY$}^cac52ec zrZtf9Y6&+`Yska7(nn=m$j;SPZ1-8ipMG;Q?y& zdN?!8z2Bi{6s)wFu}Jy!6sswPvzLGp3Il_L2WSO_l+%Bfbqji~G|4ZCxT;)od2J<= zN(rOch2yo1jPpU)q^UJmF`ZkueB1tAK{>q}R;DHQ^k_&!r${7x zK#sNWJLy>%5vth6D7E%j-gWM6`rN1MArl-DKA<^w4`-j&X(udBUYW6h;p(qVu{wIo z!XrQ%o*5V;N_*Rz5Vz5+%-=0B=7%!`U_}vI0J)(AE*a!;kWtY zvxWao9u%ChY4_Et&3`|?KJp*b`C(v?@CS`HdpIk6EPfWX$?;124$UBuwYMzXh2=nw z11SKtj-{N;xbJL{<3D9u`+mbt@6-3JJ}$NdHBCSYK&d;{^U;JS(FZ60G+8&rW6Fke zHOmD>6QG5;|1Gd1Kdu+ww_U^Qp|9T8cPn4Uq%hAY0Ii#3V2}s|^`0&KI{s{Km$WQ0 z2{^Rq=EI5im$?4j1TsA)gIkC51KCmK`nDBC&&67 zx9{}CzJHyYt!H|YA=~1Syd)&S1cJ5~lzA3r#-3j&S(B&S7Sb4M!V|T-av`Xv%D^BI ztYO*shNCbnrQx<;vw0zxI)Q-(K)YG@_aBlpr zxx3szi4~*()Cur#=5mv+J}+`)2e;-<(;ticc+InGprg$ppca|Fr-e}Yb6YN{1r47V z%fEf}Sz5HT0CK#fLA)ra;W%3=3sD!P9Y&0c@>hW^iEd7u^;1A{~;DDhhOd1%PV z#cA#h@V%gWwnR?tv-P=EAn$<`fHuo`I2#7fJG#k4NVdMfBRAq?cl+c_@b!TV3=(0W zzHhMStA8`!FPgx z5i&z65e}NRv+(2HrMTCI^Ot1V5pByr#TUU3*zKVG?g&t|;NcuqCdtCe^0edFO64gP z0iWdi%r`^BAp$fbB<0jsZ-3L`yyNb>;soUxJCTQoN3+*-)#%+HVt_qT;ypBO>$A7wHWc9amzRzOA>s_)!$zDER=S@$nU#3 zWClbcnhEU4l_6o0+G|x}avF?OcCD~IZ*rgxGy}xIAQ1!F;$Y#o_>;>@*M0SO|Ej)W zzBzZEN8`m1&>%y zNBr7y|J}oVY?flL!qP$gE077G#&4OYf@#*~N#zwO|5ax$zgzdv(EsiS$VN7a*le&P zFBB`?-e!_|&|4*Bd(Tu+^{CC0K&2Z4gG3x?-JpeE&+j6;{4U!wZ=6%NudQ%;wwgm9 z+7gQcEn)U>)>HYlR{6=NorjpbWU6^WwB9SfhGyP)P|X_b8MN2sW*P9Ot=L;`60m4%=0lWGQo zTjKljmNIcJY)^RlHIfmO+!+`o5T|TAsLjqE&Os`iAEUOwkA(5FXEiChK%QdlJt~$o@2M<#H)#FDVt&(6IJ=AN{b#!aMr)S)I)xV$*$I?Od<~I`W_T z2pmw6*`Lo}oy)6MqW6C062HYup4^ZH)e{U166v553oZOUKYGNx%if{yjIpH2*3&m@ z&WGoN`Zgd1py^x>XHEqx?nYi7R)2fZYqyw8>ORXa4-@y&e7`H$&OEvqw0MhwK_U~> z-}G?4yY&5w%@3Y0+H^ssAdRU+{z+2>G&Zw9CP_J+@@{YpIWf!H?YHQsh6O#P^Mh|e zYyT`zT`6Yc@~pyL4n00m@-I7=H(S&oITo7ivq8i29?tKr^3NTudpB)s ztLK?XfyKd|b^f4!1p|Xb4rnYy%Bl3Im8aV-OM&R5<-r0ieWm8TVxXQXNC9XrCEoL~ zc2vDL*Vg#~ZTtt4TkTs6Zv;ZKUd{@zBj3zdnW2bCHt+rN4yqc%6cDbJw%RF~b(F0Ndnsaya%&jb4zl1rqnEB?C zO4kVo4v5>Y1O+ij!9%bkCoPIFp0;75=+5Q(n~pyFyx`~Zx6o-j@O~5vzaagP^2m@S z57>g1t=S+I{%mCdKV(W>q5$Mr4`*4Xi66FnR_pZeDHE(*Sf|G8D*zp+DFF3xq@1|# z?fYVo$;_j*UES2dwmqrgQxT}a&A=d00BRn@dNy2~d40is<_%Gon`W9`c9SvqeH1#% zT4)G%q+fQ~{Yw=shQI!Nms2`DmF0iAJE$GWz#vfsDx)m?vZ8Kew%LgOUX;qlQWkyi z?kC@ukR^E%MTfv0^VT$Or5Rf_mEzw=e-({ZHnS6P169ck3=+kl($3nmZ|SAQY16q) z^1K(-#Z^AO?H*+h+0QFc3_0o7E7eY=hr=O!-KP%0PYSAE`mIEu;}0dEewKwFllZ{^ zjT)2mFE?mm7H)I4HfkSGBSo_RP+79VWA5ZR+4b~CrYBc69()muf-Di#I? z3Gj)YQclMAo36~X+%x-C`I9Z$x5FmQ{ILNPf*=K;$wzC?&bxW@G@olI9d`5bct813 zO^L=_Xng^?>6bCmPhhH1`X}9ryJB*?Z+_c&!B$}Z6HsDhV2~&SO-ft%eRE-p;{97y zkld`xnYi$1pz4r;L82UVC6kBq^YaTN9d@aI(^Ee9aJD-i%e}|GF_7kBxes`K zHQV=}zf)61YMGmK`My-_FHmou3>r-XnE)y;tv#<@>Q-sX68ihfLl+F09t@>2c z3|fFxg9b_TJzt2tn#s+Qf6is;&dS*7wvXQ_3xJwvAQK=LTi-kL>gg?$)9&0k2Tqs& zs(JtM>jP+|Rtst-SokeWm2?hWeOfE0idt)x@jZR=#S>WujZD?%fxy|tEjaczaxS+$^9N;l74 zeU}P4C2ehEj@NkY@hk{17SDjXq0ST>lI70xy{#Usz4h+g&#(9HsEYgC<_G0T1_p_G zkQ*%geI^lg&>%8M0jSyN;r!v+sc%J7Q;XkLDzgYEmmVw7 z{{gLe8$fM3DJSFKzLV8bcCiPi$?cGz9sT3=6)Vsx76t~129S5%Jk31jf2&`qG&v#9 zxM_l$=rwEkc2Fq~QjiCBWaHWye^%ysY!=ZjTeU-b)g*g%2T(hbfkC1XG|y?_$9T#9 z(!IZi8`rQNdpi9~V`Af+DUcIIBpN{jx*pEG`4bJza@X)^_B~g97G9gj74ia^AFvHr5vQ$f>~AO)aIT;|!t+_WmT(AhOE=5vRNFT0p+B@H11`cvq%UUQ(fX z;$0)%*_Rac7DLO)7Eto{aOT)@$Wtx-(eDR0k3L`av1jgz2lIbIvR(_Q-js4G=>Ps; zlAz9xn&Op>`X_=uh|K8*m9QWyKt1>%&-jc*d^Z`dec9*PRd!Uk^Tx-hO`x7C1A|1X zG}w`4?8&np%iF(UvF(sP$<-nA_xnv~bFmF{=$VC|cmZdc@r_B}j$e>(s27LY+s~MbLm91A{~dC<|KneG-`Fw%zZLLhqV+>qM7dnYy4n6SOUpfkC1Z z)Q<3Q-d6EQ)$#wXpnk^7zrN>A)w+28AT(ceg33!Nr?Zc>J&Jj4A51TFRkt~|N4`$# zEHt1xL6h_Do@ZoU_g(&f_SLWKj@b#7!Z}r2IYBx>R_q0bEgcqm)Wnhr#2DN28oWJMJQStX}z?{pqKsy?2;Zal-c2eJAKJY&U3PT;KEU z%ahIR=5zbp*qqo+1o$#v&NvPVAdnT11vB;gx@*5>g)%BRc?#q56F`$$LQUGeQc{p?Atoh_9y!~nZl2o=;QEm5( zYpy^SarJ^0%#?Y~e0oUYaG`C}$(5hZ@!s!``^$P0IxE))Sr6k;W0ZI|<@ZTBjo533 z7JionIU=C-ML%Rc%oNo>=}ZZH4~_Twa#mkkS} z`Uh&SnR&|T>^%39;A5A~vNybd#^yv&L2BXm+=VCJN{DO0?deXr3Z`9}P8>zhme?dv zA?D${p+}v|&{6(lMrrlE=lldwQHd-hS#A~ui-2f-<-*?IXv`F*oqU%j0A zxJh2z>YTYawC0@x+DvBQx6Ih2R)uL#^S(7?8olVRb_^KWM+{hFIs*L7)WxB4F*FX)u|6i}@f z=;?iQar!)Mi7ja>`pv#vw$?4&69pZ1o5~7yWXzGmn>`0Fuw9?L`ch2itnY7D?u7Oh zr-9mZ7JiFnJwDaBmp$g?T<==1n3TRB3*SQvkZGV)?cuyl;eClqQO!rGjSRwkJD9IO zpKK3VkS{R})Kk&-+`l52dAXPRPrDcM|17w-z(gc65n3fphm5+rZcA5|oOs!8tI^C}gkmGf@L|rp#Jy`Wpu;TSdL`D=J86x; z#(jxuf6HgqOxUw|XK3t8P({MPATcu*98misG!6;N+~32#sF8E^lTA;q6s&-jFtb4O zy%v6f>{9<0U5LD+;Hn|LK%-yX!UB4wg2XJ)T22q=-(O~3oVn-RJ-vW$%l9_#>N&yb z4IM0+4VrXw^<2A8&EprJujcCoJxlL2aaMh=Q9BALt7k*bB-#HUoW~*ZziQIMMVw4r z4~#G5r$Q(G=78Gv7JesQOI}|)L$6JLkH3^ z5u0?WEalMGgsPc;wIRETB<6xjJ1M8*ldM;Vi+%aN@XP7++iNCFy*ukFXsQfk0%&mE z+Vj|s2Gh90;8(&KQm-2&&-VR)>H|s#AO$PI0kzc7`IoBSqB50D%9&dhmgls}>42v5 z85ktygJwc3{PNtc_uLbjv3Yf<%BdQi@Xp%@mb*c`IUkgGJ)C{R6*$Y3@>+g$@Nl{B zbmVN-4*?~2kO`noR8mfIH&fM?yuYzUT&QHh>g@B5aTiX)tN?WatUaUE<#=|x-j>Xs zZLmeS{QGl%MnmX)_k74^+oWllzuV%~t^dgF0NZ32LY+ay`o*xrqTmpz;x<0MrWbaDHnjUF*#@)hEfyYo~zfx^0oOHK9`j3qggs zl+!A|$)|bL-!_)HX0`iOJ>!44>L+Mc5@Z6X#0~OX7u>c?a>DnMrSFfw@K}85=8mG* zpcWVdgTx}pDcreIoi|c8w%3~7JJ<0!L+0*_p9kJT0%|d+Gi2c>a_vKP;4ZnT7ecmw z+Ee_;*Fd@*I;XZ6Gy~${ylr2c@Waxhf;I_7%>4m#c%v-Yp&hZsppJ-?(}ljxsqq#O zmVcEi<(p=f*QEQM097Om3=&H~In3HKz-#O257GW5{X2M+4|RoZnNiIKU01xs3mn~R zt{;l<+A3tweZcFu*OQtPwHw|+!(l0CeA2@2dae_jhH%Zw%J7em7Q|Q%e{5ZIU8tYYvc>A!NzFG`pleZjx?u%q zL`&b(=GJ=G8m~mL^M)l)n*+L*$I4xY4p^<|1BYb9gNKT#P0}+K%&R}S=33gc@;*_} z$|?p1iIt#H6brvwZ|^RV=j6D#a{E`+JFg!ZN&NR zUOe{SXlG^T^f{f-8fO)#MHc8Oru9X+fv0N;_xYGhjKv{OQ%)*_yazI22iOhkE#+-O z*;;4`-b+vSs6j+4Q8J`<+j`)WJ8q+C=M7HB-ViX zz8=o&@--QX*%ov8nJr-QE%41L&nyNN!5{^oBh#gvHp#cNFT0l8GbeVX)mGkTs%7kU zpixDT0uUYRnKeDk^J0eBg_%w(-8Q(h&T1Dr0BUG5Fi5QB06TL3XL0+P+N$}M-49;# z-AO-Ia48qs*INe~@wM=Cs0nX6@@d(d6SKYd6s8p3{Lgm}I!n6_RNQ+w8#kJipENHF zvNOJJb!C2F)b4wwkh7yD)`9jw1bZ@Oc$%3%4u3JLJ9_VlzRxchLZSBzO00(r+#P2A zm@_d|S3gboP`M)KiRbKD;9G4N7$i3IGJv)=F!25SIcM?g>EFwruTC~M-F=!)a z11QOPI8UGYlFu!F2iNU|ua2vzZhU$B>?i1S)kctagFR;z@SCSN=E=;;kh_0*mZO1R ziy^4sU|^8gm;erk*}PvOq$aFL31uG&Z2lCJCh1=V&S z1&~9HdUr3G>K1Zh)}^5ED^iL(j3&KT0hO=}3=&&F`_(M`E*oTiY~Qp#SI+ob@z4AE z3fJv(q3x)xpcQ8x&UuP|o@sZyYjTu$mv37sTd~~ZCvzu$Xh3ZTwFW($ zLw+8;&Dh{{G|4CZj_lKpgMulKLH#QR28r#UdPB`bSR>SGt=i#;~f7x zP201D1NAi?%B#scLDS?e&<1EJr+J5W%d;`5vegG(INtv9Pnq$}O`r;ufk9#yXv{p& z^VZ^RdhcJJ&*QvmG120$mSDm$j%AQ4X;%-}ky@*DJN0K6^100T*b^t!{>0%jH^^uP z28rFEqZKUtp0IMApLlQW*N56F7ONF^a{I}hfVM#PfX3%MoHrl4>vXENR!jDIp3||% z-(%LNi$MDqdq4{Wf<5cF+vfJ^oYaq!i&kn8mwB*Eu0BuX?Y}7tTAr>Y4u5jZ1 zz+0Zz4=wl2HF{tzc^KL}*as=Z=FjKL{jU|7XPtO+8N-af&q8nhg((0PV%DCUqD=~? z?iHWi67||NiQ)bOmb#_T6txesEU@PMjg|A%&@QHIA&fF$Te53hYd9B2r>bb9)dkfWWs{#(*LdgAiz-mgx_M3 zXT}F;3*?{J%SuEf9;NX|MATJ$RE#O}Cx z=hf1wMFrLObZ*Spde+#96&eo5LCvLL&joK>B)6Y4a-Q%y_}GclY>iHnnmV8+K!!M4 zCTo6QyYtu=A7RB@zkd5G=5-O!BzF?jj@ehdr}CqbQnc+WZOK3Vm&a@}TsIc@e;=gO&% z&6}a)lPAA|Q`Gs}yqOc{N8-dNNllHI#@G9 zCuL@~ubzDLdQhVuqyUt%Je=!n?2cdW;Z2K(Jb%xbKc_wCOf)DzfE0iRa@{?bu30Pd z@tVM{j5XK8j1H>Z>9?N?jSJ9mIE;~g!TW2U|IcVo+Es6GIZgBS=8HPTpj^$sAaNE{ zxmoyKNPE8aO~9QDs}qIsSEPTdGkxF$^)o>VK&73Bv(Zi;>6c6YTb$Dg`nmg?&Cck? zV$jqnNCBw!lX8*@$m3hFQk`K^b-A{Nc+cr4>5oC9X$%Y!=Rgf`SI?F9LW!mloThix zW;Db;fA?h1symL5$U5f>4yd&+B!X_8PRTC4dAlg-*R!x6(u<*q7JQ(Ng;jzv~J+rTh3!nEi@5l_{D~GO^y9lboJ)9R->{%tQBqF=(jQaV< ze)GQSo{$CQ2L=X-OQ61HPBTAT(QC4Ok0vNjGB8M72GxERev{s(RtWm2@akJ&Va^<85kt4 zfF{H}oTVnH8;76HSv*H!@6unlV&s{g*+5P;k+>2CK8@V+tF!d!l#i*mbNv2Rxt>T- z-4JdAiHj?pU^g7qmvEkZ@U6;{`}ZF4@2{@#REU8N4qOF|_*(eAa`2v~a`)T+6~DfP zUAgk&4r9kGXjy#?6losLZ(nTC_L9*#pW1MmFVwc$XG!iYP_AZRkhlga4y`>O@h|zg z=lH5C-|nj$6^1hJIQ(4#)FB5cm5e?<@#EY5zxrG1sO9pOf$XKC#4j{ zF+){v|HpQj_y3-NCU_VaByNFx=kU>vn)I^lvXvDbK(l zaT_vb-eOdD@u-Vg$(>afR(<&Yd6)6JOz7&zJCHH+e--N9C)eGxVqjp+>94gBPil_^ z^|u)qB<_IPbRNz*UN5pfnA>S<%)P{_Sh~gRu=5@0@Z%j&E|+q;zF+kv_quqWubj%E z#rye8+y#DudL|4E5_dtvkFlP&PGu&`6nqOgDd`%NV$H+M6qW-jSwIRP>tPu5%?(O^ zJg{{P*jOf_yK3qG{rS-Ja1S(?YT>7+YEd*_Gi254E{7-H`eBXT>|3Ct&G$f)(jLxx zD)Oc-cqrrECi+HZ^8Lck|8kdr+Vl(z68Ax^At@(Wp@sM3uhd!xR{hgXO{sfbxg5N@ z3#0&4B)fS&m+QUo|AL<9tAd(?54SuE&6}qOEzIvjj+l70d`Gx6<4Tv}--`^6sLh(L zyQLeNyB~mBWEOrR?}LSk`)&0ODzqdz{5&L)%6=9)Q1cKp=j`EJRdM5o;Ch#e`rGz7 z%G;)U%oCgejjV^D0e)-G+8xVu<5KN7A3XkBf8OhFtx9eIbj>#_M0DL-$zwiq{aVm6IFJHR zV=vhAwo7xQ{uaFpvY&iTTO~&v*%(p>N(UeX|G=5|c>aVuvuiXz_1pbT->;_+v(6jCbMcZ@J zC7X1k9x~rtqHY0k!*kF8g@vD0@Kxi~E!rMzpSKt5MI2;2IY|fQXd zpRKw1Zn`qWo3B9KYJJZjm3cl68}9J4PxR(n9#|>q`AQU8h`q7_2h@q^yAJjuEA(8J z-Q-s5x>Bo9xNtwjgx8?cEG+zPE~poH`3-$rF>n7Lq4@#o78xrG~DC# z#a__T3I+y=x1doq3%}pS-?lKm{x^#&^G|R5jgM0{O!@@s^D{6=yaTNV@o+ZrVdIGk zEt;Dim?V~~F|T^xYdPqE_B+t{oRrg9Zu`RzW`~zQU6`hE?}^o`&)=g#Bby)-K*gcH zXV!HUhHDO2>pFMJu`J<`+Gp#a0a~O2QUEC*&K@he;4&jQ^6ccFZMGfa60bLvLWels zgHo1--$%L9mvh3;97-%&n{z>;a%EW78_?Dc1_p@_kn+Jc`4z|KmV&K9JONjJh0HY0 z-f;(1{DBmJ%72=_1WJn_1sA{pHK$Q#BfrE2x#d3F z54%(*K6~|MGIZGO6KDgIg3r4wQo;$e>H^`VqZW-kcHpXyiK!q>Kswe$hQ(oGJhhy$Dja| z+!+`ozBGbY)VwUbFSqna{{35gu|C;zm9+meE(9$(0x1C1dQwi(WyjygI_xa{`c?Kq zbbL5lEEfy32>JqAfUWPjoxeGR&m?lIaAC>vXKfRfFTC;yIymrE2<*u635RAz9ltcW zZTj1v_upQLnif10nlHYAW~D6re%o1J>UEW642hkSD*5RX>$SFQXukLc%A+364ckBD zUiheVI+5q&iO08AAAY&$D0H9NH_$FrDW}tVjVvWn!G#UkH$O$#u9WV*`3+RUGB8Md z2XzKrJ!{V#zwp_^!*Pk%ftyJkU+izy8bKT0-yx&TVi$#{ys!AQuYO1P`<(DUbFJhb zgSI0wFi89WxxvEEO4uRQ`MqOxh={4zW}Y|ZdHlMg}A6KpeMKc3~#7|H;;pW-f@W80}pw2hysGphOfT~y|^G@J` zq-!zw$xq}K&1_nt+P&iol z38?4>YKY0`E<2>NkY{%8M0mv;L&T}ND6&qCLpZSpHly}p}Qh(hVK1e|- z$q0%IDW?U+4nMc3{x*Nm72JJ(o|B5r=68_oSCUMiLOtFyh$HOFx&2yNN4?oiSG%+K z^}H~I^fx7$AZgP0rH++-o00NQ&e))ni6y*mSoT3iawM5SzOnF=KVv>&=K0U@E^V@1 zcbMc?oMsDwBp69%NScgR;pW*l=X8$r;im5fJU&Nz^2&FD6Rji*C|yW7-FaV9^nOW8 z$$vnC%r9RwjDJ7!oVQOvKE|i zx>vnWnBm|1NcOWev*nzug`4@FfI1!w43cc1ZDsJO#8$9%KS&a6sRaS^nb<@jnZHc;1ma zDwV=2nf<2%bfpAH!B(&v{;wAAnqH)G&P;sUMkmj=s?S%xfQ)cTa)4Uq7Jgx(4f8T$ z*T#Il&pbVKg%juB)Dj~|IB&;M`WsIfXKv~uUtDo{t1fkBc3lpgdw?{9yvGx3iOhiu{k)1}`J+AFli)4A{>0X9&t1aP-)c%91occ97$mts4GjywmL6B7^A)>7rcE%O zmSAHLf8rxMWWY+23)C6%aAth&GR^(Ka>L3c?Ah`G9skp-B|z;+kO`oqC*^dD=V3?Q zXYOi|vm4kmgO6>0IeP}Ac_7IJ8uAJDT&dJletqFPvAN4uuaq%3y=2axGoWq*1A`>D zEI1_lTQ1D{f8b@>yL-0wu7RS*ihANf-Dw5}NghzFTKEY!i01xt`ulkuYf5v56!*Jb zT!xS}dy+h$C959J6YA^b>;L5ZZ-0H{Q5qy7x7+j?*FAIb1<;z`!8M3)#ui=lpBI z;n2D=Tc=0dRoX6pV_8K&8@Cu3B>6y1cniOsGH<*N#ft1p@#nLjm3AXxSy?Y=vJIpF zGz{tC{Aabpo}E=`7C*A`*z)&m6TbP)AF>BTk{=XlQcm_iME}j2T$7b*&uad^cNc@M zlM!eyF$04nKPb_a9wU)6hGv&!2g2jZ{pY1|Czn# z-pVQO>IBn!pMknA3=EP2pjk=_ze%0tFHh(ucwFXtEm<7dvC#Lp8E9P;1B0X>s6FZ7 z+&W2FZqAPPwzo~C!2HK|wQUIEzlybTmcu7Qb;-M(E-XlN^cKC<=jQY8w)*rAlwm*$E`gI= z_z9CkpM1>g)*hSnNjH@%zHLDYXe5h)K~fYnRb=7UU?{aodUMYFVy|`PcMoXaxxeBy zXeBO40cfG6hx3>EiD8u=Qa`-q=VRS|;t2Dl&yL1%l+Fd zKRz&k792A$NJ<_BH#p}D_8cx%XDByhdvz;s|6SIpxtfqBtE3cU(aw+iWuFtJT3&wL zaW`&tYs5^;Vist%C=FS(Q^S_AMrx^-t*DaWyhY+q&M7&c0F9n7Fi1*++H@Yyb5vq4 zw}dEX{AoKT+;mU(+un%VkU11dY0!+Zlv8izN4FAYnai(#l}uVOL5@e`v@o=M01tcz zd1}r$b*AU`b)}o1SPNFDn7ohP{0XF!fk9Fx2pkUAn@vsi4r|lb~t6@)%U;A++C1E0vPZY@*yHI9-&{B#OEe`FAWgOEAcol~f4Q_gpWRq#S!z&Tsm%%* zERs|JHBls-ww``|qx9xy-J)-jJ!4+%&^0?gIkXkmapzsnjO@a@Q@o?_3*b&WGtbgx=>u0g_ zXFYFnwsV1kn1Ml36SN~(%1Q2$tATFGjYgRRON|tM9?4qqw|5t$Qqu(0IQpJ_`%ZD( zPu-dP*qf{HF$067 zHi(vT3gF-qUnus+ERMaT=J~x11s5ipK_*!wwLvwGyQi1;gxRVWcVBzqTyxamM9}LO zm)=8msY_}f13Pk)GehWe2M2zJTvpjRJ;hg*Qm;Y=v?X;xvy&EnzqhV)|F%4Y`S1J2 zMB&zq*s$$h(E36bR91O7M?JhKXqWnTiCj_R&*%R?wr_Z#0 zedk{ui(2)A|L6ScMWA*A1B0Y4r~z*6`PC?TYWAG>v*%9XkJ1xkU4QRKx&tJrb-#ce zDHkGf#UbpF(pqJnEAtP!x%q3ELJJUm(5g2Jzy9P$F9K$<%y?q2`YlT6*U~Smc|l9@ z7#Jk=L4}!zvy=YS{mXYGYL^u-Hx^Fp;Jdx+F(^-h6o5vwq@4aw+_p$VRYqF&vFeqb zwL2E8iVK6L1V9Qv%_V)$Wp7_z>wMy#bSYb4Nu7?0ijvrWXytAo26p5|)9#G-+_~!0 zk1Vwf+^lou1IN*Y{pn>>qJ2-gMGWHNLN{9tXk0jtmTvhM;bQhjYgr ziwBxV|C_$G7qDNm{Ef)->jluV+7Og*q@29>c>SBG>il4qM2X$a;+5)8c0*U(Ng9FX zSc5$$3RX<9IC@UtGQ%RT^U;|#5}Wd%rJNDuO6Z&VAGT;^#$ETf;cI_5b7q*`@9&TW z5|YNCn`JEg#4lC-)GDw1z9#c#Th-a00rS15fVvF~43fs6rFkCC$NUY>UW&e*{!-&{ zM1IZ0g4eaPLHpYo7$i+VB~85N%eRfcb{1~j7$GplLR3-qNL`vUC>?+lK+eeBx=K8t zS8mbqj#(3rU$W?kXgvNNvII-g6l8^kUvR{g32Mt?bi+0r@7%3@X2Y)dBQqfB!3@;! z^l;wYbKqnBmW%^>-5=cE*F@Ys$FK#`=an=A9ULO%)NOh9_e(az6Fmp7{h#%#vZB3k z0@Mv=pn(cEPv`x*{4-aDAANIB(AM0z%ed@t0Vq#0Fi4u61;^&M2C-SnmU4$;FO^Mt z_DCx9qqq>LX~MuDX#pyVEc}l0Z@MP^P>aJZphl0ubYjMA zmNSvYnPPku{7dK6C|m-04`c#pCM4MNqQrU0kgIlYWYsO-GJaEUnc|gT2=S)HPp})h zo0(TNvm7aL`OGC%$6_?!+9?Gx6f9{4T0U*z$5E|2d9kEL$cM~cH_^~PCcKrYphb-g z43bu$0SXW2|Fd^~IcBP`?4tbi!`9&`7VYypK;;5R0cgla$|*Wo|8pjHLSodC;^@CO z{akY0WkDebQUF@K6YCit^Gs|-&6O99(@gX`bLad1e4h-BENf4&BX^xl%QL(Xzj4vt zC6&r5dE6iMmV=CDV2}jgU}@p!!SXgMTGsDueUi^S3yz%6En6>v90yVWn&0$r7H$z* z6137QFjnh#N6S8SA%>bn$dLk)wxF^~%E@8YXT2oRC3AziRZeXG<`DJW#TVLBvjt6K z#(MJ456?@q$X+A4WVQ5JF#|#4f|=0Xf$dDNBlTB%yk5YbqrHAPQ_|+rzt8Vwa6v0p zJJ4K;gI?IcW*`;wF54L9h2f_Nhraf=U<<=K$Z+v$rb;JZb;-_3Fgy{1;r~S3+As zj-ZvfQch=`Ebi_7DlV|r{QtTmWfhn1m~82WQ`_TQj8!{;`=?qF27Jg1zZ#V1z5Zl*Z z_%Sd?X6mY6abG|KmkbP&&Y+od4`+dLEhLl@+x97?}5DQiMX87Lhv zFi5(B`WF^{X)n!Un7OUkF7DfSbYhXsmPS5a&~O_AgQOd%TJUhzys=_tarN%%ln|*o zOYX_9c6?R?%99`kpo&GxN#8p(u|2E$`@}`d%($BlNdI!J1Q`ud09v%7@0oq%y|}!@ zf|w|Y!J5u2BJgptiCHy)J_pxm_6EtJj&biQzm^;Wf7JfeF zH>%a6A3e>n{bC`x-+Gewxku0e3J*}f+r#-w&lS4Fg%7jZFP`cd!Tmh z)}wdlK;{-DeIZ9f=ZGG#Oj(i}`uV4_Pwk!cf&D`2pw15igQOoQ`&;<+J2`S)s#vkg z@Ktj|4s&Gt!^zs990gJUI_AN{`Ip4;+22fk>`i-)C9L}~H=b+7d1xcY4^#w6Ic+ic zR3T7Xb=_K+@#-Y8DdtW^7Lb(#lK!CWChnffDiQwMsX7qUe75$S6ln77?u*~-DcTw=-+^Z17#Jjj zLCN34`LcdiR>>ts-4h~twJQ(UB~C0U4TB{6V31p+oZc7SUtrX??!Q5)+aBR~1rM_> zW#~{(FsO$T>*+W*@C7e(Kx>waliBTET*^*@FQBDd@I`P)-py?@?>g}8hH=D><%$fA z?x#;_LKa|4hJqAY_|;zgce^9}L@0}+OWB&PpZfVX?V#<+P|$K059j2_81ZeJ)<~FV zoPY13JY~k`^d?X@l7T@o6qFv^Ja1=7TB`1l59Ro)o%{LAJvY567og+Sp^!PXuIt(_ zxwDnbJr>N1S)Rqvl<08=GNmpV4w+N?%byhfwb?N`b^B?hbwb|1*7=G-Gfp^UPHp-r z-CxtAE}yUn{J>Q;IrmAngAa5RB^)%T=IZIF5`0BxQTEhFik;>);(wSq?Rub*6~PA% zhpGIBySfr$_BPG3y0_Hv?4^vJSCF$=BqKpqS@?BNX>;V*AW$F09`)P0XrbaeW))D= zgn>aa64c=GaMt46zy0`|V-lYB{<*)N*J_`+dmP%0iUhT*rJQDG32NQ2)n9&K`qkzw zIv1oIbdo{60tN=jC{U+R-?QmpP3*=bE_L}v9g}`FZv9hB89|HrKnfs7*v*l-Vs@6F z^To@8+q0!bgeKiIR)9uUG-&MH!cRRj{nLwYIZey^b{!3Glz18^&JP{oj0V+R9?pK( zBTvee%WpT^ukH4+aLw7*M-f%8Bo^lV)0K@rnMYi|6Otcjia^z7J|H zgA{<~)bu?gm^5N*fBl%vSUyqT!-qqlOFtKy^rJR0VY+rotK=^UPW9Q>;yqo-Ulf+BNf#;HOpt367bG`i)=ZJit zm6;DppB4u4RJ{A}5;B!683&opR{i4c@nT-;jz;rh?>dt!Up~uhhgJvikm>AQslh)s z>GICX{!^sJv1j|D={+5w$rT0$$pld2-^1DJconp6k=ol6*hwg%RmZ1 z)7jRZ>XU+F+Eq_yO;KKWx%*&QS3}VQs1*s2^JBIp-U^pY6Z6hi zI1&0l|4ae2xtIiMkx4qu_H+LtmT=Vf-CrK3q$_i87dxteb`ycD0Od_r&zFpBPM2Oj ze*9~_VE*a-U7GTD%%F|Er1#)_;UT!X*Q>DZMln}`lg%EH6W&a2phg}8gJcS5g|dZT zfR9!>%U%gz_u%xjm32xI*FMaLoc<)40*Vt4=jQ2L(|*5MepB!H6So!bv-f$CdLvpWCWYg#iM__!YG>#OMhd89>h3B3bV+;KPnTp{f$Z~)brut2 zes2fqWMGg?)dV~8o?CU}dCPe_jQmp`c=!~mU5^1xDS|eSr-7ft?X@@3b-=8+e1#0Rw|%I;eRd<)rm# z$A_i13>QOc-DNfgmx9J|*&G=J>;nZaIFXxUQfK&&Wpmvm$lcq#_>NAz_qVWAXw|5w2 zsXe(_1nNdIFi2*C#v!adZ38YYEte<`6Dum!Ygl@0#$V2722c|!!69kC!+_89M#|aV zgMT=bUNHs~bw_|&feZ|iS)lfVg`b3dRmenMAqyo#hG_k^Qxo^>^nv!=vqAHl9?sL7 zi_NBn`KW~KWSM7Xxh<>DaSA9F85kt9LFJ{CQzD0b-}X+`(?1s9HUGBq^vOTQ*C6Xa zB(p({y+F@AuafKjoOS^-S8A)|-3i$}ujv!0Dgv1RS^RuwvM|fNUq@rVZ?Vt&bX|9j zOm!}_caRGzFD?9zx;7U5_+V%k7%-<$skrB;?vgHOzQ_fwO!jcDz5Cg@_LwVI!cPSw z_s#;1XUvY!W>PL_@w1dud}!WW#$9*z1iY!()Rw_C=^^7%P$|#AAejrAbhGxnWm1*r zcx7kpNujtx)zx#|m{van4ZngEKn|RL|dO2n@lWUDubo|@(C0t}Pa$NQ$&7{7|F^=5qbHK|oVWrH{Z7yfOgK8QE2FVi8`Y1`Kb>4ynCq3p|lx8|-x@1a$ z+Krf1(6OKrP&+E#^Y+GnO9~AII(v4`h&L&$wyC>4A2ePMGT|~fB-fb#GqDITU!EiW zJ2_3oO67evxOv3DAXx@#Pg?k?I5IiZ@P7>U<4EJ3mza1#`jZxPz^V+C!#terrKy6xU&o?jsuWojln)qSG%kS>J_CF+YUx0Sz3b^<1=>6*YEAbDKyDLBqa0|Z|H{NAEd3@(CxAs~+p_W5uPrT>{ zjg>PnNLEyUr;4gq`E{)lYWLW@sQcL4@V%}F)=q-f-4&pcM#^bNW9bZru-quWt%r+` zhxZEe{xbuGAjkwzn^xa*o{gK5z(k|J6@S=LBeG|k6_tGf&F?ZWNLE5Fru4|pnG!00 zWb!xZj(L~c{5|$A`VY0D3e=vo@bk5}d0y2*F=&gB@*`H!=lpRK-$BPGt3Uzf;cUd) znJwh`=jF>+tJ%dFD$W#Ndj}nsuL6}c)}F3YKJJiR_I>-`3rTaEPPXh^JFyd5cUQ}T z18Uo>nGDks7Ef4v@1p~AtczD)_8d?PjDbP21~T7$oAcCLhN;f-)4$kFEBwvhcEcwC zGz1J%0GaPDH(cY#Guusi>%4B2qbhsdxK;c>xf-MZGT;5sRpa<^t>v<-s@`o}8dzGA zo-YbYtPBj2wV?2D_tfCpUw+bCbn@KpZ3}}~Seo)pTA_nxwc%h#a-RD=uUeV$=6jV7 zj@1Qm8XHwhp~J9spd!e^uPHvl)vJXY11B=>lf<_6z>K{9)j#Km#l{@ zUG|lIp|tOB)5k-z9`etAxBqHzB5dBj0aOH8_+9zY^}TAt(P`V}GD`pS-97t=(j8FK zgn>b_0knX~!};Z>TQc8*CoQN?Pc#?(KWCHexBt+VSR*LFq?~R>GfWrR^SZ=l=`q0| z+gq>sZDOERb0cVU(b`i_(m9+p%s4|fAg9`R#j27cdpCk69T^xT8zDnpVtRSEzt>Mq z3vgu?S>>|D_ROn(P!KaPNH&4`n-+eW{LequaZU4B6m*PRK>k_ky#GO<{fZ0>lFgus z#lzWY$G4i0&rwHKOycSNUp_NnvesH?nrsHO$n-tCRc7v+Ete-N+o$RE`qkF6$;nGW zr5nhEh2Y3CQ3%`IBQ_;)X~z?`2|KsRZEm>^ZQHkilAeX%o&Fg+=KteYh+BEP|7VNF zOuO0gpsou8gJdhHx8&h`$#P}$6qa9KEgrNMPb}VbVbRXL(1Ds((B!<7(|oQui*G6? zAKw3c(@M97luJuyu7ZvxwSvYWtUb>uyt_E((3$Qcy?Mvx?y&nho8u~U>ag`Z*pdIf z$E{aNeLP2Kl9uci7U!3I(c7R?>g}My%)&3};$P*4CZ73U9y#7~VLtXsBKrtrk*8!k zXnxPb`NR58dneb39lkM*JvK#ZYJ6axGc;AVgQ^87Cr7@$e9vG0eZ+0KU%zBSElb6{ z2cS&Lz#!QUs=NX{AN_cy`eBt?u0KQa-@SGgcjcE_LtBF#!eB>MERE^V``9gEXe!Wl z@7)gFZ2lkZkVM-FY93hlc_ge%-L=@GZb`ABa$|rX}zHXL$F2dg|?&RcuOYc{FgZA8eKtmi-PD-kJ8Ep2kEWtJ3{NMEyuW6mI z7P=0k2Q=#L=9w0s^K$Po8|PbG_ns%n+x9!o`v@(}dmtO(eWSu17?=9~){ar?$q26v zQ=X#>nkr*pkn9D``&;;xd^;KUkkRb#{-j%M@ATJfP-1Ha9V!h{0BYNMIRDA53;6Wn z^y<~&3+kiiuK#1Bz6n}B^ntojQceYWedLFPCmhR6Uzs?|r1A0TADUBqc%k!p6F{?a9?sDndk!7-(VKGUrL@2M zhxrDECv>1AoD)DDb1A2tX7Nv-cwD|8E9qboFLmg)rz9^Zh#43pCxCKTnWs#WL-#FT zGs$B=wWfb8*s{#+T|6jHf)soQNB16%we4pu{@*a`I5xp#h3Ev0GIr>|-J}4pBlV63 zb!VM3RCm`A=Q!#Z$<8sW5?XIg0yQ)|oNW{wdd}9YFEsMJBWb;BbNUg>8KA}A3=EQ! zKuZ&)oRni0EIRo6c;1z!{2)e+eWE2yC!u3OlR#ZMch4U-$yX1lT@&3`y^n&tQkG#LYB))P6ajHrJVk@an9LL zD0}c>&!zP@C+yB(+~5FRgE1AsUKdc-j z*LTZVtO;F{Gab~waQD1zJcGG3cS5Do@eIe+toBSzLK)C{b2_BHm~u@2z~%C}F59b? z2mZ3!zxLEN1xR;Mat5TnV7mAsV&2lSB|`fS3Hlz$O+H#C3~iaugwz**WXny0=C%B| zx4q^9*NU?ZzYCv&Mim(tBxi!^3n{0UEG1#B^L>k|vogE9jpChd++YE9=|KuW1xT>x z#GHf9((2lgTO;mI*kcjTy;A2awDzBQ9~_c_Pwj)^t=Ls|T`=YC`aWAPY+n?pTwq|3 zoDB*G3%`QMn_o}4Z`|s1Cn$8bv0nDMKZik?7Nh_&R{ZJIqQHF{`sJH0bZMVV*g{mpOfl`ZZrVpo4BVIzLn`fv(#P<;;Mcqra!f-CPo+I&Scyvpi= zc)xzkkER&n2$8V>4sfE0k1lY2Pd6P>Hw z`}?Mgf*ae^+kwAjC6-(UZD3~Zz!f)ll-hv9Dhju6aDNQuLtP#t)J`n221)woP59gOpR(W&v>%X^{S2_K2 zxTVn^I#^}Ii$d(_;MIb9I{GwCe2x}bqtztf9(W-M#^bI&F9znxl5vU38;XI|* z?FSq0+yd1z5$vmHf84xN#2B)_TXGR-tW?S=_VTI7)mmR~zgwO8N7>sf?L|oTIY^bX z2vkMudp@1vRQGnN+EGjQEwu}xAFkUTb^+RBT?Dza>EZ#Ge=^D~Y-{_nb**gHw#KEa zLC!>#Tml*-u<%>Sw(ruq=;l_&G%G2lgQdx@*S-Tab{QBXmw?93J)G+V(Qc9~`w8 z+H_wAX_?2i*ngG&_oDGwa&@Q6gDsWJv&w3raaPO3ZC5k(PBlcE_7kQN>K7w_FVe5+xzC>uLc?t`+}n@m4)aY_e{9C_9AGqje$XOHE6_F$|>&bcJ5DaPrs>Sxpa0@ z^@~X{VOG$gztx~wN;gj?y&F~U{of{+p2_)Oz1C=XXzdfw0#lF)kgomZcDDHzUPpf# z1hhXYdUAq>Ul|xA*Fw7X zTOJywb4};bkSlix$_zN55jS@}w12TS8hq^PlUd#caatGuc_>CKR=H4=aEnhH)Yk=> z0Ge!x_skTXJgHK94NF9lyg5oECsZbNT=e$$erxpSd#h6x^Yi1HplNId2FZ<}a#G4^W1m;~^gRB!k5d=rsk*WnvS>_( zI&vdu!APLz=GzTcUpN03J$#bmV&Adv2iY~NK~u;K43eA7z>e(S@bcP4*1yFm`}SqM zI-uwHe)SYka%W(W+}sZiC>z^J$5Txa}2bE*#cVbA?c)huS#jshF=^X7ymUDcI}JZ_TCtd9$ih35Xv^4|T0@(sNc#S!w|MMG1iz$*j`%~xeC%Cz1Wm#KEs#!VZt zqepV56xflwin_`sGaWO2Ed1)jf6E6iUq*p0&1GO ze0U?Q=xG-SZ6@skjcj>1m#nYem|63U{gTyZdFDCxTYi{0Lao>Z@=dVk;w~w(F4er9 z=EwPt9&NKr%jtCmB@_k*$=z;XH-zZu+?&4nTS@sXh7X?GYwxe!y&RO985kt@fNDPr zKUVgdmtt(i2Ly{$HE+IjKV`mM8`RJQDFC%AJ)8x)nY;fdz5g>$F4}+dqFaa0xoJUL zAbUX_5GkiM_f{@r73Gfgi4i>E$*G|;NwxqqvBAI~xfis7Dc&lLtWxJ)AwJh`g%T>94(g+OUWF5cdP6?IF-9)PtZ3Mat>KokbsqVK3~Uaf2!c@tMGm!>Of-o%BtrzyH>w*2W1$L0!y$X|FtN5;@G ziowJiB9lv7PWL~b2HPWc43u!BoF*MHVPm)ve=z*409%H!{`^Nj8KKRjW1!JyeNT2P zgB!0-aWG45y~JFy|GxjfP4hr;z`!7REE?>{Fa=-tR`U><-^FM5s;)e8@Xu^UP?w&8 zLGm~#pe+16crOUbH&_>2beK*oJi>iodU`UnT09OKMe%Uvy7iF#;fdTnCcW$_!9Dt=m1p7dEr@#`YP{L1@W(9C-ZbTyNQv*`wf z6L#+w{Mz>7_S2wP6|ZXt3Zb*rr$D|@_Wb%VS6y^J&(+BAXzxYW_MI&adkZbhPc?zv zAZg6edfeFRZ-8u}(_H@RLX68FfwCL}gXC#Q3&i)-rKx3?8J``xIbSF?Vc{0m8A+i2 zHUop?8AuC6DQVMep2IdNTc&a>I@$H6=1js-Xo5KdDvBkYetx%CVfgEB@t~t5@Yg@~ zk7tS|&4uKwGoZK+gwc^VCyL%XR@vngnFPwo~xTb1&^2VZfDSW28 zbp>yz6~8f$TL-EJ7#JkaffkZk_|0QCGQO>l@p8qtzLlq4o*D~vNP^ZqfE0jst9v+$ zB;WmTWc~fbW!v68e>>rglK9kn(3bf*P%A*nsV3+^=z{BwONSwW4Kjqx7Fmkw1-pzP^2RlR5`ztsVn|`Ixo(%m3qD z%NVQJAA)ie1B2uRP>0mQ@B5PzttWjLI(;g>@`|l7e0#j=EGURU3P6L09?luMM^>Ji ze#!CWnRd(HY^5{feqV&Pf-ZofUCOB;e8=I{Tmjnhm#@m@9Ly-#AXft|VJ?DtY{8y| zD+3M|xM?JNxnD|>-1X=aPt_&RW+4U!$%~MqU#HG%6khTC5$ghvpQ&>v8BA4Mv>7y8 z&%hvgX&bnSGHY{EX6IpdZayyck3SdQe7pX&2Pm3B3P8sJc{u+nT>q!#^SsQaKIyZX z^hLP$^rweqE|XdKg9;A2EZQd+JW(O@oCIhfn}I>{x*s?sIq&QA=TAN@AJoC} zc2Bsi^O9YcK_mVk1)y$(hqK*O=I>cI_|GLQJ6p!4cf__fWf`<>e;w4dm2&FgGB|Y3 zS;ok~?qlv(`TI?ksZ5|E7-Rxyf%B z{z(>50nv>Mb2WMGiI1EQszs&C|%CZN|df>-!GvUT|yX!`}4^`5mDJ$Q?*g zoL@6#$G7`+%AQwE=G@X-^5eyiXy_7)yO5%I+mG-2m@H~tkGigr`&KIf2^fOrZ9=aG1rc%3j+Z^Fk z#^aYD1u1x`g@s?u#rvKvQzxp5NfsQ7dAVy@l(_{o!8`zEJrC!mlyl#irtUDga`B*7 zdu4m+>eYduy+8~Mk`F-LYbmE9$)i_pCQjh^RqXSseCxd8^$%`?YFv;4(8#y7=iI=b z{S{>j>(*7@n)=mWWuHaNT4<_%0NL5px<;|-16$UDTNVnAYq?guwCNBAZE0X&kbDGM zH)!E^=j*YA>fL8%t9*Muwc?Ir#h>L4(0=zL(Cod3bJZnB4-;+i&p$10O+2R7Bx!k6 z6Ey4yG67UA1baSi97`jrZX@|K8CE}l&QUXlCk97XhHEft_>lw-iGg7*9dH zBx}#rXPo+E-1cSZocwluMq>PB-uhe6PS8`x`sxVgTjwlvJ#)+Ta&wVxOmBwvCWeICxox7}twDYU_i<-pTNR!=k{H4?<47(`oI54GPg^X zow0^iC@&%P#U1YeA-CqRO)GhxpQ(Iq)HT)95jxEB8d6_)Us9aR->^-;+2OkIlrL&I zr=}Hw)(bK)NWKP@4<62;CwFZ-KA~?x%<=xqyEjQY&-~T^st!R4Aoa!8RaWlRYko~u znf${#R(dx3{Hy$++76@uRNCo#x>~Ru2$^TKqU+h?EgThcN=vQ0pjGp0$U@T-&5v}B zOT1UCpC|h?lchgxo1z7XE3&fhhqccMO{qg#wTvx(CU=xp^nNPTgf-}PR?@7i|{C)PEsn=$@h@@;?S+*TrXC-JliMsbMd;Evn5Ho*`OgmkOD}3F_H5`lAae?6`J+lgX#+jCy^4481ace|4x~hDJ=TbxeHNxv%l=|P*Pdyh`~Xs54lV{IHb1YIlYen+&qe`nrU;uyI;UEoaq$tW~F_2KnB-!z?8C>WtIJ)h8xj2yia5gpR{}N&>q^b~PGR=CrlAD6|i>aS{x4*5v1}&?<^n%^6cC*8w zlNEEHq<;(NI4LtH_Yr>tboAgWXgJowk4tjP`;1G61azlca~J89Flb2u1B2u@ zIq-59cD^Tb6)w&djBH@^nEKtvA%}H8v?cZpG_NJ)lv=3BMt^q_75>H@`ue?q93cy*~c2Xx*$Y`tK$N zuI>EzA^_TJ{sAhZEd1n-+A~;kIWy~9x2xMSuH1O;9$y5cQu_g-J)E0&nYx4~Bo+BC z+Q-kB!gur46(guGet^=2l+y*BHw*h%L-Mvv%VP~}2odwN{<=KY?U z{{b1Bp-JvHr0?G`MY2_W%Y+J*BXtjUx<+g8s_=r&Y+_)L`~zyTS@^xMj@=$}Kxk5z z#=oA*T~kZLC(ecrlKcS`$sW#2UZo|}q+Stx_>3>D_~DW{)5=dk^Ti)f>sZQ3b`r~x zyC)^f&mG(m{Gooq<>g5VP!s-w+7UsXl03gTjCD63NLSpcvEs&dvyHXu4Iz>BHv^m| zWBd0#eUx@ti1nn%m0xEJ%H_p(fufm#LGmAH0k(zT;TW;C>Nk|TxECby>9mU_*%>H+ zYJHFb(85~}=chN9{fSSR(X(ZrYgp?g&a-J+-Js!D1_sIhj^O^qQ3jU>Utf8AliL0K zw5a?rfCmzbZ#VK@cSFJ|Bc%ul@<0DTYU3)1;(Ecnbr(IdE*-jpbv|8B3Qe4=#?^DE< zFQ7;QnEa+{jOXq{rq!c@d_HYhBl!Wvp%p($%U+NVmJ6~8JG(E$>AjKsLPWBTXro7wpV#WGR zOvj@l&2l$NRi%L%nji(Br53@SeSN$tx~EsLGC5Z*i2WqHp*g-3(masjf(-Rcxtx?O z@%9oMgX)BR>k3};_D*3zaR>{)Gx0pZTh4C%(4ttq>gJww2~M#Ikl9Ho9?%$o zhjUtywbTx7CgC?VOOGeyURum^?q$BB`&&ht)vq)^y|miS;c)bV2`d+Z zM%x(}q9g=yiR0(^+O4i!d}j*M2~q&rk0bb? zuxq#7yW7$4r<+M{cwjeQv{3?*q69$AB@4eRlj`bXqJIki%V~Y%SZlgOR%I!uBg()a zCC~_tO_>9?F26q*XT7vEFI&~o<;dTI|5igy0F6tzd)D;Tb-v;f+3Hg1c}7UWLG{s> zKuC2UB`5$6hk{N2q&jZ(Xj^!!-}*!}Aji^y3o=eCB?QV@7Jgo84kv%c-qG)${AP*U zE%($K1#4)M69R34@^Cii6xrG$tm^JBx{)DMw#mx5O%&2wloA3dlyV9zmes2|>eskg zlKcFn)Cs#!G^_r>e7>HO%I*zzF;vix@g+H3DZGw08#+CO_lYy z&+K-YnFl|+PhWofgq6i&w4hUk_<6N{NC}wY8^z$J#3qz7bj?2ivp%FkKJ$ zsAvqCLy;1N91!tdEM;bN{gs5czkR14oWBxm`qmbjFT@}RMC97H=&b7yyt~m+**0dE z@Zsg#H$i%=QevR_e-Gy~%DK;;9~JNwP}jLW(abM!I^P7)OgRIClsM#oh|uP=#mj5z zgg5lRZ2R-5>FN`|OOU3TlsITkDcJLUq+R0?*0NZK1)D488XG^@>^UFOM3EAQT&~Ud z)%D;#8UG_S6%*QdR<HP4&uv$+FQ<1#Qv zNrGxU59h4sQrlvF1)lHVuFJiD)G+x-o++ph2PptmC{j-0p>3KJb}AU>;hBN?_U=VwCDRR(QwTGHFg;oq+~%2a1ZD6CIKuzE!g}2 z1+0=^5nC0I5PAe!Ey{sXx0KVjyQ!Qt?>0E@dv+)`_h(&RR%1OhJ;;GZmE1jdU3s{8 z^>0PiJG@#^ff*Tld zQy3PqR}@FT*p-u3&T}s=(snUq_ob8qXq}XY^Z(y{t(AF++l7yH7~lNi_hD*VBdCwZ zz#yd%37TPa;*4MrfH1juSwCzq|iL!o%1W%>_gD5WWPyZ~5-3hA{Ft(udG8+WS?7Ch zp35ug*S_-?@q$V>1_mi5&~U7W^EB;A<*VMgCLD|LPTh1UbaIj06v&BWQc9p)uIw4j zthl7GY&q9Klg-)cI;F~~A-T}JsdO3~P;&!)g{@MP7Bwu-fB1Uc?tfY4ZP3zQ1+?PM z!cWsUVXfWgP?7BmrbVCnIQwd%fjYDmqyh>s4`*-r53yV98n1mm{Hl%V@&2|mn=U{T ztqN$IGTu}Ez2mpjGjo5Rax&c#@cKp72hAjq(F_bys?1{CMTbz3V>K*#`OywH;TWEf6)((i;!w4D%F~v#X_Z zuM55K6k57xW5{9XzC|fD(3Fvs)7`X+V;h;veS&Abowc_`xgg@|WzcFKkQLt;7#LhV z;~$skbT4>YFyTaY-@&@(+ytSIplM461}SxGup@n*ol6ludVJH)Eq?!cPI2G1T)_hw zkCM^=xxvCO!CKix(IwZ>oAc49gl|nz8ya{)bE^ytQW~H&&K}P83w5++uPkU(Y&Lr{ zKjB}1<3x2x*Ir5!v~b4S^SI7imJ?gFpS?fp5Wu_X?Z>(!T%c)e1_mk6j#$P>zZbWE zc`0huJ`<8Ve~9tky8@kMQlLRY1_miDP;^`PO&9;tKV>yTX0$C=jI)~eC-*8Z$N~u| zEl|(Z!})Xl^ZY5h4HOf33tpr~CU5kEfuXahqB6c--O*~h9rCZ7Ghb(US+xua}uj8)HXLe@4*>4MUQl#}O& z!mYQY46Ku54t>^F)BGO$u@l-%0(bEPJuB??&3NeYQ{eT}MJpORem#HFwx$h|{dN1n zk(J%>^*85^*l)u3l$E>v-Af<&y@59RrpsSI zD<>Ejr1U|(B@bu)xyKG(6L{O_71MG3iSH_!D2)V^AG#;it``bMVte8VPKFl2KBc*oUf}^%6BXA)c!1) z)tGrh_>$5~1!!yQdf(6Yl6=))2I73?*f(4AQM1IFUT``Tbhsc z`MKRH9Fv4+}qK4}2w=@4d;98yq z+0Z9t25KHiIr($k^sS%56zkx$ZgY0OdIigQMrZ+Irp&;=5bSxr`TNCXxnFA7bK)0o zDEh%Z`|e)I{tGFyGH{xFFLCDW_NF4=UonYmYW?`v9e%SLTA`SO0?fkigwK1u4_CaC zpGoK%TbZ}pJUwy-G!DhUAY}nss_NmqB|B8dsi?&*Zo(8^)>6-qm6slY+Vmg=pyq*; zQ>z>ED(oPfuo*hdYZzQEVjP8?Ug&I zJq=O-*_F&`n0O)U(aV)53Xf@>3fq@hboV>7J822(Em`deFWMg6T_@jsR_{7MGAQRjnPl%>}}OF1jhJg1bC;>-Om|J4sA7lulA zSWPQ)IIq(IZFpOOVpZSsS=(LjW0TJ%-*43WXj!_)$b-!kq?3U`$_mm$S>9iD_V%eM z>*S|-ElU2e&rJA}3#jwMz#wHK53bx*o|~Fn)H!E*By@`QqQbS8yrrOr=t|juS^*x; zv1XDiuU?fJ={5CuRfhfiqkHiUs4ELH0n~=E_S}(Lu%|J0QC*~9aM!!}eU7VYdO&Lq zKniYwV{<|Enuc~ooANCRvl6wO=KK|^oC3;n3=C3spgl1ber0;|EG|!Ttzo_Yw@}Td z{Ai0{2DFi52by&9aDKf1eOde2;~sz2#e&k;_QZb|{0$lUld=O{j3DK7b8@com!f<7 zgN-F0dowo`{j|9N8chRP0qU{pdpfO{$gc9zBy#@SUsZoMuUfYJXg8>r2vYC|?8vGd z&7D~f{wxZ4*1f&ySPkcN*@>X!&cGn$0LmX0ew(!;f(`~8S5+_kZu*Ngbw+z-7idHe zqySW2dN@CnF`4x(d~w~a6)~%yTC0A~dteHgB9U?corfXi6v8=|E7#RlcU2*iMCb0^ zKdjaYfHEz}1kgy1yXWK`7v8>3%bi+O@gmmHzxlaY5_CVWlp|!#-cg4S>1(gB9`iVI z;i53F&)=8HI*`?{QcjRHdksG{gE%-YFIrcm&|!bDS9hA=f6zKP1_mi7&{8Z9XY1r; zw@i2JX%cnw;FjeozVT;oFJziV${Ey4kaF6Y^;tCQoPxQC;S8Dq zaPxflW94C^7C()ToNJUlTzR{@gB|%_X^iL=;aoQH+`yK z%wcP==msOGkH^3u^!7$ z>A}nFuC8Be*JVf8FwW>(4r(`m6l?}Nl7}xU(6zU2)|t5bUDC_ro?f5+0y>)H4r=sS z_)YdN*?w^^_p0g^{foxmCS6{`^Bxq$3=C54pu*h4+4`k~j6vWu%kZNw3MzjtsCy`? z1FC623P6(#Wu7gG(;`-X{q*vf!2P*JTjIIPCZt2#_8v@NH!NFxH~;FjuiLNv`{^V1 z-a0JW_&emjBq>i&9<}geT+ZtLeA?VM?;;x~cY1a>UP%5s7gCsef;RqoIBR}UnLQyy zO)}ol{|<|0`J$@pks#MIFi3fV21%rxcK=H&^6Gch-m2brj^)Gh@MV%)L6tg40mv$A z&*zWC_?+S-H zccs3)^lP8U%Ri?CKs$LD7^M6_sandZ^y-e>T^G-&MAzSO$(rMukg-+^GL|QUg_C3Y{khTEA6(bV9e^AuAmz6c?8t}Oo*U!tR^C06dEEDFD(j9FIeS18 zzzhsh0U(ns{GNrL*x7QqYWge2k|S#ba|(ltw}1)`kOEM{)5EzoM9Cs&X7&`ZP=+HDU#WX=#B$_n|G25Kx25!q0Nn;*I%!>?%Gp=gjKj zeVs0SvKX4PLO?q?Je>1Xg=_UVpYL9JdgkIjm*YbGZ0Vpm0|o}EP|y^rwWrIC6>YpT z7FMuC@`|(PI_EPiW`H^}v>NP&^{cfdPN<%(Rjq&3Vca*dMLP2rv{DNL6{r?|>&@3p zpCR+;D(~}|j8f-LvS#8|CX*s*Cp+?F*wU>Rz4?=6ba8P)-dB!ZVuu-`Eb6x2CsVA;}Y7;Y- zyA3VG!nc4O8OfiXcy8Zjwt$T2_UuFJPUja#K)o3Wn)kNwJGVkz07{!uPP%;MK})yA z2}b;vn7j6kfYo=`zzLApj0DX}>3hyOyj7DWs-VNd?$w6HEABmJKKl;Tzyg^7xtglI z^xx*G0U56E4(I81RUhPHwpa?P4jCAvqCtaZ7JhPlz4=KWCI}zja?bTp{|lizfia-n zL?8vAhK7f;$Dv)TIFoYkE}gdIqe0#BYu54lpgaju0LtZ3PAA{6-*fM(+9@KCW#XKW zsiX9RYnsQKo3#nJ2Bv$Ch=&KF#{v;3-WfaS z(>#%P+_59Y!MF%yGy{WFBB->t@Y@x%v7$uF!Su|BP>zP?r)C{%c7bMqKng(96dun1 z*qi^P{Wc2JmEQ5-ncapDUCSpzmRLw7fd&tQJy^sB4PeH%-Hl0r!A41FO zB*;OXVp{7ZwqFnxUBk3yO1n$^){vw`Xqrq0ZOgOpOI9}AWp<+T;uOxU`If>z@{N<< zLz@RFpv_Yr&Jz=p_fPyh*<0p~wX2>X^Zs1_sARff8qu6W1-bS3gq18X&aUt*g2om zSYAQ1d%3;xzr#o0gK9el2B|dA$~z0cFZ}oK&Ykg2&(t|zgDKXn(2j?_rK3&u8{|Y zAjk^PC`z!W>uWuJUh|A2rR`0%VezlSxLNK&eUUB?j?Hf4|30T)zF2LcKSOzG6SooRg?VGm!&D`&&U6OmP`uwNqCrt)zP+?$@$^dnWJ)G~KaMeHas?PWC zq9;OPnOC$qulItAV2}b39q&2M@aZC>z^EK`2RhQ51+v1zPiOfSXYNCWZ%%8jo{;Q$WlupP6DZp=Fi2&A z+Al$BVC*yf)Qg zl?_jW!>8IU@yhRZ7C;KpT+mKfDJR!(`9ts7euN&9Fcj*4UTNBrrV8z$}_-G`^GCH5sysLn;?CNK$?NwAcju)jtjNDu%7+Y+ zd@Q^CZCT6dW@nAnfmV~f);->Fi7Qt(uIff>s{YF#lGz6+-rLxO)on63SX~2 zs2Tt%0QK0UoD%MM&ii&#d?&-hHI{xpr_>!LMnWB#4~i^T&&;bc_FNF&*k(5EXPK(3 z$12;^b3v6E$b_%pBp1hFdx`l@<$Kxq3Da(;$xXZ?8V~LB7J}Sh;peYlt8ww|dzUxY zJ1g(_^TqFrcn<2iFfd3Jf(EWUoKt(UJo6MX>n{{M)p|Kg^UO)fE0C2WQs7f=q?|sj zS#XTurg8d)1Lsz!ZCe?z+vy1?HG@n5B^Z6rm$KWKOdSj-tlo0^A@6Z}(GUJ#Zb0Iq zNF40Q#Zh^m1%uLmHy(ezKuShtGmBLz41Sjssxl^tUWoaR%sY~S(bZ#Imfo|G6!g(IWTeG+h9dp* z3h$eJ613UB#9rr(hjw8~L4~@7-;x%Wo!^Z_ii|w#d&QJb@=iWr02(!5V2~;Wo!9H( zY}=)6cz0ukS5^J&3CDCB#AQ2rK(lcS3{qvF_LP)U!oBoUMr$~7cI`;z+!X!)&y&;t zpp|JOAzHr5)P6;zzMbKpAu#reY4* z4UC!p|EEk@X!BP<`B0>W?!8j(m7w`N1_r50P$$U3uStH7lj?&u?k^2Zk768iq^CW5 z4lQY`Kzjx~oI};0=d?cEE|dFy=?BiKk{hp8yFm-FDo`$$a$@&4^u6%Gb5gw$x7O3z z>*hVLe?Z$XRiI|GwP$)nK!DegWo$R^U*;&~h?&||2wf;5RR!5Z79E%=aC;>u-_6LS zOXPlcFOuQthR)K~fCkMh{HAbg?hMSFS0y)Bbf(=~#JuYcW<1$tgSdvBDOi9$zFY9X7*N+$EAzE6z%CVxe#sq3T-i_{u6$Z{8{ zI?(95h2Pe^`?5yD5ntrKwuwL9Z=oY)5e;2IQ3q;Ic{qPwRn9oKyk*XU2b*Us&UQ?9 z$_0&lf^tM1sPQZ1|6k^yiw>or@)4u}G+5-}obyHcbLp;3$qj5=TQ6!0ZF}q=4soSa zBWQU;yyyR|hxyOx=$<{Ztg*pk{vXHJyj`FmW?+zNECDCEC2t)!9A?aHl43OZlh9~o z*pl%WatgOp6UYh+zs}_$)r+z{{8V32BN1y9Ncr(H_gz!Eh> z?{e;RISw{A-){#%T^Eo7P~9cvG-H?Q?=#-MrGZ}?6xn*T`<^^I2U<1_QUGc;TYEOO zJ<8v)e7Ez=m|o|G8_oJ6wSG`ICbMbdB#UFfU?thoOspV(&@=WF-(5NBwC z(PUMTPx~ckTy%o6o`-XHLeI69?z)q?iUmnk(|xyY+oKOH<+?!W!P>L;=hL1`O#l9- zq%B={#n{q)F&Frr0|o}EE(fq1*p(-%+*`9?e+qr%AQ+}+_^F>JzBW2; z>5ZpgdG)2hM<>!1v)xh@BhE~I2kP@PFi7=)(nGxGW|qmPRvr*H*}W-rVv~>86DQR# z&=l1(3GB!#JWDN1^PlstYuNK#Z136KuIc{JPH``&sbb-Gt6-&J`y!rcceX~}6frK} zzhfflyT{A`nqY4z2>ApQ|oy4;1Hzl?gPcDo2UH)o1V<8!ZGVM zE znL$=u20L=4#`gq;6=`4BwVYdj?6RQvgoIVlmiZ)52D0!Az4TMk)zw7JrB!(AW$PNwDK#9!I4RPc<3O> z6wpXcuxGW`ATk4wvxdseluI+WM$dZjvN z&${`4K?79`3{ulTtzrv5&X*gwE=IaR--enW*a~SC% zWzXXFpSMG;7QBqC*%l{xN4M^a+A(NvaXREgQ>zu%%HOdl=IqkqSZnlq&IyC9DbOlu z255fM!mq=>g-=dT|AN@|mjOl=5}prO`=JAOGe8xrhjZ4lck1y%Oa0SY1S;bhLpE-o zV3z<1$(fK7O-1HAtSD=|VzX+ySp<7`Q2MLzo6x#@CMcI%dxqbh>U|+&#_gIKhSeKQ z5)@PP?4T{unUH=K&$`p4ZBsw6@}IwOc*{ixfiL`5p`(klKuvcGzs(w~rxO?DFY)+s z|HwScssGv^s6yLOvp~&e59j6UdgUCCOX>BHw9|szb11SKtuO*z^rGm0;Z{9Y)HZkb{ z%e41}jHwLJ(Z#u-ez&{luH7>E-A?s9(}Hgu<#2w=yi4b%vXwrtRhNxXUN`=>No-NKS%+j06F?# zXV|v6*PgU1|4&&i&Uy05xpSK#;V>UkfJihYIQj`J(=e^LBKPp5l5YX?V`!^*J}6bY zdRmK#JX^)g{vttBzFhdY(fJwl zU%|QuL2X%(37`_!+H5 zRIE*yFUISNTmjEbFF-qDi$Td>%4uu44fB5YRQJ>kstydII;kSb{m`EKVo*OT z*7H;Ru^<*z3(KVejJ5LWZ=Jp~-hnp$mq2#>?U*eYq{;NJ;sjfm=^n4_bXUEjpe7mv zgVa(`h+6pNd*>=C7+rJQ8C0uZs}$$%aj^_KR=gB61nA*>bmEugUk(|S=pWRvT4yV- zsD8f%vOh~|8K?;#>*+4J>35vK`?~d4Z>)=3^=Hf7tCv764+aLQWzFD#N^zR=vF7_^ zZu2?2Qw^>NvX!=2fC>%<2C3zsbs!dgTwZ#AZX8Zpeq?3v$v21J-q7qygC@BZpt{S$ z*@)w${VuV+IUjc$wMq0$-(KWs0j>2`fYt?-dH!A1f8X%U1j$r!z2rHqomw`Go7O_2 zdj;fe(cI0@NXAV31k`I>+0>Z-P&l$<@f8pAN2$S#0Us z6|_Uf2bwomfwt{>IEQp>{aUl4Q%f`1yz{@rb}Q+t?9j+s1#0|DIUSX-aEdxy<#*}D z##GC?&sP#AutBS&RiJu9-&16%#z(^l<>HLrwwk_kzV9iO*$5quUiAeWP!si5o=#@q zJUr>?kM*W(>B*$%C<)__`K z9?qvcHYTFOz7BA@l zH8epAKnW+<)BbArq?GngZ$6&tsx8aP*WI1B71TsyV31mC1$N}eGoLHh{{E@PQ;?E3 zT`l@2^HwWRw}F8{Y8`0W&cg50CHIq?^`$>(ohhl_c_L$N3#UXoBrev0(uId}k>=zk z+dCKDFlw%@I=XMh66yKz(2?Ht!VC-y%AN~PP8G=e$ZgXA{IbSR*_l{ znJJ#$Yq+4RI`671|C+^0zgY9H@2LXKAu%vWZ2)Cr3qRhAC+*9xgavV^7q^r})n2>$ z=?EyfgA{;>XZ#=b2Hj%@)vJT_ zcdcbIkv_IL6Eq{pz#z2|a^@lX;^nnxmz`{R$#wtI(+3+Sec;vw6&wrZYxrsY4Iv%C3~}PXwd6zMP3y%HunDMx3D++I`px8rYU{S~JCQ zn%A+@mjY+2CHl1LM@skPfTkrF7^Jp>#_iob|L>munkCU@?*;*%F7>IuWc&{=1Gyfg z0FpNk@6_e9e5N{ES9I~^H3~&pYlJ64OPKADys2o}QP8;7tT6j`?|NHJ>4gur+Cqor zw?pzK%TtEgeqKiZpZ|HYQ1X@T?WeDbx~X%GdK93G zez$`n%gyt+9o*n#A6aM8c#!XS-{U!}pG~a;U?~brUv8v8Ijmgp7Gc9diCnw*z1e$dKDFCG`4`*AaUDMUv zHvKksP+?E<=1IOHZ3`NX2Ppu#Mc;Gkho8y)Z6_Wqd$ToY@zJkkbDwR6=FMG@=Aw$T z^}5SjjeNOeV?s_Be`mNNEd=ViFfd5%hBOyHE{VPCyvlS{*{{{>RA#bx&C$F8nlk_? z09C9W&i1LP$1}|L?BmGadMW8+kFxH&GEnOWqyW-fOmNhGakw$vTQ%pu*g0;=^_${_ zLFs^jL23`Exv1~?z(dr(Lnt}q(87b!Wj+dP`EwhgD=7Auf&*%2-TlK3o7a|JJ8_tK z_CnV5ec4*Gp3z|~)aGtzI((Uxb zsy*(eXD_~s-~Ra6!xU&x?*k2*Njg21o$@W@*u}zQ)4x7h_ACbv(7d^?3hc=6Ltf3s)#qlI*1w$6DUez+^XGSHA+{e> zs9X45bzi`3Rod!aJd^M1lND_TUAnG=x^N5(QU^e>>fyY2@ouk=jUo5mR^AJqn-%(S z^3&APsdfW|`NJ!QWYwtUh#_9V>+gH@tpBItz42KDQxT*fJp`H|^l&!Z^s?au zdp^ZnqER@#14V7o|IGU(_8O-{*^hH9NFu3*|v1WpTHB4BXFe-fwp0} zdfIJ%XmL%r?@Z+a-sbO*)W0R($bn9XA9@9LWXP)ihnLhXyIk}B&Ff%QRK9j?A!yYj z1B28NkQ*%gG_K$Mdf?aH+SFf{zYBSvpRBw#9W(<3QUDqx@o*Mhk^9+MPU;0?nw!S7 zY~N@5m{LLOszC}snOMqc(Ts2X?5y)DOfKo`1vh*;oWT{k9^%a-pt(hT&wGi-N))Od z9{7-UAg=EY6T{CAA<)7I1_r64JYYvI{CQ&jGY!+a-*+_pe3#7r8?CVwa;Cb}G0>rB z7Jdp`#&h#tZ#;LlKK1YaD1{EwnL9yUI0go(W1uA`9?r_nYzMZz|M*!Wc=7gpubE4# z`Wm23_hXX=%4Zm*fR>vESJ+uq_^ zJo5scaZNsY7*w(_Fi0JT)SJvL)w{iBvXrj$O<-Ies=i~=MjmKLo`BSw%+eu;7KgBi zzT~&F*t+jXiNYT}kpCGNq)tHU&7TU(55K;r(QwyvT9f;UZ*q%1T>uRlGB8M;gw&fK zmUtVS*~8}Wy25xVr=MsImonEzNJyT9)SE{A+nMASe5)*0)D8^1ICWOn)^Lzc1_r59 zka|;&EycPn=);Bm^(LCT?pf~q^fnk;C7puQoBA8~i3`2&Kv#<`=M3y={#^`{f~T*pxrZd;npR$p6R(fOx-%~ z0cb#`sh8~aopWsS6L;v%Q&Q*4!J{a1V?Qx&s7zuJ>s!NrVB7pt zT;0c@<->W%-Pua}?U%Ow-gL3?vBakrCtK#-PjHooP5t8KMZ|M3)`w|_T63-ik$tE8NMh+Qzd*LjJh@cGr3rzfOm zPkMF|RDgm^0EI`HXUUAM?^afC@MJrCzV!XOh4u~(jnK>snp1oL@AF&q<)<`$`u2VAl$Tt0Kz$nq2B~Y1J?6e=9&j64c{#2+plozmdi}zK zrP{p4M#dnv%wQXbCRW;?F+TjW`7 zQZ7-FY2&sd^xS69pa27d)D6%^PbsHb=IEDOPt`m#o%14$=aSnh70a!lJ|0K`Xpeck zr|D{C=9{ng?=5NJ+p4ks!VXns2I%gp8<4Yt_cUJX`O>*<`tpE+>fWuPZ-c5oKqnt> zfu?IL{HCY#t5m(%&Sz5b#bds=!Nx@zBGC5aEzsnnhx3*!*(D{%Qzdw9S>~I_Mr;qh zy%gGPz6DAbQckSBudW`Feq4CDL?@d+#l7y}G{{6TgVZfh_uAc4kZ1evh41?wUOIE$ z^V-?~v5Ou5p^b%%< z;9AP;`TpO8PafC?ZRFesok^na=~=&AKkC{2gzvf;bC;Zcm@)J3duVBYKNDO|ww#%A zx;k6T;#Mffm8H8kEgE?By!<0&IsjdMX8v@bBUwbgS7qoDSfkEn_6WEa<*FVismuKJRS(y~@=|!Ar!;BZ8 zWwIazp!{L&*|x>7d3yP53zeS{6BnLSf=-bT&3SFk4i`p#$TN<~V`8WzO7ez;G5J#>2FF(|-1oG;FBZQ6E-X=2Eh z>C2Z)id*I&!T}v4eGE#pQcm5GlMeg%M4foG(eQI5A9pO*m&?#5%45)wm$K)Q;$M63 z+`O|hW4|NG|=aTd;>|#SJfyD}Ji!i+DC0sDnB`3=C3F zK?%pgZ|mLrllETQ>{)8VaMQ@=`IPdFZ=u5rPeJM5!}+C_lwIsim1&bUX&g9ml1JZc zS2ififlL4`Es%2hyE$HM*YBs3wG7iuxAQxTXzrO0T~PNFl%m`{Pi&p#=ujWVNWWwIQ`{179%lXd-RVX09E&gRd)YunGcZU!2lbXL{Pw4v zcizwy_iX=WTeVAulYP1*H z_Qm_8_^(T9Uc{?tCWw6!OI}{-U9cFn6s@y!BU!PkXw)8=3|0?M_`msBe z?B`ayL&u|Df|9?xXOHo8v50Q5iv2d*<>xfNi`bZ02ld4($Xd1aW{>K&PFzqey~pf` zPq*OHa`lN&H@pTlye<6p*e_Rp(|q2X>)qcZK7UgUb%x#0!Q|JVMz4qSl55usq}o+< z4{miaII6kbtofb?NP>Yu>J6ywl5%?SA?BcE{R7!^Ju6KU#8wskSnCgMPrd;S`RIGb zi#_f76P9u%4+9HjB+N^~H!zIfLKc0=b%rhi*6m2^C; z4|yk-q`Sa7^a6Ac^*yMCZsE85x(QQr(YZVEdNay|Cg!UJ@|}T})gM63B@gG#wUbs&JN(ms#i4 zetz=NZ0H2XC(vOwQch*Jn)UmWwmlMhb93cn15w=x*LQ-N1t1eZ0~EoY@;|!5mWMYS zp0FWCr^#k-quEa`(69nX0c36Sww#2mb34QP{~teHFXJo2@~(aoXo)HVgVYz$l#zv> z)|{J9eq7I3-Z%MV;gS5++KdiWpr#2(0jO>7;avOl_?GR~FHE0ay5X#xVD+@PAq~`I z2Ppu}b4ocCtogllv23ibme=Ja_l))`u1kr64i0<)4Hj8@mfKBLRDJUC)P%#^`Im2E zPu;ihF?3-6D`cklsKM1ArfSvygyb(KF4x{*ut8@hsHS0HkopE1pS18(S!<)g{=D?6 z8@~p}4F;9oS0}VVGvy!!keTARf;IcCg#$~I<3IN={PvDTpq>>}>oYJ&eFqIgN;#$M zI+{1G#eDBdXElkg2XBlaD%<;U7{38(9ar@P-L-BB;qzptg3@!E9~bja&_ z6gW-JTGeR4JkjRCerfgMzq!HZXEPs%`r-$Ow(vW#|G*^fwLTNWbQb;*`8#=Yj&&Gx zMC%8reDH8)dY|PRH#^1QovZM!FYIoo``YzEBRC8UQa?d+DN;`R60fd5s%GbDkv!o; zrsbhucb;@WXGnj726Ej!@AWvoXOb1n|2c%zrFo4wBGy;8g_E?tgdCsykQx*+;Q$Mm(mqJ>-Rs{2QAEh zZw3d{li4w%!cWhZww+5+p141yqx794w2|`{R18@7&FK7Nb7_gl>PAyxE7QC_h7O*=k zYuaWp7M(k(*3hxyzo7A2eNWe!%bSBP|8M)2l(arvh%uT)ZznX-{=Euz-bv#u1BnBw#-G}n6ictws4kZA zI}I9UVqlPF1O=3ZADin&<1+ET78g{O|4H(SdBuNP9+IM@89}9;hjY)ZMZAR@Z>K&I z_{S?{RCz&2S{alMKqf%;PVy{|XmVK4f8_JoB^A?J?#Tat#tm8AD9s2OJS+2jwy9qF z{V^vkKjESR-8F}E53wu&jeRgMNHam|i=xt&+@*}6j{5T6tnckBwl8>D07+5O%#ixR zc|*;GMSLnkjchV7NHas~iEi_mo-eRYLFx+ z%>t?~q@2XKK53{V|2M7W;dz^5C7OAU|^7D0rlLiJw+djSVi1DlzB((uxj3? z8xfN$PVEL4#nLR0gHtvdU+y^G6Zu!<@6}C-$CmibJe;|GlG&x&E;AX=+NS+Zewv?Ewure09p0TEh3>a;Mb%wfA$)#I`;byaPI|fPq1p0~8JxeulpjKUEjC{g}IW6PK0G zzp|($D?vR~kOD}b_s%-)w>=dV>4l+>r|w^IOGMoz0kUyPngbLUQceqU?uTn!m}GQn z+P!TNZ!F$vU-pLNENKpqN&23(pU=OJv-te!t<;*7Bj#M2-it2WlI7m}XnhUg#Rm$n2+@=@Xb1%zG&CEJ^P2)m4 z*VE1qkl5q`O)|K9Zs=IKaq&dM^}B!HEOeQo@w6sz8z_Jn7^Jx&`?K~t@VdQ?OPyn(Ny(`f|&$p0+@k8nisVEN6N`>-uYSf+_NhSe4i|L7iY|QZQTaV zS-i>&3=Hv}k=qXZ+ShG#CA5wC?~6@ptrC-zAk!1lypS|$@{vhM}8S7&3*HvGFsan zFou>L+>|E>8WUt-kmd)a$#~DCs>8u++KlzMJeHi^-8-+~eta5edn!o5E^sjz%;;Eo zUwm4@Tgx@fAKMQuU0*jFa{P<5Ajk>}zo++O+qflrbEY2Jw!~Y2wU^@xs6EZVz#uIM z>X3Ojw;bKS`@{oX_N<$RyAo|B7#kk02NgXa1t7ObI;mRi)^zJyZS()g%p%`LSqY&7 zp`bP#NC9ZcjhpA^d*4*pRA$bp7XDWoxLGdo*sn#9g=Er#kkxJh-j1A-JGL=&n;xsW zBC|lnr{yuELXj2*xxvD(^=J+Mry!FCf!$AIYUf@4GkaPuXw3lwgS0Rx3wk)eiQBMk z%ipP5KW7D2UOZ(W`;$)zGN>*s3>qVqa;h#{|GT@q!ZYjbtOe_*OzHA^`Q8>1)WV=L z%G&clmFgp1u5LRI)nz|-94y-_Py)RpSXx8@9Fm7GBsqC)KU&sXoIXFb{9L2K1QF1H z9Rq{3C}^O*Oj;B)>EjJ0QJZe0EK6M2u-^8HW#u6^C;?h^^=!bnR%268h4e;<7F_@q_(2@&hGuaZfV zg>ORUnx!Q{MUaIbm-lDQz<(7ppFCdDI`8gdhN$$dkam=`Bxron!}-Oevlg6x%9B#k z`Tgo`W_c_N%!jNimX-ol2U1Q#6_;PmsTU6E;cSk3%e=&A`JWEZZbJqJX(`Y^ZkZ?Z z3_-C;hq_)(vS99AWO78)yTRrk#G6vr!Lhkh`9|zr5!UIUOD23ed}jHr&)VM5xR3!2 zyIJ_T%5C|((Rfb?`^-vSzd7O+@waY5lf4XRc;3VLf{57hdrz`h8(ba*nb}7uT>572 z2C+g0)H$~H6kwSAOn~nk`{9y0Pl?^1j)-UZLKCeFr1tkw5!AkK@n_Q!DU)ue#Wt?* zp5BKvFr?)mwSV&O$;^*KcO)gA+q!4|YqO6s-S&`1j94uGlFzrDGBXKJ zo|;#0A*2cEMoG(oYX5jomUPahtE)F$<^i~?vBA=Wd)L#p-9#lS+H!tq1Ay3Xt>3~Z|{nqHaoA`sq|Yd6<8wkxNKuz1GLst1+^lj{Z?{$)xcBF4t?`%E%kr%upeX?c25B`=cv$!e&8u5~AugciaPI!@ ztQ)^&uRh!g%5n@0((0f=L=We7^;);qXSw{XI~Uqr>6sLKbx%Jiv4RwU+7VJt>T(mV z6{pVUI(nrp{BimDJ^|-Bpbi*F0q7u^V9$_`w+)33UyQsh$+=SLVY-n}&qPQMMOqz_ zssk2&5Ibp=yGq{mQ`}a$ZGV;=+y#n71_o(ONUEL{zobTpVOP|?72a>x?0ll-e^m}z zUuc4ooQL!FQ+pSjcHW%PR8q*dJ2gt_U;^~Ga%oLas+Mx95n@;yl)ZHG>9XR!Wd|Pk zmR?v4t^GAYZQ5W@r{A_I8R2W%`el{A^fmdNoNj*rGz84RAgyHx4#}MUpQ_(I3{t`r zUz_eKU9n)(%qgIua0UixZP2)!g&*7bOM6ylE7}KL`|#=1dgIxDcp5;-9i#v>$>8D4 zDa$;Y>F$?Hzw4u)=gE}2#b*0KgIWia%O#yIZt2bU3*Dc;$h_9{i!9@=&1nXpEpP$o!xS+Ihp0^qFrJ0 z>=+M1wk1mIg4$6Qel zaUy2Ir0Uw6GUq=-a6A2$2q^sB0gT%X%J@O4=ddd>VPpYNb7-mD*B!^ z=Pp_}2J*=3dmYMSed=Xudi*G;rwUR4SxFKbF8|_q#HrrMIb};;g|%{iO1%mh!I0Mf z2tH~f%+_knktfYkdt$_{zmDupw)iyxRLV0jNE?7w5O_G>6`sl~_qCxWmp$00cI!Xq zln<8BqSyekl4QsKj57gT+Tvb~XRq`B^_}Ep{~WT4L)ri|s#fM{cik|#_0pee`{e$N zBTZ8rE$8uobTTkV8$vFQ2|m92>BUaX;2jAY)epKIz0);uAISd<4AMrRAz=%@htgNQ z9{oS>9D1iQfcHeirSk!5pfv{|1)y0<59h1bTom8d8}?0Hoxo#qNXW-!-=8E%NE(6K z_)<<%B5CWd7Kj{5+&-`Kr|vX8!7~YvA#rIVQ0rLV^OkYHZsD1^Cc!t3OnQ7pfuUO9 zI<#eO3@M6bwElZGyNRiN6AfkE07vMliLI-P#0B?}pnlH7O9j9;_3+6>h1w($F1 z8c`%F66>ZWbIr?c(#$j)t$xtxDo6n+>v=c_6*ufNRt{a;awxCYMEtN^<6=neXOK1r z4FO6y6;99Q@7`>2O04&~wCXLz^{3^5j?4UgcIz_EyYK$K%?drSVD&x71c$T*C_F6u>UZ6rH}~l4ZM!cX zDp!p)StG`=0yG}Sz#wf28ldoSR(}yTe-oGMtj(cEwz&LbOixx-0!1@O0cc2A%IT24 zZ>P)6ZAnj=c`dbFOxj;}IDl4Of)s$Zqq%uT$^3iN-0CW|b`$dvcCQydG%l?JtzrQw zfb3F_`MkrS>)Wre=#(dC3;UOO*~@l=@+1R;v^8k*&BE{QCIh$c8?Nj9c4S{Dap#mf z_W?c7%m+vTXqA_TGnc*RI=58o)n0;=mWi(M+}K>^30c)6Z4K(dOF6BX=Ub*^YUn1y zUpc#Y^UQv$gSL?I2Wji&;2uhbK#O}op3%ZHN3;Az-dSk0&ie-HB{DEb+pvL)!DEM> z|G50J@vWt3PU)Pw3ooY2T0nd5wx9;Mh2M$~+%daKB_6M9n;z81ko)M&T5)J~U<=w* z=i&TaG0o$$Ok2d}Uh|b-1X~;0HokyNa7f#NS|ahDLZ*{q^(q6IR3rC?{obvS{g-hr z=$=Ie25CDxup6dd-B!FM({SRw%!{G#e%bu{y

{8ng#lVc~ac-u??y=FPViR6n1S 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

bgb>Yz(G>1uQT7vAV{CwF7LU!a`U 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 z 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�?>j}59g`{3;WpGm&wlR`6e-~eb+hJ zP%CJ9I0>qGtUYC4F1)aJYOvbuOJ|PpHC_*#t+gMNnn5P~2fJbM^t~6Jb$m&G=prm} zE~asZ^N+cIAVtt=(A1fQpUU2;ZyJ6NM^zaKhHa~jlqmU3FAllv%u^=46MgLhe%u7KI%SFxa~h=D=sjj0hJ3N1)wc29?mPoj07I~>nxp7 zf3eQ8dm>^)ZO|FS~3L`25TaxtE}m0vH(7&-s7@YVzJ2 zR*$1%0u1H$qoZ(b#N&T++^K!{>+ra31NIQbWfHrmp$ryuy`LRp)fG0UjmID zxO>_cm*;1kj%O;J!TiqY*u;}tr>z6Een1K!hci5T)Lrqv%rIo0v-yJkSw$-$wdQE4R?&^{y~XZJBzFA(b;v;qKto@Fo=aYx)_J|* z`X9riS&Y?*PBZTX`Gaa)1_t%3knzb-_MC}oPTCHsebryMjY~OZ7sWvxc?~i?Suttt zhPI_?J4)x-@BMnpzICN~5_D1DHBfo!;mo<|IFqhY!1Y_vUB2!6@|ib9R)FGwfkFKm zs8cBA^s8f5%7%^MABsP0Tz4u^M&s6VXJ{F94KhCI*1cLv{JvXxCi|`%y(*430yi!J z&1*6+s9%=^M>k&&?_%MvCzk$inzljlZM$E-aRjvHy#X3_vhYidR5mT#z2WoLAI?*^ zwY4x5Zc2bI^SA*SpFC?4`j=@s!(DYD3xzX#Ji_IUy#}?X85q=WfbyoYr@cMnIW@aa z(Yquhx6def71aOE5ISCcQxxom`*);{gq_&Bb&V-U#X-9#7c|(}p*^)*po1AL{8s31 z)F?c0FSTs-VQbbM-2%Il_d{ppZh;0=RQV1g+$PZ9s`5=ZP4&SkZ1o@{~oUwt}!)gX1!^7 zn@n3@_Jj86ffPWN)91a&VSPFMVBmSnmsNqBuRCh^`=JHM9Z)%8;m2Ql@WnQXXhW-& zi}o~c@2L5Gsu|iLy#pFM_i#2$@3=E{ql&_%lJ5a+o*S)?T$l!(D!OY7o;%pSV&*H& zwt|Rj--0J?v8gxuk#`E}$h(k}z}1zePQ3L^-*ZCixhXflUfOyo)(9FG_dx9j3%^a4 z;UCW=Z7B0QG0{+8v+F`u{WfSo-TM!oYi4}6XY%cjXL)isHZQyJXi9Vxn+0_I;l4Zg zpw1sZVlt&~_fEZ9;Z#{_W-l*qGYi@Zx(_*@cIibYDXl-Ji=)geZq8KS@Z!xJXXqBN z2cR(_3qPM(7c`W$Y$G(uJp`@p@o@g%t8Fy<#PNoDmd~mGuVq{B zP?c$i)E5syJvAw(GoEP`OO|bBmUvmwr5$?7dH;_tP~(PyLH!|UW-Qo~y+6_9hKo3x z*J;bs>`jxu28+ppf*7O#vQEr?o~oGj2WGz(PZi#$b0QDz%Y6rG!!aTKE;+ zKQC}tM2L@bo{96a+g*1v+Ma-tJ4gX!otQXtd5GNy-G-*p?8jm+k`Fg61fAIgT4M1S zv`$RYiM4H($x|(+UwPX$#09KcGg(Qd2-JQ8nE+}&TYH|}@G2&-#PErEk=U}-Df4zX zmfC>YE+7Rj!O1=#%*E%#vkg)Uq-U(Rxp{ZWj{B#f-KeLaNd^l)qx+v1 z$6xV}C9x5op|##qQ198pS(Q(3U#XAVmlLkNtB5 zDk<~N#%Pu82X0)c+yqT9PeBEUwdcd?J(^Tf`LK(8RV4R zbv(u^OfRlU4~_{Ex=^($tL)z$(BvxvgZgvOXtRZ%+x^GwcIkc|Cl~L!a!_qv&!Y}Y zXhZ8cXz`AR^Z(DY#5=_GYunt_f4%OjG%Tr|0`22G2X)A#oSHv4%J08>WsPF{SH+-a znVYXZRe`2X85q=GfY$y8d9L9O|NUaZ@B5y1ZRefc1On^D8lVC705&#aKS6~Az4|Bf9^ z|BP#ota}35$-}^){sxpUEc}j4*l{KN^#bKOU8U;#ujWc!U1|a9kb@L}>TVC`yV+}A zmAyRmVrSd(L_a;hZ?okDK|u^s0LnmRo-6e{F0^)5DCaG@9J3;4CF{w6x1dHINWoul zlC%1HCMHz&$A(jVPjWV`x7*-#F&MPDlz~D09cVh+!Y@?#7U2@xL4vw z?Qc!0eqy#6I(YaF6y3_6%bxPR{~Yc#;hg%PB?d2C_k?>aht9FS7X~}hspz7cjmmk2 zi2}1)^JSJBPdU+b4pKgR08M9G`29BESUII#Y2T$I%bWt-!wOghZi4D;1_t#Hpc2=^ z`P2Lb&YNH5Mb7C`^3KZ=K4&v$B50xuqyRLPEamk7)Sf#AB5Nk=i}U@8Q3`umEV}|) z41NT)1^YaQ;Uo3KOYnbF^ATAUqKxa4`4OgaeFwEfls&)r1l*Gg z&ukaCwmTxVwS9r6p*OUI`MwLBt#$u!1k6FLC_W#1_t$?pm8Y+ zzn`U(oi8(-?Rk91?4`%ywJ$kK<)8)WPtY1p59i?etgA(FkIeN-E>2RP#aqZ7C0Xdi`?f5^yX%DPOR@UP+@cUH=3qHG>pDw$d;1-nV%DX@^rcmo9HFc=dH9 zSCb}aZk2&S{WoZjl!c#X)tyYCx@(K}B}662`ObTvCixAN4nPXBz?D0TmWy|&qxAL@ z$Hj!tFBLy>inRn9o4-L#Rw<`>_0dUd3%fFOXPJMzbVust;~p_ka~Wg;sKI6JsXn)7 zPMgw!2W|?fns;5F^lE;%3~hmcmXk9^`t9d#ey}O@>a|AMX$|p<66UP@T>~A!{0o|W zu<(mDO_dT|!7xALd$*P8U4~7z^`X#dn!lht>fxNGsh;xZKw+AO?N3eFO>8akYnMTz z`!8r{Jl6ACM&@);?#V4rzXzA}_7}M62}pp3!WkIU|3R*6-<~9zVRV+IWHHhA3{ga*#%5oqDpn}B1x!~ojbBE$T z&a8Nn`+v*)Yw2z^M@F24Y2!)P$2fZed@N$w~8dmb-Cy?6eSxO;9DXGl6^nTG~5C<|KnmE`~7l!-gZ zoS4paTIkP&D-H?Gkk+6EGbr(TIQK1AGEx7ytFu{r#b@JL_1hm^z6UA9G+01|y1wU} z@AE@5CEH%zje38t=uw>K%SsVYQ?*&hK%9HM_ zxUQ+U-h*m=1_li_(BPrIXL;NA{g?i5#HqXw&N=kWD!V*-7pS)kQUJMrH}CtIi8>4R zrZ1gm(_kb%)xg}$5tN!47&O?=g1gmQ7z$UqlvAkJrp~U1=Ps^%efF-ptlaM@`YoUZ zg$xWD9H1)N+H-;-kJRto2aZbrTz>cI{o7Ux0-iw=496mHK$YFTbh<0x;iFsZKDA=p zd~Et_*dR5p1}7+1E&M!0)V{A{zBld48xK4EAdiQ3@0uYaS{huSAop;tni^&@;YOXA z;Vzb$?PXFY>!q8?5)Pd;hzS%Ao!>1A_(^sHqa` zS@3U;Px-DFvui~5u-avm>|<#u0CinJ3LyKM4Qpyn>PlSOmMy;B{z-0WK{fjys5f~) z8~QB#xXSlF|9IEax8vcVxo&f2H-|DTf=rod@POu&Je+$4)fU)CGzUDGd>9&k#dL8Pwr{*WHZdZwCO>p)F4cIX-Xz)T7iu~sdnZTs+4(g4(3W?<0Z15F)T_$6~DJXAO?r6s)KUd*lZYrGRGE8dXaj%2WB*zb0C=&1KaK$`>eb&3lGNQ*q(q=wz)7_>F+BC($ zpurERH;#)hyRG1N7z&GP= za1C!YsPJN7&=7>wn@3WXEm+i0{JYOf?Y8dnT;ZcOysschP7qRWzG~fB+g#2RXy+Ri zyeRkIjZ(v>x1b6@^`^V$`wOwjICd8Ta zX=X!%?}85h?j>PQKqU(UgN86@%-F(DcH`t?JD)oe)#4tHzsQ&B9?*OX8Hdpj28~;L zIRC$UL8|KD!KXs2-l~YXy!>axejJ+Yg+Xifls(Uv=$rhw9^Ikfc(sOgB437!$xhJx zF31W=m?#olevITk9J;;3YNbmGN zP(oo~&=7^RX-`}!Fnx9?kR>rAIp5pjTh*akt)PAdNCBu#E9K-Dyz0s8`P*BXw`{g` z&az9MxNRF`L`y>yG!qo;xh4P7A}N(`#aYe)9o1Q(TN6(21Ra$QGT{q2>y@t5+tEBn zA>rH2*M|4&U*|#ul+F8_FILs4p9BhGkOEK%Bjq%y`&ig&b8)F9oXhV|Z%PO`u|NTu zCdENBV!@vF7cG@)E^kQPcSh;|n&6pv`#bkdgG9H471)tcd~#85Q!d?4e{)LWV20V{ zjSAO5BmN8w8j_&)gN2{}zr2Go^ArMHXT|j^XguC<`^~RphzXLQ#OvX_k7d)U@-RW; zn}S!*yw|hwUS&}MS+t`e1!}_tdus9@SsQd~RgiC0$P|O6hAvaYFM$?_FfeFHrGed$ zFEnGO=)^77tGm@dmp}K4s&Bjws)`sGG^9bJj23=kX>*DKKCQ4&Tju|4vgVV#m2cx9 zeO?V|P&wh@yh?i7&A%5X&i^WRrR3x!rn5T>=YlE{1_lioP;^T<@#M`Bo-3&JMaAJr zzV*GA{b9L|kQMtHGLZ}n46dG6S+?xcn=tQ&z2%#7m5UZE_O5)8=7EL`WG{^3goD$T zFk3kksz|e zckUUW5*DQ3EjXa$HqUi`uBrA;(jt@1-qbZ^{_rotaZ@fafNlf=RL9Yzw4%JsInHsKqg@|6hMjB%`@bs za^}^qcNZwuT)l1e_0y}=u3%`2Qse=WE|8oX*YbZ5rpl zgLK3+lt9y$Qck>QLjO1|Y5Xp_;Ks`%UBBdSZ@R?cH|?b*peek&vUe*qxRar`}0)HSQgYFXJF7!0cAl8KbM6M z-fS}rbGvu(*@eCD9@*s{5r7sTDxf6i;kpaF;E|mfk8tJG~wgn9Q8TK=I#HO2}TobHl91n>l^XI9Fz_i7&O!!!4qB%R{u(B z@6IW*p7-NWm`&#Kc{eJdtwHt4U^lq!pOVRN{-w;~5&^b^rgdyhCe6^gTLaXkv+!H` zGxkz#YO{LrNzI$iE6q0SE;5459cXBRI%FQs5g*Q8nD)k?^-dqp!e=Ym^k1#m3hDc6 zXoC6~?w-lcW?H)n=lnlZXc5cM_i6G~0gJbg*wow%c7yg&0ckr%?&z59jL~u_j9zj4 zYoU(R2GtuDeiFV%uHTOSl%DZo!J&O8BkpW!tAmDvHfXZR!#Ug0>CwyTRw={T{HHdV zb8g|YKM3jbYG{K7m8G1x&Z_bBx`ds6G0*eGDaAvE*^^#?HUls)XlR2fH+N6tNj~px z#;@l|{CIrPv~`w}3348w3KgUPlJy+;?|psRzDoTm-_-Jz!N1PD;!6Sb@fa91bU{IG z;g`p_b6r46V0L)J!8P%+n-D~S1%gD+%pqlPZ1l8^V~iQV$=3TL(ZBBt}Nmo?Sj zZCt1Y8Q9m*vj>OdI}Lf?Zl2#=*OatYr{Co)6MGf|8E(?hp8;->zS}SJS#Vj*ZuMo= zS#S6FWq0gJ1C8i0Flgw5R-Ab_=km;Q+jZ)Itc6lMbLsYn0#O%kfVwUW3>pTY9$T=d z>$<$?zZ%uY9R2uw$~sGu|FyV4yAKB0U^nEmu*kA`L;&t;3zu}dzJY&b~rpwD0 zTJHJMQ==&isty?#G>n#j9m$!|C(E*RZ8(R}?KYX%JdVBz=d`=mYG zYkwpbM&}<6I4zL-!N>#J$1wqw6CTc?zhowdCg0_;nO>Hk_~IAOpM4>qHa!D_h6yN_ zOF4Dv$5cO=#?Mzhjcub#m{;aYR~yhOSdaox!qN9sSn975d46x*{ABq_hdUFGXiwV% z@;^wyF|Z@~?r({4^X#pAC~b41;R!dR`RyoBcbb7g!weMd7JmD7M2LQ$67h4x#^+@V zeEJ^Ol=MPl(+o7Ch|yP(MhZGTTQmeN#@=-pvVeJY9JFp`9sQyS>NS;q)Ytj z9}$Vo$~jI)Bt`duc6NajfI4LEo{R04vOf7Fc6964+F0F~R-GE=4ba?e&H#2~_@O<; zAt`%!AH<}oh!{@%zVOW(&>S-ZgN6mDVzuzIVYt=we}3=#kn2GX7q)%>S~|%EGHs_} z0U8_gaL$e0@PhNZl=J0Xw-}!sJaT0#;}%d5gG>O`Jd#e@6EElG{91f}mfzp+r(QlN zcDJ1eswY4SKodRIp84BmvmX9(Vy|i?}qbK!v)6Uxk(ZKJ!^3Pq|_Oi`boGmY?f53u8=Fz3K$qPtU&{JQchAYU%cHcw9BtoH1)~R-$I#}9hgDw zCy)ZrNJgw@$EG*2ier%KCi z{bM&v3mqTj$IiI2@a1%9y=e;?Wp(%Dd3U94kDcZL!G<v=sZ?As^G;+bf zpkWVMi{arMqMXWH-ov=`R!)UZ!6DW3wtbPHiBFIMP`^{kiMP$x_E4XQRpqPIE*?`O z*XZq?268<}!36MZ)Td+0ub)lIwQBWf4|ot&Xx4vk0;qWeQg9mVNSg(c%m4U#Or1CJ zl9!8uijU0Ctnls+0G7HCdSSC%!v5E@zHd}hUGP!K`nF-=UrNNK1R&iwIuw+ zn$J&@u5@HR{{dONq~Q!2Gz#+Ev?px&lG>9O4{dHZ@!9;4!5s|g{{dLiAmzt(t%F1K0xrf3)ZF&X<4L4BrDCM-}R0aR>7<1c`ng4!U%e;Sk zoI@MhF?R#adk1^+ulnG&KfFOEX=C!)T@!md7Z&P3%W5~syxz-~zUPYeE#r7r@ZpV9 z)>)IR*{z`VGy{W%J7iw3*iyYh{}ylj%xnAaGwrb4=*t!cYJo8@Xn25V59f*por&ea z%cEzfh24L+)=2@c@m}N;$3Zo3_RM<3719zi++}Dmdcf^kNNU(oF+=8(5HM z&9fq*u=CRG~C9(py3PI^7C_Rr^z+rnfYCv%QuSf^u}Ifj)m5G zexTCc!q4;g+s6GpGmqF$G`jQsgIAzyS|(_z4FiLQA1D)hI0sFuG>P41{%HTAgNzANV;1N#~QptR}Xyjr&H^=aSQC90u4OhGzDA|cTXppu1w zK_d{<-wg5;{4VcYR&)Q&#$|OGcDKu!?ONray~RMtT_nze>)*wMs5E6uHjB4ep8T9S ziy2f;FfeEYfd*_W{OmM)4leHuQlA|Yt0h0}fm2A%b!egu25pY;aGvih;F+wMK5vsw ze{Ib&lXTHFn?NNj1A|5|s9KP6QrYmdGq=!?L+*)Gr9#c7CA^9W&>|=pG)5Tjxpc3L zj%GE(w~y1S7&6{VdAci~0(lQ)0%WCGrg?Hi((l3uhG_9iF<#$a%@mg12WcjSLROmP zz1rryJbU56N$d?}N=uv`bo~?owF?*+G(thG01sy`eTHa(@D;-Q(tq-*F$Yzrw{}2V zq@jDj^P8^{^%hJ2xgya0zppB7saD~{*N`C)293~b;DrGdj}2-R({|XHH}4PsRC(sB zsBsvmf5pI{5e6w~U1pwE@7}{O_tUF}^Lh8?xCFQdLZ%Ki!XYKCb#|+q^NuM+b^Pz8 z<}{k$ty#_k@;?KEMmVIT{Z;k&IbXvJv!<1sR+im~zwpK>{ig6loTI+jk|k zIdE3V^4*>Prz)F$_o6E|A#2?=A|b0;bWfU`Y4S+)%_*y`TJ+agIQ-ZS$ds8zB&d-S z@3|`C%&x`Fd#tzqTYmjXUGfy=GYrrMMik`A*A*iEw^?$x1u6;YEWMt%D#N$B4cbJB z23cX@ceDD*u@V8Ri72qX(3F^&gP|wxF`Fnlk&I`w%6^O3#)>E7h}HF34?Jn8xtAo>_Cw^Xv~MkbsHf>T$!hWJwK{j9_w3LejwPB>3q7oUV{EANG*b$`P@>hGQ-^rIe(B@(sXaLXJ zGsgO|j^?8*pCd*)4)%XL`PVky6Esl8z@QNaIqI`Q@6=-zA(l@DOAnt(?>h2_ag8(N zhzX4Z&>@i)eh(IXWX;;tP!PT{VBgl?RV=4io1xu@1W>Z~aK0k{m+N^_vR!3X-t*rz$$!pnaTF(2%&b=Z}uIdN0`wHTH?dmFNHX+;W-n1{A~$3>v8+;C7Tl!7ttG zRa;+$-JLN%M~CI?yA)4QI$&VXNCPd+v+%odfBNGeUD}J)4?O;cwu1quL zk`0qAeir3bef-pQ-nGyX?@W+m^*vvBn`IP4_bFVy-|*spj&qwv)*fii%IpFM)TBk0 zam`J0ES64~q3|hPXY1-GKR}Vhz@U)@+Tmp3*XK8(*!}zbGN!EFJ^FXr*BuGS01b{X zFlc0h)(?6(Uyo@1%{p1=%$GFz!0^7U{r{Ie0;Oh<0?>%Blv9+1mH5i!OWeJ8E>)Lw zzr4M}{xc|uK?*>9UTe?HITH-##+a?@JH?-P`_S&x2Mctd^+h)1ejLdUXBcc-9%V)D zlT7QpnRcP0Sq~II3=A5%pvv9Cujua4>a#ZdKLeSW;DuU&d4*Llz|6UYQm14GhD(_hJ|^&`LJv7)b@v--|Ng$HqgBtQy4 z#h|sPYj<75Y3-m_k8%aSwolD+f1M-%ZIObG9$}31+x){Q_vN-%neH>?)>YivdGK+C zG}MHA(5hGqzq0n}xfLPOyyrjfa!n9tc_cSsEog9rfk7i5R0DfBOLLkR=B(LZ$)wNv zuHygmut}5OfX3rM3P9nZ?CF>B>$jJ6*?BReH^1G_{{Q#*&mK_M1*G61I5q`1b+|lO z#sB}ZJ-dT9a>Zkj7t^7REVKfTlup~P6P0jV%y$+vMHPd(_EJs?J@+fNGJH=n_$I0|Xn)n7JHKI=))S<)B88qXRf+it7oHv$*olH*O zxBc<`MQ(P7B#c8R+=ljfOF=WFQcg2B{ji<(fW<&zPT>E zHf?E=^2NKG)`5Bj3=A5TplNLjKbb7K`yckMNnL4dF{OGzD#wfKYM=lDDF7{V@NmxD z*Y-4Czgm`WW96|f?>&duc1;DP6b1&3Dphb>?%vh+8c8uCvolU;-FjzkbUMuNI&@0C z3e+kt^PJWgb+=ONMY&jR#h1sfVtxU+Wu1T5d^ z`4?jvciA5a}IqYiWgjfLO#UuDwncb@9oofK?f;1b!;YUTiK^wxm} zbUmD_@>jN>%m1EzUwSehql;zb@w>jD)-cEfP)JHSb!N2Rsf)8Lcgv1^;V8a-kNHGN z(0m?90jL2U#8nTMbZ3Vqnl{0L}M$IIpdWO_KfH_2lZa z=&7oYo$HHpzJW?N1_q5rQ2)Z+bE?vYIYDMYH`Z0iR7P|Dv!|VFHP}J=YKoBZ1cWWZcqu!z@X6t%A*#3ZMP48yC2_PdMik5X_TQ{RgcRe$RbaT zreENNL(^AOyYs(%8~;`Q=Z+A&$#n^0S9&0^2|n&Z%E|lr@!hgZk346p_CXV^=cOj zJIiJnwb*vIt)R5Xz@X6rS{7*Gcet$mPDa7nS#uPBH=O$UE?D4t(iVstT0z}v59ehI zT7n{$u$C4WC_Yv3|9PClVi9Pc9s`30c*a=DDLrQ8a?bP9>LlV^FBrK@IrMqvA!zO2 z3R=4t>}j>ZdCBF=+vRFMi)w`F&#+!}WfpWDNb6m2NH+F28I_uBTL1j^u_<8^)0r-a z{)3v(4%)b5;div8Kxg{o{h!z!*qwKW*3135_}~=8k?o+B>K@KsZ_P}ZGHq>4w(g8@ zTi(6U$(tEE`PdFRvq#G5jF$DaX<^a}W6RiM4qyHdFXE*Lom^-KS!L}xZ~6IzR^I!Z zhZ&7Gm3z-qp4GwuSx>9c!3}n#+l!hhM?x5dU!K%s@y(8W~gQq|ImupZk;cv_ix% zWC>{eg@Hk%8?=MN!f(lpA5A93djdRCL)CmU|Fc#sF#%1LffRr$77ypgTbs{La$GUn zA+M9gN6Y8T<=d9far5Ha0 zoHCg7vH3USSsS)^2Q3{I&}qvI3>v+l#B1Rf%UgJO@%nXFEsoU+O8-3G`C(BfsPh9- z0Ga{uaDIDd$K0zbiXU0e+2}6syJC8gm zy3Tb3R24BWX!L<5TY^0I?2yV_y>#-S_sg1MBcfVvCf!*9*}kpO2U$t-wpM##aYo34 zm=ymn#f;Ar?U>V{^EmyWmbr!BJPSq74gtnQl^eI0?s{YWqH4AeWE+~s1klKyhx60Y zJ7)?-*hB8N?z~oFMV|nFDC1oPj}OI%qwql+)d? zmpc!uY%aeNa@;vj@19YK*CSA_1}Oj)#lfD7JWJOvKP5JQ=?C{c<3EB%|;n&_bQ~%rA_WBr^xmOo0V9Z+M z#RVOXo(bwbdpNTm`c$w$sBMjm(S`#nlQukRpK}w`g=1jQmMaABms;q4q~+kQ4={vzCOyM3^u=Vlk7CJuG;i)J@d*F#&R zb3qC%{Ek+bJlucuc}Zr{wYWJ?0ww#hUVutB1_q6}prH0}-V@Hk&?{-h!Y@22Q&vH* zVORKl=v2{M(ENqIr|Un_!pW(BFI|6Wx>K|E;(2X>SI{xBxtGD=U~1VII3qjvn9Ma3 z=N~5XtEPCqhL-m8b-?Y1x!1NZ{Jmsz_(MRU(>B+ON9P3WftC;RK}WcGI4|FKK8L&Q z%ztBr2RBz9XG>UGCIubInGYIelyb6J!F!H(vg)JhZCYoKPLR3xb4%|-NI^OuGzqEi zc{p>u_pha0n~vrthNOwC=|8f77usx|{}t>=9^+iiN{RnxXWX;2U^>5ibGiiddQFXm zp!LNTex*Fp;+pe9mxs1_+x`{2z3n7h1t_5~Fld0!sr7KaW5X=QHO)Tw3de%CsUIsD z|5aUsb|)8tibE-<($njOR8Fio`)X25?7Vr-dC`8Jpw2MJ1W+E;_gtwuWBRm%#nbz% zB)1;Sw)!z`$}3P(V_?u&1lg!k^)@?h`b@K(_4~VC%w)3o9hSHW6oL#48jC?~d<(zM z`(^z$_7|$Q-t5RSTCxB5!njgsvR@1ub@y;SRd6ak?{A;Sr!Cu~t*=ML_um$RCb`9+ zCW@4kBj1OsC2tM><^A!!(&fxvYxv3*RO>S^Xeua!Mj;_lw~v})xu`KYgJGdAl5 zEKYHQHgc9gCP2O0)*o`s>#Pa8Dwmh5u|+*@$t!4uvJ^4_s$3zuCq{W%Z~Nc zWtRL{0nHanLCt3m=jT>$oL60ak`QFh_{4GEkyutUR>(lD#xl^*my}c3ikGVL9obJG zI;u9F>RdRjPbCOcx-l?lECUT}2YJp3S!g;lP}qBlW7eHjlfP=tv($u6B`+%iM>qf9 z`SXKr)yw|5>v+X&3TyiGiLs!h#=xMl9Mtc$@O%7xZuiH7O&LdKmCmxbZ1sEDLU&M& z%fO(q0+cpAoK21Y1pDxL+_?K(Z^r$_>+$Rw~@zeCNsS$yU%ry9RV?Ly+gj%)AY%-R38Uph!tyj!ERXc^u-*_-ubd$O9d%z1 zxqUnCkm;!vVlxhfstD>a8$|AJoHY~LMA-n!#1?*Gb7y^DkZU`mPmbx5gVXo5;?E^P z%|r$UjSZk?f`_xHZhZjjl2!SvbvI&PJkW{LV|fXkY}yE_v!t9HD?GMOK00Ul%l{P( z>Xq*<@dR9iP9<*yC4YTSW?tbhyH04%jmur6yT#t}J?ruYXp-9q8MnVzbLRZBRZ}0P z+^kcr^GI_@NqY!N%?u10n?T(u3qOYG%scKsuCuAFD-(9Lzss6FEgDp3gA_ahx2w(L zr*WQ~rgM(#+L=|WZ!jmlxwHXt435TT(73&nlZ_9G`3cQlU#&q zS>f8!XSX&!a@28Pl{;YYH40jxYy*X;g`YXoi+elIguZuvf44Wer|xEPhz_WfXJF9S z4r*6}Mp^S_sQFf?1tjhJ*W~5&Yg+Qr?~qizJp??0!K0uZb%2*^pCyBWpHQOwv}nf% z&=nNhL77MiDwGCON8D~D;xC7u^nKS0M@fE0jMP`G+N zxGA#nVC(bi&K(v#uYWNVRi96V4sq;+TpD|{Y3I@hNAfEr`u}=5xJZceEd?JO!@!`i z8{`HHzo4$%??2?et%y}_uF(xZ1hn!JqyUt=J)BKX{tpN}eJ{63PN40q!14U0 zeL;}kpvG>{xRjKWSJdpHrH+#qW(wS@{vgXCB(_=<)Zhl00BSzRdWM=OoVb2n{(k*= z-#D?kx?wuAjG(;(P~(>|(oa@=Rlr@l&;DBPm6#GG6n=j`FauO2GcaiE1udwv@RNH! zHHon}zJ2@u^^D!G>K1KFnF1Qg0x1CXc|DxNo4JZVxLVCKe*IO;#<=-f@H{W;r2Ys)d6}{U)shNR6V;?B-26~>k{>5JT!8G}HUHP4Q+^@2W zRvUoUhk+D88s4Y!)OVTN3vzUQ32UgBDO389`vRy^XJF9S4{3OtbJk3fS1juARJrra zpI?mg-l7N4Htl{;CiZZS7GHZZld)SsyFqdCxA=d1*gd_VMezYh!&|&7S}{MwW}k8? zr?Rj5_Q@~5FhH~30Z?nO%(Htb+v>&hC1N5zF~7aV6H+W8^&eX69k>L}IA4t?+R@y6AxYqylU-Jt;mzCF^y?~!!=WVZfek7Pv7M(tX}vLZx98Je>Wfkys4oZSM- z55%=~x!x-C)c=u^9`o;h0JN+=v>Kdo8WX(4FlZbC zEf5IwJl}C`Up0%^?h?;4?i+>XsIgA%04AT+pid z7-$O7!}(9<`R#iH5|p)lF7ADBF>*$Nz9}eAGB9WymjVZr(82W6ljH^3qUsN|{|ob7 z_wQR5bl~ndsQIky89tG5f{Vk^sY?4amUh$}P@4Oh5wxrUWCCOd=>IIeIR|&oa8WxW zB-Hb8K4WKr5Y!DPKy{ae-}421bHzRhm+q^0Ff;xB$>o+u7@&hBCqNmi7{;XwEtf8WWOo>SSH;;Ov=0H9N|tcoYR~vj5=44q9>qG68f~k+o;s_F0Ro z1Usbo!vcS}XaCSY8|ecbhCK~A+pWj!?xSt~#Wxb>UQCwIlH)AX`wK0C&Vr^8E&Tp& zyryzzfoG@X|EPrJ>8s7)zg2&3X8K3wH|05;`W5L ztIvYQjNLqMv4noHG%}L9%%yEm5}(Vt^*|)3A_18I8Tw;*P_ft`QP=lmXV1L}g{jr< zFO5OHBL)VI^N^vxf0A#fTL15~jdO0{y!S(0g?TPJv~7PLWRiz7yHHJfKdY0|s;>K= z#BU3%>3Zh?np6Op04fG0o&NN1FR`9mF@tUPUB`tBmbTnZVS~;kod-=aD0?=EnzB7z z8ZEv-&DzOuk^Ix7LmNTS3^D<7Z`5fvi)r^PDz+#tQ=1TYZs7+8vu)5G>qStz+QLuE zb@$F0dZyZu2f38KU5ewlC%+jqIKsf7aS;?39?t7#{Ab$s@MZrzr%lbTADeN%pR)*B zfLsK%?X5lI@AMS@nq1Sr-|O&F|N8!|9GUE(z6}F|#w9jzih8hX=JVGX;{Emp=5s_e zr+oS1a24u?%b=a07Jj}Rw;pXOF}Thi86Lb~SLG3%%|A0BmHTB-TzEJadAOH8kK|9B zI;r5|MZY`wM`gc)N;d`ujmw}|m2x@}G0VmG_JfzTud=wl+Os^`-tPgLTmdNn4I;XG z9^swUf3fE6)g@_}LZ|hZ(=O}p0ySsHKU0Vx32X{B;w-Z*#d1@xd>^J$AUC!VMEorZUT4Wy1Uec0vb*vhHW=6?W zl@@kCUUWhilph!vG_FBr%w^w76gMPI*{mLyTIstq_O5E7FKF@=qyREwezP-rr@(u; zv#vG|6Blzm=bLq~4iv-;3>w!VGv;jaA=!OfCT7TfD7QU*DMDrYrxfU7`0JqQTo31a zA8V|vq*=YYZv5YAF)=!WAw(9scvVrOwi;nVk@R$piDT#))>&NK^IXqWcJEO2bD@twZ$&5{`x?r=}P?{(+e zs%nFF=z!JD&){Z~uy}K{a`?Bo(!9k_9YcJ6G^aekzwE%NZr7f?C?DS)i6KJ_!P z#@cO)4*zS>t`C0sjMHPEf))%hFlgM72fN`wr&YdUUSM{#?0yTbKXyry_eDS>dLRX$ zWey(B8>gM~vsxt3%*^)4bO~d%@fJQw=&1W0(0GisXUi9sO?H_n$*&hZGSl$LmN061 z4st!ngj?Wn2$KEa+PQkVyqQAsjUCSN=`696p~KPlK>aNXKf}#mEmRFx9K3d2UTNjl z{9~UO4@1j`d!SKP59hmV*XI}hpRMTmZmYtg71Bu;EI>Oy85kHe?t!N7q?{xd1^w1< z?5egpWas=-#4J@Vx)+odK?*>VPC=fp%4+}5(#vJIxXjqoT&T+WpNbKviN?U7aUU}3 z{#7k4Yt4x}f0y4r>tnm9@{ro|H0bc-1JJmXh2Q>(iC^Y3@&>>6aec9FlZnXWAD=*7 zSq27;2cRm+!+D|a_Jelvi=Qp%Wp!&;`1+Q^L=kfGlEwp21`6`zU3BR*ljBVGL%cgL z7Qb zFHrtKMMu>%aMRcHjAzjK?nj`GsfV+>I^(*q!@HXP$lqoDEBob1+UG9l1n6T>yG6o3?BPeG&ZZk{a?-i6y) z@_uq&aQnnj6m>WwQVBZ32|7xjG1BjDO3KLx4Js*$^;_gb!w!Y6WA6v)WMI&E1{zJW z@Kf1iwdBpIHGeN}ZCSl(PNj2R)^$(_GB9X72W21+=X=2qexAG|e4}UC&9}CK@%#I4 zi-M-}K?*=4T2fBSkL+xiw$?Duu3RUIJ?ctn=Ji>i?ledNsAX#H`QTLi$v5?}7L0l; ze(}%h*ZcQD1g799I3%U!ANX)1Y(Lkkj?iYMvn+~lDrQ2*#6_CcBn0IC+PJ*#_Vywpw>ok0t~^-n!qZWGnjo_9P@Ga~N3>t4i9nvz- zDLRXVlBTSzs#wEcezjxCCB;0qlaM6$4zkytYr%KJ#2l60<5?dKc)iqIn>u`;J@@yZ zw!MX4_SE*NFLzi!kUKT4;PgcGZwrr>K=bB%Pz&9|`ML76=75#AS9vLipSS+oQ91fd`H&pYTx3Fn{r}N@u z{u|jH7g|BfI~W)=K7#5E3%{gu%VdOCPjtJ*nljD#_H)&AJqc(F6NCBvsB;}-g_G@%Cr>oSG^JY8k ztS8wF{PUWzPA*)&%VYeTUovCX^ocjPXjw-%s3G?I+ud9B+Q;2em{Q z7&Lx>+H@9vx-Abjtaq<&|x)XDI6F)&Kwcnu4 zWKvFXpIbv~`>ijP^tPtUf4*T*T4MxSaLmA<@f$Sxrtew0_u=wG&D-BQpNUEPTiiZr z?js{m4-KRMG8|oNpTG2i*yKGQ_9y#w%iom_UQ-X6g<@dP_zM}1uFk2ID4SXN^n&?f zP2GYc%`pW`PyhMl=6cH8_RjfkkK;!kzg)M>oe5fq{RcG{E&OEH z{B>FK&f|>n=NE3%xCPIBxN8q>VEhLahaS#OCzkH`c|$F#LinxAV)04u76&$g#$Om1 zH2#B{tg)W1du0PM(z&*6m61H26mECt<`jL1FEkk-m)}i3E4t_L(~J5Oed4=q3g4D2 zIU)ubx7TC@}64_NY*a|^S)((TaMsk&Spkld}w2ugAu&PKM*9B&qe^FHMA zue#r?#ut1%8PZhKWPHrPz!2yK5(rU7TdhQ<1h9A4G z&XZrzDzNqZE{92>E8qNSg{+R&WCJZ>mU22TzI8|YWwsS^i6wij`)0BoemWntYJq`4 zlMU2cboc!I)HQ}(?S;@ZZM6;3dd>IeE{lc~#hPrBz>ZAZTrRErU-!-1;GocFVkfHi zEsKYYx@)q7_M=$%33ypnz0sX+$ncLl%`u4~e2r2hsL9U2pveJh%Xv7z=}$eV%)vDM zL()7&>pkb}-@dK_tr!3)05zLkJuhAKeR}ms1T&{q?c^^^mErI8Ye6#~AO#!1ZqVw# zU0%a0w2Wo%Y9H(W{t}D)vmoP9np~jNZQ(a{Lhrv{-Y)7JPX=9^GkGFUqJ9VD6bnr* zP|EUf?vS~_w3^%Z6bpQ0~MeQ44Pb^tv^yu?rfQ|VJ`E7IGSu%JfGg@ zxAI*aq{phs1!|Egdp`JToIm}mckGR`A?|S-pYSacg7ywHxgcE_&L@huzocl3_M0>} z`n+2r^**r{vOq$U2NWI_ejk>%f7V6#l?Y;k|Jp*sG0#Rk6@_f{#eftv@KJb%CeRd-N$ z$Ht9~mz^_JnZFr_x5dwtgA_rUe4t~QE&Ohavi*L{*;C1K-mCi7st2_iDa#=>jwT;y zWsQgPstenmM08tjHezp|g)dM>#4b|0J4v&+-(y8B2&7IA3`fQEc5{O;bB5|Z7?!{q*Jd%TS2 z;$9~4-Jptufk9IM)UEVzKIOl6SB@x~qHK8+W`t<1_n(rPfburTPOxaO^}039coI0CZ(mEUX*^H{PNWE z#1LBsJ344TrQ?scGNZh*H72b%R{K^e%xue3t`vE6;Ci2{E!jyA77B6I!kD`+7m z3+cinP3noA;WYQ`<=*&tpOk7!e%%*@);O}D_O+DLW93YxR?c|V{g-~cHQZnH`1_lE zpwf+jK~oOYdk*$wzqm6b;cSAuWN-m;{K{Gp75?tXpLfEy z-qM^PCBU@^vOH2#9<)!*!q4T^;(6R0`^vH}y6n_**)*l&?PJiiB?E(|Jg9u|a8~cW zwY4a?EZS;I#PXY(QTz3s{zGF^0hINmoPJzd@Tqp6<`emea_7$GD`y_ltA;fGH5EYV z!P-;AW37VB*+hxEU6t>x|4bA3w|W<39!FCFvS-jlM=dm}Y7X-%*1o#z zR}2iAim$)}Ry;|0Cr(!efaU32GV6twPE0+kOQ&K<>^7d-a8Z(eJ+`qT1R zDT_N-%Rn=Z5-2@LIF%paSbc->X|up(hYLIY+GQ+wDhV1rVPMcy0(EJFJVPh0IrQ(d zOlC?;kf-Xwt##j(WsY|YVo+tqz@VuDX$^jV z&a&KlTjn8~{X&!Pgqis47dkf;k|tFktwB!5v;VR$M{l>bkDa`>vBYf0deFhv3?LIg ztwDWH(I&(5(@bVJuK#ya`0>?t^ElfKP^JYbxC4&Oy_K_zk`m{=ePMS#YRS}_+?8Gz zpmnzzsPS*%*ZKae>8Z0e*_(E`>rW&X#6XeOZ&tB}& z^0hoKz8Kvp_Jb&7l0{Qp5$s6unk|g;r*A$~>$_FKb&bUdhgaZxvltjOHLAd| zX|U&@1B0e6XoH57)8nTi*S@&@=I@>E?2){s zJs?oJ3tBbnf{tbi_UzqzDfR7>sa*L{?f&_bRYeTacp<|Jn!1o3UhdP)_dSl*HSm9Q z@fF*poVtmdLZEGX@CGIeKW^Eemy`Fh)x|$M_4=pr6aTB9K0u>eA2k2(;mmI$;HKlz zQEmQPc8cEog=Lw?p-WXY^+DyOl#}~8^S0?z+d?mz{*=Es?Z}4d#`{2La4;}v>Vpo7 z2=tV(GZXP$?Ay@wGJ1ZU)5FvpWgAdm7o-5v8oafS+qQhO!v^7ldlIh1XB;!hEP=M= z3_*$4!f%PF3M0GyiJuccPWisZwCNtJcOkTdF$9&D9?p}$Z)JPt^Ze~(1J;x0_GIz7 z&XWK+j)6hb5L8a+d%7EWwjB(*{ZM_*`=GDci3?PAM1v+@K?=@+WAob-?b43j7TG=m z6X&jdtR1)K@dr==%D|v$3>u%a@Kf%Z9B!G*_X2eHfTj!?7&J}H!Hx{_nA-JYjnky-e7m{l)UUai zViF12j;9Hpt+nu5c+q>^+9Rdgj5T&<@3)hBrxWlJGX$Gosq?|frcbWftvwcH|!v3$1_zUJy|m%6L?_#BD=Ob6f+n28JL_iC3D^QIS z>{))tG$xBp{;AKz$!Hx z$Z8h->23OFYbR-4-*I|{$*cdjeZnU~+fg=<)hwTQH?|8T$4z!*?kRe5t>E^4O)F3| zGcah{fLb8Io<|pkxjrnt;v}2@!%B1g{l2G&@y%6=6%d@{(jJs)(*7x-^2N%$GLaL zOZA#(^Zr|GY5id-`;`n(_X%VIsA`gOG78kIUi()2)UV){7e0Rv2=0|t1g#GPDFC%V zf;?3%R>pNIBrde!t>&`a(y;Kl|0&3pKuvo$up>2-FIuf>Yfk*Px97ie{w-#&Z`@FC zI)HMwh2NyyFgcfP{~W%o+c)p4!k!sArW()$;{clI@Nk|MdTr~G)b;iM6rCkxOwH50 zn4Ul@6h}}ABjvO)?U2%zpiRANUrbt)5;RAt(C8R6MLB}Dv+H}>eVr0@bP=&?% zr*>6)h4)Bxt#`AFUK9(OG6X3Ajjnk(>-gK-U;I16-Z`er`9hmY`@gBbK{^>2G@U^m zb8F8axf%Pd{=MA)v0)x}X1f(vN^d`Ct{tSH1{_elOV2tiK0nU#B3xTEIw7S{Qo zkqZU}O&3sy)WT2k-13E|Cr!O_VZk4doj3RGzuc4pO;N6(WiKAiKQvon{!M&e{dJ4c z;{R()+iz{?gv`=vx`JX=%1QS4wo5l0a%MlV>10`M+ru$YXdcuGS5W&}-*eu(gAGO> zS`O!|)MDP2H=}LMBv?bs6>=cqQ|Z0;d!sb}{jS^Wc!a(eb%>*iZt^Ls&8G(IiTye2u{E(KZ)dV&@)m3fNI zKCb`foXsH@4j33Ty&!`FCwFbRXcPbSmO!O2Ye2g6hgl7WK~*vX zgQhnq@mlzOSoNrJjrQ9Z+o$U^bk!VtJVIQc?P~8e;9k;y$HqrZR-3BKdGAZ@ex)>HNrOc1HudgZW)W00N2sl-UZm8H6%{J_AV=>u6M&JgtJtN*$zR-^SX z-zAKfn$`T64=t;GLFJ`|pGHUEQQOW(%ToWx#=U-UZvHV%b%5nmICn2J(lma<4(&$yg68#tJe6WubSLb`J-gM|M>CSf)GK|`Pxe(OB8>gbuQ)mxmhDYa&)*pGJME|B9G z7&QGsR(Uv!UEpI9F$&zrR8qb8>qHLY$=h6@qe%gvmWY&-{cVMVZ^Uc1+`O+gfBSOj zW_FqRP%8pJ4R32tjjuKf&xShfh`Z-=`o%K4ZyoyELFFR@gJwVhIO}n7MOtqx+59T} zcV9tUm-U{`&Ce?!DJl>&cxK^er*(t#;<4${zmJ&&PsyxPUoa~hvVcl62(%#G!@2CL zgRuN%yapG1b6PYJGlS_d5i2?DJrm2z67|JQZJ-*2r+C#z>o^|oLN$(Ro9>ji;!A=-l7egUVx@= z85lG}K;yI)eqG;smTlRn?9(B~C+DnrViB#)_q!Vxlc~CBJqsP))!4M?BYGlHuf5$efyH2xt}}*0U#puk!oZ zR81=!ajYz`N5K7&JrKz#*xWt$v`;>fe>JhtYG_&b zi62rHERcC&QfebM>*qgRhGTn=Lo-eoXrY9Mvw>F$2j6DdXF;r=GtVu#KXdK&2vEO* zfk872v|y&pbEbcL|B`*ZvbF^;a=veCxp5+FH>e_EV9*Q?1-qg2v_;%Q`B}egYMc`l z_blL#lidq#KSY2kRtvwj<EkDt9TTiy4iNbwhrw$Oz90o7=xyc*z28XkiREyPwkx{o89^bS~W+3a<_$_ z^X?taQV(_Jr(Eyo2)*i`*m-UObjT|jl(IaW5AXbzQlGK&__fAq(7YK98WXbiTylj^WbxXAKNlR!KK_YQ zt}FW_BeV#LJ_&Z@(R;f4O;m3wCitKKw3n?o<&XAu(8-ky44Sc^GTXxM-z_g^FWw#p z@s%p7W{mG-r%wJ09bSk9LjV^{tI+vpIIYbkmZ&1)#c$fk87)0_=u_*@qX^srxy&h5p^RN%L6S?YL*qk=}UF zF>)4ufes6cn`JkwUZrfn_>yz2Wn@A-j$o#frfH1>m=eqZEK)3e|E3N~n#pa6D*fV05&nOy!N>k=SJ*HT`WL@{?Duf-KU|Oaj##`kq=L z>^rYWGTyuw?kksS#v**m;k<*Ho2;dG6(zO&QFq^ddC_6e*eC;o zW-_FtRZ6$hJIG*gdS9EksMzM}-!EQ1fVPU0Atmjl6$|%1eZ6psu4`3j%%=l)n7!6O zj>*zYkp??bro#W%#z{55*X4;aG2XR~nP>9>l++j)G*dt&ZLp^p>l0hw%A+qbOK&gP z=lp--k=n(Og(8|M9pI3(xu40EEEg28uDQM${!s)5W&%Q!KGVMCp4eEBEqCC&&X+@uS$gTVTW%Da%H^}NH z%?!{yr-k43Blki~f9t(FW5amuL6qUXd7A`5tziZR%?!{~iHEaC#zfzu0B_${Uu%+o zmvhh4Ke`As%mh*ZnmSYVR4x-xy&dCxHQjdRTzj`){}waCy44wwt#Fdb)ju}-v&;%u zA}lc7pmqPgX{DffECvS6EKtI+@aubW^KY1G^~C?SKlrs4h@X0}d?vJQp9LC+@Nkw5 z-}&8~XuJAh08wI6~!51!xg{m02gla&52-P_-K{8cv;L#XN$Ud*7Ta%!L1!OwK;23UzwAaCeRs!eD&N~D7+HV3`_QLw z4rHl`W)7&n@NizMb#?OgCAWRqYft`kapBZjo7o3V)j6Q1yQI_lxrVZnS`NEUd7a#J zegea(jhS4~A}9ycesK4cdD*URq87PeYx|pxMwf!tMmbA@;(&ocGZ)fpo{YitY`0%aHm2F*NB;;cWlbse8J}{v|XJC>SuU3 zuP|76!&U8%frETom`iEvI;m_k(7Fc(2F-j>uUXl%1g)IZn}6~q+@ zjf;F^a6ny^k}ur$^r)NS{E8dpk0SR>n%xdsCC|X1Spf2lh2Q(53!}eSYMkG?(_m8K z6tM-%jy;APlciYz3NR1n*)z3kQXcJyYbcwwqWJEVufh3xpnfI;gJvOUlZdsa@X;4m z%7=YpMdH6qdgN4Z|8jz#HY8OSx`W-YJXXyod)-u%fEn|5@vOhfpV+ewIz3SYYDZZ3 zd2Kkb)Kt!P=M{l3!n#c_YW80R@0ny^&@2LFVh?ARzl#+<=5*_QoN<7G#q;OkGYc<5 zXGn`dd*!5@w0HaDm8da(7M^Q3!J%NT_~t{eKs|N_2F+s7vROCJf7%PaI-g}{owPJo z^v11-;|ci*pqWvSf(Ec7_suHZ?|#QAWVM83d=Nv#qI(ObK^AdomVkDXSorNpRdcrC zR(q9~q_pPj=lo-PujfL?NJ~LS@pw2p%+PIFx&Qs;C2!jHf13H{!E~lX$TD)xQjkI^ zr>CMli81pERQO8Qb8kGg|7agGJ7lwrW+`X|W|`;jn4?Bov-jCVsdy~7Z&dh;aho}0 z#hqp;QAcTQIvm6ww7Jl*KUP|@f{&oAOWXxS{ zc-f})W)-xLQw|y<^>AMJ)_3*&*;o2nH+URLd0r@;92g9$NI)ilRv1}(?wXLi_urSp zYo*C*-e8GqX63au6^LHqut zoK{b~a3<~7J}W)Gn*ttvMLnPUkAPY~3=Eo;pseTSdD|dwLFIwJS4%Il7oo$v`s z0!@uDFlbgmmKNmBnj_;UeuC#$a`vOT*8I$quQox)2CG5Y-@@;!;1|sn@g;1>$^#dz zI55$&>AW4(k=2l;1y+_n)|j7my*G8~qTeTOsD74QeixeLYCug^DJReQ?~6}*wa-5L zsd@YVmra`HkHet7<{Hq_0&7pz2uo8A-VMtxmzCb<@|UUF{B$mKl(hzOFO28fOCKlJ zTgrIWRUX;r)8cz{>s4sqzZSH7*uw8D%g&33KZM#}&0eU&Yjarr(yUZyF<1+Vb`R&? z#f1ji+dn^d?AYyB!))BA&0+{ylBZb*8g-U(x|rQAd~N>yl8ai;R9f%E{JwW|8EEE% zfkCqlR89tYezW90ea1Ot+W+f$_dj1ex?Awl3{Ybiq+lgDUwqQ{&b)c)U(clan=z?} z7F(Ajxr53k1_sRrP~x@lt6DRo(oSb~(dD8)&!eg(Y6{l;1g-7@DF9_X4`-JZr;PPQ zB4^%Prgi(Lb9=+Y<;|crJxBqlAdzxf8udn?cpaxr3>*K;{_W0Uhu_(PnyMfLpmgEp zdHM15k~{Kz+pdWS{eB^)Q8l0U4zxmPfNby#2}s(1@$X8TOLp5^H?Y^O^UX+wPIxte z7Lr-`UEj@k%iHX{^hT!Nno}OQ)fPRU3Tm=5FlaV`vYv-?vh%LFQBIGZMlj!FOyzwi z^7u$YH%rg+CP!5)s)apt`K~8+vV#Me?Kc@&}2NwgnQtC%30&{#8J4iAV>Tm zZ~lM55_{3x(AHoJsIOz;SG8i|l%tDxx~}{0&na+ga-H>ZL(q^P1A}G@XavKs)&phU9xpr%?zF>n61-C#} zN5AiQJ5MGqzRl6!oQJjAdF9fh?9ic}Hc<6w;kWPMSLg0C&4Ju3uEO`bm;7;)5(hO4 z7#K9$K+8NloQafT9wY48SJyY{M+kh zkz135#Er}EAoWEDBrax$Z!+W#IU_yk_`SYk-FqF&JEwq}1q=+D9iX_7a+-Wr@wUf- zN{fliwXNF@2Q2=zqy)693Z&pF_!xhoFPHBdzkJXwkiKvG{e(>s*kt3SjkbSI;pEv!|j~7mM+r8Uoio~vOYmZcd=8zZ|GH{=q}Rkac33y`A82xTB~W`{VShUne^`+n$^cgvy!-O$&qkde_9wmjyJI90P;q zL{R@i%86TND~Ga*o9-pmBij}||7rBD#sWGMG!Zm?Y3=F3X&TI^QvZiz`x$ffWUDKB z{tD1;)I`WS(&^Jg)=O!<{atRD&+B|farN(%6lmTAor}U?;kWl<#_>5`k^8UwzA5AI zOC?Nk;u>gSJ{hu(^mfD6&8MDzsI<@%oT1qJ$!^yPJp^_3=Eo6G{7Nw zPkv|I#DAK*BdVJh|FRP5S2P zlwFSQ^3Bk2mk+zH>(D5knsFH=>)6+!(uR>$~+_ajo zYs^QUFp|=4sh+x9nR)z#*>rGb=Nue3~P2Js4V{%z!Lr`+c;8 zZNuA77SjX2v0OM(wk@@<4LW)-3$mCk>MkSGaTo5V%6nq0givE;TYK(^ULS4hwM658ndRDgvA^exR;>5B z7cBfXh`haL+VO0Sk*~qR&oM|H$d!o6^#QOMd zP(PD_K@)tfft1s?>y|sKPUyXfSiExcn*HLv3E$^I)8sr*k?ig%8MR^GjRjx#teC{{ zPU}s9d^O`EXel=zGSRc6AnUKVMdJ;7+qS+>>uz(}7M%g@S7cz&TmTxMv+&b2ng6!7 z>BEAl^2~exPSG`*^oJE%J}dzB7CoF(1u7o!J`do1wfPh0Q%0dBZ|CGeLvkT#U|Y&* z?JXhYe^Z&AtY&etepnS#@V-+TIuyJRGSPEJPDMiF+?<@&9qX#NGy?<=JAemh7#K7c zLMD2oKczhG;xBa%*6-N-zwMq={6}6;wr60_Tm))(TKGM66nN3aKXJ``-l$-U-?mH_ zD!4$+Wsm|;zth9{-rR~is}r+Rrt4%dOz{4d<56@T+6r0>O0-f=v0Y0F+tSsP%(u)j ze^9(8Xflr;bo^m4sHBPa?C}bEF0=Hh@m0QrotIYGv~4`R3));0LeWqPKtG2qG+0=ZjF8xJSrajb= zOK*VP@V})d>$j}3@wTq5a~528`MgSe1$16-IjD1N;aADMPI$ea+=Q#z{Q-B@eUISx z%?N~KoaLZ7RuAWG&JDZdp3M4``FY}Iiz|~Z=zZY?Kae679zlE-~R#sS^Jt7{#mKz8(Kt^{oku<$#> z>-_PX?5Vem9ZR+>(^LMO6;chY^;Uw;xA$-sjSUFy%bc&Wzc7RG9IxDuKQop=r;1jB zHpB;cx?h^;+k5h=fPBpHkjHi_b1pqQ4_XAzz@WKG4;&7g*g|6-zllAkvhye(Q&eF@ zrEmtc!MPfw(890u%xd4|U$n1>3Z2V#Y>}(K_TVM77+ejq%EOuaDRa@94j%R&vnTwV z`t;%5=gw}RY|p@;xdyZ>PRi-FaLq)CzA6TlRqI0beZ0K>MMobfxq}pdtP1j!=Q)-j z=HSL3C+lhWxZ$?EL8m>mj{`bcg)!2vM*X(cx=SW6GGtc1to4@pspz>8G?&J}pt%;b zUe3brrH}f9RdRE6g_7L#Qx(7Jnf9AO4zSf+2ReP)!+DRErc=m+uX_4hSL&I1JTcA_ ziHGKkb)crJwda;Kr{@ds-95DYz=5NEmPzsP^X@|%TI<@u0p)$BdqzkzU)zboXUumN zuG((5{Q=junKWZj+JFZKy4ZRisTHFaz0P2{# zd8U646N+T3nQT5MMElVrJJ;#*0wB9V3J!oBSuN?Bo-$+lGQKzLN@1#EbD!o(gBF-F zFlcT9mADpux4M6u&Q;%8RraVOuP^~7 zFyV1yx(P}4n?T_qtrPy89(nxU(hQnq7up*+{3vchj%K|{}TT*+Vh>OS&vEGs+a;A>H;YM zjn7FrrK>$s-Y3m%`8zzQNv76o@xtx%L7UGR7&Nzn`knfo9f?P3<0SmKPf%>CuxlMnRD^YnqT90P;qHc;E$!tbPiNXrSy@-Hf( z|773t>Mm^efgZ)9xeZiSc{q1opB2Q;aPiEGW!Db0TfMY>B>x9GJGmWHu}C^)syeu- ztuT7Qx3KS<;EY+Ce}5)IPM6i(uEM~;pzry*NOOAJ=ihy2A3yMkdf6krXk!_)nY29^ z?8w(EpUFy@uF^i*W6{^BVEp0giX3Radk3g9WZ^gY`1dPDljaw1I-|eW=wazG!#kTn z<8cfOnma&?em$Hg2MV`2S1jATkulSu(5+LbOUnk@0@(?wKlMH5?{#|e`IM4Cz4-># zV_%i3zAtzNQxFYy!|H8E&o;X@66Q(M58v74qyo+A9`*Ed;fn7#K8ngHCUV z^~}sH40B#))4=}!nRWRm&xH|e>p(>hNC9LGr^9l$jV&5eoqbkK_D__%EW?+`18T!D zFlg=pwF)i#tW%N>v_8GJW~K72)SVSKT*b1SKmo+Spt)BGJQ*#QBFp^3(lqqx@xv3+ zpB{MeE~I83B-!r;t&@^+lD;W%K>Kj-Y2^L9c0KNS&=oa%L8mWUdoD1(x!QN` z(~KY0ZpmpM)-<&0ia<-bz5BrdW!f9+7};j9#}w4ah}i%0G~)(nwYVQtK3Mp@n0_Wv zwpu1gJaF}%6uoFU#e81Kp#+-yLB)WFv-Z|(-_v=*}k1{h(P0 zYft8){*7nm$`$QPkbihlV*bXA%Qr#&D+UJ5{g=UR@YB=2_Id8v-@g@JE!w;FDN8*wZCUG0EBDFd z*6A-ZNw^GcsvQJ{sFc(DE3W@?9=<*jy~ZK@<0US+{o2*g&fr1NEQFh9nC7*a=07jU zD}{MIFu5u8Wm&x&=)5Eb2F*i|*5JzPtNyAvA8gUv)9bg`$9bB>-4&qy%nS^ghas)O z>UmKT>f0hB!`JS8ST^asp^*)rE+n!JLt2AD3bH)gBv>ocpNq~()wen@eZCf`bOV_H z>Q-8N#@^@Y zzb43N1_sTekQuSFJhRO8Cq27$zEAhukNMl~PfD->m5(3=pxWQVIrvn|p+l~l`QwUb zE#z}4ba>)u23o}eQt*=jbUEg0hZYq#yItLi7dKyLV>v1KDfIxTDq>*JJZ1-utcF(? z%Phi;Ua1QdpL;UXY>U*2F6i*WaZroQ!mqZ?{je@`Twy%_Tk{y+cIn)?#?UV9aZtO` z!`b`YovAbLS*LJUXqf*y`EAaTNqL}k4-5>NCqTual#|1}<5t2 z-wn_N4@d#173AjmB6a3!yF)2Kg*SfqKP_u=SK8MMEkI5{wl=(PxGN&cp87jl+9{WH zcjBQl@(!R8UIqrulc1W%!q5N5=AM<-YhFG(a%I9#@z($4W~)Ji$P5gcr$Ezp9?lIx zAFSA4u^XNE-?%qXF8E^+^I7N!#wk#;*Z0i+qN}~j=lEs=;l{h)OO=28x>^s7%~SQ@ zfQoLCiG6tHH0$3JwJxdpKfgUV_|XxP9!`TggP>C^v?iZzws>%M)Bea>wPQ{DTN$Cb z`wXbw@Nixiboz8u64Saj-P>Ea8-<_9^t^%gdC!2BT1YvS>CBVQWb)q>7E@WbAbi#wXbORC57zsT|7a+UH!n(y?3FB_B>>`sg|dd>r_{Z^sxv5sab7j?_SBc z59)X@Flb(Y3^yH_P-`i|v}l^ocFxjG*77$q8@4Zi1oZ{bSdfSFUtWRNMa8#sWP&bR zrZ{_rf1S_|U8Hdl)H;@OTJgygF~`oY12-%>Eg1CwKf{3zx=XTvE3fD+K+)j^Ae~X zVc{2cAtg9CcVkM%lUGOf3$IdKb;bzP*JWVPybNg#KAmy!yu+blJ=rdR}uj;yy%R{MItUZ6#`WmoxjtvkYkAD|<>S3ze{Son2b-eGdMtN!Ee z!@=t>it2d0o_z(nIN>U&g7t8IxajiA!!>;J>l@NS|L^tx`|ge~Xe^9@LGvo;B4ant ze=lDhy0NNzhwm*TyU^zBj4+e?=OA%$6>=u(iV2%b>USuIZqwM#yYKzI@|bQm(AEwH z2F>fB28M-S+p&eq&8-gK&AB2ufibOZ>*KdR(Cs$YK^+heXN~ywXI%3Z3a{G`c04Qi z?Q>bqQqZg<$OKS#%Gz^YL96%c*n?h=Uw%)N+I27V>+U>Ir4CYX9~=($X@}U-B3?6A z=!^Sa(+t`FFli;Io?u|mya~GY#KP~+#qgW^WiB|M^0|C!?)StQSHAZ_v))b6Iw=ol zivzXuwta0qt!HMn;)aRy#+`qTgX(OM2|E}V7$lwEIBshBa%D(ysS`ww(akNtg!Ig6c^8Ae^_Dh+c&Pp6)S(9RF?LDRw#Et?Q0L` zg*6MUc8GWUShC&fBHxqEmrt$f0kuRK7&PyJPTY}law^#UKem`R<w?8GX{a2w?z2@w#&`GxkpbFN*S)=jIgewy6LetB> z8kB$8?Itz%4rmn%1B2!RP}g3{X|`+UmY4b-e-5}Mgf`y|RDI<15;_L*02CLoo)4N< za(q6P+p+W3&z*f$i=#bYV$WZXv zml}sGg7UYE#-F`?;joyN@y`-yqJ0Dz3U<5ICu6RYvtU1qS>_`3Kk>1SaiF#=1B2!x zP@yj66!l5;#nFp?YH!Ui&tGh1_EjrIAKHC*1R4s~_q=xRWz!Ca6$0(&|4SqkruyG; z-3d)mkDh>|d!^$0b>D7ZVf-7t;_Bsp-;)>VZiZ(6C!p+a;pcKyS!gcf0ZEtl=g)dy zTfXuziwQKkpMZwGJe;@6E$3Zh>elb;X&LuujdPt;+D_=Az9*oW!7|Uf+|6~&50`G* zTk?HU`&`>uN+vf!4NV3H&8Lugf5rQpe;Ut*JgzW$eoiZKo7;`{lc3QP1_sS%ka>ST z_k*v~_7{rE95;^LVya+#Hah^ci4LRyGVky3@U())S-!cQIjWcRn@=CDe=Y=VfjkE_ z6QrE>{T4Z7o65zO{jHhZaeI;Q!lFwcqZt@9pQ|x2Ft~YsR^MyH`INKmc#QFmr=I_` z?@ZPK)m0z`kb^RA3H7&SOm6ExWj@6w#`(e~rJ{ULBrz~(zJMH*acbtAXHC9e`#V1b zrkrFm40$cw4b9yzKq2bkY|D69_;6Fi!tGr(QeJ6#JOUBDpe8#5gXT-nkdKtp(}f1{ z$v?COzkEwxTeZgLco_Q=(9|hN0jPy;?YY`vjl*s6%`0DC&X?6Xf8nj{`ZQ?HdI>ps zY43uykDN1A^=A|nCQrzCHS3@HEKuu*fkE>XXl~8I??&XjQ|D@}zfIh+!Fa0JJMYFO z*gEsqpmh))&XQl}oAMh3wkN(Sp6PHxx6NSZ6;PgJV9o; zGKnM6E%SCjQ`Bq7-bv4eC${##5$q^(D`K42T)LR&=|oW5g@HlyEoAScewbaichkB{ zu72#*8BCn!uOjRrhZ1PM1vS|`oVU!K%Bb+YIQOT|*$-1#N_q>|M}ZoeAQM2*F6Fc* zO?=U-eU(SUcluOn9*QqA2Y272J!M$l$Wg2t>^dl(odN?nY2|aUDHzBJ*{dI(0&Mwv06&X-(egth` zl5|=V+H`XkD>J|UQgiP7y~1}`dv-tPdR%a-6?+fu z(td)>!rY&oVJEK5&@b(5eyx?EF4DEr+F3lBDM7#V_%M zjtzbXMYn}tT-l3;>*Wrdbv&CZuDz9-U{x~#6iEyWn%_aaMi1v&$Hz+zw8uGts%}K{;7&ce^a{<-YN^)0-{Z&!P!tyJ5)$?O#<1Q{4K|A4~7!+GMDBf9+yxr&*ybg#zw z@yqf~4gjs~1}Ok_Y27?S6JKcma&HhiTKyq6f~#kZiJ=T=u?|SVcW`8B%X`Vcx_@YG z*`5=s8GZi^+Fz}N?sNYK>dIO8{WiMD6uQ&A?ZA#5Q{|V-I?vqP2O1P$V9@*r8u|8c zesOZ<`fIuZb}P8{>D!-dp7N!17PLA5U*2NvY16b;d~4*sd-q?vzu0PbL9jCAI&^^I zKjcOg9i`&Md2dUmU-|AW#=;i%?n4nLB-v{*fJQJZ{MPwhi@V}Gf#s6H?fC08|KH2_ zECfxqF)(N`fL4-tI2(UjyEs>)&`GB2N#`Ynr3dz2^npyeX)%BX&7_<@XYZdi^+pos zPy43pUWPJPW9y#gg7c;p18BFIo98=^J%V3kJTeuh<@!Z@&AdJL|0d9~1_lN#Mo43? zIr`N46I^eEa`gY|v2ZKZnogJkX$5I9K^l9mT~@LWz5cU)`L^w1|7(fQs&ohDy^=Pqx3NZ`6@5)Ix%opC6=fcLjuCRL9F0I-4|AGX#({t7#OrzK>-%**|Ab%n!D?@WAon{S4MoER+<>P>b~-#6H^XhrMk#z=v^PYc_h^=EX| zgi01of&>)%8*r*l{=H$E2jg1Kq{W4;a~8KxJFd|P>X|SwXmNtt4;Fr{3#$#U1?{qQ zuiGrJaqmghpWpdF9Z`@1(5e;>=b3ZaPCRk%J;=50ju_vmRYryzia@;rkOEK}rp$9j zlFib$Z!WF+$yLX`gY)G16BEQh6$t}_7MC^H4L^Pf@NJ)4+^+HdHsigM>!)_6O$AK= zGcagzgNCIo{A5=#DmZ^SFYtIu``uNkvBJgW;h-uRqyXd=59inVO0Q(11nr{)%D+F$ z%)je>eifvw*5Uz0nziTEvl)9T<;7(l_i#JL{F;0#q8?PjGB9ZIg96OL?|PwE$+gK*Yc>k6@~ivO zTc9}c4`{refk8_ERP%T^$NeZ;`K$i?hxD>(uC+HZgJVPLK(Po?0IL0^oN8aH-`G&z zU0S})HlNX3ruO)WnV`xHqyRL1=jwUwPZUE~Q(oK&t|vjqxHnBI`H&8&{j~%(gB`gh z>i8)Kj&F&7Uu{`n+Vs$VN&G@koz1|YB?NMVg@;^ucsC(_< zynEaEBk!{Q^l+SeTQa$|A!-M&185uyqyTgTOQ7f5HH)tOQm-%xWVv^Cevf(L8m&ag zJg=50m@2@2Wstzpt>~2pz`#E!c%U$b(j34jNr__jLdIJl{jl z?uky{g-w#?XFC3Jx^`LPf2};#c zPD}LNPi;FM!hckzH^MRY*S>updO+hZ3=CS5pcT2wo~ut7MaD8S1T9^=o9|$RT$qfd zFKBoLqyVyQIk=;Ki$m0_OA-As=8@8jOLdY=Ng=elT}=qUU&O9K~0bbErJg6w3+edkXQ4w z!27cCE2m9c^Ly?t@E9=zgO)U8+p=vyO!7e;J@aI0Em=^cc{smZ#O3u(X5t2AwaPsa1`(Soertj{ zfglB-f<(&cikQTnc5@+{xmoLV>(_LiP`J1fGLNGr3tG}{?a3a~&@b&Wxg*Z(mGNbz z-gUkE`5^0~v}7TtPoEIoEw=Lgg|}~(SVzd`aU7X>W+v1GdC-Wrh2Kl=V}<*tTmI!b z>$oWSi{G_7+KtyBrM*08HHU|D@`a~@GOP0*W^SGFUVc~P#tD(PAcG`Y@}SO;l#|QZ zba@WB?GA^(UsB-avcAe;`4C!=%7dCo%AN<4(tplq`+s!G;mdD7T@q|&_+SVb;nb3c zoaQk(r{oRu+m4X?^Y`7{zTBaB?q?Us6p5B1C~aE!eYo*VsYEk0VD;XjnkTEY@AACW z-2ri=B4`Z6!#T_IvD2T|C5{>IVtDSZxzcWU>M&%8LrW2KnunB=*@3AY@9X!U-#q7T zDTiBUjORl^(8wkOgO(y_xv0M9nS}}UI|ZXV=jp$0sy$u)c~M?8WJF6#@f)~&U=q1G zYqi9yZR>Bo5MVgC*p_*c8z|c|FlZ@*0?NWKpxwFdSL}~>TV5`4|Y1v?x{v ztsL-h-n;)>W5=;DX19m0)HS9u&Nto=0~uY^QU(?3Qcn79HXCL$oxlBA?QQ^bcS-;B z9nsLDSQ(U}0zL0td?54CagW}IO$*B2?=My|)?WqbC26TxfgSnWE>UDwth;fCWX>|d zr~OwYJUXEYR6!#d7JinRhi>fc>AuL_Za3rkqx8(aWo3|6pjxV+0V@yZn&k5;OEV7N zU8Z59$YwUTeCgvfP@T=dprr;{i{kFtqY(LFOI$oz$tS`^p~ zVz)2dyD|4TgXk=~n6|_>dhgofAWK!X)Ik&C7JlY+(-nHE9eaK*J56b1$@4ba&nL7pB7y>_c@RW(1vgt{K;jedK7^+{+GMPokLkw=do*Z0hS z74<;=!EDJ6mNYRt=$)`ynxI~ih2QGW($lxike_0B;^)Kvt%(|Yl$9VI5G^gxVlEHo zl@COwZ1ys#ZTB*n_xgiq_o~_Ppwf+jK}!qNF_&`Mb&X+`jBh;uWyO_WR(-uP({1eu zXpN%=mG8%NxpMW)=I!}sv(@-#Le4eN3=ji@md;zS z8}_Xi+%t8q?cJ71iaw_6?&gYkw?lerT6&=Fl!YJj$yICuMZs%A*U$3cZIFEszA*sW zrqu&Y2zxlUOg7fM#{WltVvF0J<6SN1mdkts^$HjmwDdrI9eq!!%hU7DRsL3=du>*) zYFWC1R@O{V!2wbLxuUB>Nm1YE)U~zUriMoMa$eUTZ~p~q!!a;u8Gv@}Tlnqv+|4|# zGw4-BNO7b0(XJD@HCB**mX-l%d!mPPZ#UB`mmN>v=|&gqWq!eEyO&QAGR&f7aE^h2 zA<#25nA1Jw!XtyHlfyDUWt?;VoTUTV0;XjMIiA{argD4#$%G?u96ZxM=bqcNDMtac z+K+)j%Lo+R7JiHgb^Sko_eGR_-{-b}Z_%RQG%rxc1Ec`dd-ia?@aXo2T?Z%DnsKcU zIv}Oxoi?ur+O{_WB{@l_!xw+Kbgv7Z*nh{JVdb;A4s1{FgL-HT3|hvZ!c5t7@BXw- z)`N_nHZ=C_Z*VHOqW!iT+Lkjm0Y}!8*}SzO@4twY?rG0s__yW#^@$fCi~6)oKtsY7 zey2l=+9D^#N$4-id?&i%#M3Rl?VzHEfkDdz)bRFjepltZ|4NEq15Zd=&&0pWFI4$T zf`&F27_>}5qpfA0i^6qM?U%25y?pbfj&qacFUpjefi@F@6f}d~U^PW?jeUp8Z}!&i z|G{bjfy=avpqbYUv;@n-PoZja?4nEl^E_HNbiTTOP3WkcB{V&lgBpDv&Qr5o4Z1y_ z{gplWKe>C3q8^`m7w8Bc1_mv2P|C9QJg}VS^hQ53<_?5ep|-WPS1fVP4xKvlGb-?Jz-;R|;)7`pB~Q%d;Gyl`7>F0@j! z1Z83mXC6-X&BE^v6s0dSe6(F~(y@7mu7alP7#OrHK?O;$XWWq=k_o!=yH!)B{PbEb z^7YhFBaj400pt?E9_NETe_yIUpLnQ$C8NV$yWPO9m4qe=X?D~>$e3lTlQa#eJ+{@S#qOg3kqrv=R;YWci-4({&UU^8yy+W zXD0F61u=wUj*&nt!JuBvTepm%^vWk{H$SwMwPpfYy>|YeL&b5fs`RPBg z&yV&&x6*4lNP!)xF=h3Mh;*a6ZKf4GSIvJk_oSzSVv&JC%MsN7w(wJAEtU7!eXsYU zv3pYY#?ALxzbZl|dbAut6|9G|7nk*{Z?8Yw6!QdIyZ`lFxHP%a2og|^pdoQ7rKZTl7pxi~tn=koDzt=ghGe~0hot;?(j`yN++4r)_bR6OBKwq}RkI5u z>+yviTy(YbIA6>^AHB01&s<8VS^{d^FfeGjfYO7M)5pF|lexRxmp@@(<5}P3 z^@_ioRUUL80t17V>pyTm>t^r@d4S4n4`-H!q!$;CRm$GXyK|Of_NxWT zN->}Y76XHp2WY-m%4sKeqTZs~)Wl;c7ya9Po`?CJf(5k)s9G%ZymV>NUwLQgXwDxu z-|T04EzeLK09nJSAUgvV=BP|li9r`Z(#|wEapdsls6&#X_e(aoQ$jP%n zW$vyOAxeM6gluv_+s_ynw7ftCs)zIWuK(;OSBFnnak%Bh!#9#gjYXuOeO_ZKNP?A@~jpPPyjJ7 zX!(E!@GSi9Dowv|rbn&oYOZAw$Gy^sZF;8A_M{J}YVvSan77}=mw!_C;YDtTdtQ6a z-KfU^8D-V-)dX)spZ#^yqE#&m`A@#J>UFrj?%T9Yt&n9uTE3vuU4lJZRQ}8|+OYe= z^k&xw{R{3&e2Lo#+WW!4pyfLa?8vLdS(Au* z@c7?`&3&xULd+ks4Q;<`k@?rNp-wDw+2tc&_5Bf;90{7&WMI$=1T}gs{FYZm&fyVy z^|`eAY{qom+5Z&1zCe4dfsk!z2V2AM-SnSwC;9ZbqY9t?y>7Dc0}ZBwOaP^BDW{0Y z{b@S`&%dx1&*LrVuu`9>eI2q*RVxsb9`rpgxGrOAJ0L7?dTqAHM(30~S)Y~Aax(A_ zI3ycd)P5y-D{tJCbAG4Crb}z$KR_>?*9r!$=CJTwIla#CxxyAiDu@z16G zOaHCFetKOJdO?Q~FfeF^_<$Yx-MQxE zOr<%|+(#zWT-thQ(mTb+&_XN}v@+MiZ)VY}RvR0oIR*|4bJrE6FY%agKOPd@p?AT9 z13|%MTFH}N9FP%wR43L{nwNUl1yuAfFldE=26CmGLK2@YRc>f(50d6Od8#Sk$aQ__ zRyeIN&|pctXNncqYqh_R6W?{RUH3H0IIMneK4gYeD{LOvk%!7ZtaANVwaam;`0Zs^ zxbkN{X5IpELpW%CkcD5ZnEnc}8X;Y$fF7|^5}V&`KII1O<3vCXR%%xI+IDQ#syD?u zvK_N_oZj+YULIN$M}WH5Qcku@v+u{pWaRDfzuR};#y?!kFC5x*j{uF&xq7y~dbT*< z=HT1t-c#Eq`5kLJm6``?PctxRMO*_r@}4I1MZ4-fQ?_5X&OXQZCZYRU1hgoQ0=dD$ z@5;>mj?TRd-^_c>7nS8nO#gXw5!9Pep!Go>&U*zPaqm`_S#1)leyV8q|Lm%EKWM&) z0=3YkoFarDpQ|5)5Ls|>ovqZ_Bc6xtLHU7!K`R#ISShE< zw#yDI-$WDTGei3sc?@?sKT3owxzUORt)PhYeB{{sujJ+TiY1p`+s&AB+&}keBDC2Y zTLBKq0I3SEO%CyShGn6h1>bJpj1s&BN=Xb1THtlo7Jjp5DYXj9y0X3VK9uq8;`t3T zY?gqEKL!S^c+lcs59i-C`EAQJZ`*{NUb(ccWPRSXJL1qXDjrn1#d>-&P1d~@(wJ)2 zvm-ozr%=75{5oiYiC+hH19zE5H~aRedPUx=MUPiH<<4u+2jwUR2CYO;*Ve)>-BOdu z|9HRoA^{+pDdhYbhBnwEVMdE2F*@d__4jH+hVay+3{HJ1*u&B%`fgm z>w?xaGcaf+gF0d!&Wa|@j>QdJ9s44iCzsiz9jv@Q8Duv|0cea=(rM+CDXPouOAm=m z`H+`w|5%o5rY)!g22ubT*tYh3zp-%o&ac0J&+jT%sQhNxmZ)_F)SYHv&`J>jhh*Ky zZ#@DYFIjyPzbfUo*-Fly=Lu>BGB9YRg6457{5}^M&3(Hwz5U8R&zgV*`ur;neutdi zpp^E-x7f~n zpWZGBO|)q;U^m1Hz0hX7^xFPL@GZlQQMsJk!aqWL&FP?e!@}?0oRcn-@0WjK?b+R8 zW6OH?;%P4E_(M9V3GdnELAb5@7#4~;LJ;N4se>Uc0PXr+Vt8B$L6d;VOH zVcWbbB23)nxk|X1=d72YK0gD4RtBi{bN3XJ4V@p67a6(P(!4#XnQvEQTROA@k`V@W zVDG&}T^y#sHb4A%;Ed;}@wGC|qj!teGToeYOfEHOm^E!j7C7G)p1lL%SV zr92P!0 zk#7f?_t(mToT~caOU;hNL$4?Mi+s5I(E62`Kw}3eH8U`1WrJGB7Jj;K?SmIg_{8CP z^WneJH)<6haxy^O1_lPL9MF)LhqIKz`N$6uUbk%D{m+q!_7OZbaUCcnffRtMCMl<1 zwZD!O7nt>KueOm8Q)^0L(<_8#J@B?XYtIGiZo3tPnOzny7t(5#wD^7I`vuUv1;_-* z-bs-~rg8Bh@x{^m6{~D4o{QK7E`#RHJW%$x@SD+;CB)V>-lcR?<>x^f9#7L z&Ij6RSMY%uT@+Hc4U5_hq9ZkoSsJVqtoK4GMEu4rjJhRXVDNY*gH!HfiB@ zLy*x73|eKN1tS)I3|mu;*EqhmG1|$&qL~waD{1?DXaQ0VYA$&=I|+%$);qP{=ajv_ z%GliCf$RHe&|udTVv}7Bp{`Lz=9axjqkGaB(Wg z3vOPu@A@QRiMB`3`l1rjWUW>z7vgp~`%U*oXU=iyOz&w)wa^wwC8Wvv=aIEV^Uhnh zkH@=L?N#3;`c=*mnlCCrP1az~dCPaooUkoeJ8`jzlF;6+*Z$M%pru?DC3b;8Z>|5 z;mp~@vur@k@jt5%5krhhXn7Y-|W6HL0P=6bw0925AI9ty97c2CW$7#wlk&OcBOV2lzNkOMb z8bEU?!JaHSvA2s)Oje!!X}9*CCysA8zH>v{)eU9fRK0hV^9z>#6xL@&zgE9peZM(y zjU}jI!N8!^2pXrf@VjMax$n`#y1kEj3ZI`;R?DAxLIpaa)dXt8csOfI?k?X_uRP`P z&al00g2%eE!gvS z-*kRg^HOhtO<$xQY&^@C`Pm#gNYbx!Vn%D|x2 z0_rte_rNwJkf?Bo(e? zu^JuJmE=zXbwn8$wAw(;Mhm~T@^W^$m~SziJ$|Kfiy8Y*?vjUQ|29y0>EUcD{(x&q zw;f|%XJhSIfmv%EyPzk#YPEs#hqWjFHL<9b->g)6Hs`?A}SS z39eGKEeP1o(OJ6n!Tc}lk3bf?YIT76ofdvGEH8_+s$QIKbydY_{j5nz_W~rK-s}K1 zQ9PVGruZ7Rw(YPg$eN)jb}YE*yI(W3lHR6tfgYIT8v+`^ApPw;nqA>&`BlkcL`58u7B zlUWdSuoMG>Ru`yR^l+ZMLbLty*_(!ED`HRD-@VLwZ?*^IHZ-j+P%A*nsmSsI`%ZJd ziYw~pLlzjUh`D~g9NH=Ff(#z|e%2P7ZT;A#wc>s3(HHNY@HJRMvwt^a@Nn6GRiWm> z-#_G44s4&f^+m3Ru{*SK?*TO%E&S@=7w8>MlRN!n+Si`n;oY&kz3ZUmLl0!|(DHW9 zHY?fVw-loVCpFdT={q&tgHH7HfCdlCJkM!9yb^oz&$M|-ZCW`+HyyNIodJ~#3=CSm zkUPY^tkq@j_aFR_#(viG&AS&<65L;a%0~tUtv=B7orPbViSqJX^QOyu9glvrIL^Ns zn|}v1We8FLiW3j#wuhJZ9#S-x-j(u{W8?j~J(HV0LC1pnK^3f&Q`w@AHrx%JtCOx@ z+h=ja^X>l?rpqC%LDGJq&9@fWZRM^;{}(}LtNXjbsoG)5e*+Wg z{oE$Of8*C#^)-2W1e}MMFab1sZ{hbho<*eg;= z^>CiQcGJ|OZszOOE|_6GLIMPi-Qo7?5&OF=G#IpUJiKRTEQKH`C?!@7AP& z8oMA9K!usU=Z6!gwUnD8i>4a>PT0J8_S?Ca>p-m^kb<>fM>_Ry{NH%=#kP0$D}wFT zZ7MzSiV50lo(x)vY2o)mGIRC|-79+S=li1cW-!Y=I3wFb- zT+!3-Hnm)t*~dFs?&G{|uO8okrs}DXnZbIFqjgM4=bS`zgX)8>JiUJZeF$U|nbuTL zSH{En+-lX;|L*K^tf^W1prGuejm)hx(9xu+pgbz+B+Fa6eCeY%8ha|tb8PSY5)PN= zp8|=Csh}xkch9>{)4Y2pcE7&APpb55w8SpwH!jejo@tP(IlnK7AvxgsM_$f(J3eyH zkXq0h3|UvK1-@d!!f!%f-{U!_=FEP-W+Ho|?n3pv8Ec?9YdWNAzI4q&^!v`RaQjX9 zuBNl+<*@IW3{7&=Ayu=_TXSCBRhbeV{hT3AH8rz7yYoN}Ezz0|s+yHO1NJ^xzQFd( z{0}ZKf^XHu__aR!3u>Y+BuKPlXYLHmT@sKb+*&h1Wt4^A zq_kkQyEbpP?fAj|uHb((0R9LlU#aCFD4X+E~+Ec;Q7mjS+CrJSd^=|zHuJ{cIaW`kB1S@`WTF-e=_ zD?H23@z45qVY@oqQo14A(6r`&=5supzq!8XlV&k$NG<6Q&zxPHHIw%Ms3Xe2pfv}S z9`rpg?JKww|2{9Vo-i)Lm&;AxQ28uk!0O~t^VH4ii_9qY;eg2hBi z&m&uB7_EOM!*uVs{1nbv!oogA#vG7*vEU;(pbl3UJ-nP;I4yGfM{D2nfr6(w zT%m2+MW98{7JjY1U*@Kid=0Q$qbT~z{;IxPGiM*fghild)Xm6`(pN{>4R!J1_rHVp#Fu0-@}wMmjCDPi9Zlp$zYYfujNIlJZMk= zqyV%*!NZxmcUphKH__wiug(SQHYF&YblD6|QOiJm99PddiSA#wJ`c*_`==&6$#}+o z%PrZU;*WtrYdPeM+(#2+TNeBMYT&lK$|R*}6FXI@9-94E%m()kif0LIu)AaXnStTw zH=B>jlfQMIgtlQ;fE0Q-D_JZEcRchYaQ&I8%WS54>0c6Wh(aQ3C1~hR%BitYD5U5> zH`_mjdD+Vp7G`Sn_<~Y11B2E|P(Lf)^OpOng|5PlQ&~b1=SK5+ZtZhY0?o#O6ifjJ zRMqRED=a!(_wPTy6IZK0^`hyrT+p}!1B2EoP)EeV@1d(za&VvYDi=5T9PtBzJlu(Q zK}9eFgVt(Lta>=x*e|m^;_1wPe8*)vbWXW!STiq3U47sT(iPcPXS2HsT#G68Zg?J>>!i8hl| zf-_W=--hg;^y}y680cWpT2Qyz!tdJ6Bmq9TIaj7fXO!<V>?FcES*F2S zZ$Xr3!Jh1V=%CqpPtBoZF=)5MrMC8E?4AT#{>8wcwGq@Bl5$$nzbMXCceC=zXBvy|-xHkZvuHJR zym})@p|$7lv`1czhV9e+^rzaGxRoD#@G%g&j&u_wZ~j;rai-Dx@0RZ$k6n3dre1b? zKKL{=1_rIoki2>6=d%(=)gAG3?II)1<77_FWiWxRf7lGko3fT!_jdohYPt1T`C_Zm z=NTtjUVutBkO`o?DdnVKeM>at(8{v@i6{1*yuMogTjNP+Y;FOqJdE|+{?I7((O=;w z`n%_SJ)4lpVKc8DS{-aD0Y|q_aqk9c1$Uhf8<{oS6(7`9Bs_!;H*E!Z*TS!6qJV>h zx=gY~0^`G;&#$EKJyLwAY4Q-7lELpYgSXj{VpED*g9c5w$HFg;ow6=jd zVp2{mr#lxGTivx(ym+bOReP+_&AZ8<{x(PfXp$k=vo%k2WoQ0*qr1<0TQ<)%RC_IU z0ouRV206Ql>G|^(n$qU?O} zs}o#1cbpH_%1+fzgSMk~K(@Lh-)rXDJ}v3&;ls6m*!~o3oniU~G`GsYptTFK)rBiy zf<^g5ouYi-Rc5iT3LU<(JA-O{kOGiZ9?pT=PL%vR^5lN#G8?&nDw30?eu@C?a04j- z4Yx=+B{WT>cC&$FQ-bYMmqfvbbkLAYUHd7Nz&;OJD zuT-wO{Bn~?F{mnHV9?qFX$>}rK6eN;m0QRq9Cg_%zhcgWxed@!);*xsV40`J|C0&V z6~bcf1`|k|}yCE{bgz01KWl{It3dz|g9KBVbDXl%F7j>T+$jki@!k(=nFe_-@RVI>cT=rDr6XeL z#gccCTCx+MWz>Gi-pM^XpRW08u$b+uV88T(^TsE0CFeuCatA+kH-eS3dH>#T#IvdY8xqle4?<5Rzs?+dB+*-_QGZcU~Ybco|1s0NmDiak4j zUFLqdYkRgYsA|1jr#Iiv9n`pCV9+`U8uC&0JQ;K*@P_H-fHtKyGZ%xtX5GWmh z6hOwSCv5EqW60R^W^QQiGLbh46SJq^1|@d}2Cc)O#;=8+=2-@#F9~}T?y3KI6L{xy zN$`tx(Ei0?&}gfNGe1+(oK315{4L(S)auP$K4ta)F34s&t;3*>xs=nCoB4mvdGI%B zo|+$fo58{8{UK@S80lfqcvP%sS%?o$#+ydFy%+azZtZK|HO*cUT0VfXC}X7Gaa9q< zBPU)rNWbHnY8fM>!I6Frl++j)w2p#$OBQ|~WA?V`Td!&o)Ue+<)6r+z^r(DL2@6sH znj!UYo@Kk}YyHw&IaeNizM~Sk@KNp7QcxETqyREi#CGxNr~N^XJMQwPUnu9^{yHLk zF0@N~3^G-uF@-VkVSbd!qNMek=VS)uCSSLKhU9Tj)okG>%3s=%c}IS#+p!QH*&4ZL z2cOJ<#^!NQ3*Eyxd83$LzFlI;nWNktUT-;d&R@LZvj?Xq}t^t~WO=|M_+* zUtrJar4ClHe0BL{CEG#E=s^lV^SvI<3fC$hbn1#%w?)4^yU(!HiT&paP!Y_)pmhqg zg<9G3(T@+a%6D6+b@}>QACX$WQk}^FRI-2+KsM~u_`Uhb^I^{y2bo#F?oWHYT_oWt zw6S*@)UCAeJJYo|$s+8=hKLDIoQkvW%@4`ch4!;fp8?MVS>`@$-nM4ilzXqQ9a`XY z@>;0DRcLSV3~2F^wP#C_t)el<-TKoKF%xahoPK|eZz(7xF)(O>4kl!b^pm^QaB7mi zJ+mX{QZv;h7j-gUI)nQB3=CRlAzK@6EZD73kvi?mt0HB`+J|+#0@M0CV=dqs`2|0J}VeATg#&aX&dR-#4 zCDb@7u8b zZu3Bk!3&^OpcZ~#q_4g=$lkWMVM#ILhPAeWD|Q@*HvTVw+7TYki+69Xd*bEwcjEjQ zR(4C5>(|wppxuWHpi~|2X^_Kyaihis_9nAlZ?5jkxu-OaE`&5uE@EQ;kQ|J%i2Gaugyk7yX7JhH;J(WDVd7AQ({~1P^o)6xU z-@@-uScF0U>X%I%|DQXY+PizD!4@%SWL<+yfHvfD_i>hg|Fb)SS7Fo7qTJ=)tD!@G z*FmM7loNxK$^GSvFS{6q)TJnV|6=X2=L0nBT?a*0nP-{RZzG|J8*c^X)YewBX->=fhyv?V5YE7f`k>88jFKSM$f)+tHAtSvU2ddUy z{5Yd;TILd?#HcsxKK)9UhdA;!sGP9yJL|UiiplqqZ;|rRON1-)S}s1D0u5O7UtzGd}mzjL@gabT{s2?t-GMTVjj*R4vG>}7u?^` zKJ9}@+tbaf|GWK%4i?=5Rjk3D=jTlg_~-AP`{T!v&VQ#bXgz0w-c_V^F9z&}^5E$H zf|Zu-adkVQ&Kph7V>tU3S~cGXHQg=zmil>bDw9*TUpY%QpZnBG;mO=4&=%=^P-Dl# zxvBV~D3kk1YoC>m&u`EBoNl=_5?Y8o0Cj1loSuJu%h>se*Ea0m^zG590zZx~_kl+D z15h6)$aA}Aq~BZ?u4^^xo~JDqKAcGJ z3Tmn{FlapljW%2O#aLtsK9^ng)3>#nWd&pW--3P0pcS2`iJuqx@I z)vtuT(~{@Z>#RzJq=!eKE}fLq!wc_!h4b_TRVL&M`Ma97_^>% zhGQ-K>`s5(|4cJc6>_CN%$5ALod`lZ)Jm8@dC7#)57m@iOH73nt4x}b%i(> zx_2(f@F;|inZE$-&+>5o(>pIO;&#o7#A}?n8QvGf=Kp1cCb^fOK~zbnQopl%nZF*5 zQ@tzN(S5+@l9;Cmt(yjFqA@UNy#iIy7Jk`50%^h1J>Q5bYV+`4d)6?6eLr-q z+AGk6kB4)SZ*MzW-v-l4g+H5Z_6B8cvd)J#4_ zYNV}U3P8PQea|_k)q6Uaf}I1h+xE!L3M%{B=K)PHuPechyj>c3_43`-4=eL`I*Y#! zGl_M{g4P#rK&>GQzh(#J+1EbUAD_|wPfk8S;JE#RY-n`91#K_za27n2WDwWCe)f}N z8EKrW7ZtXtcR;Op3#y{yJ(s*m%;4Q=S@VcndyZ!#U+ArQil7b{1B2GvjbJzM#vHZX zwk*k{Cb_-&@67#sC!{NbmTogJXuStnVd1B_ov%*Y`^o>MLQc{O_2&aWJG_Q=#NLCZ ziaeZ;r}GBzymeePAw=aZAFI@q=`DEzkj(oYH2J3Q$^Ar8a z(4c<56YPcy{jw)Etgm+dcKGt6FjD5C9 zXnObzDsiQpF0Y*2QhF=rOxrwF<+?2kAA9LFfrei}CV;YDu;;2bPO3LH&2b1zQ*kv` z?UYP#H1qgUiA%TH|WtyAL-7 zQhnXi4;C4(U)%%U(!ju=^%c~u_HYj9KDf0cboYYLb;6B@8rjt^ep7+g{@*}L3*tQ; zGWK5hz0*zL|AkbM)&-aRCLX^5%~{{tz;1Z{u1u!y2E*m}<4442{?>D4&+muMR(}Us zVc{1f8hl>Qh1oP&_IUi^>GzXF=6XR3kRPDIA`j=+2JXK!iX+8Vm0xtTwhRoL+ybsA z7#OsEfVy4*NL!+$ZiE z+8+;m0u81!FlhaRbgM&NI9b=r&hSxZ-DEqdR+P2j+-m6J#$S+bHM?V*qWS5LGcR~f zNyL?;O_{UP5jqC)3)HTZa;lvd=+k`g@tND_MSPz1bMamiodIoN`~r2W13jb4em_{d z(rwD7R}HOEJN_)qO^5+CEEpKHe%%8Hlu~8M^4!-aT;v_L$F&5xE;+;Q45}v>7_|O? ztg`Ssv0}3L#l5QzDBi65A6f7DJ5+rP{k7LX}k0|$D?OmMh?HK zWVUr~=B;@%160B?FlhaS3?5EsGVYZ65SOSq z?thsUbr6)A85pz~L3Ekt)L#Zib}#hf5B#kdJfG?05yPFIA!|6b8Rvo{%WkXeE0&A< z1d|s2W>a=goSk-72Qn0_%>>$GZsAw{{dv;{10ERxpB1hajVG-wUI;;2gWAlX!6FZ5 zeRs!~Qt}ga2zt-HSh>Ud_4B8TK?9cz4BE_)-84dX9SxM%?0wSSeSKNZ+S6S3Pt1fg z)wDr}OfyFM$)>*JIH;8o_U!ob&t2Oc7vx?N2UPhp?V4YZK!pgzNn|(g+%cW?;}}1$B<&J^OPk zWuoGWOjq2uI{f1Pf+u~tpKQQowKnTra5%i1dawMgk`O=t2B!_qyRu*G^@|7XU}0d; zW(Qee;TInI>#_LDRTt-;^U2Hj$#?Zh%6HIk8%P1DK=p85uDYvy@|~YuEw{Qlu7-Mv zB*lM$R0rDZpaNCO$3?;%UDwAn!e6z-nv1;*FK;!3XO z$Jq&{bvhXMpLhl8nJ_SDb3pFKJ=IZ=`Z?J2PC|Fz=PL1d{;Soj6rv@*#Px>&m;~YfN&sK>FRW<7vZ zN!pyCO@&fUvzycsp3EzL`G@=Os#u;(={4>$kkLhLE>N`?${;P@SP5nNPuXjI6 z&RABSs0GRX+FX#P`^jZ%<}dn`w#D+#jL-(-8<~Z_^+4-j7#OsGw0HtNs#dI(RIb?BAi8_whKtX z0&sNuyq$hg(6NWRLUl@TN%f1)eR@+NW5wFMpyY4icm3Mcj{?FQ6mmNzyWQQ;Y;j-c z6KG{N1A{gnsEzO8%B^cb8(&o}?Wc;E2WRzAM|C|>J8khi?0Gc|Ka>_XMM_+rxT#>mtVzHafzkKDD zeFL&gR9gTPS<0RVLsdG@nfp6^I{wXXhkNpYl|~mKGa%Xmka2szl`c)k%w^9B^|MX8 z@TzvPTfjfati84nD4;C-Y#XL-bD5)XzGByfxN|ITTFhIQLpnj)LZHgc!};6cBysL< zK{J@L;__c^Q&VjG_!=}D$H1U11R7AAO(=a zd=xshyC2?rVXbm#dDCLq9a~Ee#DFHc7#OrgT)|_5n!2yE`E1r5nCM{s-+S9+j~8xk zps5j%0#Ir1;rxu-Np#go$%BhhwdJ=qhiS?$cm?XxgA{<~Qly-mZt0e8d2nO1H{%A; zt>^sZ=Vrx)YyRFHGCOI)sL1N*@UAAc#_m5RAKHhsOmV7@_DBolXsd=@9$aJS0^pX*&OitI?~xuVtrHK-D2g z0chM_-*dla(jz)0q>G zISimFN&-|yS@@|va(l(_QdD=tYx9qcQmq}+8NWcQBuUT;0uSejCld=r)k3t5n>HSJ z#BVis`A%-gfrQ$Upu)`6v+3zc`(t&7*-!0HU`#qu!o|3P?*ybMmYfPs_T{Vf1SF)` z15bTqyred{YA(C%9?;qg1_o^@P>5Ri&8<83BKLB|4XK6O&P~o#_|93&18UqbFlbAI zX3jmFjpNLovTfJi-V~nFmwRt@^SN0a(14N#mDN&CYpZXXMh5;@I_i|!ZJ~bqL&ohR zvJf{&gU+Za^X%ncy?W99P8N;13!VP$j&-G25nhT2D0!wFaFid_xPqWnv>aI9sb$v;W)WK24aOQsJH0h{A^Bc?ba)S zJ5=gsr60)J&pGp6A*h}JnQ$FE3_GbC1E{pEkT24aPr4%m^?8se@V;QJEK)5{}Py;$LSa^z}g86^+e z;$Y#&Xch52DBiWoy5x@XgE#U!m8$+j%LjRocRifX9zFH9y!&==`H`gSzxUZq|FZ5d zWClcA0hBJJoIYs3xbpO8M!|xxW!vOW1ySD$7Z>hLHOrpGv2mjK5u9X5!=xS?#8+2wEUu;n!>#m$3Z5 zkj|3KaDOhv;DsgjDI72Pz8`9K5? zG3nr}qt>imEdfJ%L3&jkwGD*BgIPJ28fqcQk)#gvxtpP*JCNC9Md zgG#mJ1hq*o|H!J$iA>55IMkAuMy$b^@+4yewu@bfabkaFUy->PPjo7zHiQiXrzCxPm01_o^%5bfbS zTdZE;M(F0t_AA<}#P2QW?0z}{nlE%fJrpS?J*)f;ocHE$^*jDtapL{LB@vZpAVYuJ zx}X#l>*>4abaKd%THOOZN~^y(7FE`3e}z`=x+UPuJHbk)_VM}^x~(250-DY@e@pCJ z2&xVl7_{}yf@@x{ASPykqbL2osG9I5l)ephe`yBkXKCw$3J?$HLf54_(l;M!3X8Dl z9uk@@>6&~N6bB3p+WMg74c4Atb#53PdVQ^gXXD~phvq;V&*tZl#cbO89bh-)>Mmer z5lS^GevNDK_xhM){2<#hW&(5ki7oQc<-)oc)c9jmln zT^cezsci_FDUJ0^_h~s(A@V1T`{M7d^{Qq8GUrl%@s>+BJPh zXbLSaK8U`#)@1Y=GFGf@4vKCIKNrOiAS@13NNEX5;Sm zMsZJ$Vy~b6izJu)f4&=3$}=!%TY?5CEc`Z!>DVvNJ5=is?0L^JU*+ja$r{Ki4sAbhn$3N@_4!?>(iIsst+Xgfi z;_f-Uab;U&yv^q=Q8l&6%0irGkK#aO6G*`#a7bQKN}aEj)*jj1@liXcP_AL8)>2So zmw`ds7Buu{;df8Z@7}e064O>lysWk@D~ey-u@2hUvjc6v@^EgqGxsW;7PR2-?0C=R z%|7W~#{AGGiXABHNjY)m$|>Ic?AmCOuCmZn?ZmF*v4=o&iVO_ecA#8t?V0b@(S3QL zN9jrBv-3a9ZN3(;RSFbIAO(wJ9g${B4hgq{m>nL9vk-=2MIv4CiO^O+q-^^YvxI(zdj#jGok3dISOx-I-pHkLk-5B(*|SEc+f z(M)dAVR1ib&)o^MGS|b|nd|BsOP6}r?W|k)ZFU^CD$n`>9RqO!ZBKOdY_EG#HugAS1onE})jFhjYZDg6k(IZxD$u*!ameC-L+@7pTs3>gnLz1uK57j2(Rr58o1K;l)fmVzNCJJPu%)>MakNp zJiDWKpxp;oTd*VRZvCIW?YyqYIrl|#|D;HtF^qcyZOehry0h?Ox_ES(TO`MP-tK+E zyM&FMCm7rTb%q%jwB62uXXXC8{hkswY3`|Ktb0tJ32L6{nLPtEFu}l}?Jfq+7fb%G zbek&gy-px^pNk~ZjiU8Y@sPDi+U}rX25Zmvp}!n+`4X&G@Q2xaUHAI=3g+#gt_#S7 zY_KDfKWiFreY-8X?E7;M{($4b-b)Wb^Mwa!-H(MITh})iaZ(?a7Pln9Ae*mUqFwH&yR5p`Bt+P@G6Pl@>+(Zs^FUO!>TBY1WJh z(i-0JwbJswdX<0R{2BfJ(`<2EKUd=oby30?hap4P@BB`o7*`-xhwfRrYmGy!y1_y%o ztOm7R7#OsDAyXtdaXDw*LT;G9+tpR4AU03R@Mbn->9V#jXwXQ?iJkB6vVH$=U&}b- zqmkv)b?f@1e9&Y($OKTLwf0=2EPk$qYm%Q={M&H1Hvs`65&Y1a*B7$ipMQf>=<8)q zZGU{vo3b=4a&Jo71<3S-wm&EnTlj4cdV20{SjQWt$k$SgjI19U!-Jun{u@0W)MEg#k-e^|Z+ zGIyXI2wLQ5;pg?%qo#ewmjf;iB>^>6hqm1iTMKHUF)(Ncf<}BjoV9k`yHdo*ZqB4} zf7<1o^MWF6SD@)32-Grl^Xw7JJE^;Tp9`y%>2;TtD#8bvA3~PHX$L`0HF;>nQFMAz zQfm8}<`Bu*;{P|s*MVj}7#OsJLB*kkpQQlDt*1F3zqXoP@P5)^S#5swDQH|0qyRLp z<>BlxbE}P>jOI$^1cwbfBPSd)^f(QzFG4_T5Tu-zh)!R?syw|!skn~$(D_rM`Ff?$ zaxw%IV6mQk+ipZ=W<6UJI)D3~%R4=mUK2J$ch8il{*bS<1Krk9dBU&+Pl$`y~Tpb;Df2JNsDU^o2X zJG}hxiN$mBme=urW|{JyH~TthXoG=4I|5W3TKGl2pAsq3bZuo&fLPJh9i~oecV`Hi@6HJN6%#&j_lk7#OspK>aNb=Z5=l zUrsg=Sz;cuEjdl=MVp~iCUk5t3PkIB{$t!&dcZl?yY|xEKiP6StzzC>1uaToV9<_+ zOke5>Z+-YFvucGzdse)BU~JaoKi5EOvltk(V?b52g7*HTng=} z#epx?m0#A z#fx+I51g6z&?}|ycDTTr?lX`ZxU>@?CwX2u#4DS@;^f6{own!ys`B|^A0~i`9tH;O zWKj3o!tbEdY?hlV7ap}Z9BqDm;f~6ME2lxDI~mkL_izq*HT&g-P3-xLLnCrT&M@!r zx@ZHMI{}#hn(&cwTGXnO{A14l@`i|zwG51=b8e_0cA7HS4VtaWi~SN*HXXarKgss7PF&<& zM$l;m3=G=opu)_;?|15pt+{R9k6mM!?UHXb$~>Lf16hHooeny~$-`Oi%&FST3KwoL ziY{#`x)t5=ZjL*2RxTaX0+DhmXWT88p5C;kR_M@Pfd)Vt)L80GfCg`W_RkF z#Rh8w0*tORBx!G0cJtM7Xl!PSvAm>c@}8+&DB#^?1_`D76*@9s%!CU z{r{0K()B>oGawUc!H!H3U%X?+yl=tjtE~0EoT~Rd+a3uT;$dLW&IY-`!mmu8|Nm~? zDYJW`d5`|x^54y4;ug^C3j>384yeiM;k+m7^eXPToUb^h^H>UoSFE#Ntr`P~%^Xm1 z805+O(k|p-e|aFAYxU)o`d(}frwgFtlQ}EEZg_h8dZyd$*V!2tpDi%x<<2d^~d)cB-ljeeo9tH;O0??v14`(a3 zKXVse$adZ3w@>%?fjpxlJXb)~07wC7mQu>e)IQ5x<mC?)IjCf7dj|uLred85p!nKngvav*&&D z-B+=DrCR)zg>P(>j9)~lf?8l81)$M`K+n&je~BZ3^YpmxMYN}g z)q}=H85p$7AxAs*XHEV1w0!cE`UM(ampr}1KfnI_Mo4T{fI0yde)?}-m1-Ik>f3(~ zOl?==6MVPC7FteLfJSmWoPBtfo<4eBrR;)>-1%#dG_%imzJeyXO3?nrV9#CUO;7eY zIUUb&T<|{Qr@w)Fxd*fmtAq@aw93fZy>OngAaqt+Z|8xv2f63-L+ACXAcG`dSDrc1 zk=PM>Q0AjTh^`x)w~|gD^8q`>dO0Wmilq8 zylegQivhfIq0wCnIQRQF&2I)JJ$60$m@Nt zUcRKc-7vJUKeh_|AAHw7zKa2D^ceE3zwWhrSK_e0lx%l@%_GF;k!^su^^c zu!Y}W&I58Edn zL7hMb2JIHmPH`zG(M9w5&0ODDMVzb=`}e!j%!IiIvg%K}1vH@R=J|V~-l->Boi;O0 zH>j)mz5Vlb?+j3t3^Jhw>`3EGcFwH{LYyp~Yb5w`OVi3H6@&WQ3=G<>pl+0fpF{4# zjZ1{Ct7yL|_?hObQ2Xa?7-%kyfkC?sl(RgXm7j~e*pRxk>t#@6+QEFDpARNph3wbU zZUfaDQcmqcYg<#MqXvsM}6&9-vzMdvcLcjS{w_9jcrs(vhW%inV9@RWEhO`BzBDl|TVrm^j*HUkzZ)jhtXLYT1!}{A6o9sRNI6xC zEdN-2IIXT}${W9(+deL-NNI)6Msbf9k<>v-yTtLre zshk$KbH-&$_MZ=q2Zd?;IC;MdS@Jp-eu+WQGww^)K`AZz}rtIK}Wp1KqaldC!?ps3FYqiQ{%3f9B9!1!T)X8X(ArXj2W;T4j~S+yb11k(fQXN3!iF8jP| zQo`0Kcbng*O_Lk0)k7WG3+ZQt?eyyGY%w^eao(c!n52fX%e=RsTAzVIyARUOy2LSG zda9Cwp2*JY|HY)D8X4AJfHu7QKtb){ye~7f!1cw=_?+lt+OLXc>vaK! zr#U4DMdycnKEL~Zz3xek(`wUaZHCtVeW0=8SkK3A*y^V%JZrsWlygeKsOj$p@ynpW zQw9d@{s?f2iuZE;_Mm-_?!)qE5BXV>CR>yphmNXE0M$Geeo9tG)7&;@{PJ(|n6G2{ zX3gy0&CtoF37`R84`=SuZh6;@(w+Az+t%-@`o1Cf%5+fwih)6UB5340&~r)FgUI)b z*g5CT=;q!3;rT6V(>`e9A2hng80q)-LwbQ+b=wDfRc&jwBYvA7zuyU+37Q02qG;h4 z@cgabrRKl4IC8^2&N(Qv!nJG`Xi$KGL3=W2i-U*riM!8t?w&KhB3r&J|Ha0+8)oh< zfrjK{(5SnVljgZ66(_^aX&bJ4etR45@uwbkub~rOlR+j~dpbW2IJ`;b<(u7|zrwlH zb8Hf42t!ADCqs5V2G8Z0rzX(ETz5`8VD^Fd2A%uT(60Sd(CmYS-w~nRo0RHL|MH(0 zvx%e4zBhsA3ACJ?3aa%yoIfyH<=45MyHo!`MRP+%lWFVB>7W2&V9=flO7_8?oT_yq zt;Ut{E0qH;Je7Sp&-9Qrbed-B9dKm*b2@U2)3jOg*&==CTEXezCY3Xx!%fpc#ejvM z?D|W^A+@1)PWvWIVSf`}5Z;~)Io?5gI%q)G!`W-e<6Fx!()M}yI?bOmt=@!NW)7%q zVqnmo4jR9=_MC3EqWH}3X%ly5un6bxs?#~xT?b7M(;<7rLgTmjeLJ3UWv@LG_Xa-u zx7J!>pl$;LgZ4~Nv|IQs4_Nc-na;=cZsG+KI&D5HBnTb@Epq`W05zLEoI~Cma4`vy zHcm?n{HSu@iFXUPIMj-npsu~X=QEC(hXnF>Jb$-FB*C)S-CIs{0?Y)+o*=I$dl-_# zkA_F|9?q=|{l4asy8*Ofoee2rEU#4t`%YC;J(*qhd@{?!h=swoKqH$B4BE3nLG9t} zo#838nx*uP!iFoWl22dVtiLr9q!Xk7Qo_h)Bn3vxXXgJmk`cU8e7~Aq&>tFEpoO`N zk$&Fi<|S-CxIkc<{rwKV`P^2CH?}~Rn#_fiFnkmKd1=Hj|JVOBt4;G%)S0c>PoU$p zb0H-RKf|)Cfm04!ICT~H9l53yy!87MUr2Q@7gWN;dmd%H({ue-NWfRwBZhI?mWrG1 zhb?BCX8}$RcQ$ExCkh%GojbLNJ*T>RM*5uh(3bgpkQEkw7geM`T`RDdIw$n2v=@N7Q&LVk0z3Nu z#&RSzsJuU*ap1bq>beY2wg)KyEg%Z?obPGw^;si~Id!JWi2xzR8Ou{vgPH{(1(3Gf z&nF>uD>tm%aZz)=WFG`v3O?Z&O#U!rMO3@?jA# zxH?Fgv{(H3TVwX|2pU`Lu%8GYQbgmYbHSwPl_9rIoVd)@+VabaN4 zUIr?wEc{&J?rv>cHJ|(5roWo64qcMCeP!3BaO`Nvs zqwB6;Yq;<6^0YvFv0NSO$UjS>Gmorf`m`eB^!)3gi{l$g`asiE3=G;UK!^EQ`2At; z6rZ&A^kI9u@K zM|xL*OtSFvdc3Z0;<;Qa$%Mx}Yuzp5W-D-khQb*bv{!+~&OMyF-fWrwD)~&~iaE{G zdYcme3vO5h%99KX+N&+VO*Ow)hqRAv^qZFOx^&s?s(X`qY*v6`5u^ZeVQWkCoF9D2 zD{2m26{}j+`g_}ohB&})ttBV@Y#{XJSn@-AUHp{D|!*h=Bbf~-Wyhnak9wS37 zr~}5ppuHB<_|^A(IfL<;){U^s>%}H2yvs;mpK>W3G^z+v&qjy|1-E@RIn3#& zVRpx4wg293P-B;YL3mW>zZ5FwO{VM_d_I-F-vR3`v3(6(6|EwgZ6q*gUiF& z$e#V)BD?H8jE+{ECK+qes}FvMPLZq!P0j~;e%(Cb%+9!~bEzwDY@BiQ)7Iy;=kg#4 zW-XRovPQTl~BcbTpBa)8y1^r18EH7MVR6+ZC8zDEkvaxTN*1S!p zCgR%r<|o1p2JC^Apjw}SL3=Z3iKc~LB;%P|qRM~b?V*dGw}R%BEd2Joeyf|Ry<6tE+~FG;t&z-D z@r@b5T`1tt@go&jQYUmb0`c-8u4Mnj~o2l7T^cJEXa|N`LPkpBrbH zdNe1k{L``{?_+Q*bi{i*sNV2!_B_J>%8&8tZCe@p6p=+`tnO_RHhf#bqIGtuBte6$pc?#Cy) zcKnGuvCjs&RCNz%4X1_Qox zI@FZ&waAlg_gRlO3%_zua0InY7#Otof!2Xo__@C8o4Vr1`psICYo44kU0t%(o)4NH z_JIbrJ)B?upQ(1|apNi9?KA5tQ|2>BX&;1+VC(}W7%8VO`{I6zJGq|nX1!S-^6Q-4 zk?HTD$$lSbxXIeHwDy&8gUzdppBAs+3Mol!TqAoMTI1}8bb@woU8vQwf~$TK)x6&<~C*-(T-EreE3T#rTE)iv7Q`@1~DtdW{`)UhgPqip16P^~C1= z-%q?*cjd9+HrblP2b9lCfX2!h7_^T5rc`io*+G{@k3>;AFoHieR!arLg;!~$!;k(Vd4}IGO9TPhVigpXXDQEd-aclF- zX@A$~OfUZNG0J*6w3l=e)X?&9eq<)^obXOJ>GI>t9{b)J-8I}23mT7OV9-7ZT3A=+ zIayp|$vr-X>ra>V)_oSyE_@rV3Ti(wFle7L1-s$y@|k|AU#HyvW6S$pJ}cb!&J;J$ z-f{*8?bD#^Rj^*j9J}9;|b<)oj_8%WY=TOdqM*c1Q z)FZmj-?Z44$!&0T&9$Wsr|f)rpnbiwpur*!=VYhV`}c~tZdp-3DfiT@MOVrdVEePq zfd&zSJtuccG8=h3WHwk+YyDU1p0tkq9nkm+1B3QC$mUA^bIG&Z%8$)nRg@gtX8&E! zH&qfElIKC~N((;@53vXDUuZ=JR3;qMS}FF*@R}Xy5FZ8x?F*ppgNO5zmon9h4*1n7 zuymHW&OWFmb{W==x&T^Pqwjf)Veju(VyC~ciS)=-l^yyTH=7CCbHA_%91eM<(T_Mx zpWZy)JdN$WU%uJ?@6OO_@gk^Fv+&#Ra8>!!xsQL6Yz42EuUb4~h0t>7n!QV)a?-dzOzI+Q_*Cs#x7UmDBgMEVLJ&x;{|u`i`|L4*sqyf+qV* zkZni5Z_g}AwRx7Vwy`)&nTJ{A($Zp30m{IjeFd`ZC_+qQlhcHY8<$k|S6)5p{7$qY z3zVxt3P6$O;cOt9@cNO6Wkz($6AR(u_o*eaAE7I(u7GGMC&3F!vTCnckBZdKx@)(S z>5S~@3810}WWrW(i}Zu@1G&_<&Zi$)-tW602;LLTKw7q{EoLA2}LkpDU7#Os#fd)xDoLfYs z-k%n>YyLI;`h-4}irkdfCC?yb)HTpjO(~}WN4GC-AujBbdAF?0$eqgk>$*5}n&uj4 z5Yf%kJ63y2h3AqI1IzF({@NGeeE$5P#LB>+eO(qDn~nv~{U)CAO*E{LbzL!&F*Dz^ z9NKKY0dlN`AM^6{egD=xKXAJF@In_*$C8qVqnm|1sa#K@N0USc+-~McH^^{?f)uL|F8A8Plk?(-2$x= z_i(;uwOpDxK}K9WK;UtyZ*1K5u&1DoCyPyEG_T2e1_NKjC z^#2&;fJu^Xtqi&k{ew2$??Mi!^yD}q?f9%j>YH|~{=#5ymw%V$Lo1Yfpu)_;&)VqT zcDvhg%S^qFTvs`}{>MUh7ic)#2jveB=bQdc^>3uZ*D5s}+UA#1`RD#!252dFA2c52 z?%64la%#mCxfwUQ?Ckx*G$eQ;#X%v+z@U8}vc$sbSjw6uySDFid~0BKFz$l&yG^G- zogW4U?S~+fEc_(4{oAxmQ~Bhji3LwsqEFX{A4>ss$UzD~LG9sOd+kqIv9)lo%P9?A zmUQXAd&?Z4s}~-EIzwfiLfa-fr}f`#uA07mo3BIc^t{A8=wQ(!W^i0A5SXz_u>9^< z34Yn>4Bz&9$SZ0?2XY^S=Jzc8dNbA)S)Xo~Inl^a@31pi*R^mzwDJEK)UNb!KC65^ z|4-JbEBVWHRfQjSOy2c#D>PLOcE0qE$ob2Uh1ByU+;{bB|F=E^+Q4|?33lX`Ag-A|CNtM;zP(5OK6{F~F_$v5 zf$}26*FBWqCZiEn^_ym&qgNxTYYr7zsQ{+ww(CCptQ)qp#2O~>g#(hEBfyiZs$|} zjQM--?8UQBJlhfsY7K)FK-O>y%v+oF?(|PDPxi_el1HyjeDVAxbhX=a(1?zOpYXJ( zEqu>{H2>b`HPn%;*(uZ70BYPYFlayj19oJ6fb84!@89;${c`AMv7GAHh<LqB&iG`o7)beGoCW}see|@E^#U722 zFGn^&mvFxVb%s2gi@Z5Y7@w{Q46eOYrE0N!eweR5v{n2HG^ZrxByqZU6IbCh8yAoB zA7Z-qtty(i96CGs3e@1z_hb?K*wIFF$;}b0c(Y@YQZ`bmt$?{^HH> zfkhy~=Px2*MTsm*TMg=fU`ui0=4M6HE3 za^8SS+A>ei?NNVz>}jkLjt#o0+2q-l_IV>z!CT0F9RKwnH_VXr|9((A>>{)HOI`_^ z)1Y;73=G=uKmlgq_enAIW4-vA3ntU5MN&GvcvjgShYmNr1667s&hMKQ-)*osz_u@4 zZ})zSM3K6Ji=bEpnE)y$q?`_~c_Pq#b(OgilWE&2uA`0mKPy4)X$A)E_aN`;d-iX? zVb#%F=Cy=bUNt`Yi5x5ML{L)|q`(avl5eGcW)&^kY}EE9@!gk6*IpV-F#-h;1B3Pl zP)E$dPuN%2_`;;vcbrXCXFpF+n87G?57bKpDF9V!9?sk*v2}a5)VM0e^gTP0@WSzA zZ$EVQ;Ug&dOF21*cuf_x^Ybsey!^q()UQ_#H~2#5{Xc@H2!cJo=H{Bco2h=zY@bt@jmjCTa@1yVZ{ewcj3zPEruKc;t3_!gtUN5Xc133L_~eJ@z|E zU+dY@k&v3=G=e zAgjDKytlvb>2BpoN$wk+r>tIa-ScsPwu--l=GH9yUQPP>@n7nm6|WeNzuMvLckhV7 z6;Q3uz@YsdvdZiGWk2zo5&WmB_Gcc>IqsHqru+kR!OVA18D;JH_KwPn?*Cp+$|o*$ zzP-1gYOnVtP)cH8(Eb6Ll>c{=K{uI|^ZbQ*>vEI}-BbfBU<>MgLMG+6`_*ZL^nK5> z-_drw#%}L#_m;cR4#-c)q`dln<#UaFALcO$Up!Y?uJN#Wy)3js`2`w%kM|U~y7TBB z9h1Ao?r9mVGG@p6mXw3~+YAiazw*H;s_RW?*B+4?`OZmvpU+Nz^sQU^4#;~94BEdz zR#^CLeI6k2QMROhrynPW|G$i7tF+6ZSr6n(1`p>TKh`_t%JZ#6Z*5OowRF}zXT87B z6!iyGkVrcD-Tt?%DRm25ea@|hX;}r^ZEoEFo#Dm6p#2Br7G+O=zulrM^;kZdJ&6%1 z|2yNv&N-2wwhKrBWKv#wqvfxd^Hb-hbS>KDyXyWKxj$!xA&s2Bpm9nIzYmvJv1pZx zaO+1iWxUt*v0WCJ2+{c)o-KZE z7Y%9r>o9=E2BnN?ZOwdD4^` zsk?9YJ_Qs`mVXcR%MsMh|qDK;!ow&YRxz9=^iXp>qAOda;>ViR>XRZAb${hY7Tq zOxe>*z~i=nRr%(>7m9z^`-M#{vV9I|Xz4J$2fKl3O7P1EHEVX|-Z}l=F0c3F3jb-> zz(K9U0!j}Seg@~+n1niaJln8vN!&lx=gaM_ze2ilIxHaHcsSQ~?_~>;I(5Cewmaed zrd^qxJIjlJ1SP5!qGBD_{LYitx7jN0z zZp+p=7OA0Gxu9&WMTv$fez`;2*Bsq+ zCGfm-=^}}hL7{^Er(39=x_#t-EeDp zmbu-DTe?3l%{ba@TXOqF#92s%qQeE6e6#T5e$XtUAu{PH!@s#FghU)14mwwW)=e@n z=x~9i20WbEU7pwEcok*1aNMas+}GW^GC?2IOJrcs;RdyW^gVxFOtQ3ycz()wx!2sf z=#E|2dQBl+7#;3Nup8EU++W`HWO=fnb8`2LuFWeyZ)1W~%{n}w^+6VXDwf&TeyGo$ z$8hPte(>o($(OC4f~H0o7<71Efm?%9Cf#57V8z@z|JC7+LI*s4eS6;y>38e!f=U`G zC&wdgZZ8W=Hd(n^=^vPODCoyQX-KW7 zd#?4wfc89q6hON6L2lArJvF7}hj)K?x9sAPmi=cVAtRhR{E)7F^}|oaheJ;--&&lu z@znE|F^7vT-G?L?eo!kY)>G?J+7DNo#&?&M1@8xHPP!jGQ4~_j=?Dmc9eJgClSXIe zgAKD?6|1jpUU~am{XWpN1OtPPAZVo5!ms6%(o(Zoxv%G6ys+3vr(^4_32Pt?3>`tx zc#Ma$)HHrrGv}mX1!*Z9+`FKub!6@=nPN>1|6Xkupgn)6I# z>zS*3Cp&|$T(}0AG1n0WjUHI|_4&!LWL{laaKGu23y0Hr?vg*^!(MV`C>CXE*)Q_UgrVn z1nG!?dal-w;DvI4a zFW%-XZ-1^GnR9oG4gZ=id*rtNg7jE*#7==78Dejn^EEsE^O8~@wm_k+OEj+Uf)?fy zpao?Xe!O<;JJ#Rjx_YCo_C&_>rOSR^0dJvaV9=2Ot%vb&_O$U@{Lqr6R%_)UtsPsU z7ZrSX2Wda(NPyBqu&1q?p9Gsx?$!&tVkI~JKY8TV(Z8S|2AKdk5a7+uz|hrqnQQ;Q zW1h#EJNIz0odBq|V_?vc0*wJ!_|-l++^p5P?dRb=^G`It-tlb1-0h$^04V@9em$Hu zwWe?OQF3^Aaf6upynkE#S(T$ft5`q^Kq<@G)BD7$1jhtJ4Y_Tx2R-!p&%XK-3|YLS zBh3X42Q{v}Ub2<;bxU`*+`0OB)r6Fz?x5YL3=BFlpk>q+ep4bN@_%M@&CT|iZMgGS z{hd=T!Jv@~kOENF^KiZ)uZoSZn-M^T5-tx&h`N3;nX;^u@*bV+*nH46Gi5wj{&>~L@zgvgi zYd+Li)^Wm>VfOA<*Li{%+(4&SFfi!IftI9sINP*tsCDKH=Xn0XVN2#adF9J_QIO`M zjvS~MaQAF!Y_lxd=;U-f{+`2JQg%dXdKxO_MvWPrYU&eLGwOS|urgYG4m%XZh^fXw47Tb^5sOPF<7od{s6hG^mw9 zlk!qd1{a%G&9+ZTWt9onH~DgU<<~V8pt*Ji1|4P4;RM#6wkPZUyyANrdiS$SXzez} zpvl`rL6HPf0J-hxW8EgjgKQC|TC;3f-rL?Zy0d>HRDlYpr()qZWlzDyrO`TXeXoBF z+g%+cqHcN>)P-YU&`|}o0z8~o*HoN{EtZG9<};VXf)O{-R%S~rg^Db^`9bMiW9KxxhaJF>QY z!}{j|_v%xND-?cxiNC+8_a$VwNk$J=tNfr1|4lsiEH5}5%TQwTVGkjJMEe43Mc8v zl-_(64v7nG(4>=xbN0(!OWOWEkGPOOSBjyQrP$kD$2{2 zYiUkI_sr*)r6JuY9c@r0ALQwI_^a}QZ)`PB>K;1sA92avQuh)xK*PYGqXRi3_nK|_ z#$$(edu?|+x;7=^N5)HkL1^~Z1)X|i;g?jpGiLj9>z7Mi#Omw(bP~R~8iAH~Ffi!o zg2v80oSlwXO2lu7>)1TIuw_eWobK|vy&wq&1|2=n5=AMe2b;cYfB1fG^I zmfyv59J1bCM-Nm^1bSNC`lEbu`3JKI#RGhsnf#u2yqyniSA*`!VT|;<@^k4n!TGUC zrPrBKI9ahW@7rpbgkwKqsFcv z`z4@`2LpqS5vb{E;isqaT*LI1(#EXwRwf>5A!oVXt3w+(MxadW;e1H3@a37quNHo> zlDv`qg7JZg3}|0B1IPr>+C?cR!v_I}#AbFLIn*nVnIS%_(!VYjS}huZDimu^nXsjg z%Tmz@c>ZhrRmu`EO`kbC}ukP!?&?^^tL6b}j3_2#D z?v#b!YkPsBI}5lc<^+9S82>=vldQKcWcpIa1T>Q2;oK#gpCV$itLNYO{^>OtKKUkx zbwCv=$OO>h-(b&4c2Sx#tNd2Tym}sXI@O=keePDsIT$*oOkg(zDwZ^UzZ(AANX?oeGDr8Kqi0+b!E>dEAF0*{jmDw^vOFlwx#=Q5Z&Ji>OO%KKu!bu z&z=0G>#^0svdc9dHra{1725wHqe(gzpe$(N*UItk%#Jz6(RI=ylNLrtbFw7F;j8kY<5T5Qsd zhKxV2{nXo=2U$U(V+9(>^l*-^dz<)fZ5I@7z)=c0+tm9h| z>(1c&9c-8Smrp+UH&XO}9b}wV#~M^l26-l#Xe|m-TIzQ4zI>UQ8uO(Vfltsjtu0{4p{nmB{a#|fO5HoU+4FET^{Vs4|?_QZ?$8;%X)mrPiO&R z1FE|{oL@c7ZD!9szuwu%oheK_cyfvFO~|0SjxA)K_hj{&%KQWwxjRb>f`y6-x!)>& z0*yN`FzA5p`eTgrW6<8svN5_nK<1;2Y212Fg*35l(AWn9gN_}j6=31FU{l)3O8<%N z&I%ICP8MxYa1-?bRmlttI`)ux-o&hk}dqU*p(JtIhShu;;fL^>XWB7Kk4=W&G&;8fI4Cx&Y|;HZFFwh zRqpg-Bcu4SQ~FHY4$xZ98C2TEdz!45-(ET={sm*u$5#ddb;WIhMUe3*9T!MnuT`(4 zg2$OK4VFVn9gd3o)04@S#%*Utr)>#HxC z4mH6I)YmKXjGA=p?lrDwMjeIGmG#di_-HM818SNuFzC2dgLBr5EOQB+NsEsB%wPEB zZr;X?QCrkO<8cfOI_{vcQVYL(UCFKPg@?cCC4XuRGEDkZ;^7Ke!>Qu|TJ`7QEMc_i z!m3->ZMu)Ao)XVlboSKpX2>M0jt8icmvY*9Ex7Bi_K)&q=0!K$cIW+NW`6=LKs@po z7#OTQZ5C-9o4ca&r_KV|!+YB<++%b*2F<*nv(*_R{j|2SevEFv7RA-O!Q2EgR;=R%DnQ~rPiynD6#JVys>_B(da})~TdooS$}k`+9)bf(syDR0 zLNWT+hUQ8 zH})zxcCv&m|1S5=vpC>We$AtQ=fHQtf=mFFQBqER7bi`8x$$yXCD+nemgE;-*Jm?; z%14j_P+Yir&OGJQfBWpiiFa6D&CC{6ne)cu8>n1hV9@cE1Uphg>Z^+szlHU!&ei&{ zRbj82Ey_WTV_?wn1G&M%ukm>Pp$lK%$RFapB(tH5kMT=l3bYXO1C1tmIM4h&dzQ(C zmNRA=dlU5%70&EaR)!As_<`osq?|Of9bdlBsu8j0Z8lG9%jb-KJ{dH@!@!{94@wW# zo|7HhD}+2aB;QCKhf-Jn>Px8jhJu4&baw!DdNq0OWK zP%&WPr}(X7^&1_NwM+g=e0q4`H21OO7oc_|1A|TgXpq3edAdul|Iq*@VU?SkbG_bw zyUgZv4>U-`z@QTdsurZ2-m(2nkty4_JN0APVSB4-_vN|kAiFPh0zu(X=D9~wXi?B9 zyVVPg|GC}tZ13w5P6w?A0-3M@>`2$i#(&?IvR~oP>a5WBI5qqAB?f5MJ{Z)cv+(&}LUCfGtYSLy^if}^{9O^9<|dB)1ik1|V_$QZdqK1~HpgflSc z1cQ1@)}Dc{!`B=>I%T@D-MWf@F9c8iI3)@lehfYWb_0*KncA~M;rChAuJ%!>4F7#z z>kz1^%D|u#3Ysdi@GDrXU%6B=>gySwnwbGM4Ey=l{eiY0LO~1CJ)9R!>w2NOQmG}i z`hn(+=hwIInji?;WD7C@l!>LB0yI4}!|yuCXGX!oDK5~`D+UIg za8Oxg;V0ZFUB2u3_Nw;KkCk;ie?v0@!Iv?B6o5wfJe+l7<7(E=@Q6#*rJVHsPg$?9g=_VZOW&B*+rB&VlED!g)Zw6oL&2UCjm_Sc><`v&A^}o-o9+%cjey9?$ovm zCYly*my8d!ME{7G4oxtTpsu}#^Y1(NH}K5-*717H&w8)ji={r9@Pf){1_qrdP@_-E z$+V}3%kOxr`#RB$?(NQhTdKCTgSv1a1)%hx@5%7RZhcwi$!!9Kzc!r@+aMLx{RdRr zffPVa(n!^1b0|^WCe#(pRmhay8GmgVBy%(9M1y8REd11$M7E|~yU9KA_jW6v22H)X@?rBkA2`=5P$I%yWDgas)8wPoBqO%+Y2tTD`W zjpP?Oc<@cz`^W4o&~|kUWcB0z8G1WA*F9LWy^`mv`Pl=)ToMM*UQ#S*wAI4z=t8a& z=MTT!!_I#^xQqYuiQtS9P%JVq=){4to`*9#$NgIz=F2B>>xCa+s7sXFHZ2v}rHuo% zWu%`OT<-)OL1Z|e4? z`tRP~KCM)J->EDc8d(XTj;Whx#~FtI&&obCCGD=6x*;k>?f?IKki|R;<^yqk@A3%IQ~02=aRV9-ee zjWSyJZ7a6@Y?Qb~Jj^liU%7(iq|Uk&=)heX=*SHZ=iVo8uP(lEW%A-B0d*hp{Y8Q& zGeZ{4=%j;Iqy~E){IjIRmr~!ottx>p#ie98%j^@9gLGFJUi>v$zVK0m%f-F?u*h|C_3w%iR}o z#{TN6^oPaQIsFo$1!*QIj|O_~_sDz4xc`WD<++BfLMxLhn6G|^merY%TfjtLO0>nC z%E?~s6F!eoi|v}u*IwulM>c3w$->V)ah^fRA&!4J^S>-8HtEUwb#pbex0nqYH1crf zwt01e;kC5hqk`1Ld}RyHXE%5tv(-A;pc#O8Pw$;&|8=}C*3R}nC$l8j%IwzkrJ&l5 zfk7u5vb|zo>I8Gw6088qPB`w~l|7m3S?4tJ5>5a4yj54F(3CJV-0( zi)^|~VZkcF+>&RDPwtf7p8wAqvOq#7AJPhvnfU3-DwjDkUTM{SIJ$C^Tn4*4XrT-P zgHArA71X@(`EJK)lO^s++&>tW!Fqr_JRej9gA{;TLDrsEl=eKnljpr7Jm2|9Oo61X zy>TR0#J+0+H-m2Z09w*)&yoed1uJB z`^5Wynm<7$3rImb*bNdB4)X0%V|>2ri~F=M|ElyKuD$}wQ49<^rJy5;Ed02ho_*`= z*F0&1p{P=NvRTjbm#m<~%D|vg21@oG&JABmyptT<_Bm~1uj^iJm~EKL0d3QkfjUD{ zPLKZP@8LFT4as6)Iy>j#m)ED5nLx7+AQM2zKi2bes80W<8~MjHrWd4d>?%qA+a3#= zo&hPi4tAvGl9Di%$6?cd9(|{o8ds+4@iPP3wyywXVhg|Y2v??OVNXtc+PhFEe#(ZM zeQvv;o#F~mt>@uf*_d~ltMtL9c_*#xJY3KFbI1BZ)`{s<3 z|Jyb*db1C=Et8#icC|)I8nnq;1sb5R_LSl7b6sTSo$-RJVNqV|VovK4@ab0!3_8_T z;D9o&&^U4S!i<_tk2ANv(KGMt4lDvS(HIzXYCt`A3%|BHnV_hnkGIWRoSMFpX`0L$ zK@HHf1V{m>{`7F3vT6E`CC$CMFP=nwc(d`zo(F&XK;thA3_7)-(F1)?-zSj^E>u=- z>ptQ9({Rz74I!IYL9>z|1&}-Cl}@oAf2>e2afj^L+Nc-$Djd$Sp#2663_5kQ!C5c+ z+NZ{~y3-{NuqCl;z58RZ)K(nS@c=0Rjgfjd|B_FSj^504>w)`8!TAPS%jW#8g;uQf zpsD0C&rPa5I{6C@u}|~1PWZd|<%`?DYM_1p`ibCha0!g!I3fE>?y7;n;XC(MSh(m% zL(9nqP$6dF=NjRE-P!7Uf6}_zmw$t|JL*lefmUjbkl9K9DXv%N^jGO?oqXI7n>}}} z{)H&$Qj^9k@PL(qw@cq+9tVG+0!I6VF0a2l{PF-=9W;VwC-ptsUez4i_GVvD%X0UG zV>+_+`Y-aJIja$}p|8SmUss|1jdurCok~|KI$xU-^9bsTW>8no!taCFYL-t`Zlxae zb9X){3s}&6?mXxyWCjMEW>7KU;e6ySC%^ZBGeRPEa}v zD!dpNbXq~By@&I(YfC2ITy$UUn?mrHD6@ihrp0a0{zWUK-@SBt(m9(wbL`Y!>S%fw zew945_BC{jv=!9vw)VUlm!G*-ed3Obd+R4oyTrG;^ENB!3@-)-oi@m+Xd#Zj=g&*8 zOfp-%W%kEKvHAj^i=cV49hCho{3gse^IFK{;;fd$57il^H|Cv~VF+p-F)-+WhrT?V zC$Qx>dGM>vKeO>jXXM8lyAB2I01Z@u6o4Au?w)Nw__UVYy7r>GcxA@K)aTlQfhC}| zybKIF9s1xT_gh==@Q;;#J3cwh(b3s0?(m>q6jVMkFz9rGYF-OJ51kd7A}2L3Z+Paf zv*vWL-mVR|ph>P1H2LP?Ea5QGGyM*aM)HzZ8H*0uvv?mA1w|4AgH9J{5K+p>@|45} z=MS6tN&;s_f0(>0=l>iR$l67nE>NNk_FN;-zxU>fnGYD}b8D%@AD>lXV-8JGU8P`0 zw(Xo+Bz^b7W=57g{kuh-<*`Kq;6-W-I^CcJGZuc8c0aWL>2H}aOVC@+#QMXUrqkS@ z89@dHogPrF=i%((z4(scl=A3xDi@#nF||F`)ba+cFas$7wM?a)yw5NHyPH#zV?pyL z>DSla1;ubnzlMwj^?>3c&@-^|<{sJXocU{aG49ltWxb!<@fO;(?}41lx{pObYMz?< zvY4`So0sdmnD~&_GAud=I#3g4oS``8Q~KLCjHbuE*A6CcCvF} z4l8sXX9B2wZQ=Juz3!smjV(7i#B;sGt-jrGsaXxWT7!W>X9B2o?BTqkozd&MblFtK z=DEx-R(lk#cl`tkAdmu3QEctmQMLNEN6j=VG6qc%F)-*%iU*gp%WDrm;P;X=_j}J(Rl7d=Xwy12&>B{d z0?_EYhqENN3(M|~ICr&+R`d2-uIs7h%>|_-kOEM@TgoZ1QDWcG98sHxDXE92>pq;j z_*)gU&pQd!REhWGzxl%Co`LSf)?~Xk3s;CuG0DFTYML-G=uC#}g#Eg%j>AVo>#g&Q zq!S{qTlo8@n}QaxF)-*%0oCCaeqwwst)3w*to1y>OOq>)B{aH-f<`Vt3P2qZ59jrV z_s=!SS2!4bQ^YNX`_)4|-d&)s3j>4BRM1XXNvFHYX~o=kIKMF*uyR+}GC}?Iq@AF> zVIT#d^x*Dk`sA>|>tzYrk%pf4t&jQ$o7T*OHr1v=>Wl9?{CVr6?npAs>{&IxoiT!4 z@ia7VPJ`4J|3m*?=by1Lxc0)!fPU?0=dU?$q01Ylg96OM`Ah9r`5$~oS$tftUP)WI z_3S2t*U%A+>5%%u%4yF7_t%H7`Q%6KW-Q;Vd~vl0Xu6JpL1#LszKHegYGIAY?&V|V z|B<_y_xAdL9E~fW00Jq16vb>dVLB7HHnn8r^{=w)ZfnmwngFUN7#MVBLW<%&@t3FY zF5CU{uXMd_FZZ;sWp*miL6Vt}qS&IO_U`RXX$PZJz7CA?-?cYqd-raPDJF(`;L=NL=3SN`s_duH{ zvq5cpDW{G1V*=Ut%{G>9*`ZVAqSq;5p$2M+GBD`O0eLsr)1&HkgU9SsJUXH`^(7^B zZ?)_Q2aOtl6hKx`DB1Y8$Eqlplr{;pfeY=K)}N9FH1-6XXESs zrG05PH#Dhizxj7N$n_uvkQEeGXPCG4ADHlYo`a(Dtjf4w#!L%CA%z&|L=gr_r?itr zJTjk5)>}=@ii+FgAbh^)HfUo81B1>y&{#;U=cyyMJG+jYD1c_d^z+nw803ee`k zymjCLBri}UXxhD{4^A&X;!(S%#vzVT6jaJHFz74*B^(RC+p{lNO9y}Q-euj+^s(Zs z&$Ovau<%)v*v|O!iLG!E9xD&Rmn)etwZMOtePFVOcvaT=KwsG<@&IN6Dx4L(} zj+b8wIVMYI321E0!@0ud?HczR5wGHwE{;B-US$~}%mavSNG{DwtFY;E0X{A#bw+OHY;fX-86V9;3xs$ebr z)&_ep@KxPhtKljASEA+Js}*;;pi?BvKtb){d|tTz@cA5xbTNiKg8bg=YzIsdp?e<+DfR($_yd*RE7* z{1H)Y54yDiq`(gB$b*kXt{mBvG4a7f-7huMOmiN)KLXX+3=BFeK&8Ef-^Q**Uko?4 z?>HcCDm`iY*N^GpN}v%OkOI(%mWT7(m8qN7sn(>1oG5KtA2J+~*_gw_`uRKbpnS?B3FVS~+;*4eiN*NA0$IZk5( zRfh}=IvYXjq%8cT{s$xli%dv-(x&)yl8dwBwO6~LL%|zCj`eU3xN(DVa`hPpO;eL6 zU0gP1Tc_wk*Ys`#HTtBSN`0>QZ`u&BB0Sssw$F_hw=OJL4eje~0_Ct+Pm_*=??tbi zv|iC5lK*WA7wak2I?%o2*VIIypsk|9qE7x)Oe|`J#*O&82d?B)+@{xf-XA7iN z{N5>ot$vyCUfu35Pw)Nw68v&c71Rw|K=~uqGbG|5vv2`x*WBE9VT|l4N9HQr0S#P& zOgIV-$;v6gx&XB(*AEb}~hSZCY*53;qqZ+&GfEqA|Lvi=lw;m~$Hup=chOM}8! zzdJI&Z&K#}*!iDzT$ey6A9sMNBn!VShxgQ}|JK)iw$p6&gy;9qPkAH>ou1gSADkw0 zf2SOuJ2A}afUAN<-n!`B90je=RUA7()uNQs*&WlF*3=o>glzs)V5{8i%xBySwPGje z&=O_OjeF)uu`LVub=tG@REE@oH#Q=7p^g8YE?`GWO}@8PVx4jEgRgFJYu3eU7A)q1 zj+_Fi z37>fL5SqJpgJuS$oaRrOxa)dMzO-F?$z!$fzm1&h_CtpscZ13Ych3hxsa$(RCoejC zMtej2M3>VOr=5k?-Mj0+j+FZu>S3UHAUpE!U(8#xipZtd# zY~hVBXE^+-i1=&qShFB#C1~9w1B1?9&|)?Z=iSq18Mn;3uD>jLr-$g>Ne_BgegYMs zAO+#z5sc2hA2vScmXyqY#2`?!S8Tcev?HK4JxBp)sYRLR<;$7p6}_WA+*6G(KP0)$ z=2H+8sFVjOfLu;dYE;lZL!4b>zsJ4`mM@=MPtIe3mXrHIYn(0omU_JGoRc)o_So){ z0wco$@uHIq&`NDTXr9x7OgCC4}TYhIDiHX85nf-gLdNvd0N)DvLTadZ3d{2Xw$8 zd8eWDzw&$GE~~|JCC!gWE!x|^3AC7xfkEdWsQ$F@D}S*k-nr=4LQ6^SGn>B(XqA;5 zfmZGZK_gop&fW^Q0)DA6FL)XvdSu#JFPr0h@1VK+5NMf)zNh=jh_f#eGdO=QcUfG& z+CQ@HtqbG`8l6KXU^h(o@4uR360b(LezTDmQ+aj4mJQJEY74)`mp5|WG<>-y z;8aTKff-v<9wzrgOS!|Kg%TdlsTF+|^P9}q@8#cOO6QIov0Co&!tP=YWBiRj`*Z#-0?p2XOjrqa!!+?3K^Yk*eEq*D9$c?)889JW z60}8n3Y2&){3a^pzhjyk%ip)LM=p`UdsEV0QBY;Zz@T#q~B>^q-lFm+W2{o0PsBG~&;|pmPD#DYo$YRQq2gMs>erQE+Mr;{o}cg5q((^k4>_!sqvEGhNgJrUH;WMI&_3fd}b z;b+*z?Qz1X=&H@8oM}c^z5EnbFn~s~Kng&q+r!yA@b`zzqI|+DdpS>+m3Dzz zU?2sc?YdGx(263E0?^=qwdWPiX?vuCwlQ3La3^c$ zo8{6n?@^ExP12YX&D zUb6NOyVh*xYYOK#2*13lsqG9MBfTLAcEgi8r=AHaI!5_(J?7ZC+~VVrgbj(`1hs7~ z{3>^-XrIehbEsoBE_U%Q^;SBp4yth(7<6uemWz5gue$0VyuLQsG-3N9cas_;y(5w; zpri&;0BT=LIhhJB>f*9L`1fH-)28TtgSoDEqd_fl1_qs5pwTrq&p9Di|7Y0PZE0F} z+9vR8*31OwHt0|f=m1y7NI#v%X-7XjPdlRfVA6JncH7=3TULVFa10DOw?PUm{GQ(B zieOipm$S)ApSLe@IainHMNlshqyW?^^l-j5ZT`#j+miy#{;mB}K22edpxb585>*BU zojaf*pEA!=62|uYd}&*&>mBnKFA(ARZ|Mo@+kg~64u~i%)GsK0ALxGQQ~|%(4Uzvo z5BEdk;w~uTSoj5B)+dL4&6t1q;EERbTWr zL}gp;|Iag4SZ$8_rnMsOJhc6AAGA2Z!f)DEh5Iu++-qN&U2=+uy>(*V=S1k#;R8?` z-@|$L0`<1WS$|);@7Qs)plkZ8ROTzt_QL~^Nx`1hv)Z4vL@KU)eZqRyI(6QCGgwlg z^~Hm;U^jSeTe{2PN%4#;bK4uwzgxtfu~{G5?|uX-iY)wAq|K^{%V*`Bl~CUBM(O7P ztF7tKHti$OLMjjEz5BM7{GYT)eWmsDB|H4i*Lrn&Lx-ClfyRW&Jj-58ng8#V%jplf z1)rX8o-_Mhb{sSu9?O8;5dOFQ6z_xGS04x8`1B)V%dDQ3si0V7V9O0;y1*f?A|*o*Y@x49j19%2H3SjnU*gSaJMn z0I2X{V9AQ_MbL;5}o?_$FE1Ac`OD7ooAp00v3K3oK~Lw8|J<= zOZG(0$DRLV)zrb0&>#h%ZATu?S*stl&6t&b{pyPQExaM?`QNNG12woA7<8V4ibE-< zo~H_zOZMytp8Q+qgUREqGUk~o(4PBqP$8!58F8d&{S?M2xk-VV8my}-S1YW03R*@F zG68Zn%kRXG4dNVY4!ZFD2wm+QBa-`U1vDgIfa1i$uS&=AaKZfmxsBE?7V{(Oj$bPI z0&1EtFzCDh6(k^yGe~IonkIs!w)505z}}7<68O=Jnh?*&T|1T3#r* zmdJlCVB?pF)t25ipe4&71(0SE_oYlfmHd*!l2Rfz!K^7~>l+k7Z8!!7omZeZvGAMF zJC|c_YuLIocC!`-s~P9|$8|vm&0d4t;^Dl_W6gVZ173pz@-lbbeVfF4*RewP9lQoL zlj1$u*SvjvUFgg?g(Br^)BL~vKGb;$njT(5b~fpJzuNwMsp^(x(>k&@Oe=f2qkIE& zl=Ush3Jbqk|JS5u33Dvhz4_f1qu+vBLBXCcel%Y9@XhLXOEB&V<_q+J7GF|E1 zzD$Y7a^H(%Vn)z_dJl?C3%}~zsAJ;69ZwThoLjJJsa2-yfsK&+^>p5YW+6PBPb>(P zU~P|_X!+wyNTKeT#GZ>KpmqZTgU)-SC>GH>Rxwb0W31Ejv_>vY!aU}AXna=UZQmn|a2*Y25v z`V|ZeIv*kR#St#iwL$Wqc#jI(-TN-dTztFy8?+Pj5mH~QP5vBoc$xn!L76h!m1~!6 zU7o4|%CsO8K=p;br%k@TXxDbUw(3FrKZmfkBI!`)kUDx3{n89nmwG? z&N(K&N%h~Xjej4+@CMrcko%YjD#SqwK(v$-|E?EbGk3kzY&dAjU$%<3YuVf`P#=$h zLFWq(_~12Ww{|qjn~!Dgr66250}KS(DG~`}z2brSrX)vrXe) zh&dex6&wr?DLVU4S$BKiw*K>aHQ2Ayx9qDbHKAMb0X3f+3~c zchGFLhx66^mm-cUou_Vla9G5;bXD2m(&NxZ?+;MEkaCLl4Ps>lJ3Q-WK9$|gnen#mhdpT6k%2+yR}y$|Aa2`6*VVB}^{4hna=hG}`<-L*8tACUE_)TcD`4{9sfV!P8ZZUrkJzksiyJMt z8iUrLFfi!+0j=V&@bin9SJXUnc7$=W-lIJ=p$n!cbb?wQAO)Zh^>F^Vq3Y63=N$Da zj{Q-))wsX73Y`YU0Z0KTz@(f+8|E3k*tjlj^ZXeH{_}5L;d((1T2}u7O)e;VzJDIL zqvc4mYLg4skq0>{$@6shp=I?S$lcjbGbA~_I=))_E$&Hc>hWym93JjZkl6eO8tSm{ zvs3bn``^3zo@Pzqqg1xdf6UwMpyRavKqLPi&NnB=wd^gkxw2!Q$mxp2k81g;^FcZp z70R7ID0ZjyZ}u&eCgUyWl{qH(>? z4!Pdi3SIR3-w~W94;%_h>{wH>yhPjHbg$t53r9FFL6W^L18Abd!tcAz{Y$BCzVlL! zycZJEcwFr(au(z`1_oV*OW>Y6*BZSu_pR>R@SJ(EsL^ASQ?_tBWExkO5tJUJoP7SO z8BUScWB%s-xbd#q&)9|MHbat}E+fdhfu89T1w1r1?~DpN^f_9!JUVTu*<8rzfi7b! z*pc1)^uBg)ReKj5ep9Xf(uT8FCFemp#kx%Qz+>iedsnxvkzH&1>Ehok&sBRAWdao; zHI6PbsL|))e7X3A-|u6U%YGQucddB;uTpWxHc-LAz@Wy0b1n-Qm_>4hCnWhSqU7{mO^aZOd*XI&5N!nfpQcBgDwkbtk}ZO;L4Jx z7khpuyePlyky*5U>fb53kdYi+R**su=RVDw`)8@Bxt->iUZVWn=bz{E&yY2ox~w4I zxOuJ)4>=-b_W7UyvA9K0<`k!gORr3EbUo+GQ zQkd(qgT@9e{FDOUhxJc4eXv6HK-8l)lvA zwJ5Lrmn>7?H?59+d=}@wKt>OA*&+M0OeW6E=y%b+t3IjhfB(;3Hmz=ZBXF|U;rT4@I|;U_qb-6(!d>+m-Jo1lT zX;P6|D=^U{{z_KIPlZrWi=2T$mm8Gql|2((nY4CT?Eb6PU@yEX$>{Bqi%p;+7^L7U z*bSGAgbyl)B~+}~zI*~-yr6ZY9?oIOM--b9E;sle*?-(NTj7FCxGktf&cL9{3z|ESa{BD?b^q*1KR4~V zrSi_g$NT9TDHX^8_`1BHl|@0GQyo-$4hsJAF7kD?@aL%aVzKdo=1o4xqQ2Nkm+hx+ zVpeqKt+C|ss$MP3p9~px)8z*hs1|_=BzhX!_3DQ~!EO{Hy6l*itMbSbe3)vPl>3 zu5x6&(FB==(G>)(B=K-AdK7xMLFTw?$%QEuj|7fBwh&?f%^@)`=n8>$aOivLl@#{g z-1%B#%he~Porj9`f)e6D!)+i1VPH2{7N&cglodMJvV8hR&mgM~`N?p1$tEsf87mDe^)`r*{242`xZ`LF)%SoDaO>X)3%GyX%8X$OpVw4W6dbw$}>KgZOcSvJTR|GUh81Ko`RCfIm>#LBp^ES^u z8(n#u@46eLMXDoZi@earWY+VV^JVu$P-O=Z^UP5WUO3ItL zehTiAYj_O48k~Va7j*J5W2E1&%SW;dD*HD+JL@MQ75!Yg+i)$Y&(FZ1D+LvhiqpO9(u1>eXvw0d2El#?=$ak-9L^-of(7b!LE-*JcE zbi-P%^UctLR2J0W@^C(1$1z>8h{ba+Pt$ehxr&jU?H-_}2?K+!EGSlkJw=WkaF;8* z^6qPzEnDOEXyv{8p%=F5%0f;fSF!S$w^D&^`n+kY>ObD<*?*(S66Ajd23>hJaMpWy zY9+6T;*)20T3PB1Hb$mcv@eFV26g2@V`3i8&8plN)SSzXgjjOE@lE-++;)*6q!pwq z4=TjmJ$FVP@p1aZ8S-vZ;)PRtrtf~{V**+8uPYB3!H_MLObJ*SH*Ko=)OQtKXErWM zh=t6U>ncJWAIM(}`4+S->G{3{F3XSKK~rT647$po zj);Zd0m~&P{~ueB)IMMN?nmdzVK0vC1od@63P4qphx6-Gn^qcboU$dm>O;`QO3{Zb zD_NkWy)tNEThhtni$d1(7zrm!p^K~b-ge`t*xw52ck8Nv>J5EQeeN%pn-uoXSQNBs zc5mztK|Mu7$oVk3Dv&ew7pGoUv^&I|mY(0zwg1jBtrK4+K+7mqQ0-^oXL)(L@l)yi z{3RuiSQT?uG$w3Z3mWocV9-?srA-g#w+$utW1elE@Zh5$!+HgYRki)oAwwLxYM|b8 zu;)(pEsI&QwZ8ZJhq~zXnNEB+IUO|i!N8!a206DmAzQ&gMk6M+b@iLLmPL0OT7S1g zM)q{oL0x#=nWY>)Kv$Sb{@`WBW5~&z4oN!g5odJ zw9^ycJeb=J8Nk%l08Ki%d#-!BW>e6`zcN=6N-~VJ+?8f~1;j!!jt1nQ&hvlWw`|&c z_Y;q*?-sEg=MvUgwSlHa7#MUlAqRD)|KI6rQraB+A<1P;&g!0nlkbK@rZ081KfX0>)pZumC~;kJpdEFC6>?uBgU*VO@4@~)l%&h5Wu zzA%-VVU)`ErRk#8e_nP_atE0JIp)I9BsZn5CEt`WrG>S1n!@)Ri^2DQFfi!qfyyWg zzgzdOSu3s9ZuvJ++Q#pb!}BlZYS0F!9^{ydgFB))FK_#yDroSqEz11+4hC**(0KZ;^>(#huYWI8CRffRt6Y=NF7hnl(e=Kh%z_t0j>i@N7K zuAdbJwE`I!boHgc0rj==@`Pv8JLMm_yscL+QVsb~q66(;7=RXYS@_+tG?KVuo3eIS z@2oTYhYx@2JbM9@VHg;64OW9YAbnE&DpO_ewgeWa&eVvW{K)EjAthQ+C1+k={bK5~eJ?i}-1z}&>@qOu8iM9GgFRp9Y%k>Ay?Dlnv)*THgQe8>$Snko zB7qb@Ru<{0=ou~(%3G#+nnCI2)qdTD><>U=Knx7JMv#?7tt%t$c6YysyvXPvx^C8u ze~%gRK;;5R0Vrj8IEN&QSIFHdyRx8o`GTxj?uN4#7=cnV1B0$HsA?|r{Ks%secRWD z0)d%-;|~bW_$*bH4b2zEkTWogT$~ODEP7UZWc@w9c9D6H9$rX-mJg<&y34}PVTD3e z;AG)L4AVL%{bV{6_UpuCXa~d;G-K}JT-9-E=Ip~iHv1iIahS5{-87D^zd)C)<&LK?lf50&|uUhFu#{NK-COMH^L|9rau8eL^z&^3oNdT*+KzjvTa=%Lxh z_B9im{Z1-|_JC3nNCBuw_HeGtT&J6>xXXw4ZoA=jMk|?+jkch408#*H^d@dz-1+0h zT2{NL4<<#*FQt7ZBteTHb5NsK-}BF(z9q&28dsKliWi^v(PZ*v$!chdvJeL+xqXW= zLOyJ0TE3$3GiS@q1xZ$AYeB^y1B0$*0l3!7(Y)PtU-L-2${W|`x(6Eeudk|yEZNny z1hq^(oUP)b_w2EAao=*?QuTvn@c~Wmsh~k3kO`ngo>ERz^4$dYADU<4e!jP44rBJm z)An~k9Z?1bT`SOed-|TsR^DDUvrPTJw~f&5-RHag)}|i>jn9GI)lC`$5VnTkhR?b@NVV3**h9ZGddhrw89a#81JM6!1L;j4${a4?s1iTU1v+U|)P#2DYLDvqn^3cQi#(D98#L1P3 zfyRH2)O+j9^beZ|O_O$@weEqQOLQ{gWNuYWZ3sIu@7}(NRw}B~L8FQw6Xt;3aQwaL zd6m+)^IjK<9qum|;hE&SfK1zD}o`Jp@|T}I>F{v(xxfish!-c}0K4HWPh*zsuDw#liyzz)d?&D?E&OgX#E~wbIVB4} zjrSGDYZE3fzmTuAJLZIw`O%4Uq@fBxLGIxk?C&T1J1Wy+h1Kj_$Js9K*B?KI3>N9S zfR5ada!OgPWwS1&?b=6O!yi1?y?GwF6oN+67#MV2K>ZAB&u7u*9-LQBectK*>aM=f z)byD#sUW*S3jTo|`C{jmd>bR>xjBE={YnjR=lLgV2yI}vfd;lM{OtEuo6bG*RHS6_ z^R(}Byt{A6--V`0H_-5#hjWvLW<&MC<6ZBzOyBtJ=+^k1OJ75~4{o3qS-j__)?eo{ zO+QV`@>S28eMgwF;?Z5mIa<2zki)(lBiG+wR;|pUp;vu7_>^?fn+wOFMX?9S3Jbr7 zi;I^>b7;!{cx>LsdT`fo?#QW2Apzw9s{K5i*JUK1So=!xxDrpQy({Cgdm;MXknP*L zo}fYHV9&oivKek$e-;RG&At%)Q&mwveI7LHc_x9w!Sh-2zp2uzUTt7JY0i*V(wLIb z1{t5!^#bjwweWLl+z^%A*rW76>Sml~uk_ys7hZwd^b8ETUZ6_N!})`-z!m!+^VkDD ze>W!GT&eGS)E3l4V_?wr26aTFoOq;GEI9P&L&?5*T3%C1eRL+h0u2E%fE0ij@t)hJ zZRa-cQD1iSRM{Hg>pW!%)1YVM>UwVhJM!!U-NjMU{LX4FR1VD?#VYHZ7Fw2huPWd z(mR+6pU;@*qYCOqf=qY^cI4yawVTurvOT!mzMAWdT9oO`xh~Kah(G9z1q;6w1{*_) zbfx^xRw{rv5QPqtx;=$4mS|uJ36N0k90kuq){nt#{^=!3I3#wL`Ti&bxrv_@vGBD@{gEFs$ zUsI0X-jY1N|9%tScYjOh_&cLx8gxV}7&K7f;XLiMdg9aAj8A2LHEX|>oYDU9eg>!o z#=xK(0$STE<#e(#$)2w+?Cf2R;*9DO9~I|qc850ILqIKbH_s~?|B5CbQB{5^FB0`v zIF{pb$bQH|5#5l*U`Hkd3!eC8o_^=|L%-!x{eL^Av~WTzwNOy|+QLs@<|Y=+$CG$> z{nfnQwq01se33k8?F9paZWw4V*~9sDk3X~RI13sO$J z&(-sD4}CKHvXN~GpSXW;;AIccxC6)p&{hvO&rj}u8b9~iu2JY*bfoH_gwBT4C}K(H_nf!CGdkUZj`^IVt$&9O{{rS8oq(x<`O|@KR14muzkXUCg>`;nnEW zV(Gbh@&7r7kl2hk51#P4`a9)SX3JemHvYOp-!)!8m=d=RvLaVE0#eeJ+~e#Q&7Byz z=b79A;okKE?#>AyoeT`RQIL{0e(zD1<1VuA`4_!S<+{J`uX2VXC^dr=fQms6=Vu9u zWuI~{9Q|D+fA3Q2o7RGFZJ?npkOELiE9LZGX0y7g%eST`(?^Y(9({|yW_LroFj1i7 zAL#k6JM;P>(+^yU{W0EeI(eUOp8p3lw86lj8|?&+?v_v19n4Qtc}?bhYPyw_KYex3 zAiqhAEBV)&tFa3~^(6y?Zak<6l5$#iyXDYEuiJ4i(x(TTrt0pk4NeDT z7?1)`&8zPzD|ggXNAx5|+~1vx4=_$kKD*linlIuZ_bqsZQZeNbM?nwH(|i)a3eOe&c2R81iOn&c8e?FePhh-JTT z?8t~`I+q-9r9|}5>Xn8W&^B!%WNX7I^OK*pM9G)&=_Ccb5ZHbfIRr5W^H- zg_MwG_6e3b&~8*JXiUh$uTbRe@>47&Mku#lw56Ue50Ci+4C|`Iu`#jyh;(~18 zwf$yH)2@G1l-elx2eODuHx)EnE9I1VgJ+Fy$3Mr7XRQSfu>CrvepejYo=gRG2CY5s zYyVIXUb=DP&$GwQoRVg;dYy0z8W*Wwz)9|mj9|c*V*Asxvwz1~ev2$;I`oddhy>GrP`nk1zi`kp>SH+OC{&cfIg}Som zcg0J7KTFHG%q&^=T%6=@aBM*(beuK|GCLXnMt8r-Cf`-_FZ9`_bWHj@qjC?lMVbwn zoxGbL(0pd$AwA7!FOzsQ(~4y#JOb4;3=F#2plKQp=VmF@huZsno0~prv&3HE^Xa{t z3DU{Hpqm4kolJjWt9iNLU-FSfXyhCh?n@w?|=kIfsQ$vzLXR5RA|^Pe5EOd|Mhlo)r@(^9;+{4 z6Z*vkDuNjpbPFJBdY4oz+GX)Wv0{N{@#`dZmGm0r?~q;Ux&=!Z7#M;*CogH8G)ZP} zjPblxec$h_K4=wg03BT{fSfRM;CFNj+oSt`Z+8AZ@@8t&=il8YpzVhuP*G&zr~k=^ zSM6lit`jr(+~+tdeNlS&0&;VNZV{+m>EYb9_2%B5J9}I!LZ<$$e$*);Ui%Kzc41)9 zEdtfRQckQd*NgoRld9!7(z;;nC-FMw2aqMb47x?2)hzLzll;X#Hw(--Tgqv;vGU_g z!z1%lK}9eFgKn`WIBy1uE@2M6v+z~b!f%(pT~oC#W)uhYR2dj_OF&~F7Jjl~(g|1Q z=T@rQ?c4ij%Htl*L+?S0J3$ISm79li$GXkCvUz4G?Y}F;cuZpViPt|uppCs!P{NUN zT2Pq6q0MZuf^QXT@FC?>(feLELlaCXC`7G2Sxnn{RD@cVPLbbPJ}aT)-5#ELP?w&8 zLASIV?8va%9b0dnY&AW<$%Xqng{CZGBD_tgW^KpQ?$F_ssgiW zDckj=pfjr`&06QZ2~1qExfhx zd+|k=eV3EY)(;nsFeq*P8kT)xJ9OT^610HG!}*i>(p=jThnqap5}2bbryOL>*$;|l z1_s?q&dCFFz|6_)AKS{0I=W;eWNyOx`_ zl{0S=v=dYXn$ETGvreC&d`|6q-``ZL5}6>sokEMwL1)aXLCc3doHzGdMCBjLxNhNe zxcA|$9YXh<7eWrG)U5`U+3}wDA|#$vooZqK6Z7Jk-M)~wnrhFW`Jx(fc9ZqxKhsoJ zH%$s_Km6;eY;}tr+j6LaT96eMes_{$N*!j*w-+(dne?))BAshv-!e#Bt`-#39?t*& z9bW(Ht@e!jBASAZKORWFk4^{ePh()vtp&|OSbP5Is^29w^Z%1=i|rWwt>(qWN@hS7 z%;?r$2FJzSkUQHALM^u4cAmNG-NW~x%6&Va{qB0uNREYH_-&!bJ&^{JFS$4bzWz0# zC!)9+n)T{I(-a=gVLU+r3(FSFTk&oB(&O!?tUf#LgN9^1sC#YgxmWFl_Qppi)ox8n zVqQ>RcgObnBxs_ohiurnUL=2dPwIbpdC(9PKt_mpWT1F z_D0@~gW?_Yxwd{haTIDo3ur<-)^o#OJQ_TJ!c?)f=1D3<6Jrpd)*2E5RYzoVw`9nUDTvzhA{y z$1_MvOs&`is;d|nbUQ#(>lS|DrhJSk5qDg^d`gnJE0{HBZSGQNXRrgbbHT&8!ci^F z@s);t9>X@Dyl?g~N9!Y@X|e+}T_feRzk2#%IsUt*LJDzDG7j~39ToWZBgozjbcz5*wp;*flR#*m+{-bx?Pj zfkC$mG)Q9M7qn;h5AWlXFLrMhEUnag_q;t!4;mL;piyTJ=TowAamMGWH#lCc4*X?$ zBFZQ*61q023l!v1PKw(*yLvZhuTY=52~ve7&MRIO)%}`yD?Zt;>dlfm?;T0bI-r>k1_s@JPp(;4ry&+~MHt3d`c|4{D$a6{G;v0g-Z=q4;V+!Ne`EMSuNTRKJn`(d=3- zP(Kr-05t66=9z6+*{Z%V>XE=ok><0Zl7XB*+My%86Yqo5q|hG~RiiDg%4r!rr}?!y zpGiMThmPz`2F>qT_^mL%5_!>Y_j6^fO|Ey(cV_(#PX!em3=F!HLDLf+&dmy8!d)M( zFFDsfXOh(OOA?3U!4e<^puUc^=URcvb7>sAF3+j7{}6TWS%GHMOFc-6nhd$BOyKp6 zBYgs;s=Nj|@f$y#T5+v+HgptaDrnW4g`cxw#j^hBhSysIY~RbRbZvjNxg9!4G8J^9 zh==oh#(IaSg<10sX!+e64wOPG_i2jYfJzTL9;g{!Q{eT1SKX`I z&`UY11=JB`V9=coT8d@i7ky;!_uz7&%KBdyW?Q<%UE6r&Ij9Q1f-mvM-}T@_63}KxQpMo>W13R!c~pX?!zolCm`4}*2GJtg}<7% zO4k0`o_@V*)iOPC&-O4-hGAgPoda5f;o*F1vyFjl!8sXzF6-jfQ+Xl} zIs=35JkS89g|8d1_o<@& z!Plp+K?{(1pvJG1lRV2An_CZ7$Msrs-q?2KxX)J=V`v#Q4>XwU=2_OF?{>-MQ@;3? zi}T}uiOfnDnh6cbd630R)d$)N#V(wBvX19V!crkuo%Mo8p+kQQK%>qUe*5l-HXVE! zwfpA}#(*!vFYfVwC7+eOvZ+*)iFti#ePF9&|$cn+rhcLEkfQ>W@g{D%qvsPmBI6TiD4hvEUVG zkt+j(?m~WWlKU%PdIc7L?|A3ArEdq6REc`^=zNvV!hnLAW|GKpF z*dzbRy?u}qsB{;BnoAzeg8Qp&&Z=uVW%XaY>AUUiMdhdJ&}D&(KutC`&xkW885!mN zo%+76ht03$xx}Xv8qhSk7_u3EU*qxcV7p|?X|22uU#}24addYisJ>)i&|Lyr9%$j` zyIfuT%F_tfjVCRRG+v(i;a$pM=y>%KP|f4vd}Evcg%?=|q9;ujJ;S_qwaY^8XwY6D z1_s@wpasbKp4=)E#N#*onihEXie}WOicF=cN}!|$QUIC9ng8WO0@EqwgHGA6Cas*e zf8p!D+d;E03=F!*lXa};e2HqzOg0xB0k3XX$2LGy~U-`_dW zapK|koJ&q~4c|9kp9-B*TMjZQ$TMi+0>y3LCjV5`^p=t-eCfB~NH}x?bUCD2?6Et_ z>2Nsqv~7&(F5|bn4-Pj?1J&6K47w{I)uQ*_TwQw(>CP(drGDM<6LYuOuLMoLf)qfi z#r&%?w{@G@FfPZ>7sc6{Lz=VRo*yvM+xyBd__Vm(j#eF|M$cR%IR3eRQM>o$o$3g`wkO+X5cg5BU5 zztOC`-2Z8%g}V`pmeKKVua-e)Y1e|rf-L-O4ttmHH2t`Bv(1Y}Q6XV_qedra)>{kO z*yrIa_xz#7Qn6)^Z=7@g&*;qWH0$dI$j&C+wV(lADW}hVpOhHX#XjYn?EEuVq@&(5 zyB@OZPp@A*!?|;3 zfAx#?hwS$Kv19s?x4ZN7b4O^!x*jrS?#!~@rT6`#tyOC)MJC@q^-lAvFw_m}L1X6e zo>>n9_8)n3YEFY^p4iP<58~Q?{)86A8v?)~$u}V+<>S9+^Es_!-YIMA{MRx&4-M*# zpiyTFKh@`J?y4v5IJfImo$utj)~xvzi$Ikb1B32H&>*6RvwHqN`-cZ^`lPapoREms zRWI;Yf%*b`dV!QvsBLuMmF=G-Pg=R!Uts4Jc^kt7&6}G*B~6g$)a5!;ugl4W#h4h( z{<-U*k5T>#$WAxiO^_Pr{!-b-t1lVY?|u4ZvVX(zeH&QcL%Y?RAvMnakBb+&NJ)oA ztrPcre{EM~&z&A>zYR=)KLTNid)GXdIc-U2EHls#X_ozAUU zdh^iy@2-1V<_2r-`Q8euCm0xXw?GbFlds*w7Ukd6n4ZF9E4-L(@~zq@pf(%>gYH() zSdfL^zKqwNDIO*6Cmxx6++u%s!o^4vXmzj+G*IK=eCem5cG;OsL7h2Fuj-QSf4X>E z1=Q$gV9?zL8eP-(>^$CIbJjLiO;=dt%BqU)h7_||Ae|rukZr1eXD==bOyrljyp{XX zzp2dZ>+OX8KoZP$Q1-X*i!idg^yc6!VQX%q>=QSdBcz;DLCKwgL3ameDAdDwNy#zs z4HDmW9*K|^uzve{7W{(at_GO^s&S;8#3Cgkm{TUN%*=Pca#cV>W%d$ZQ1b|+0925~d(Lz?ntVx^ z;jk97xE6cVY~P#4@}Sla1B32v$S$+PCHITpY}f2~BdKGMa%wcMm8W zEd2iEl`h$Jh3~*zll^bvw*;LMGD?9qwDv%DnN2+?wbXjc+sRosrSinX>Q}rs-3x7^ z>;c7vl+)Mvce-h}`qHHg7b-4%!}nTC?>%TZo`FGkFKC?B+B4L>CG&=(d#8uTg&@U# zPnEhk%RnUyNP#;zByAY=Hc0K^+;+X)(%y9Cg?w{$4^RLxFzD_Bg@c7(h~2fNo31vv zKYQ;Q>HXN^_a50yXp3|oXwb~VS>;&V_T?Xzy=qNc-pbJ@u7A_&rOKyVU|`Ta2-@nR@A;|lNzr=swjFiOGxlZb z*UdHYs0VdKK?+jA0Tq2X@Y0N9TK)CwuSB=?z4n#Y^M)>eIs_W(u<)Cuo3}dHoMK?mJp@`H;NdKGtI_&u;Qx$q(s zy#kN|$f*U4o*&%XKlHBtQ*%jqo9;1-2OB~`V?YcHx<^5cJ_|pKo?jbyKi9sx&UN#i zr6;eSi~UScl?+k3om`1B31{$cUDy zv%&fH%(acT_Lmi{oEve#zqJ-Lw86ljdmJ*NC2qI&kWZJ#y$22DXO^tuI_kbD5Hzw0 zQULOehqE=qnf24A>{X0EB`xNAKt=BLTuaC{Ro&yDYQfs`d%?PStrzdE)B1AB?8aXy zp|bW?Xfx>qWO+ky$V}_ZIltK2|L(oD`CQw-&TlrLq{hIYdlJ+#xA5E2ujwhi$VgUi zqd)<>6e>eC5e9x5K_lA~NT8b5&j5QPL9@d@{Ijvcqa@^dqhky0@nFrG^bNu9m2Gl9Y zk{dHk)o?fN?;@X%|IK4wu;tXgStpd>Jg&vi zaoW?6B{vTl&a)ZnD<~Zku@5d=^QCxd+-#^L&wzql%E?NUna#sL-Q)e*gL_IY6j;q_ zc@7Q9GoU3m)}G(i*EdBoYl^bg-q^+9tiL{JYdf@$a|SZc`#56tmkAft_k9fSTF9u7 z`hVMb=+;Qxv!D!Q;rDZ4z`@jjRW;={OIut&9OJ9DaDeV~I|rHPHIm%Aui{qG3qDSX zD-k>2JZ_50cnGO+&VgE{l1{6$<|{v_zRM7l@U<{!m3_^r7yCht8wLj5bD&{2SI_7- z{#|S@Lbu-a<376C#`g2Gw*keldlk*nH@0;vM;C{7Jov8Q1YK%!0hIMToXby0_@_%Pu&li?Jw)#68?NpL7SJl` z0;rsnbh3{<{C0^A^UUNuuYb?(bUXRJg%`B>oPk020%(pk*t3*9ZkwF{(YYbFr}^Kn z|Ks`nr!lnWevt=U!i3qkY6`dL~pk?GzPG6M$ zlV)d6zbi4VAoY$vpZSd{e$cXMkO`nBTbbus)mzLw7nyPsSI=`_;dr?)ab6{Kh~si8 z*paIm^}F9cdbjcAVdJ;b|BNzL?(T**S+9UbIxYMj#y{kHA#v;u%g?%xN@t&>hF491 zmiAXc8#FweZxmRXDy_?1IEN|PA?oFvKT_)sfR@oSFz8+dEx6V9jJ|&N&9s|Qv5Q^q zy4p7$kFZzOf_CMu)`H!TGNncHcweukK|p`-T?dBQu}i*!vK#}0?ln-_wD4nk75}}( z{AaSPLmTU)#zmj^PkaF#*}D!(-5$;h3L1Ax+1>PhRDXCM%bJTF#i2K$b@z2pTSm(1 z&8`H6Jq6r;)1x{W1uwYv|KFelt@W;h+Sh@e#V>CJ=Py0ENPf@r6pn4Pm}?$!fQlXl z2Hooi!H(P>{5dOn&gyq990jKXglcr1Jf1?%Rnxr*nsl=8TTv}s+I8Qor+MG2zU}Sj z*M79hg*NtXg7znQIA`52J9%xJPEdxs#~zjR_+{4&Z9yG!1_s@mpb24XPZ4G2iXQu) zK7W(AOZm6#`Uwr{+n|!h!?~h3WS3CTgr*w5y=N;9#xB27umiM#je$Y; zHmI*7BF~3)aB8=JzMf;vAIjiJbdk33M$vGUtd#pDvtU>JtseU&1?dv}(6#Q53c=y9HoEet<%~PAm0PR5rYzsPgFj^62S{1{ z7&PB&;rHt+gUdE$*S+#4`D_1|oMBbmybaV`W?;~L0vfmXa5gEAc+GG+>R`J4i?e&= z&o0fLYXVaM>X7MsvhT6gTq5)B{s!G`EuUYBpZd@E13Dx2q!R3gZQqspON6iSEcN+$ zJZ4)~kzY0sXe%HCgYHw%3JME9?LLXeXV#ckINp5nEqYcr&t(&cCm3{}fm&o9&N9!&i~j-zgn%@a^mssFOwb_K@~g)&FfkCdE~v=bz9dOlzO11hvfvtqup709l$i%j#&+ zrD<~~A3l>I9jEE1`@f$7^qnDFvm+1b#x;@u-`Zb}7F0aqfI_njvg)Ze(P^WrsN374Lx%<|%v`%uq zH~)PasF?^d0hBg_Jl}Nb_#Lo)_cYesK)8A9=JoGS+k$3iK?+`gW0S*E`LpjRG3LQNgNG*k~pozJSfK9O6KGpG4(a~p~LcT zKv~e*^Svei(Yel^^<^t+yDHuWe&7jkg)Y)~D+YGtq1X+)^On{gzfzPPYd!D}pK#kOB*^BMsIb`E$H!-)f~$)5I~l_r4sr0uQIi1yDnifkF2(WdFrykqWxJ{`T+k%C#TGh(@fDQAJe;ppd92M~Gq&p0s}D{sPiEQVa~;%v zVqnk(&y-qwYMu1{^v1cpreA8E-JjPh{`>1OFher$SICu)IjbanLT@+9xz)`uKIN`I zb@#O%=tS^$P;^`PRlY9gJojAo$x`1B-R(Ua^712dYau3l2jvS7XTP{Q%ky?+2T$A) zEv~WX|M&Fr5y;_hy5B*q04b;Mh9|CsZ+Oxfbe?6h;tIJXaiPVanudWv_dBR{9P9aN zcIo~l5xeEq&nTF&Wa@dvnG<@Ub=D6CaAY|w*Yqxr*`T-Zergn?PBPfkF2-Ximw)+4j*L z8Koz^^9oGAtz96@>E+Pi06HlEqyXekWzXh_UAz{l>627k)~x^0I7#4qc^~9(NL|p` zER2zUk@IzQ0@yEno4otHz3izL=lrSM(4}a9K}E5Jp8)e6mS(S2-SX}0mM*R?y}2zt z4I0#cL8YCC^Sd7XiBcyueD|-4nx&F_tm|Jq6SThg3p%+m*mJor+rfDc7dV;;6}Xnn z$eeOLT@hLg{(}tE@W$U+%PnKFgze4O#g_T;%rd+_przXk47&e89S{pY6LX#3HObuv zjAt6|y!$$9)+U!6Xx{vP1Dw0RTo9M6wfL}L<)a8Mz0pvMI2h`D+8v@)g6VUviNocsL1ZMCjtZL5nx z9dZT+J*Ii!L|eV0Y_|6OS68KD8u&kC#fC?8i$UrvJ!X&_Ec|xXUt49tDCE;1n*C=# zkLxn0+xI|rGcf3}fU=;6^UQx+)cSIh3#tx53P2UB zl#|r?dD%)n8*{mDIUTgU{=(yw$^ob^I6x(>tLLYAQJ;3k1pPF*v;OxFp@S8Q#cLpa z96e6RaUUj&QV*`rdcx1Cn`bvI`^H_l#R8BqF+DDj8!Y^a-^VQ~a7kPBv+UN4ZxLn1 z<*OZ`k;Mg?rtomC60bh2&C=U!?H-=6AvVT(=PG;9umS^v9ye%_f|S!qZNmjWuD$)= z&$lPeepk}1Uyb3A84x{gP-*Y($zpt`(CfgM< z`^*LJSaR59SJp(BFRm5S1@$W!81#5RE0it#^wuq3e&0jq`ie~TZ-o=xlFdA7A#E5v zUQpWfa5h-&esia(7-QhPQ(Uw;EvlOyG$nO8dF-$gJHqDZ4;h!!;{(lOSolpVYT!6Icf&6A zxBL|>H-%ii?@V%sBsqQ+aQSem!Dz`jL+S6|%RauWdc2!$zx@%&LQ_3{Q1vL~B>6bv zZJVucorA?vgN#4u@q>2$#d`*3{pSni=ulbuu=q!ie^xcm=_jDoT?`C* z{7=D-{9L}wWw zAFEvw|KZn<^L0zqK6IT0WjO{0Jz-E`X5n{g?J?FX4SQsL*Z<$06)U+WarSkn8-zh= z)5Ce@fk$WF9u84?p)*Y<=Wve0lz{V)rHOjNpz&%~&kxyBxy=F>7ar+oTwQjX<)`uU z!_a^dfy^BUOTX(W<4U#do#nay$H#25hu2?%(jo(co+xDQKv9x&BHOG}7lLxj=KtC? z>-Vdt`k>McqyW_a_He#&)8nJb$2o!#y?)dUfXVh3n&gn>a%3{oZ8rOA2x zZ(w22a+*^6O#b$JE+a9}QX2*aJ@6HF7Jh-NHC5E_$1PVBmwel1rr5v5&ZHX>o8q9j z@NkYQ-tPXUWbe(|c-H-LOM2PaU(`WEQUX*ZNjj}DJ;65fe2CW9gKwrYXD4JAe}Ud1 zt|tK+BnbB0`YWFMwZp%gGoSAKT6}oxR;lYfpu&rRK~Dm5w8HY+Cw4i$H!rv|>x<4z zhv~O2Izt!C=t+Xc#4P;wXWSAxvMozX@93wp?HjBaXE9uWZ1~laf*h@&v8rodfsER@ z*Q>YMXRNyO@xhBzpghUIpeF^&qf$=)r(N_nWxqCc>YaeTZIycAlQ*vg4GMr1)H5(J z#CmeXzTG(6qrrOFf%-1V#p(_r*@n38hvS&&fd= zdwMdUO5Vcn?}GpF2e&?3asRT2teL&Kjb=Q(b-TR@aqaqX zQ$j!`ECYj{45&>P?|IhX%(6w=<&Nhk^e}5}&pyyLcRQ$jWMI&f6#*yvD+Rj>6bzYj zR_1myF`e$Z@!n)FXsC;UK~D~3g@xZn)ys1imQ3urcjM`u_NLqw@@Kz5V^a>a&BDWZ zfqi7)*=@lAPH}24{_aiM&8>U|(h}2?dkgO4{88+m#`@E9+jB-{`-@jMNzK>ogAD!Y z$%9r}{1Z0vVvA$`}~*7VR(Npg655}N%LL4!t8PEO`iYM7d0-o!mCIGkW9Yc3a(3OZnmfk96Z6c@pslNr-awYz=&6E+#`QgAN-XS_8hbZM=U#lY@y63gTTVf! z32MS%M;_prrt+$B_w6=oQHP8t?5j>Ry@Cv2>ZyaOBn!Vi^13fR>8H==T)(CLr~TK) zr;c8rW+DTFo;qmI$ivyewdU{6HRV-*jUUck%{eh*kE{%6`~{={R4rP29+f|G=;YRcY$Hy&eZzd%?h< z2bwTvaP$1`5LV(GSDV9X?U#IBQIfkq(gD)7*VA$XyCLsH#Ju&Qt%Wwvy+20@nO$Mo zQ4IBkHmG{E@O$rZ)Xni){W``qXJ+Oex*K#YI1d5{pSn<`5|NG zdb%K!Je&{K9{L$`V0Z8vlZE29rd+?u6`c+(g7nnE<%9L^^U9Wad`lxmVh>nV?6Y2C zyc^UsVPMeH1NC|JJtxhPu4-e8&sCLSo4#Om`c_}VCdgt}J-q^OK+QNl?~~Po`4j*A zxo~sEl)6*JU3)-hfHE-X>4SziEd2g%QjXc};;`m>gxvI_ZTum=yOO;jRgwXy2KI3N zI@3dYhyA^Ma}4ZVGM)ECHMCrY<}3qHkIl`qsnl=rg&L38Z#SguZ~eC4eCxOZD4H1< z^b8=2mySsE+_e4p$?nv5O`+>86ZmJyL_xZfdWMk2OJVER?P{2Mj#;_;Z$j?LjaP5a zo(D48y>nX9QZj6zpjmyIbP=F0ON1 z=YKddZ_1J1DoGb1bMAUZyTRe$c`kL;X5rp!<>wPOg*UI&l5uhX-VqzPy}t%ozKcjwcS-YtfeOwPBb<$izN<`EC-XM#)s zbt9BL(@K}rEM;`OZE(C_*?58fHbcJ)pd1BK0GW(l*ttmkS>gv<nLzTUvq=R3Lz z@4T8LE^!oEh?#-9Q&LVFPT1wnDxPa&{Xq9|wuY#M$muS~e3qUWs1>B|*;~V_?sKrP zyzqOWMT2gfSLKObP>USohMVAk(vMMlY&}yX-0SM$h5JstJnnW!2GVoavj8otxA1dX zt1huMuW_Hk%a7a7dIi3jGGjU@p)fG$S%6m5csSpwk-t_F{Z!;^qQ(6>NyF6ZJ&Pf0 za`Y@VF)%Q=d44&&@JjlmpnsRXZGCE*Xe6Rr#s*E*7C*pl_<6E?!SvO#{hC!dCxZ=^ z%L?^IK!e&U5IoExdhqDSOP>Eup1b3Bf0FvAva4pQkP%KjE6`AnhjX%8dPrT(?;l&I0{Ov3=Dc!pf!vVPR1E29pTe`H|FW~MQ#gE`}ZsSI%wnqqyRLJq3`+U z^^F()e0kg4d9uQP|Bx{H`r$ulfQErV&sqZP$QS$qA-C@Dcp8|ddwaJ@fP%{FNXYsJ zJsVIBY~i=-OveGPnxxk*FV5fi<6h74QGNqtU$dSKXa#|X^9SoADiO@PyUY%2pWH3+ zsZ#aoPiTYF2DFe&-!rYII{Aj9RI6?dgX43#N8eNrPJnibZ56<7Fgqc@WqCe){o}+{ z&hu|C$aVCs0GFT)dUl{uMhicU70uIj+=^JMmHXlCovZ)`(XeF5F&BDvkd*^k*%M}z zYcKlaomzfr)taM5E2iaxf|!9p&ki(wC*`Df{>iK+14Dt7!u5aJn}mybP3}TXum|-P ztvyetM^*Mp+Z4EpU0Zza$(tf^2Sd;_6$68wJ*1oz{^1?VUgbC4Ibxk4+abOyOXD*k zYkKt@Amya7soDj*cC%&ApPsldozH|dz3B>QaVG8lSfu|o$^o-J^xx+^y{jojelqUFa}MofE0krNjJ~#Su$6qZs;>) z{g`3 zDF7|jkaC)?7G|)n%7baTaP05K(&TluiiOZFj5DZODD#{paQ=)~TfY7ipFo2=?wEV} zbKgPph4Tk+bf55;`0La4-J7nR;`!t`KU_B`d>yprbp@qv3%}`y!@HG@9)2;Yyu#7{ zpx@qFs01|J#=xNG3Yrn}aE|(<cu%j6yZb{9MVM=Hv?o~nab2dzy92Ub;2F)p1<#(_@3M&tNCg9(al#NtE2VY zK?*&b*Zcf-THby2I6OhdXmC zSRi$l2dG6F>$yG7^x)c+McwNX16M5%eDQF>$NkXiz+)0PB*m=Tgq;>GT(Z3F{I04W zB^i?X^B}VidY+(xObfqrvwrF9WSG6Ct2sTcM|ZDizS>-9LFxrM9MQvBZ#iciONA8| z-@2vuKC`AxNPlu0I{x4VYBt7tPVK*V^ZjR*w@D2)UJer~Jh;xYKo%D2c|lGb5;A<> z`d6JfZS&?H9of6Gv#!lq4sCe*fQkVNzeAE6HSH{f&PX*kC+>GRwAH06ZVSYlKA_QN z59dF1mHgeA9p8@CJz?C&#_}up>_*ViZ3YHCAJBSIDW}4n{lB~FZ_9;Nu}`lmx-ctj z(+Oi<$ki!m9Ev-KR>nYqjz6F^wJhR|6s5q!zV9^t>fHf-n8V%tkCrA8F6?aG`3| zQ?-2uZS{ZG>`&NC&cJOqLa%MU1(gE9=r1W;TAd75pXp3~;NDo|kF zESI!@JzQ0fqM(i5(0^b@?*8`dN{wHm*8PQNc8c=x85S@@m&-golP z(?yS%ZM2hGzM4(@7d8i4@jcf;PDq^LYe$JjdPt)gk-Osbo_Cq+R@gMBD z^{>Gaqm4Cg;*-;+aeE{>Zo4!Iv?hsxK`%lJ>;@HcYk)WLA;e5*Oztlv%3B@Ppxo6J# zr&N1DbQxrQlwK5Q;!DbjU-FjQa>@1UuL!4+r#xj zD(A}=C9}?^L1!Q0KxMXvGoz{&^V?q^p0!22pWV_X{iE`uDs=Q94zx%?$|+UO{^+VF z8qdyO^PRYGR_mXAd6z*(Gcf4Ifm%Vap4{t<&qjBBz5PbxVYqzwE4`S6GoVQYkOIgt zn@0AtFDA{NIoWNqX5xd!!ur28e<6Em^%6icAQpa&-4PF)=SlQmddXK7*#7DIvV%#` z;id#owcz1g{>*vLMz7Z6TX!Z$wQ)a>5HPR=4Kpz?=p}$=AEcZL7FYh5a^<6Prh577 z;CUA_zu5>tdj|=inpfX5>nI!NzA3v!E00Dbo%?v8X?t-g|DN-W}@&i-MRamHSPe_=dyOe_i1Dwc8z4e{=rWm&HClfAsk=zyd2qXpYQ^V}d4 zK-HqY=j=ZRE=&^W5@c4X3zx6!FW9^w0-E)bA!mU$Xn%X8>U?WftImAGLpAsJ9=rYs z)VN__&`SXgby)cA+I(}{Jg&tzK0Q)P7G)Msu4~&3%26N%pkZkb=LZpI113qcRItU~ zo0ZG1-x+i56J!EZF9kFKDCP9eX13!g?=w4ZA8=Z{&Q^WX=d-S$dV+yLFBP&O0}stBY2a@XOGn9G{gt+yxb-+z*4nO1bg?NdI`&R`m- z-n8&@*z@Opx!uyN<1TW5grfaL~lUuL%&oZ9#*RS+v+-t$P&{8fPH2mh~nY8UkVDi5Cp^O|7 zZ_JOgKH+El18wZ3LsrxrSn}3+_I^+9G!^x`i{=P2oZPbpGYZK%Lbpja}^fEzt)Wg~Hg}27`I^o?hnaAqOrY~xHYnLK_Z^73IAPEKry=>69oQL!D?Q7(*DQLIkjw1CrHYvc?Ea(jmI}C_XU47wpCssS-MgK+StnmH4lP4c{hnL2j|?m zQnllb{8Xpln=)KRpz{tG81!<)z$Hww?{)jBPO_)0WWp_GFh7P;sWq=(icjP?tzDet5e!iN=diUDF%?f>UK(h`E40`#XB_|esQjyL@ z?6q5a?1R)>I%fWHiaWajT5slqI$|EqF~(xqUw`k|)p)rf=u$chFF*5YXiKaB(#QF_ zMt+{*t|qG-W5?2M-M+^^=9EEGbpfQ0Be>4d<+<-X@#9vHx9!~!=Xcnf3ADeRfkCej z(#M(Hw08!}srg-ArqNf7gsNTcpDhAS@Gvmw6+!wqb!p$?cD$W>+mnx3B*!}9(!Uvv zpb;F90!Sa{>(}l7SVT9P2%q9*=(M>0c-l?^bmx^V`kz+*vo{PA zo)W>Zw+9+fMc2UrwPwx2=GE)YUgq`?W7nvk5I#fK4>~Sa0$O-$;g=OGF5os(viZx2 z%fGLjEnZrEd=+R0h=D<`1T+@p;rzEaz)}5MNv=SYM%mh5JRXmx7D6`D>6L)iKS()! zTOODsZC~O4>F$PARdQ{I%r9?)db0!+VAh`e(Wx&^t!3i={Ln-#N#WWXGX-sENn6Sa zcH~r(3E_($zFPM^g8$}&5b5v62a}=Gc4eSC+`=#M>dIg5-z-`1YGU%zDP5Z%a9Qhs z#w8gT^vXa}XCBTSQuZEoe**99*UwHaay-h^pdJk>#6b!`ogsbCC;ysDW*o5=>3uYL zUe%(sB{PC#lOWB5a$c|-%(bT6c`3Etz9{O@3{Ad6WelQ1pjw}SL9YVT8no~`)xtaD zlvj)=+l2rjB}v8gHx@ZS*4yh2m&NpT>{5`mUv3yp90iRfHPxAcUm!PBuG66LD z9_;C-JnN9aI&s5$4HmMhv$a~3-48;$50#J;ZsP>fSJof*Q2dncQ6m2C-REOQ*CDG} z^r}FuK?}c2%FAP2P8^=qYqP&^S<&TO*%~!y@r?k=l+Yp>cUuA!duetCAo zL~9>tTvUS!F)61vwx1MjW-DbXI5g*U98#Xk+Zq8`H>g()X_>#sdZFW+zj&{~(;K!n zvmR#&FlU15Dh39PMX zhT~<~>lZ!#mUN1F<~-9{JNuD#P*I=vziq18bxq-9>P?16!m zm})ZX^PrhEJD(rf!R!xNlcQG)iVHW-1^4+XmVf4bzwm?A4)<-}?ur_mgEqWt*MMX5 z;gJIq-8oEMm!EE4xT7ItSMS%qAn!3S=+%QJ#4Y^fRwPRrEe%_f=6C+&%lD@z{q%YP z%5oqDAh&op^D3=A&v0z&*I#+e>rkG7wNHGzu#jB9pY#N4aZveS+Yl2^4}IuFuAyA z_1k^xMBhnx=t9zDBPeBgIE&?dz3h}~woGa{=e@H!b6zB9>p`pLMo@Pu*3*4buYtn; z6XDx-&r?WPpEXNfS_HCyO0NmB2BRQDar>1#K}pM?XQI24*jP&5FhIvhn?ci<7JfC) zlv%}N_I|yn@aUdYS^r(z`8v>9xn|J%2M_1u$EPn>?Ndm+BjRW_IkQc+WqUewMNKnk z4Mv%#*1yV7<EEBdpkW0D2ECR*a5%iakT+wIFZ=XkGWXX@W%|Br zn8N`|C=3jGt)TF*@Y9%}p=rKS-Jo6AnE!q7x%SFGyCK^O^jbmnr-!rE-qItxldse) zZLzwceI=mgodu*X$e`B-8lThmyrX=4*}L^qKCNz)o@`~~Q+{q?8Duk^URxyC4F^N# zvhA&zbpQ84(}H?ShSU9~mC$BVJ7^Hq!msA-%$(KF_q{bPs-ICdm9ekdS<(^`7ww=9 znTPX1Cf(Kro$D^`UZPcdH~G@?0>^F824@FoAh*m@pws5Z{r9C$?w*TSv2f+IT<2vS zpf)`NgI)*ZvJ%O^vv(|Rv0NPdBV0Xqv3)0J5Hl#bGcf3Nfja0Gez)Rg=P#SEF2ndg z`{%GVZjEim^FbpxAO#?|csO&d>lVLw*YTnLTK~NN8=jpjiMb0ZA3+L0<55yhnU>c+ zTycAxC6wB+(Yc5-l4pqlsDTAi02(aP_heO@+$%lv_nnW6{%uTL7U^m_BLX_g+I0#X zP`0fbZ0=UcC>)yhr(@s2g#9c>R)A_61_r$zQ2lA)SK*JTdO!Y@k*?hna!jRHL)y_=A>L3+|Pz1l9T=6Cle1!%lv=B_mt8g~|BFD~*>k zbuRr<0!c71=z-EMW2B#Ga`+nis*AV&8Afi`oh`xl&3QJcreR>v>jMqcSoqChkp6!@ zvi)T2(kri7Ib(Vz{d0mgoBKe;fQPeFf%KI*1%~U7e3+Y4B=WMkDQF6`f6)gD4=JZ< zCsR-Tk4u@!{98M==8v(`um6xX4uf7Fs8#IlxzWdA!rHu&je571MVIL=Jm*p423?Z_ zI-7+t(od)`)ZL`cIa=BBYQyEP|16jEz690!3=Db`KpDrvFULSJ=#8D0RMT>Yb*H4} z1@rALgZ9)WfSRrz&Ku&-%=%h>+oIQb*Zy@jn=afcD+VpzVqnml2pS63_p}M+nJeUQ z!9U#7fj^JY!9c2S33TdkB4ljP>@~+P{nsY<|K14PaEV{)=AD~MK${{M81yEAqT9kR z%Jux4qObhZ&IfpZd71WFR{G&fX!BqaC}nv#pFOcVVN%=MHMf1jrM}F%n47%(Hz-## zFz8JNWnw9(iEl0%GP69aDhl7~av^$UeO{X+r~?L402&(%^wgdDVgi204ad5KFJoxk8Kxpdh_;Y;k$LToCi$6DsO z<5`8q#(Oo-Eg!7}Y;!1Z;P%98*!c}mpK6UZqS;ghs&$MRed9svpPiHp01ezjZ zV9=WmnvJpW`?8QTA!E|yH+9UNYjw5WWqWI28KXS&ZB?!o;x=8$U?Qg8=b3ePP0oehb{w~{vYgygVqjmtF{aD z-k*ME<179fI@|4ypv~r)pg6Jcd$q?~VEZJt=eu@oaDTe}V;Sq^2hc&1nV^n{hx4-c zRXXpSe%2d(30#$Np5gbr8TR`jWztQA z*uidS{}X5y`}?M6w~+D-i>Fc{_PaMiEBD!;+RwsI^3LhGftsnAe)GQ`>xqk-A~EqT zbji(Z(7|gS&bCu}_NM7w*;*poUG|`Qvf)Sl{h+m33=Dd+LCIgr=|Sd%)>C)B>;CWL z|M%SBQ2TwK<J*}uT&^jiO2q|rP_%GRt!v-E{j!431%@1a)A(F8m4vPZ;)JqD*Q z6$I4!#4*?XNjy>l8i!(F(3=Zd7+~R7ugtt?_8qG(e$Tq-w=eJcE)>!N^^QOaKwCXL zoQ)dJ`LG5FUch=n5JZxvk7SKQy1B2c?&^(5#=QcUpAnD?bb23ePgS&qIkrw;b z3(9gJ1(2mj;e4+i_HOStesb)Mzu(-3#~z%sc0hu9K4|F6!cQV~X5Z@|Q7u{LP4lvg zRZL$g1%uiR3=DenL2=>X9IN~?HNhzJd%BPQVPlD}SJyk_gSt-)40;PdldzIb3!W>4 zH%~4wYTh-)i{~X1fBORuXp&n1D(&?>ziipeCidpkRWHV;=UM;Xy%SQP4P6(s0MZF6 z-G6B9cG2wf>n0|ji$9ia=&27|+_(^w{4M-eT;ye&CcfhOoJVo4VQUWf|2vZhot0Y% zYMFXCUoAQ0on#|WymaScqwQ5Si|6|LLf20&0(F9LHwI5{+iUnhu-5AE-_^YG zZO~EoMWFVByXQxLo-W}sgNPuBnRl)n+4M+!|7~cRT(k%ro9Rz^omqcmxymX^`+l7} zXUeCt*Pw%?7#Q>xgW7Z!ehl9?tauop$cs^t)!J>Th^wSrxn7D!T3f+4-oq1aeZ}+r_hHeswFDaB;2JRaM=TD>=40 z&`NC?sIg<=H^r;;Sc)b$!?j;MVNY47ugUOS4z0VFf!ekn&P$u;-Fl%HWUzY4<^YBN z_J8>P{sYxj3=De9K!^GSdlq`exJ8?PR)47WBVlFAQxksIFz8Cu<&d=~`=;5y%3q|$ zy1e4GY<}#kzPPzj&}Ba>a=^2+>)c}_=AGRTBcVP;cd<~V;mWQL(22hlppkD6=Y8sv z&t6(TJEKnJ7MpYMn=2UtLC{f@6`-byq?66L#`ZN6EVgu~Pu5+)vP~&*PcUd)l7T^Q zC8$+w?a6q}_MbTagO&5Qtp4<{?$?v*^FN>k$V$kCN_?SRpS~Y4&Jc_C6nWb9f0Ov7 z_s|tqt7d{7dGPhwRY?wt$xdxa&Rbux9{aCS2`$W5fyTrbD?SAr%^ZJT? z2bv9UD_Y+Bz<=W@Xm=S%0i>a2b|cC(d*@GgkMLf$4aY)OPrY0K8Z2XA&|3>>XqBA} zjdD3=9Jal!-SyujWG3&0F5H(doFBv7UFa4;(@T049`2YA35)0 zI1fs!AO$DE`C|I)Z$aYExy83n3{La8I6aj)$r?K1y&jaqEd1)FqP6SU@2olI6IBGRv zW%1d()2IDa_HCL2YV0yF=&c9s{0sDKahHkSGyl!b-}m->(W20hTpDvXhS9#@2VvJa`0O9p!iee8JbKfR**~a;{3)if^bLZCd z6v4y%ahz|VIy>6`L~~sK0Z@(0 zz@WDcR6Tk)ODz9qkXY9$GW~w*g~m9&jw>@Yprg&(K&xV}d$i(7v!bFT&U0 zoq3V*HBiw5G6B?MbN6KZKUE}a&$GW>;l=F2Q%>gG27Try z>}QX)*TOyiXVyW7ICg+qLl%A(4}*2}z6yTeN#3vVhU-+Sw`~QedBnh=w*#_Z=AW-# zrqHY%J2|KL%{6(?*7-L7DReYx2dIf+?KweZzO2@-B`sS5YZ6uWIG=QDSOE%RkO`1e zmp|M$Ef>-{_Blds>qI?H_IZ0QcR}M~7ihfJ!ta*Hlw*>Yh1FdJ<~>~T_Jq{+G+Ss7 zWf!Q8@8SI9-|^#m$xCWwpPk7Nd~@`m;5$D>P=qr&1F zD?ZddjXMur)w2tQ|rsXUmQFd>V5u<&_3@TP^oY2xwyc<$fo(@^BIQ~?73TGmQVPY3@UmU z81(isg3E`zADo*@cdd2xE%~L#|Lc}y@-8OO)CdEE-ab(FxA6NtW6PTTMs-?jack2J z-4#w;^4kP0<@SNHpojC!!};#_4qm-C<@=&Y^HkyJT@~q|l{6p|KqKB#PIe_TC)IM5 zk zlrKD-zi*fMHX$?aj`%q_ALBVyv+Nswf@U2U81xQ;&dbsFV9+}RI;_INul;lJRw1vP zhbr7(nf@lJJUbDd2X6m5Wfz>FMe$+C9e?K~3-o&b_&J}jc3G|>?<)78rx!HD!@!_- z1hjd`!q2&4(zM;{SM;PM=JwuM`TuKomnd{O{Si?8>EV24Urn6}gEePH(K^HLt^XQ4 zRl-1fffyL{j)Kl`l5(2(;HX5B(H4!DV%dwe!+b>d3-ExZMnDQcogigT|L&g9f8P$9 z7*+D8Dt7U@@HumV_B?)|G#jG_hY0_pFxq1xfbDKz%+7zjOD0 z{aIQ0cF%;99BGH6FUL;%eiiD-*Fr#m6C+0ItmVA+FpygK5YAeY#rgytkLDc7URp zfkE#iXlBg9ParTrz}M29pjef1`uK|R3r~*Ufh{%D!Y)g_tC*1}2kJI}tN_i3DSLkV^;Ao?Z2O-B zl^d@rW?hs#p<@k7C?EyrzyY=T>)%;B8Wytb$vh-m7UXy!C9(w6rDtH!I}KVNW#PA6 z=j)cLuPv+A89ceYX|k)TkX;9;WC1Av#f69S!>;ZF4|gkgiL|#pF72DmXyKv+TFMVn zu$+N`q0IA4e7@=F#o9*eSj~$cxo4Ue^B({;G#ME5&d7q@;J5Hqp2m8AF@czeYI@&T zZZ2J91zI4&z@T>)w9Uf8&;04z>#sx|vS%NPPWSlHn3iB64@yZO1)vV8hx3npXW~w+ z49YuE(IvB$wer#Klxk?>|14-y+S+rq+}G#=!!6>ftDb$zx*BxudG~Z^xB8qR*bTFF z4j;ZFp}wEFJ@WIJI9FYma@En##4;S4>d~x|r<}C}p{O=094Mzg(uuW&5JPS1;#A#B4IZ3)+Xnz@T>t zG9*6jk>;uZUjEGHbFRDI z`mad|)h+_94hJa!wZwuvHElK?Td167e=^HV`{0Z~^FxeNK>i0QfMmUk8$+9FPuaJe zK6tUgAa_w+$vY9~$lf(b)?>Z)<#qq}meZh_{SE&S^LoSf<1Kl@p=h@$a_*iS!~SU7-kHAn%d2KI0+oE(tG)WmK+ z`~Gde=L>TV-7;eYHB~_hK&x5GJe9abIxnWMI&9PKUCM6Tyvv&T0%&Ok1B2deNY?Xz z=Pa`6?wj@kW)bQA5$nyKD9?me2X`P@k2!14C#Umj`QSa@$%=u@e-`Lb2>8xKFX$eY; zAO)bTXYIM#Y2`ka&Nn?$o(zKZ)<-mMo|^?)Fa%N%501@)xl^*!#5b;LxMrDtxY7S! zSxXdXXBPv5-aXJ@iG|oAw^4MdsnWO37;Xj%-uK zV-aaghWEsO=AC^Ct+Vcf<`|`%ybR`rmRSp$ZEtbzntyUr!=EFsL30KS40`uLRdku> z@#+~9CVl(%>q3>wWoNC`hnDGtgK{-U0c2UAcS6;A>vb4>0;t(&?Wy!)Lv!$pz?PM#mV7ASQ#`jdVL3D|9zwQX$tcNRc#%EF(WqQI z;Q7j=FwOae(318sXb{!HZ{ex!HGWUl*k;{)5HlriwpHrJLQnuPFz7u7Et~alp5w2} zGS@I9^M=H~#rfO9j;=iY99pqH2Ca*ca!Qb{d3I&auIUyIN!9F%Q{{f-xkHDW9)m^^ z0zGvP3KcF)T*tfb#$u-B=YKFSyIchtBw}FDdjeVf%>Pv5?1uE4%U7lC%X`&(Qr!OB zMNspIfkE#nC~aE!NpS4BlKaWCr1oOMnL1&KUk`uqKsR_k1$84loNb)hGu1f-r<`KT zoy3$MR~l<34sA9+{R!TGaae1D-}=k_f+Bk|_ja9%X5TYa2~@H$Fz7u4H8Au&?|rsA zVz|KYTk;>L7~`_$=Z=#~p^5gH6FAAqw*Hh~*!b?<5xa>x?_2-aPG9}i7*f(chm3fO ztyO;@@bvG!isjtDZWRbV_I6tcT^R5jGU8oy;F#Lwlm=%p5toH!M=dG+(>~%`tj7OY6kd9XM%g9lIjmU{Ueb+$Rs@p}nM6pixF^&#<`V*Jc%{_@>x! zem}FECnc?CI97crbyiCrJe*k*9Mc<%q3QqZ7&0~z|8HSN|SYi<5n&d(nm^$QA>m5e?EYRfV( z=)Hvu{mF4jPIQzol(^)mT43|&fvwupNN7{-9Vk{koR|JD^%Yg$?|vy`*SgpCnv+h5 zgn~{YV_?vG2P(7UJ!@wbmlodESfm-x=)6)o`0i$pQ_zXOcelXdz-!@g;;7}aljSJ_ zX-oE3y}MEW4q8Ti09j$-7inFuHMR8fuTS?DrOTd`w^5l;9|1{GA3&wPhjZuSkn{6T zKR&kFLh4B6+4(mFtfqsqJp+T@2T+9)>-pe#y8o0TTYo)Yue1J9(v#lk%3|nR){l_u z4EioF+jlKPy-m_hJeYs-r=Gq;Hc)NV?+HM90z0XGAfNDK)CgS{L zWv6M}D+B{P7Mg_SS%Mmx3=DeUU6>Yr&Y7Pl@_t)i)gI7oIsY6__r)S+P~!%q05p%` z;oKasVaEP;UE{z1*W62s6uPfIYXMZjS5Pq^XPn9>}ax-_n z=$3U!g_e`wK+7a8{ARNYc$9Cn@etr%>zcp9G1=?+PH4{h2HFGS;e2tfV~tg+h(mI2 z=7rOx%LI2#n+a;NGcf3V2lc<*JtJDOCO_KH%fao7 zp!XBh(DHCDzbnb^_E~Ok`?>RBL6htJGfp>viXM;xP>tj2sdMaG{kMP3-hHh0Cw^b+ zy5wVcLK703KOtvOm~B4wOsrCC(x0`KbsM)Y+i#UM8FD_1-Y-y(&BAZzgyqgVgj*fb z7*;My;}F;&sk8^wm1SVi`wdEZ9?r?@FT6cqE_K7{`tmo&lM?oMAASKErv@niH8iB0 z3iIth&1io5fkjIqclu!DU*W|GbkU zTP%0A*f*BvfaRo<%9HND0*&x8FzEdUg@c9Pfj_0J+9vND?*~p;UH;YaM{FVkbcfgf z^^ju?ru;a+YiCbo-K78fE@&|%ZLqme2#Ku!ptz873fj}olQ28ZyzRt+qGYzoU3oWs zA!kSHGl0@VkZ1a~_D3BC4o~OSURy48rf?be%WTLBZGDDhup@O6cb4i*T-dfyGGF54 zn!u3I85*D-I|GA0BWNJk!cTJAf1%Cc0-HZRSYFHOGiO3*elMhBuFnV>$?k{8Vx>5Q}pg9C7r`3mdv~LmY?U|W-;I>D~@q-QJF_2nMp9wVl zsPCDz>_*&zuX}7{Ya$lyIu(9!+WH-!vWbB~pQ#n>$Ss$a3cc0)c6obJc0@r+MAa9I z(~z}E`plqqgoU3@_xyh8c}w$;|Ek(4IO*Tw0G*AHM61sN8ddUee){&X-hb`7d-=t? zPA{9YKUjO78fb=?fkB@o4%~idpFE#I`G}TN&70~2(TPe|Jye6Bjs(|T)}C7@{tPwq zczfjT>hy{O9=`>Y6~06I-TEw>!Hx{u5gx6*GBRt~oYH^gN7y@d>??(2e|<9R59eNC63tm)vGHM%11Js{ z81&hC!1J5agmx}pwe5BGVvAYwN5VfR9Crq{$UzDqdnY3m6m%qIG%s#uJu33;^v7#{ zdY?f33I+y!4$vw{3%`5u7v7YF-K!62+v&}yY(I;Aq9~}*4^jZC!#$k6rvE5k#<2JQ zLjIYC%S-cq-l!~sDVPEtUXXJL4-$%JesoCq#o8}9x)XNoOM{GH=yP&`!y)73E9FIX zGi55*={xwiuc~mCVTUw&^|?SDG7G<1(_Mds*q^x5apuB-J995;_2z3p2DJ6Tm*9Cg zPm;9EJv+f+Oa0%BM%GPjTJc8|p^?S)7#vxGY1bzT+jghARsEjay?Ezg@y&^lRUG!8_3X~J~yOA%2>u*sH<}0z3j3ROWR&W&S$Ri zfm8?jJdhTtT0-vM9goi0KMe_L{vy9yD=%gM%D1#PT6?DEfSm7U`{X6>e8$ z&P={?V2d%^Wr>%0aebiGp9~E8e2^CDZHGCsR%d2#CmZ)?I<8u_ddbTBpe{WFgFe4B zI3zPZp1ppnzjV{u^JQE%f>-~RUQPogHIM>Oi!{jdL1+!XbmxYf>s8vLqPF<1Zc?{{ zlu`Qpkfo~UQUhkqatM6!J63v&db_f9vcfLVtOEmsz5u9lv+!G$Vj(H{C}Q!$!r!rs z|NPzFE@TGvuNWBg1woGWa1LD0A|XCm{M5onSAxD3h;Q+A>V<}+AZQ*#%IWwO|H~{N z*quGz_Y`I2Ops<)Rht1W2K5C&!wlA*6aMf$nAEV1K_(&KQ^MY5h3nNCKuc{vR%``_ zWWQWNq1c|zgVo&ykKbH6_ged3G-OOnUl`=`;je2BZ88E%8lZs*1_pgmP_Nm-?@3jP z{i169Xo(BI{#QFRFOj>o5L9P_6gYva14Hh%2ivrpT9f`vJiafuVdbPv6`*~*AO)a2 zD(U2SSgy))_P2i#?QK&Qu&mkFl;pP*5>TR`Wl(OOyY488#$NYc$I8MyJ zK>AtwqA$UYO!4>|62#--yH77&YeIJa?TfKupt&>#27Pgm8!Y@}m!DEEDf6maC|KEZ zoJ*zQTJcn9NQ#5v!o#`Y;E%vm6SF7Yetf@=d|Up{chy#C#t{dN9_V{6P}zEMU&%N7 z`sj70`pNPpSNP^a+7J5TkmDWnHhF#LpHMK%WZJpQclc*soOg6P832NheILppAOuu{Ee>Fq?2KCRu>bf`T93gFc zeMwN$RoRnC5?tcl-TiXFjY9JFJ(==K~dupGZPO)vZXSaCPrh52z z@*hyIfPq0@8k8O^{N9)IpVXUuuy)p&WTov#PpyyY-wG|Or6JQa+BKnC{p6+rE3H_z{`+3Fz* zCu3Uv_{iHlzdrw0`~_%zp#Zr(Gum4C$Z_3W%ozs?xI;FiYCV?x4-H90(25!hzp2l6 z@~z)_{iLoH=Y`c@e>yxU+6B#7N}vfJ59e3MGiUy}zbKfS*-%4Wt0n01xz(+WF7w zyno=qFMrm%i;A-Gxk=eVlf9}SI5u@y-G1aJ>YMmAzE1A2IxnHtcLTCMN?#2W9u|HA zeABM)mv(=+;@ke$49f!o%uPKZ)42L-poIY*&U_!MxZa)I+IZCCc;&fMht7-Ve1a?k z(^ms6c9nAa-Tmvh{>x+UD%lEt3tQ;17xWr}ia!PheRa?nVUXvMGk2Hh?|1nsopdGj zvWV%cZ8={-+pa(g!oZGvQo1)t{=OoM6yrY8h~Tvq%YTPL1_$&tK+R?gKY^1XEv`r+rCxIsbG1#Y{L9kF?%0gc7^l~^ff_Um_W~2 z^Ms=0L$5#EIr*tlFh`Axa?V>&2r@9}gAPt%jPwiJ{_5b$Ljr2O6<3mVYz=-1$zBJo zCuU&K*Mjuab_i@da7bb8=J*34NzR(Qt*R4lL)ISXYlB+m9?nafUNi2T-Rc_lj9E>x z!tB^rUb$tEvRWHd>PtBtKB)fi3eW2<-QN9+cUyLDk8+s_S+l3F4eAtHdmbv=RN?FS ztK(JZM(Hl05Nv;kzVmuF2Q77Kw`Y%}&bLG^67mI2C@-1l2Sk6Apphu*f#-?xs2u_Eh15;AirC zq6JR6L91qcP?>Gv=iv0G$JdYhQ$X+g6VY0YlVaTsp>EIz^;A5ZJs+;Ty6I-{tJJ;A zRxegCUBY*#3|dC%gIYmSPKCUEIi?pYbMx+Y@zt&Q?pXXQ7_^#)fk9s%G=LfFc~H>7 z;J$N^%7GipX3X(rFp~?a0CfTx81xNa);JbKZCTS?}e7JA)cx0BDe`@2E&g&}C5 z#=_5OYuxl5Or>9Lp1=Izb>f5dOnZbO(-ZoJAn$rOZ{M~|yS!hpdbZg^ooPN{pBa4b zgW8b{4ElzkACA0gOb08^Hr}4 zoEIzCnWQzJKb&A$xo4*FJWwx@fkEE{G;Jl}q@>_vsjt=;SsB!L{mNCQ*+=hfgBF7( zpca{{=e$;Lg(SN@5>C5gpRo)1{_wN94w}ycnJ^t3PN~mNoXW-Gi6Il-GN?n{U;#?B7JieXc58(jwr_F?6_wjsEKVIQ`L=s-ys7O z`WB$vZS7f@t$8W5=zLj}3Cr9rj=vlMN)Di+hk-%gQUvTsF(>IQ>n~o~ykUd+hWq)J zD>I#sLyI6QP^?<`$#lomKRvHosC*^#*CKUgxPyE~A=oeGGQ)dRWa<>7M`WAj0`K}$? zmKz@}TrAZZaOPv~-jnLk#-0tR$L8T&-(_$n^*&cpZi=PG;o503xn0ko`N9@dx#@f6 z#4dWz?(!g;H}H|)g}HWX3@fuiu4iD-x3vSiLCD(Y@B)QbGgdsF#jJEd^wo-7Mo@Lg zz@Tpj@~(xSV^P86OX(`SFI0PFZ@7u%WV}d)CKx-=?1P81Va(fKKZF$@)%i%wc;LRJG#u>3!97-kNeo^#pH4ZMJzTxy_FX>b>x$i=nudWv-@X^@hUKiAgIjfG3144& zZKCPEJcH*9KOvh6^&LQsUkg7Mov38%1FNQQK9tVR*ZYU{%PcKWa%W)BcLcRWJe=>& zt++qkbmk@Rd9%(7FuF-DyBq|~IF6w5Qpzc_>W!W2mnVmJu3>t-=9-J$krm~Tfqi{P z&|GV<=PE~^o_Wrznd6?BG0fj`;vn;CQ_xOekQI^os*Xro`-oHesp z7TN-F22CYf_$6HON_;2uuTE=b;*$4KuFtu4=|Ho;GiVp4hqGkrJd+(lam{P~9}zM= zWwpGUVKrpTT;CZqoh#*ZxBtx6LzB7c?rD{A@cLHERaC=j9A`+AHTJS5|L$|EIAYma zI9Uqr&MBM94H_e6V9{&MNTx6jWnO8x=O{;rTF>od9d*QbQL z&#kC2-69`%;;-0_Zy*T<27OmhTgJn=t!U}gh5u%qX7dt$bRc-<@jWL#gBlhf1)yk; z_pG|UZ1;O>Upw=(Iw4U^oEAZB2XdDz@YCA>K%AE2RvvB2v{OmubHOt(dNva zvb_$wpf!#MWT)HXG{eh}U-fndPVrFMcHOP_!Zuq_OO$~@-vbmE@t$+mvv-;?Pt@pD zG+kh;^zLNj)+WfFAbpQ+aFV-eZnotPuVrH1s<@I}2`4jizxsg&1sE9gJwZ))3%_#X zX5HEE=2e*9y(K%7Y4SWBp_|aQoEK=-n};*o7E6!!&eHK~Urk+^@#r>liN?pvkoJQY zD7vMbcD6geHaWYa=tB-?uH0LLXVORYK*LN74EkQ69*VW+{R>;=nAI1Aw!Hn;B&OPY za8Y14WKdn-3vvd9SK7rTb&ptO3l`1O_~h>t+r9l8w4C$-g@c9P%$MpLR81~Bzt+Cu zl%rw&I>=@(WKv$=2h>yZa9&s%vf$Fjs5BqG;t7l`A^wujnV`Ab2NV|)PPuaOVy`qe z@9MgdB;@~e!;Ty2){t#z`aYn^Sa(n3t`AQWzs00(`?K-eoYTcOH=4LZn@K*9-Xedm z-NxuiZtAR}(uYKA)MMKlcpzh>`hFlcSopc=vHmhVH#MU3dBEf?or_*Xx}`yb+OG-R zt!_Rk@-m??+IT5zM%r!HI|1wWWk5?gKTvv*auT>H@Wiv&u6tee^-UquJ?`pO?*ugy z85s2aK#`^IS(~u%rgi3I&e>CX1ao%$-y1kDAy`IN(vVXr23o=dgW9%IPN5HQZ)dTzjnR_~Ycf>ou~_c2p=R>v=fGWUiXU^icEj zN_iKHmFm`u;vB@Gecn*e#FvzlxuV6AK(+n*Eeh-R?CyDOnEXK+R9`YM=!b$va$-Hx zbk};tRpq!WIC@h^I;Kx4uTL5@bqZ4O8tlkhehlnWe}0N_>Y1Hz*sA?wN~ABe#t8@I zFblu+6FTH{FLj46-`X22#Kv%=vosFWjbvcZ4+m8&9?qZbt6t2}$=dN~md%Eh)f<1h zW~~7=@<0lXFfcGkIvID=yj8X6Z7m$sO`Vo*TnZ%2O)DLYIl6s%eC_nk%)2`XR+o5SP5;SgY;kRemD?Z72 zGoL>C`2V}-3;pazJsr^QLnLUh#KU=J_LTQaJ*ONx8~!1G(zCq&lQ~hK4mksZek5p* zq^qas`v;3sgbuye-;=ZV=E*;tCpN~OgG6@}pbHIvTW^#lv~YQ{7!Mf0T||E?l6# z`{nxfI7?Z`;spH|(Bz|(Qz={39PtX}lSQp@>6>l_VDFEeeDW^vU?Qfs%ShQ8IUn=S5$?!9pJ1U{ggE-I*Cu`5vZ!-)Sr+&@*C$*yK zdp>^$17ioM^8+#gawU^W*q5wnF~zYv_uiFDxTK$Z<0K=rI!FM`j9K_Cnf~R+1+%?! zlk>~!)K7fes99YN8Y^dD&`$uh?LC}#ty=MQa&qMwlgOmP7i;_#w`ebgtZmj$0BtLf za?-o(Tj{hTQ|JEI($Ei%+}S1Xr$V-|>nDI_#)3SpIH$icz9f+?c)U>lzUhI*tN$N^ zPA(*}f%An!T0-H!`4P{~pXPtBCb-u4lnNWP=bi)_!Lab#vcKY?=Vq4dJn!UXiNAaQ zeZN`>Srx3G1ZwPgIA5I|%^dRY?fe(K$v4>Zi?~9P;~}S5=qG_jbgVs}c6*5?Fn#%Q zvi+@Of2_(Btv@oL9vTCKKJ-+RWj%b#C*3AE@xGe&O|2;Zp3T7yXk!n0s!7u16)q>a zSIv7gDc;v3qos(qWj-|PrGVCOdN`MTQ&xQ|9rc2ZyE1jPVRr!EQrLtS_*4^p&xn1F zL0evImDG>?-Cmw_{?VM@j?giXR3&gYc;(G_zVgrU)JsOj+S#n045wpOLt`@yG>B;7 z_g9=RQ7<^4{?_(WtcHJX?q6H77Fyb;fpWQr^ZyfX4_av*yCyAs;9BdxUHevjtOpGW zFfiz+ftEK&Il1y0zp{Sg_4K;e?P)jI6cc5ZS%PLh7#Q@^LB}h)dfvR4Ybb6asoFoe z*H4P6vEOj#3uvvE9tC#fqmB2TwJ%F=_%!Qr-=Fg;a@L}akmZs386Y=U_`R-QG>vKQ zkGuTEv$g*6{{8W@<1=VPkAXoy1JtGUaQ^Eyckju%`BTgf_K9zqZmaQ~MHjO4NIw%a z!sqU38vLok_d#*$r!|lNw9J&YT64q+>PXN%oQ#ovuTSe4{BP4a$a^L))= z!S(5<-ppRbqw`Oq%DLy+lpfF|Gy{WvE@+37hx7jC`uE3fsGFYbs{y9t7BQIVB&j1y$0Gm$X5n;%%zJbTzmPZpOy7%!ddtC zo+@*McYsPa1_u3nPmJJ$)6AIrQqiZ{vVTOGfwm)p6o6XCWu7_AEVgWK zZ*SF4*b{GO^T^%m&~#|Gx&U(UyI$X-T?{Gz?>^4`z_9g*&V%~T&?|uT3qi+zSon1m z%(dM2V88OE?9@%d8GQz?ZFQlASRtsf=i#iseA9&9^X}HWVwYVljThc_`=}wbaxVl8 zaY#9pgsQ*Ib2EOTVbbQLRHxFEwm$8Me`zrDD z7RdDs4EjZJ;AFpJ#l!@Qvy*yVShAn3>2)viI+qJA%!@%=s4e_nS|5GQBzojYTiltD zf2=D-53GK_5@JO$XzvMQV>anonHB!&k4@+P0WHi+K)Vm6oOb;56&(6a|P4^11W&q zepT%gbvY;YMX1J>8SR_y8};+q)InRMrJx*U;dk4xw0!NB`E1_DSydP+|9&{@_Y^d0 zz`&qi2D$x8P54-0%k5}=w;ey!OH$WG|7>jn)e|5EpcaUfQ{Y9OB|d4d?Af-9b1~Lr zFZjUp8We&c1)$w#Zk|5V{xju%-jc63fw$qDjEC7~myMw5I*Ijqx{jcOl*?hJ4VjDv$!uz@3znA^&X6=aYBKuye<>`$VK3R6~ z<+a}H9LiszJ@+b51?%qVFlDbs_Eb~5=e8nyZgP0d$+~C-*;J@s4QU0jI0nS*n#kj& zv2^)k{x3(lG)k&KEieWK{TfIsXkMRDn-*$)aoL@V4H(hmI;>}#mXxP;j2CCE<81(BvR#^C1UTA)CKV8W&?|=_qe8GPf#xq_} zZ`OgvYdxHkl>|-rc#oSt%*-oVasS?Y%eTIe_4fMppjJSz=lsP%T8V)Vle~*c=KQMA;B`+sY=V!%XhOwO=tl5#=`IHz0L|%@iU(t zl?0x8RZM4BtcwTrOc)sS8$k_E59bG3{~yiU{`>52nYc8$YK_BdgT$HBGdn6u{pGN&A~X!`Wkw=I>=rn|n4M6R_mbxw8M&$CIGZ zRR#wAW>A+_$|-KfW-mv^*j9^~W{baEcgTL2)C4W%nnAfd)^owG2Yx*kzvtWy{deI? z>_KI#3H8wSLklN3peB8{(>lm#^?uQ8HTU1W7Siue$bxh-FzB~}T4WY}_nQQ-e!Xn?0Ei=7L2Wq?=Pev%H)irpm%jAq4T3wk#e%| zb*dEXS$DQ={|u$cdUDCft(Bo;L9L(?rp&Wx?TVhN_}||GpD)VO`9Ir~^+W@-7;Gy7 zJCa$P>k3!2#hlw~n)L%2thFxiZ-KTS+Cl51Ed09a>@1J1OkhqtD=*MH<%PK1ta@lu ztpk*3J)9>=EIl^gr}F>&ob2j?V@(STC;3B1lfb8&NIA`ac=gxLM#pB3;3tib%EiA1 zUDXA(Wf>UsJ3tvo-}9nb7(^#vNH$hni+-GE>e3~>Dd6#v=Zmt+_Jh{q zFfi!%K&D6-v|cyA{n}}~dA0fbHP3d$%uwS4bv!@{K zY}Ni{W+1yk3P6RJzGqh3j)&iq4|?reJjqP%v(If6XYk2WAO(>2L!!>n<$Jvad^^}@ zZJW}W&_DTeJ7{K zrz3C89;qL@C*>BmscQU~B;J(zSOTJ;A9CGl4#V}+W&tbPKIfHG%>9(dBzuMlH15E_ zpg#e$f78Ox{PJe2YYPLuOs-&^5OHJD(z6O$kh53xCx8|&c{p=k&XPmkZ;Z~WlkOlUw&2Biyq&y^Oh3eGGS2!1Z9y1*?gBV8!V z9aJtbFz8PX2Iq@=$Ab>+XWYir(_?t&!NL6t8cH968r%#F`rw^C7JkpS=t(uW7;;`) z@9-h}7*{@%>?u%#8>9df?Hx9+H$%XMIht+2$5#Rh7X>KmbB#nV7#l!f1dvz?ml=N`6kb%@6;2!5Ec{l7k_ z2xef=pAKmSDf4AdJic__M*l*+qqVm_FMsv>ALy<}kOELENZFG?T=~rGs%<}~&i+1M zPtUzlGMxp~h65>>4-TjfyYqu}@0)-R9z1Z~8eT^3qe6NH2!AK<0ub-&{Ro zjO!x|rC(T0v#EPzbgNK~W2y_rJ)D)*k=t6g1Fn-j>L^5{C3AZR|1fkA&h zq_LNz`hCW%DCQ&oD$AqJH~gA4&-w|d9SKqZDknXht7iPVnS3Vb$oAf{>v1nmaUU*Q z0?k?TL5)2rC)uWQ%@?!mGN!KDe`kyT;?Btvd!Yl`^Fdu(ea}}?e8$J-%5)mODKg!| zymp6Z_kU=Ibb$^yph6^1|MmK=ANc&)&Iy9o-o8EPcMaMCSqK`BvGD7^Yt(Y5LOwO% zse{gG-5DKnjge4aECiL49?p~bJQQ*g*u5+(9xnWyKF{>!-v^+zSqu#Ni$DoS-!s{y z&M~W~LHt0_xhW9~i+jH<2?334f)tp5-5|rTchPRS8I%5P(Mq4Q%fP7gY7BJ!@re2(NKw2P6c--O<_;%jRynA#iE7?DSh!PSXJOM> z(D@e(4Ejqz3oU~^D;C;#u`9i8I=yINsjTPS_w8qSpjmGTWWD_yuN%3IT(=J_&1inm zlgct-&D*`8B_<3E`b$B@fQ4U?z{8aX<#o3kJFp4{TdY=k==U2`aDWs**4wKTb-yXq zW4BQjUUXT1dDpd>y+1)^69a?(GD`*q25Zl@BilnK@11$YOHSuV1^)cqd^KF zm)|WDJ(Hts_FMMd!)@Ec%vbX1sTM#hl;xmBjuw9ZozFkh5lr0f$E9{ZBV^8niluy@ z)Xc!3zXBB09?o?qZmoV{mtD9*lDT`?)(1QPn_K|}5J&-NCdAd#DtK#4Z3;u_t$VL0 z{djKpP+jx`OabJ4`!EwO*S@)`1z{d~U!BW$p5BzW9F)`;81z@Z2IubV)meV0uVuSR ztYF(U*DG(?Uajqr5eofPpsLx!`AmM^y=rwy(c25Y7)m~IZ175H2UPE>HBZ^^`aX$AU!)bfm3IZ3SbAs3H)kct_Dr#Gcf3{0}U#B zI5YqJoj)yXQgr>i_s0tla{jQoxF1wLf)s$NM{CbT+8sguQ$x?D23=?QE)gSRF1#Ex zR?fhnzn%~5h7X(H_dTqrUa;f*p5vujVMk21?EtNDXJF9Z0P3Mw`1u&zZ&@c((4lPsGc#UNXK zL2c>0McJ^+x=h^?yM-nHsT|H}9;Uus@O$TI+2B zrA;ZP2RpXtZz*doiJwzCy>-Hq{OWi0kn=$FH-U=5GS3`~DQil-E*bUYzL;8)b<*b$ z^FwGaX)|PB^Xvm!ud=;EzS;ap<*2gD#4X`%hlZ143VR26gG&ouRZtUkjApLAPJCy{on-CsB|y+gZd=<{D`mH4|R$E zXPB}cy0&>IsOGWo+g8rElJVMtuo_E|srqNV7S8?f7}R!QV9?(Qs{K5iyW2P4dl-Ck zO7lyb?wE3y`q&_2#?kQEkwjiucy{pzmTELbh6{4@H7@ygahXi*Hl1JlDf zzH8s}XM3imEMVRIS}3ZdWAUvH(0&632L0WjHEY(M4;W6ZboY|?YO>hNy85u>yVVl0 z&=Jl(++a5_X=m>`v`~r9G2`5k70YDTv3ul!hWr>9^!I|Mvn~84q*wCATuKY>Im$5A z>RNE@BZ<$D{hRuGK^vewoFzOC70&75iO4z1`YYDE$xiV}FR17NnER;wGDIU{^^M5ZGnJ(;?&Jq?Lq`t|K+)I7wxrIG~4=MQ%AYDgW+qC_ZS%T4}j_mDW}a&_RBXkw9oJNPIV7eonEM`HXAgc z4^jXsK=eI}q=l2Y^^K)hPyRT0pFQ87=lj0GOqd1^$t$Z`udH2BE_FY~!(8IZ%ix~2 zJJ1oWgP;zXgSgH0ghQb4ka8+!msmda=(24dF5N;Q$5_|(?s0|=1s?(}T8a1EZ**UB%OcLl zo`+NRy2dO?oxYj@S`;680d{1mhkElP%PCuTWbod;u%M+nyL?k60|@9J0c~ir@Y`-} zR{braChdMxj_(7v9i5N=U4*u)kAM_71B3n%&<>{{&k4PJ8&;}&O*-iLvS)A2j)-fQ z>Oe;_F)-*K)df59?83c5Ps~LHa`YbRD%d(W+P3bVcC&uS zzGj~7tvEURyIq1~SMEo5P@f;90CEJ)j^$S$zMJy=-@CHoLc4M&Kg^pXz!6QKEj59fR5F0n0nEiA}&Rc5v8;??3?o)m&+ zB^em>PlDFnTYEaDPfPBf$-YxICAQ}9Q|0B%8$Cd!8%P0UY2v02re7viYIDBm`up_D zF_t8e#ho`HA$bav{4M-ydtYj<$#LN1+y5?2&2huUZ5ytDyvM+xe+ra|J)C#(SWRBm z6I{AqQatqAnG{>YY*uI)bsAJHNI89xu1?*yL9urr=~#H%bf-_RRTTF zIG(#69zJFJrKQz(947KzZfj$`0&&CXrQpaCpR%KQQMBHiX&>bSc^y zQ0}(yd#xrfIWtO9V%c>)K?N7i8Sj3vf_kb94Ekq5(eB~Aw&zgi<%xfaHtm&foBwz( zldT;Cv@>`Xv|z@~bEd_~TdXB-ugtx>gzJyrU+3-Nzd_63KqedkyWy)@hRe>I2JbYR zf3~hnc$=l0ej60T3=I0`L6gxIewWP-+Vt(ceCzME8A~>lBpJyDu7=K-p9h__@8R5# z+LQ9prDg8(67FxlHA`3Y{S1Vhp{;)&)X+);gf>B}wdfrb@8 zR)FR&;yvelv)*dAGTlB;fI~c^TZ;8)@)T&TcL8z;|4Th1Uw>~=4F(PoQPUF!0`1K) zpdnxe2K|em+->3ax?aXY<%MwlznQV|_tcLhOPpE(4eE=ac?=KdW3P|T?wUP;Bkf4b z@1R7b7b%jhP%AEiN*F1p4)={->rN!K&sT^Ru+523TA(chsz?|Z^e=&CrQ$vN3;DB( zwrYD$XgIMZJgVTxjUBe2nJ|z7$oZ3!>vl?T+&RBB9MQYv&gH?spQjQo9UFSsu<=GyFHa|McT-RlR4E(5q6L|M`bN z8&nt=^sj(Q7;De_8wwAF%~>K4=~c+OBynHtiESRx8PY2?;Mh!Qb{2@|ORX#7@H4B* z5ptAT_!Cr_F)-*~1+}Lv{2Wa`7oK_6vW}Daz=A8ct!sYf)lLb06cx^e@ z4d?HO+^D&!yY+mNc6?CKntib;S3pxE3=I0<;W-Px+04gOj~b~c7hSNZE%#nl^=i>9 z&?pi}0mvi|XJ3JMhut&YnVMRguy6Pxm*3EM-~}Y(+yFJerJStXo421hQDozt(;YK? z;@|yWZJD5B<~KkkO`vB??^U;xnSP=tOg=8z{U^zH-?Q(~bwM{E>tU*d&Z_R}@W{XK zkoDIgYDUn6z#M3g^%i73%(e_&AFj#ww0zQ1Ha}bx`A=xG5U4H7z@UE%)RysZ-gHJc zURYrDth-NsOHF?`rB>Z+GSm&XK5h;Zu4vB9O0#)fL5x zp!O3;0ce>+tmpX$H#TzKe#>JW;F@;in$J*=M_WkzFI3ql9An&IcT`CO{MIW6+K_4`;{QNgh(K zr}tm9j}#BxI_*E3*glv7(44!J(+jSUgX=d=y~>cfUiS0fV-wSCC7}aWk3lmb!Jbl# zf?M*+u5XBzak(ny>)-l0ss+@r0J-50*pcpGca35nA7`#*KlnW~(Zk$-(ic#EU|`UH z3d;T#enrA=H$~5%>J~k8MSgD1gjpS~;1e`J3P9s99?sp9UY{vd_~)D$wsU^1_KPhU zS(88&2}l8`2$FKD<_Oq-S|PW{V3qL(-sd+i7L~q-P6R&%6~%6zpG1$(w6dH0Ih1!( zZ{2OP!)#x@p@sP~Q?Mgfw=XK!SY9@F#abj{vN&`_|4bN}u2iOV&WzwF9CR(!4b z)vwJjH$8%6oL8VAmvXYYF#|{%xAMUGx1KP$AC1pby%$&lu?!RJ7oQp>JdM2G>7(C$@ho3*t3_&Tqa373vm# zb<3X}2;gIpSy3z_5njIST-P+@go`CH2+w!)0g16e^}fvaDBTx;FO~ zD8qmhfCjduoU%@3TurdK_CEHDSwQb^pM%}syFlpxqyW_acJE!R1e8Gx8O_XjXYFHM{Za=n>F{B?bolcc2PZ(&^rs z%K=)Y-GO^FIm2$N?Q+4VE!5=zoNa(_T5P-nEnE z|GTel%)8%pIX*6Jz5v~z@d-3&X5p9c=CbT62HtX}fJ3o4Gu75^(tQUVJOtl@<>5Tn zyfN|>uXlP{|Jt1TyG0zUtUrTBE*Kc}KZ81h`kq}!-%6{^eY@o1ow5V5K|&K>>3&)Q zNwl9Kku-!p7M-Uj5LJ`~pfB7Jm2le2RYI;d*xZMfNXMiPiP@ z0`7wfF9rtvFQ8FI59ggx@&Ps!@Rx93ALmqeKpEO0{R&FmWu9LGJWZ1h&OZA( z=Hib)HvrKhGyQMprKGnr=01E>lhW!C$rvg-nwVM zL-^mLGod-_C#dFtsL_j4h$OO>1RG{aXt$)hJCtf-_JK9?+ziHdvm0bp#Ap!LV zvM(t;G$}D8Dq7RC#gb#O&y^#$m>Qr9$^L?-vn~9VT&&^BbQ9WqS-E%nS%WiKc5QyT z5EK4_Di#mt&fA&Mo6gM4v!7PbCF`dY?Gw?&Ygj3aR52T!=W_rza*U|4?_9*rb(9(QN zEpvZ{jlaCXWyl*1`BvOBdQ)X_NUmTCE&o>s?IGekgTG{^){2_xkcdtETF zSC?%n@BZ`NZaUL4qZ-G_v<-% z<190%G6N|9^}juwf6OcjI`(v(?NsjKJgG)8F1^WB_27JAzyTUwkaAkHiR;5HIZ@9q zlJ|3z+kK~W2AF}$Xa)uYP6-CkzMjTHR*{*`bzFg8TP^fOtk zi`7A+NDK@H{Ggi0!tZ(0!B7{8-LHSHojzkROL+N&>svq_QIG=ALQ4Bw`?_4xZOLzoJ`ajrgnX+u;d}ca>&-@}KAfIY`Gq z5HyG2;T#{lZ)^D6+cEPWH=R*@dHm#|2U}_(Nlp+H?NUw_pE$}pS+Y!dW-lodwqEh5 zGouaa3qjBzNucLJtH?EhzOkLFXRqhIqrJlIc80L|0imLMysjQQ^wwvpyUox09w`K;oR;}`67{{ z-Kow>ppZ}TMR=2T1ZbQZqyW@GmvR!Bw|dURzyIEr%U`)SYsF`KiLauN-Pr~rkXBGr z=iVzp&yHW&uyvx2$>OJzqVkqO+O!5DkXDfT)x(#MRWkP^gf^$1yYb82Fz*$p(a*qO zAPUN17Jhy^ck^o6?zg||`Ag+iPEO3RyP=R(!3Ls`R?w4U>3=#twb}RDpQ(GW{B*7G z>YI?}fq@vP6%_2b=19QovLh2*9%;Pt(wV;atXc8JuaKY?gUnVZY|dYPls9U}M2pHF z+pcSV-hGXJ$_iQT7d(!jh}(RKms&dE#=f|x3N0YsJQ&iBCAfv1X5*xtDzUp4{k)$d2cG-VtQoqO^*=G4< zCS>=7ffQ)i&BAXn%k!EYhhrzSSk-+?ESdM#`YwkW#G6u}F)=+mfq#&)J{3Ctb{2Wgd{^`BWHu`Av^t^TuXje7^gMkdB z6}0-SuSm5h*CQ3y=dXF~PF0*>-wqm|1u1~Eg2bmQKDeIIc&4d>&rM;!xw(IG5~KrS zAOmRyElzzU-mrfA)+B!er{763lm7I0KubAUNGquLaQr7;;V<9+oY;MksdtKpUl~Ul zBpl=*tsov5T~;^F&y{Vge-uCOc=jOlgg#6Gq!qMi&s`l&tKxkr7x!Co*Hn}qGvb35 zVsfBXkhN!&jaEUBn)bFXf!msEbG9yHp{z+j*NN^%~~_uACIM=xA` ze*Fb5zS6Z46IsvSfu>1C&{_;hr;sh`2KAfy);u=+r0*YbB!AlLF37fJ14Yo3a^jKU#;jATWWs{(jqlb z0`>hZ{H}0FRI}I}F$Z)y8@cM}b z=0?+&K;uFgG=(VTq>^D-eNraIUQ2fV`FBr+!>ZZWK{~|-%AhkC$~>!+rw8pioE|YL zz38@5cU8;fdU??HGX@3&WyqD#>(-y>`L@6Cn$4#re}C{!GWfzQ18R9NFc_$UM))lJ z_A%DGhW~PZu)*$0@T-@14ouzO4vIyP0#I4y;XK1cRby+(-_v1kT)e@v+}B>)cmY%m zfE0k%lS(vZ=ep^6ky@Ulacx2-H)TO z>yMZOh3`5nRJ_0$G@{4AV4x1ldLGUzTY1a3-;`XnOhmL?=R|#0nCeB)YG9B8(72Sl zXY1#~>x{mf&YgMmVdtiXy1Z=H^Ptj=fx$pS0vwy$4U^?P?ficFhc)>K9J#x8*;Q^( zdzyj4Koit^w(#r7<1&59zq+%-CFtduldi_;*BwEFWgrEhI^4tAMJniFv+ky8#}7nC zO7-`hXxs%J`UEKe&73QHZcI!)x6d;nBRk>q;oj-X_h00>0@BIAV4wxbdPjFI&=S|p|NnzlsDn%ZWj!~~_n%AxgT6QE_TE(a(~)*}!k4l;kg*^G z9b<4f1T_;G7!344u^Q-keof{baULl%?>X8x zTwfobIBP1bcc2#wcEjh7?6cP2J0sn>^W=(U@%q0QTSGt%3kC)QeUM2Oejlw>H)(3V z(vIifKF6U(>fNpn>Y%YvkOI)Ww}uXL?TDFZfg4(1vW)yEJp9_k^R#@a>Q<8_&HDsEirW3qOMGq$aro-ph5ZiR$zKXN=F z({=`?kmCebybG9eFID2s3?JVs?~XN3_274H&+Gqk_igT#o$Dv${50xxG8t`P-U$vU$4LPJ zy!k5It7F{x-R-?IU(_c+)(sk1fbxfhUvl96H__js3`=}=oN_)nd0}7z6EyodrCo!h?%gXWk)CVfzS?c<4>-+KZd3%uRE1=2jQ1x*onI3JuCv_j+UuRF8NG&kQ8%eD8`aRW^e zF)$d|f=;K8_v~YO^i<_b%(>*)s}Gsm8aH-i&jf9WWMD9`69>EDa$`{3PL)pnS%Sa$ z7k|nt?3pteIyhhtvcke|R*+@E^rszFsTGIi4YR zR1^Q*N&6f2ZvS!cnJf$p2KJyzUdrjH^Ye#WoD*1e4~7O@-qU`~x;6tcQ*7V>TJ}=r z`J=UE_pEpGzP&6xpR;b#@t^It*F!rX4v^!ByWQ56{reQM@Y3qS?(Utof2yW@1&v%V zFc>(360e2d>F#`GXRTe_`a)&5%Wo{R@~^xC8n9zvFmM8m5qdc9aeP+3z(p^_!eDu8 z(~FvYZ(^5#dIcZ_pu#NBQ*7F_CsxO9OI&JrDJjaGx>~CIE+_;+3RZyw%0pq^k)|k@ z_u{#)j7pb=>TkPp9W+kOz+m74nh>_|yLe_zag}ae^A;7kkJtH^^S=E44Ag!CDFE$D z@^CIu*u=V({mnzZRj;@Dm4%pFw0^OJ#HI_VEo1F@#o$_F(*F-}po-f&Q16I=!N3i)MA5>}=uD8^nMbrV z*-vg>{LVQ6vSG)-4YB|`-s=Y6>x$D;8~M4Kc29iubV5@mWKPY%4Ya^e%ISD)|65Hb zzV_EaGnouTxvyu}DS(!kfUE$O55b;CPA#=;`dzJwnh9hzDqCo`s*f&M=CK{Kh3DN3Da`0~)>s&s z3z=*(@P*X8bAzN=m&>-zaQr{pEu$iF{qnpFP@ZI9Fz|)cyl<)$8t$nbkv?~&;N8x@ zCEhv32cRj+4^s2W{F?5;{Zg`mxp!T6_3pv~?hlWk!*2eNns@fu^%j0ya|0Gn`n1eo za@+G~1>v9trVI=Q{-B!I&2y)lzQcLf!t!gX47F9I7n@%+{)1Kr{*Zl1lVxVI|6a#$ zuz#n;wI_R{e|)-i3e-GeU@!;-tx>Y@JMujeE6`q2AZSEK%IWo*CgvH@)9da%JeQuL-y3Glmjvp% zfUE#5b8z*vd$DM~(1FVe*R5N9dj7LmE%G=6N+=)&zre}fo84jQ<*X^fWz#o)kYzY~ ziwO!9E%J7E@h^knor=Azpt zZnhS#dDATnDp?p941z%o4Sml$cO`Gm@?o=VtP&8paj?hRdoDVKR_{&cAE{MI{rd)+_AIb8-e zwl7*BhqoAnL2g1neb9MboQv04ezi-F7I3RDz3c1%l}!u`2H~JKjD=s0_msK=lVsj( z<@vSPr@86IoR^xA1-Ay_pxWQVS%A%sTlg%;?78up3tikB6*g|FfHra>K zR$u%1)3M~ch=TOH18I8FZKn#L6>B7DiKd0$iESx2^6oZ%{-X48{?+QoaZ7(50rid; z7!0C7EmIF?+N;G3En%WSjU7p+{bt{nmHycrwC7s%{`Ut= z8xQZD2bth7hyo3sS$i6lW_;oNA$qCxCEc?+fA-9f4mls*pks4SnlHb?ivs`|x; z)rU=S+W&LgZ`UhFUswbQ`9f>nI8bpYvXv!$iQ!Y|?!NjsF@rzgWlp1$49j))pg^q#5Lu#A={mLHqyp+qQ zrz^*b>X|YATCyB66J(G8sd3U2)O5`H3TLt2=#!k|FU08}auHN;FfbS-Kx&-Am)om1 zvc)n*bf;#lm^Aa=k&^q{cbT9GN1NMriWBevr)>4{YHe`yKnrn{yIJr$qL;6@`z0)w0DpS zN)PUyr}foV@CcN}DtJ2luxM}8Wx84bO)#l5z>aL-)5t#+{hL$g(*c*Jdo!M7|KNqr zfTV%C_7;AJ9zH)Bd$!obK1X@xuB?QUMNFqb$(@10ARRPi=HYBCcuKg+t#WF1P3^LY zI|5Fwn;s7hN$};6QcepZ4$k-TEnM<8)mmX%?&?~$s6J3*7i0pcD0cV!CiSnnns3k6 z$u~{8(_9aKDa_jm&E4sjz>dsV!SRM&{@%NstZ1dqJ)A55--q4+ZjcFDUu@y`^XyXf z9je8JOTHR!`fcE;D&d+8Sq^8A3Cdv}&M*J0t4Zw=h|f{sJE-T{+7YP}2paliU@*u8 zdDq(W+M|ns?#rGx-eEUWHu~{%{P*ns{06Bls;IIF^@4R1TXnI;qk`qW|66E;@ zn#W>bFvte2ZnE%`5X`oG$Rz2Z+ia_O)%Cl~-x*$zd4Gd!P&2{9S-oma#OxcNgeJao z{P!VU)aUUR1*jvlK`X4JoSHY!S~4q)zc27f%`~Ryo&MVw{D#iLWZwkuY-$wukzuso zV<|2*|E2obd9I=s8$oRs1_py1$S{lgi%qwW7PkGL|8?*08JmAH7j))86KyVJnB}^V z?K=H{lU5tHY|iS`3-aldd=BbwGcXwBLWWtctWMPCd>OfX_3`Ta-#$MNGd2$e_3=Oo zK*KCjP8Exl(kxmdwY1i8c3skwTeWVRG{|TM27^3Msju((V9}YKZZGm*-+I6E$(M2){LX?lSqnh(yz!p>ndZ|K zRJ4xuXWvV>HF?@O6@?-fNI6-M2ToBdejUHH@8pMHH+SuI&5u9n9kpv8w82>jvckge zld75aVG*8@(k~T&gAFV`EjIr$rGG`n(yd!h zMlgdKHw+90WuW;@59fm!jVklzojDxe!WO&ZFni9P3pINn-Yf&P@!dUF-g_BirlYXmriO z?_~I+*IawDk12aj%F(g9wwQ-{``yYF}&KAD;nR$jfMEK4j{>i4nFP&ZUMgWcfCRFo2#w&s@|^W#$1sn3>b z{dR^br~<8OvG5BGZdzFV$L!8-mepULi@Al!{4D`Z-!d>5RDqV}c{qRnd;cOc6N|{^ zPFdz$pZ;~vnV*3s;~5wXszJVq_5AV0AW-C|=JDC5Oqrgk8(*uN&J8N%K?*9tZeWRe z`nP-UX2q?FT2Z+Xxh^>^cR&e+fx(~#bPj}tU+lL#bC{fX**gB!NiAHkh4pj#Z^()o zgIZ8W#KXB-u}s?V;6{PDmprEbh%%p0zi&2l{X=aK0|SGb=MBwMR;~xmo-I+1UHawr zYOVfVt$*@yT=H_PC>YZ+XxD zN}HpmwuQ%wK!rF1gF!u{LaAS$`^M{}mT*kYOP+{3sRFEP6?a3@Lp^A`TFOby+wR7T zALr)xt8bc+S3NI^_t-?}FiSnCLb3ML;CZdH!A0U}bnh9@3lEOWo^aa)I;7j zvKPCgGv;^ZG~1o5m?#pz^S%}+PckqVfR7xp@VmA_+|T&$$5@FD$K3oGCnXqz^r6YV z5!3+pa5hQ_Hs;rw{<(*9gZIB*hpWF#V*|CHKqi3tTT)I9-4ohQF1KoL{JW{={j&Q@ zdnb25eE~X?gu&gjHFnO`!o)6xBy&koLC?#FCr$N%c0fP_T8xo?HoWJrOpv{suJOFf zNA|SCqLfp=LDLcp3DW}P4-qD6PpRn?OpVhJ|RhZ-dmO#)*H^_v~ z;Oi}}Z}{q(cEl#?@RThATc-ZJ|Hj7z+I?t&ZYwDKoOtWywVy6-EX#IQYga1>auh)# zs})ptS@Q9x2A&~@6@?g9rgna&@eC(+m)>iGKt)SYHvFlYnKZz_8xrD$%R zym|foT4nQ!m1ZJ2hs_T{r)kKVIIGhyZiJ{eaHAKlPp0iaTyp4+CdeI zg@@fsl&PJ@Fmc^CP)Ef^L5V@k7tpwlfq5^y~*Cov3PgTBLV2r zf(}-2X{H~LTl~(#kB!YU*ml2f-%4oTzZ0}1&BE__)6+2Ca+hgS z^pkho%~j}{9T^I3iFJb3!+1E0Jq@`rXAA#J_j%IVWrcTr-dc=H-tK<58(Kiq@=?F3b za_vjRDq+Fi=RAw!YFk2g@pTuSD|LkqRc{tCy|^mU@5twP1AT|Rm{AW5zVa_!5mYGiElthwh8tf8th)o0{<4c+eKc62%N1$ejQxX)XMA?ESU*l>b{R@j|`TVt%UsqS7Ql zvyu!91`|NzF&@qn)2nudKl-WjCvYaywk>D2DBs|KM%Dz-fUdRY!>Cz{(p2AkU)8(Z z?!4|&CW|~NP@f-U!clN3C+Wp>WRKUzU+t}*{_NV{Y*Rd|1F|*JU=nB~!@_U%vqS$r zI5YGupBy>o_bSzMUDpJlLp_r~+m}6@&vxa-b^1viKGHPpn@Ctz)^|e}P&L57U@!?Z z@@?(;eDmrRPd_hMZno&f9nR#5#WL)xAiI(cCfx+PVeZ?eU26n0i{7X|7Oq|+EPgT~;V>DAVJEI0!i17ct>mL{a*F#rbA3mnzuiH>qL5cJez|PB z7!OS_(?NY-SI@FAF=)Fj~575-<8+kMP37An75 z%X4n+qe$p9?hKF{Ed1t$%=B6OB+q&A9i0{d2kAo(xND)QdIl($dpNVj_c<=&nZnj- zI?ZL(<7pfh)sBF60y8ie%mghpk#ySoRF;iHeaVvP#Rd z^9KGc5n{W4C)~^w4cO}P{x$m_XsdYUOmJ-Wya~Fb9MKeSQ&i?Bvg^Ep?Ne~yhJnFg z7HBrc!te52maDhEy?lCZ<4N5;hkyCjHTQrTHw+90vq7Ut9?neH#Fu<6^7qP`1sYMho6ZNPD%J^t`r9A{kW}6AT0U*R$FlRO zOs{)_cRjySe)Si0S>Rkqs;=7IOEqXexE=7LhSyXP9ulkZ=&xP(cFt((g?FM0~wiha;Q^|?>M;V?h# z;L;naIqWUzmz-p7Fm=XSbwZ94G?))6X)XL-i!z4a)yVzqFTDGW+<7M}_vz3bUIz0) zQzahG{z|j@vJcLkEw*seoJTV&8cN)fp>wSBL8ZNvljCpw>i*uIHyciV{2p?=NV|W= zQP89U1B1bQP_wbjGw&#~<(=jhV{QiCPY;B?ct%}W3EC6Iz+kYz59~;;u7xV?D>r8v zZuOgVY=y@hhQrH2b4Uyf1`9zouZ7>vJ#Dp>KiinTI$8Ff&MvmSsUQGaiU(2v%ETVd z8M1OmYy0=vF?#*sHoLMQ|3%U{P|?G{V6X_32i-i^Xy0vDDxIju=IO;($+%r~_Zea6 zx}Zgnl_Xb9`oCSCVR(`?h0V;YG)B_R-W)WN#lT>&7}QI!@N?#G^s3_VQb>Ccp`p!t zep|_ciI9U43>Jf`M-S&;wIAP9Jlwoxo30_R!x}v$o)lAPV{Zwltd??mH*v*__@}#z zqz>OsF+8yU)$7i@pA>7co+|U1y$7!=@ zy6G-Up@sP}P=%uJSu(HN;c)ie@{9l20`u)}b2IJV4{A3sFc>V`3y#gSoZk~0_W9W@ zzHzEoCI3K`l}jh6fyKaJumW_7gN5IZFSAt>zTRJOTJ)XF5&@a*2k(DXhWKIyXgQdN zbHl8O%AO%RmfcE9n|NiWcq@aXC3FGR3eXsUwdbygWdAF%{%;tU6udpplzZQsAqAAw zKvqEJ+!+#Y@$X ztI#IvDo`cw;koP51m6ls<-Z0EedL~GcXve0@YnXo`QRi@#OrC<_$e# z7^S`cvTpPg7tpu^NC9Mb)n1d8->YU-MtaW(EuQ$H|78RVBWMLG1B1aDP$stUtJATV z+9#UTzurPELs{?m=MP6ef{X?!0IeJJa4z|iGvl_Tge1=j<@Mbk94=MH@Po!aKng&+ ztK2>NlQpGHI@fNU)$^(`O?;yC?!VihV?k?Wz;TglBK=xY`okMO-k675)mCXw*_jAx zCNeM>tOM<5weZ^=c=dPcB$fRfJ1k$E(XD%_`|BOFC|(DOb`R&LvuB*~wUFJkP)F^} zhCMPmjUH~GdIDqusOFJ!TK-{HHPe#<5&u+t+p34_pnrPWK zt9;wsZUwzZQ~2)AUkvI#F)$dchYW$5d-s?o#s>b`mWyz?V)S{O+H%q zRew+KOk6!}?sBE>lUl?LErXL{!O(%+ji99#!Jf=fLaCKvmMb4x^>$i1 zG%tE-zX+NpH@1L7vVc{;_s^a`4cm-9zH^=zQ1vqhGR4YZun9C2Y~h#T#u>Exmw6Y{ z3YVsay21zFjD(=8-8O>`NbqoezwC+cFGg3D*^i3f-0+(I)ntPwH2ZG`RV%@l}S$pz4r;!C*6}C=T|#T7FV#-!6C6TOG@61y5h@^y>)PN!iD(qF0jsrY|k{<3fg88+?$cR^BgQ zl{I)JD+dZe1_pzzU%&zNV|}{dyJk)&zs(xw%9}o%o)>8f9VFTA3tnnsnD^qz?5z>& zCN_sfF>A&=Dtci7sz?|Z47P*%I3CV=q5n7wDyQeB$K6yZ)))}8|VL88Z->e zz+kWg(ivo0zPElBr|7#@jx^nyx4y|a7yJbkpbQKKJ3(cYh2N=Wwt4s7Fk~5s{%*-w z7qs)hLUHH-=1x$R1>_j(CFS34Gzg1 z&MP-A{tnX>ed?z1)b7>_vBpa1>S*wC4+}qiO>M6F6}3NYRDOG0(E0eM^_M4fxyx=) zq_NqCzop+s_dV}#dsMcp-FxUf{WKj0hPY7P_IeEs73zz#9eIrXv zZ!Y@9P-WaT|Y<;G3BcXYb`InH{*r6+iUX2KX44EBQ>To!&7tbI;PEj5HHjs~!Yq^x-DxaA9U z-@yS;-R0pNkSXeKVV1Rb(fq4Bm%cm|+n;n4S_B;c^>uxj{891B1aKP+{ibeCTRY!qsB7uJ}rx3!qo7f3;V6ycUs)uq<$6DA_pmeny6K&-CY*^6*{PX3^Z%+;ava0btcnMEs0%` z$@?qICLT6gcNa8B#K2&1>@j!@M9t>njGYJDge})-80#ucRJ>vF2Q<+IQUDqQaP<^F zcT@BRck(Sco+aQMC)Bk4QSby@iLMOye zfZSl==jf+Dy{VP0*mmc+T~#Uat$7Q#f${?bgTaZ*;Hd%q+h=|YeND*A39RedetsK^ z+UI1@a2f-H!AVdBE9Jx-TYqp~Mb=@94;qR~&i+`n`?w2ew*W{1X#76bQ%$wxMML7= zCl~W%z_O>KEhPoRT`r$M!!hx5uM_k7dDwD?P9R(GyE*O$B8(iA$!dKy&y zNjWJT`}3Wvq^@Mu>+n66@87z8wef%^xznHotM_STD5Lrg44>H1nPXjg3h;iQPHZv7nOwNimO3 zC)c9Gr*^M64jLN;SpjMd1$k<0@@O`Yn*3yG^aTOt>c|rlN>e~9vl$o+&Ozo5-V4gl z=vY{8Joz?vw)=~RksOMvpu@1|A#(@157|7*ZeEoyFYAq{#6DB zgA0%)dF(UiHdWZIW=bf!EVI$oNw2wMA*kiSz+i9@G)rmWr!mFz_<0qT$ZzM0y{B`Z zlW@L$64cNHDFAh+Je>DjyRakSY$fl5(17B&m<8MQP8mR}gNu+QdB&l7<$GNYSgTqK zGqf5nem~)288j{~fofoD&!Y8uZjRfpCfqUmw106@>{YgJQP73xmt4Wc;IZr39&B6x z&xtA(njP`Nkbf2PDQGxc2K87i{Nxp^R>(Z_-#cgN+&9X;bCtJ9d;&G{7#IvLgWC8W z&Iucf3p=cqw<@>W^WHo-r6uC}M`+9Z3aE1|<>Xj^-x-S}a(#83m|3Oz4 zT>+Js@t%LL`7K)0_44w9{W2`?avrUFy?qmCUXy{r;0olHz)vcIEVpJVnJeybEWIl- z;oF9lme7qVS3%)m;b%SlyS2gPBP$-wSJB;l^FL!l-wWu7_cc)O*~8gfyiJSYM^9qP za?@*xS6-f!iJcCrCm0wEu7To0(kVwpVqwfSW$|jG;8ts2hNSiiXHZQ8QUF>lAME*W z)#?}566dTwG(GcngVLh7o}S|!kkbAdt?#>07o>c49-nY&-!CvQRxk01cm@O{uQ*pE)OTo82DdmRmK}|FU z27}v>vRcskKjYVxuc{Ut+4g(+WA_f1!qcF+GzJEPJCL$^@g8$W*1uZ6IcUbplm#juK??=wBA}JcE|;ijpp`Tr1)v!Kea{PTGM4kn>1=+x;^2Hnj@cHb z(wv|JbU+FqTj|ez{3aJ`efC6O;-Q0Y@}eGaN-uLHX}t{@ldGcHJ03t&)I(5DMas!-t?muE zh=^Y+bIR{e(_1ILA^aA!$@&n~$0_s7|CZmiOvptpOv`fb_2i(|O&?Z4``r&A2l*Ps zr>Qf|@MV&i6#HcMPV-69VZG26>0{6kpoQOOo$kLY_5~dN8+AfRtaINRse(_S{uKj* z!DG-0D-Y+--?Oq`Y$69;N_PTkn_rU$&{2qb6lD7Wc z-7n67R^l=+7=TuRF-H3BJsSD_^?!p9_h5^w52Tdij`wOn8=Oxg!F`%V#O|I6^%Ka&1!fU?~m-)4O^IMb4yF8=BbE_ z-8FsoANMs0(B9%J&~jNRCmYsBrAAt2BA+I&^2jX(i&VDdw(~JIXPnI)T@>2Km{jYWT%TE93Ju;2K`Gf{t?12oCK0S)j6d;X6pPUL2h)MMmKtlhs){IAch z98hv+U@&;I3>=#W=fy73crR{5TC=V(|%7ElN4vI&+kdZ~0Rd zWA!h-f=d)HMQ>(?Hncv0hMSZ*lNPn2+uH3{Cc5Kmldp_uhQ=q3QDCJV!O7o@}bQU=#d^7c`f~z+mtN zlzBazFUi^47SG%;;nV6K<$jG_2V@;$Km(T`1)#=`l+)L+V~15sc_g%6%u~#@pTN83 zf$mpG`{4^{elN)Lu%l`2Jj-l(yLR7ucB|Pp|2TCCRNFBy7<@GcJ2LsM|9-9OlEHyD zO&|S}Ip@_Jwgfb~%D`ao4O9bL_=%?_2d{qDaz3$=(dqR4?HRrbFQDP@4Kxnn;k@B! zY4hJ~C#TdMJz z6Eyq6z+mtLG+^W5{Q6w707vP&$$>)o?z=sU79TfM1v!p^!Qdz8CN3!_8Nr4(_eEEB z?ED&`tTaXa*D5XtkkKFopuzQEPpLq=GdGs~kOPcRn~c zpWC+GspDCn<;le&%70uyYup(a41PoQ1pQK5CDJI#2jJs~KOrOP^e_wLRIxxaliQ0jOFC_Pi&4+No7N@9>*N_R2HYw7i)72Gqa; zO&$Ke3J$1?Imub7H~xk0e=M_UW@&DT*WcZsY|p@8@E25fS@_8x{aSyd@y&#)cLC?W zYP5cKyq5u8V(}N$WAkv{eR|^y7qxt^y?-<}-&p3Rkx;(`T9Ez)on0j9R6M!jWoUl; z4Wna|cva+&wTt8)1`XhXtT+x{)EAff!%MaCLEzP;|LdMui8{{{uZK=&|AVYEKO;2l z+$n`U*4=PA3{LVg@Q)qc?rR~r9&-Wll@` ztCv8{Bai}6^4Is2?mV4)sX5kM+T+a6lN%zRd9pBoqM3ogkU<3;k{V^F0@gMD{`KsB zk@E*d+c!J>f*|8ChK!)*frZ}&hKF&@F%J!yo;jZV@wunI{6hw0xXF+aR6ck(r>D%a zlGs!7JF@R`XY{@AqKh+cLq?ko8UKQZ7fd!Ddh%}KUVa&+t4BZH3Oo4j@kU63F=PU@ z(A_-+7d?M0n$KT-zQbj%>#=k1Ii#0l$O1X1clPvtiI4@_ zN&0#DtO@V+l^@jdKqgrXSwU7<_=$cnQ2F8!F;8yi1;Hc6+gDtRT>z9Ku-7 z*Y1G7^DK3rUbd@V8JQoDUY%`c9ByAPCx><sep3nA4?yrrpY(A;bFZs4^Q|VjJeW1BCkOIg)6vtVICe=9;tz~VljWNeh`)gcLZ?(7wsk01uK)obMr>i&pl|LU%zk9GYQ8>wI|3Tjy)sTrE zL-1uC%AOYIm=-HZ*mJQgW`7pG>E*rM3qOK}!WkG0c_G6rE-vElHtOzvbw$eIL*Tj% ziC@%$Atj675Q)&0@$08fKAlI?xopSE_1?VU&R>T|`=MJIA zElBgtD2Mc4k5^JB9%y9-Kc3=D?Cpp<3pxpD4-&wFOb_{)l#y*u|iJK{rx zF{GzvD7+9H4z{zbZk_cj*w%1A-u&1-FZ;R=!H^D!p$KU4uZ17Ww2vhxIHsA^%$;%~ z{z~rtpKh#>ITSb+@57C_Frz-}67;r=oc00^6UPWv!|L>r9T7LWX(_ z#X-qm%E_eI&FIt3m48E*K3L(S8Sp_nbrEF2jG;KFNRIW?aBsMm?SGv2J z|KAnT``V$f?_ua2jr*YGJ|G34NjDGYoIcn2({7$;efaCBv+hT>Y^Q{IAlHKwfEGbZ zIoS$aKl#o~VecKa8)?^G$F18TsR%jp)KChvv|rzIPt(H_y6@hH_cyAW?K%?LrgZr% zq+M+&1vzuzd)~plC2Ai_FFs|i5tA+6mGI{dXbgyf!B85s(#pcmMOE>_%n3ZX-REbN zdT1|E3;U1(jZNtz;H=m9OYQOG^>*)mpJ?dosekd2YmYhP02xCWP#a&$seRI_<<&)Q zKFm?FiCsF9^KPfOK?V;EWk7jU-}82XeY(JLvxwrY-C}taG2DI+Uqbr4hBA<>xA1SJ zSiVR7;_B^w)#vjw4CIB&phdAPBlHwXXTMqRu;j`HP>Dom1u=Dn+;__`NG3_ zZd=o3rD^td>$C$d-selX`t_VFs4`<1juaEe|eAIC(C+0PP9Ih;m+i) znwt0vvfai|9y9}D;WtsW?fAY2dp!2(A5J`MzdXt#yAk9#1_na~&={eIb9n25{A6wa z0M;Ka67vgc-FhF#K=yzbDu6~ArJPK)_by~Qa%}ZX`C9)csT)$&6RtrUIpDKdtUc#x z7q9!q`Sumtzp9kI-3t{JWEf((_~d#$qPq^ew!xQ*o`kgekn3Yl!Ek{4V6H% z)fRq#be>nV-DrILq5RyZAEt-oE3FbiOA;9v43$7rMIO#(al6${JY7*1ApCyA@~f-Y zKdhC6wxg6lo2R6l-amFR|26lX+_JD}{$=Z3u5-68fi^IdKm)q^p1<{<=a}!g_DHOc zPowpB=vODT`JhQ?kQMj9j{FsU$6v3cZ{dN@ajjKOK^GI-dm;S`LlsaP#=TZ3{(lee8PxoBoDRiHmBUsg!Q~o;z)I$R)fb6DGopQ^2dTpZ2@yKjhyQreiX1~1Z z!Tl^lHOOw7e^>jKik_b1@|4xnr7N~}c0hy+DAO`97^;E1>)~uC_;<<1qkT*EWGD16 zPqc})t=|hu2OtHYcBPaP`^qoc+EaEL-CoFgsVCMx|Gr!^G~=j&#)5)9<(EpGyk91J zz~OB9&4@)F8G^T~AblJ|b;z>eZ)b&%A6yzSiM6q$J4bDw<7!x;t#=Dfdq zb)$*xTWH;_30dV;&2~AnR#sbb*~c>e6b%cT^ZXs4Mjiu$q1JM6&wXE}z@KBU-nDwK;rBk#c%uSsiRpqGoPnN8JYI+;W=U$jFS3mDySQlU z)V-;Y0SZH1$XF1|mZY0p|5xz@9^+||PGsGwyZ#4g=@kQmp&rPw7JmF2qk4aHmtA1( zoMY+uoZ~`$)(U95S|5}zJe-Rs7`?eR_rgDpy*{>=`BXoyR;z`!Y4t&g*Uht@NB^+? z@@qem-1dLtejd6pd@*zjn4vyo?V{RbcY~H0+jd<3an9@@+i7|J#TT<7$=(puez5S% zd(fq_B}Z&t;O13IrpM-;N;NWv3@;cOf{G#!=Qf!eX)iZFxW>EOrHy&f4Yn=QD?p=2 z3=D>bpqU^kr{;GL4w#%3Ht;L>cp|BO&GAEvze3gx8XAHUj=twl%jHTAH80=l+^F57 zpt0Vw^7sW%RRl8OIkp!7*T33bpw^6~dvhsG&(ru6e(C$MI=ea5WayM-D+R?t^j$qrReM|m3eFlvpffRtI z2;w~x6Kc)aeH?X;W*5htKgCv>r4bG43^Onon#hCQAQQ~~GbM0kX!hIH)?4ijx0+4! zflQ$qnu4sb@LRF*pcNDz&arqc42ZO3+XjNWlcKBh_1?ZC%!^`ru_gfx+w;zoW~sGEhsDfx*xcw9wMRFUsQe zn+=Kra%>D!4NW~HV$=PTK#pTzFth?S8$F!4PR!WdF61uO&*`nASM`10<1b~nZJmyVwVEdmkbPsHlUGz59hl9uhP}7&hl}-X?mae z$S+B!Vo7L0Y6EKH$9i4~dp$Qq$9wrLY4+7m`23vY_w0w(SvLQ`Zn*Vj)%36u*6B&69?)cO2WnrJ zd8%`sIXkWJ#Pdg;Yqd0n15+F;(;8&LD1l&QHiiq$RW!}1Qu zDh@*jP{y(FJM}q@ap$e6I~@LH$v@Oz`!f8gI4D0bFc><3QniQk9mrrJub}(T4&F|VCV?Syi!gnNm?$78WDBBY>V!s|MloTllK`k{Q^<|Y9<7F&U_JS zQ7P|y(5yyX_iI3X{3@Z9kZD{)$JJm*>Mm@(;$3*=jji{}O;dWD>tfgK)P@vd&Y)JY zg`a{e1CztMm#^53RxpU@2)s;ovVn|=89Iadd>+mZ|4S*kEs{FvcsVy@p4-eB%GIgR z*mMRppWQs2uP^7?V76kN#V6&v)iXn!11qnAS{@7xhR&zJZqW35kZJkwcz>0f-MqKa z63@Q#=|k%*SIF{)3c6#y;b^ zqZ+5xB{%JO5AE~1f?7lFo?TnS?3NZR-}C6l0y9?YA8{4eHdR8r=?Xd0@YQXZX@#9$ z3txzSJ~v^hgOU3ppoxj&)1=gqz%oD0wRF=I+9MZ@yeydByDw zXt<4m!O#=bJn(RK2yQl3bpIpLSTgPJ>doArZpR9N<_tgzKuvflr^JrFI-VO`ucq&0 z>0S2rd*{`PiO}@m1sZ0E^-S3x*zfPixZ|i}Roye4xz3Z!KY?7&z+mW=297L_fQWvT zq)7&Ij&3$v6#Y^1gqas;0GENm&>PfLv+z5YwPfPD;|nfym(4S|XZ^_Lrym0-1VIWw zrM`#rVkIfNdrp?0)>WlkF%Ot9ujaWuXmvOPgP{+o7>xDIow&s?W}l8A_XeF<-bXo4 z_s1(kTR}c^z;0k?`1@K}@rHMnnYq-WM3Z;F%l?A$Bm;w?FKC3*!jDn?`qtFKSjByF zJ&&4xv)Og?cROSV)DV0UwukdN@96?j%CY`sCq7OnpT3i+HT(pqE6c!O=m$!?QclY9 zf%2Y?uJR?p2e&FOcRc=Gjvq4OZRiIoK;k{c_Wg2cZ&mDK|R8GQSIUl zd5cV(9 z8^%R!=Mw$a@cDOflgGTgM-w)E0>vT&gJBS;=5hC2dVT5h+Ve*;e`;NgJA07D{a(&S zXiF>@GTI#CDq^G=-WtBNFf~1H)%vVupR*t<_6OwvG$MFF?Z1PEl2@qwAtFTzBk?RHn_vYqR_x;kEV_j`G0k^^6Hsq7iMp=TEdI|u91sOIoMi`ZAI}fTCB1o(iW0j#d91yh>TCuE!$?r?Al{S9b%8X?%pHw$ zpOm+idvgE3@@*TaIs_?b0|(U8rH4LzsEB6F)Rnh+(zclY%Mk%+KPw7kg@s>pZ|Bhq zsw+2Idl##05I;OG_RV`}D<~Q?ur# z-gv$0^;*r4hpjRU(CQ!-vMc!>$BTkx3$uAQ`c63~aKh~G=f!WKy#w%x8Ww)nPwv=m zZ@uZ1=V4h-@wIw2uJcl$sX89ihVgKI{qIoU($<<^-V9bu@hSV&ml_19dS@l*h^%gityvc1A4=g(u)mTJb=3$EzOZIe8|v*0zf zN=gLvvn>4PZlGb&N|nSmW*q~qvu9v1OoCiqlYZvd`#*;AGVIz@G9Mq_pOx{W0yGKDz+jjR z>e5;G#TK2NcUSZI`Nv+}YdROcwWvJ(09t?~gVKeE^U8BStM8P_zu&}nmpeE(i21<& zDo{#dU@%MpjmKDfx=S9)Dp-1J(YC`o7;mW;MdqOe38!~|OXWLC*Z2R*t`l0j{+AZ6 zm|PZaB(DnU41*MaTF2I&wRI~+Dh~@ReW-r*M!WvIXQfH3(84?evMjLiyCV0#htIZr zyO!;j`g^@!O@DO&q=d-?4Ru)f=~zDxU`bjd^g1zHvu@45Vwbl7H}i=1}*FMsRm+<5HLt?Qut z08(%s99gpuE^XZ8dD%WMuvF$-#`1N_;v%5IQw9dZ9FP?je%ZN9PeoIlO4eAq9KU=k zf9k|iLFnjW4ybGE;asyYCciRa<40qOfUB1-#4B(4tPbt_=YU32KufT^WI_(#IhtU& z=0?>UiO0#}S&+pEhB=_JO4(Ck&xB>^-?$QAci)?- zS|DN1@65XsA-fI@3qXBe59dQG|G(9n@zA(u$*v!k@6X*cQM$A8vr+?txW zP0VFHCRDpRf?A>=1#aMgV!s~JtI2LH`_g*KAo~~lFaH>9NL=U6@R6Tk)zwps7uCz;Gt@+rwI`I2;<370qpe7mvgJCI1 zp_`}ww-;*{ByaPi zql-38g$@psgOZ$-lUBOW_Ul|t5A=?N&3kL<_iBTV7AUzhFc_AD=33)DXFUm-KWp{= z$CEd?x3czhn>kh*gDQ29g6&{OuHz_e@N)e0NAiEosZPnN1&;*wOopU~N>Jjp@H6v~ zowi3nG<|1aOqy=f6D{SU`!AphKy4Wh=bxFKSG}hwa&i0hYNkES+we)O4LZtN2^xox za#|DmE6+S;l32zOZ9jp_^$e*6il8}W1_r}Q(7L%;&%L&iEBDWrlT@pZx-9=r_kOtB zWN4eViXH68$0rJ=m)PDkx>a5Gt|)|u+4=l==uA*GDEnLZo!uLCs(k8``pFe*O79ss z`MhO*4_YS6z+hMn+K=MloS-FG_jlQ?hU0q2ovb4dPPp{h2&MouE9L5G$Xc*$$-{;< z;rwFrPWVK$9MeyRPW043E-T6MPV;JbX!g&)V+ zyvVn0f_vj;wMr^0q%Adx%7!|!7G#o#^Xx-272bKqpY1Iz*6-t)`omi_653>~1@)HV zJ>OmS?n#m9$*PE7TgvPlQPt`Ly|3A@4su8)>&#mkErOuWZ59i!0zT`dgJ{`Qpa@fqcw_{Sk z%|p;}+6GYTSjve(tm>h!&L)pF@r6cCi+Fjqc$Gp^bpxncaP@S(P}h7k^z;7C%1ePl zdz7yv=2$|@sD`QF$a-Kb@OGD5VJnAxMxo=+Zt)ixUm)uS4I4pju<*ON=2(_WZrJCw z$EG$c7k)f9)6f>Qo|u8bun9CH=HbjA$6>>7B4DlJ*YWiIjf*OWNbE(04*oC_EeRV`44vm~0S!A@`2DQCdUloe>ubjhXDtx<^>9k@ z^J&m&{T9%ul85t}-EVfx`OqzD$X@ze_>0Q>ZvJ)9;e{5^npP>N+Ak{iX1q+!c%E)n z8D_|L{PEonph08?2E!ImWa)eAR5P|7*!n{Ba1QseM3?U_(GG>6;T4bqNR6}HXXdOW zwo)go=A4_Vw$){a=;tZWa7g3P44Wl+)GM^|DPjPRLD}CwFa6@OKtZO)b!N z0+0gGNJhNpM63H{{^ei^GY}IdJ zcfE8#NeVP3$iQIO0m}Xse(T;ov36p)pD|5}Z+~y+k+pMo@k1BPbb$I99?pB#FM62a zn%lfIG2qbKqstF+KPm#vtuinec7lo^DJN!~REtA0PtKl{-Lt*@f>y)t+(KxQ>jcen zT6+q=(-%9VCqL!U%BXTa15Mpdp+EB>38oWL6#tM23}cPBE5Y^s)~c#`?KNleRiIg~ z3lt6(er0F6-{v>lM?9J{!M1r`^3qSSf1tI07o;dw39XoNK)-aSujoCci7%2{)r)U} z7Kkt~7FE-*^}OUVEYR#VR}KWV-M#-lk58*s{L=B%JW6*`Le4uSEuN6LBgSTIe5JK;!>VN zikwyJgY4{kTl2)?w%=S0Djyjb40}Oy&dQ!qLPw$*#E&QV_$M=3%FP#lw3fZzw_R`2d?jaVe2E3y*w|?UhxvB>%zcb*bnM0#d~r!tuc(7&2)Rl>f4i5 zC;rv-lUof{Faff^TP@*Um)@k}<_kr?w$>k;(EarD9_ZSGi6AR1{I(RfKa*??*mXkh z;$7h{la$lxugk7T zM}E1qEcw1es)u@1;nd@h?N^4AKw|*Po*C8KCg}VA*~ojECEw&p-uv0<#gOIGhLa$x z#KlkjJ+W$$)>ZXVewm7IJWq_x|3QnO$)JQ|;dkr)R+e9-{yOS9{Cn>Te!jNkRXj8# zCxgc4Je+SFk?&vXV0U)O(;r$APTdp}=UH)Z)Yq5Ws|OE{1%kJiFfbTS1!X}CKaX$m0zVrLyBpr<@-B1wF|~BU5>PJ@qyV(!#KSpV znt#f}O%coXWhqr3Xb;o0=RV*INpjOb9n)aX0^ZcXH0gK0>uiI&H71oWv+X(wP4?3u z9gv-K*>41zcQs8sTbLks+jh;*`}0BNBLjosbVvu}mCi(uRSMI7J+$?k@Q%}VK9gb> zv}->D)GG9FW)@oir9b_sjLtX9wGTsYuXumT8`_SV0qTHAInAGv_%C_(w3K6Y%EsrE z<*VJ_tpx3PU|=wu(Z#^P5aikUnQxm*WW(P{=OdKw>?phT_}(w*NX`t%0_^Kqxfc(r z{AljHs(CDTmEi1h{{rZs*({J%7Jh#xIm)Xg*R6PK^ycNaRUT!>)~|$`FbmZ8^>AkX z%xC&pS%_(8-_h6CtU|h?`}9E_as~#&S)jU0+0*HrhsY%5xhZ=JBtMIH+?@IU85gJ{ z3Q}+bob`h8t7lkN_XH$Lte#c+ivOKvwl>s+IiRkLh2On9#}ngIXRnWx3hkWV+N^(T zvKF*LnFE>$@^H4S|MIYmweFo=^pD92DnD+|*xv{$f*BYL=YWQtq@0#a-=)x-WAi!s zxlp=O+A%Ai_GKWWK?*=gFW7U>E^nizPtX2w$o-5B`mz19?-pUuSUCfO;aoYeBd<&N zI|L-ITvz|E|B5sxYuvfco1i8;1B2l_(82%{`6r(F%jxpAf&dM!7U(GJ zJkSCO59d$%4|&D<&*`&zSi36hwtkqQ23?_TI1kj8k#u@kEOsb=#^%Dh(-O}jR_^3Cnc?XyQ5ZExj;T!=h{QdTyan}z`$U*08~zRIDhtT zJ!g0NqUFYAOEYv+x}Q6WC_>l6ECdw;Qch`Gq61x~pV$}k+7L)_d+A^ zx?&xs@PDsWR&OY%j{H#d{mj)bU;RPz+zbqc3n6E-Y`9hPJ;YGQ(aq7$(EaV5)3cl; zA!oA~E&@5$!tbaWo#zyYFBXB?lOE1r*ylxGopN?-6W6*U zD_)(d4z|4payfQO z00)nJ&nBya5>R&0>U-g3|7p$)B- zZQ!M7JStBAZe7%jU->xF#--NQW$m16(44grw5ToEb6!t4(@Wo$so~5Tg%dvVHRRQr zL&pYJDT3W#$M7%Tn(KYo(%g=^w?->?)Gs+eXRB9(h8ZmUG{3E=xS-3b$FW2-DtmcO z!km8_K^x#17z|f~w%vF*Uo*Mqwe{`E`N;)h?;mks(F`j+o8n$v4OhMF#GthYTA{21HMoL3IbPlAyWBK6*{tb8{@Dj+vo*!? z1R;)G2f1cc^3ac(_1XKnT+iI8;bsw+vrF=Yj)ANP4U$;+&1IV2+9UDFI#9bef63>F zj+j^m(BLTpgW(2H*Vex#NYZf_P+x5B!lu$qlK%!{u$`Ew!WZb`@EHV9(h6+!*77p7oHh+ z9N4thu3S>i&fGiM=|!^sFQ_*+feLjCzx5O5wjRBv{oMYA%t7VlX@7dzctO$3z+kuu zT3>AJoV3Vb+2Z3q*)bB#o^_m>S3tAWAO(>6!ex7D)bA+;ynbzJHq3wee%#H`hK}2B z0@WARp5HiMuU#-9(ZN?v@5j5%?e8+LEQV&i&1~T4zS^el^VPBVe#)-JKQCP^y(r~t z2H8q)xCNAnE&SX+)N0p7tqHC?8|(Y4vZ!Kt|4V42cME7V$-}v4-S_hsKRG&I-Ts}W z+eesj(Y)i(-r^R}P=}OLtoq-DLfaktcSacR);q9dKYP`3>`U)##0xmW%?{kCrU!qeZ@x=aQ&`WYAu zw}Fa73%^5tOONrsFJ2pHo7j7Mm2S4oS7vA-2A(PLaGo39w`A`7=Lf%Zp6wF*qMcdC z`30ntfx&P)XcVQ)Q)u5sj!PMPyi&iUU3ho7_CvSt1n30E_I+SCtT~kSfP1UNfd_&2 znQT0B7EE(+f>x|ML9~TmxQ%*lNfPUKgBKgDuEjm;H=S1oI{k`)!EmQPxO}iM%|CES zW9PO;*VTLO?Q&xK{L&OOBM4Fe3Q0H5lVM>>@?5&hw=;TrJ`%{jS+T4Qa)7Pj&bweY zY~WbVYG~~Ict+^VxAm8fFqs~n3%Op?a5rf5z`{?VA-`YluMYn`)%_yt%Rg$~yY~&$ zRApc=+zkp*59hSGIcF?h#O_$L;AY39g>BCggI9w#z=ITk8hvG+Yg$CLSNu&<4qah; zKkkK`tGDh#Xx+UBvg*&l$ybiu|D^0>%S+Q{U$`u;WGDg+$-R(Of0gS0_CCs-CKZ%? zc;@$n#N@;46+xXJ1_r~up#Fu2v+Q%jyDSTj>T|SjeLN%Mc?tJAYfux7fx&PeWYyo+ zC4c31M%LLbI9p)0ZdK}w%}RpM?!!KL2G9y^iRz}3>CtsLd0}_XNSns2wLZWN&E5MT zQ|dRYjZ~(6VO#Xvhf(WRaZ-U-MHui`-r7@;ZSno{yqwo3-FrD^$U_Yq2%)nrH2oz}^&Ml{RoVHq36%{{YwZYa6Cq2$A_lJ%R9s=#2kaD`Qz0_dG zyQCctas`g3yjiARv+C7UNI7{36r%c`ol4CTH7_r|{#swe;_v45D{|KlP!SBW0y6L4 zXq9IaCCd2Q`=81FmZH2TmI(^bBzG9p5wq}0?k8_9C$Y}66Z z_0%5D*`*eK3bk(kbET(iWk<*UnqXlFZD1S$bq1xJ(w(0-7AZdw(l6UR!y#hV%2(R@ z(D{oapz1Nub75r59R4doyHiE`KihKtYZadlJ*U_3$OCXluK8)4lPeIqsjg`@B z6XbK7AqQm`9s|uSTKM?|_-;EM&Rekb*0oD3{ih!O(sm5GF6bC&O4-BNt|h_u&4PR9 zJa^n*sJrDtr~HlWppGa5gW)mI3Ic1-eS28s54kH&6q7xFg>_rn=di*E=xW$wU%+md z5xPn9oQjLv9?R}ZU;DMjQ^U7I8yF`*{VfYWqZd0)1UA;JTkmst*9yh`^O+|)K%@Hv zC|`Iu>&|Yw_3!vM71ljF)pKvHezsgL6?85P1B2lSP#x~($@wNhS+(KstAbo}J}E<` z31JMoK{X8ngW*YGup6ZAM?Vb}FzIody7y#fzv?e>(QxSM$5Wv5_ALD5(jHGax-qa) zX}v7Fx=zfRUj?zCMU4y$hNqT*i=b~)nO1x#{PV{3VEhW+vc(ad7f(ZHt51Q(gaSPe zH^o;@S`_pkdyQHw|G}$_QdfMTi@;CYg598YU0T;0>&v`Y=dNfMd0r#wmh9Tn<^dhiIs;PZ;T-X3TSzC9=04V_hW9T@f|Bm( zwSd}B3=D>6L9Ib4Cx>{Ik8^j#yl|{;^b%fN-+A_@J17=G3P5$YwP%f*@I=`#k)6@E zHpT6Y+E=*gavNwA38Vnht>)Oc#W?Dw8NbD@p!z#X*NvYh6oD!;1_r}(kZyI}m)ZJh zy!nmGucR99QQRk7wwDK5cc1$M4yZ*d?gxr@E#K$&w@!DPEK6$TsZG$)X7C{m`kvXX zpO$UC)NERETjziDoTp1wI0CXDS?_!?IH2qcpL6eXk&Wf)NE?s_lf##;C8AVBpe@y%D zvjx<*VPG)42x=x-d&-|W=M%Y=sqwu^q*SDM{Kj2zpP_m4VmsIkI|L-JEclYWoNwNN zsFl|w8TQF9fc6$Ifkxde{1P7@mrXSNB7T`exbV}wxs2w$51?Jz%OI;foS)1nlsgu$ zl@jpp_3WvpyT7^!yF=%aE`xd~Qch1U9>2EE+W33()Vz6hRywCettW$W6a$0dWl&ot z*z?;lg8iLP@P@-H2<-SJaz@^)y2a``OSks_aqM4dm&O>BSaeEbFf_HzgKT7VX* zFfbTi1r0}A_~r0h9z2mM`&Xq*#f|-GoT}ZvG|(6^NCBvq;NdKDNpx*;o@s5owxL=| z$&oDW>c5~;9;5)Y+f3hc(X}6rc3yu3U$TjYOcYN)es5Pes0aorfNXSCDEV&M<`iDF zAnW2H`+d&(854q_`?Id=fmex_6li)Mi|h^yY22d6n;~j6>)#>JDi#I?!|R|KArI%m zpSLOsgkP8+@VNb5VC|;ntk5>-g!pyPCJ`y8WL4vI9+k>Ey++OdyBGI%J6mvoBtRyB z>d#!8XQn}{uHkGG5?Iy`?=;ND^}F#pZ1yp zsty?#3~z!)zAgOfD{bmyUL0f#e!cgLwQ>H`3Cj;a7naiamK5YLT94-APT+igjvwc}5pjAx_42JhXC9Q?uDUmg*H`l)|3Eg{!P2%?HA6MOe zLz{~aK;v^B&KJ5HT~C@%ICjBs&7sxPS8V;Qp$DA-c>pTyrJO#O?Phx%z9IHQ@cDaj zZpl;(AxhAs2GrRlFQ|q{IjAfdig6G*>#0^_Z8-LfVO2aFc>}oMV7wj;<#OV zHpZ!kI`-d5{KGQ;{gFRSpqX+82E(V2yy>waFFi&@?99)*jO*e!4o&}E0W#^~*Gc8`cEaBJ3nzI-Gh+03m z2pqK8d{jn`FC2 z@avt@ENDUcMiT7EB8FwE*|GoD9b{YnbPK~G(~uZ_=u)(|pe3soes=;(eSVhj7CUIs z*R(`si?ovoBebFQ7Br>q;k+iIC8ai%BWc#^X_s=Zbk-L4ZiKc5--2?OloNM=0jKh- zhm03I?w#4Lb8&ZE*EG-?Rt5&ccc9|X&C|u|@ak=XGdx)vo~1Ufx0)N^Xbx>2ybA(5 zvcrD9SrvP!9N%wthI&EqyQ+16K7cnipXDRID7<^b{2j*mtzvo81GUF zxT$b+6HC*4`_m$jPx6py@JQx|#!B|+Epeg*}Yh2Lw(%d-6ozWcp@V^gfcIcd{hMoVbJ z`wM8byod88mmHn{^4w|}|M z6kEIS)RG+NVwEos!2#8l(rQ}GmggS*CAP#VxtH^Fe=Kw)=NqU}v+(nuGt)nDuf>A) zaW#6%}wLtaI1g|rzciDSBKjS_HI%EDL9o!1~@5c4`*B*x_ljlr1k{(rWaA9&S zbjs`pXuj9OxvzPS^}8}APM>o!G232hP1ALs4BD>Dz+m_T)NGV;lIIoKrFP}qlVi8m zy8Tf7pe?uaBxpLHfx+-6C_MyuCZ3qU7woB|;54Hv?5t_nbr~58P=_3(AQr(@dlJoNBV&{{nP2E$*V>~G;0oO)OK>Y4@X*bo1+vYKmP$aW|U)LaHB zcmi(QUty2w$hUdz>)CfX)j%R6mNk3}bX*Qx1M7R9nH0?z8T@?f@j~7wrpBLUWS)_N zPV4`MoRO<1+Zf|7dVRil`8zhg<1d5)g`R`Da10EFe?Z=~@DowHp+2>zvas-par~1O ztrMpDGoeGEe?S$AhjVq~#r3OSnPn;7wMkO-n>%gE(JRpQTwwu~7yF!~b63>Fj;aE0!E!=rfi${OJ|9 znR-)zcm;Hh^*^Yrw)VW^JNtygBFrzeo+fe`~_Aot*^kXE^x^t`(V>aToy^fJ`SY62u*7%_s9zlU@D)X+H( zCDv9=IP=l{P~6Wvwlyz6qpJ)IMvNfGN;#zlISbhP2R_l$Ctl%?bya~|Fk%MvP=Y)+-M^#RSjnF?^ZBK)&l~^iRbFj{>>4m){sE3nh3#n()06k@ zs#^B-{p>rH~GY5i4lGM#|}`Wk>|4+yAXS;=k{4R27?WtdE0K z%|@)CaDU&X){>Ub7YmfWTn8-| zW?(Sl0xj0C@M}7_*QQ@JQN&I+GP8MW_J%y0`JfItNP!c$08uTI)!{xh=Wx{2t3C|I zlc)Lew?iscBd#uRzNn1vt(ugyOXZpO{#)X!q@-#^pbc*$F3>oPyXUkd`Tv`OE=Z>4{wqvq(k3!<^shdEddkBqLsBup2&wzp8LinYD!T;6JtZSB{Dovwj4v zX=Y$B;saS>;Ww#kr}TXz;pun(ynA-v%If^B56>kaCh&oZK@aCQz0OIhwaI6+L{*l5 zX?(dPH*f`{Rcyou8fLNf++`TZ^W;4fV35#4nf91jKGawDW_A{1uh1xX^~tM(WBOLNQ_D8mJX<4 z!N6c72%2Mb^E__C8l|Dh6Fwt%_0?lHj%D>EHG-yRKnftOAmjWC8QbTFaQ}9G{`c97 z6FKLughDpU7zsgIL27A>YvukoHUvH18(#h=@?P051xSc{qza?i6n*ub#d* zOnMpgOM<#6;!QO>#$i?@6cEbsU@GTB|=lRFvzjio+ma7C7+!g zt#kODx1Lq?-rBp;iO|Rro(B#|j)ur(R&$D-zRWgY&OCI?-gpZWw4@aQMZ1OHi*?RR z_pdaKfBazk;TN?ZR~@Kc1d1dE1|w0>Xsd_w{CkTs)3eXGZs#v{4{+a5P=dUss+*h@y=~3tIij^1IU3(zuK@_sbeBt3ay6r*FWvpI5T-4mV==DO? zW1z~6fx$=&H1}@d_oYpaoq1(p=iArIDykS*oj+Kug}Ol;)GG9F7V+s5WoOYBtc_iQcjN16K6b1o9giFcxvvh&%C83NBTgGevlQQrkb*+3S(I5)}s20pVfq( z#@PPaRuu0GnL{y>{05Fq=?9jZp1x+*%y=7L_;@YTwwv!mpaqCDXtK$|uj-Ne)bH6{ ztE)51bQjDN+u`Q^6Ea(EBn_G}@^Ien_$i1#a_3YNyOxgY$ zn!9Bn=ZWDb?{ZZgBt6K2hC(g;4y<3crnQN)%e!Qz^L!>r z?<3#*LF1AP3`XGdQ9PU{C`DgUvKNeX__W|*x#rBIdha_>Z_0tvgOt;klQ*h;b{Vqp z-Lt(h@0-_hHNm5x)t?LuMslEP(baSM?Z5lF6K=#^a+hD3CKS8&O~nOhg(3$zaO{t; zpY4WsGdTKWm!}@uz3SH07geD0k%7TT9yB9l;Wzo;!@dRY{@%XHGoe!OBY(olE6YG_ zSq26p1<*96hx5bSm%4Hb@_*zx4_ewQ>;Ol%a;AmcNzOSh zGSrofy=yGDH|;ftw9Ji^KvlGb-@;v60u>-0&MTka z{IUGjWyaU)KBZa>Ra^C>z}+VX1|uaBS^ zYyrDLrMJ{(W7@L9=9?^wZdm-oV-F-SR; zc%DB3wwZpB9ew4{c9hzE1_p*Q&(^8iZ`w-Px!u}0-+4F7>aVBb7J#ZE z1_mQ_$az7#|627i%qsY7GHdF7XZ!ZaM&D&Yg8~c;MjD_7mxZ63k%-$<;|&wE+_Dy$ zo(M>DwUh!)go6}-8hswlHL;4{#M{}VZ`A3q)d&`ze^5{l&3c-kerKR(opOzx6@TEf zgICpl+NaGC*OZ4Qj#% zd!Apsy+=P)pmko>!$rQcax<)TH$i5jjI<#e;V(p7-fH!xGs$f6yM?+Bp0@B_1|KxW zz+j{cYEN1C<(p1^wSCUndtX@ZUq6w5{7%RJJZO^B1+~aLoRtC>PLX!o#<$f~r{K;) z$(v!AV=D<(~(a@A=7II0rN+z`$T+3@R@@oZqWYV)yPnllXsW)sIVGE?;-3 z`3E`l%*X`Pz>spXEPV3r?bgt>S}X4A=g*&ZH0l_GQ9)E9YI4 zjNi{baraGBx~~}|*_%MFD!XuVmiBt}0;be$yEa~AW3#85Y@u3c|~=* z4F}Ul;g)4Pr!-2-yg#r4GMH>+28uKfXP1!8GBb7wZC?C#j>O!esmEIM5;`GPn1Kdz zrJU^E#U)nE6!mkcNsz7SJ>2~5cpqp-Gy{W?Ss!>|VU3d7Ud{GXI-6!@@H_bYIGfn8 zA7nI00pz}3+4q`XS6ueHUHwY&TmiI{vjAwO8>4e+6+1e1Y`wBp}Xh%us`{~O{R(bWewkc@%-n{cP>kU+Vl(zMwZOr z=+0d6tzp-T-&NmkN`1NIedKrf(+Ftxw*uu03qKp1Nb$>m7_1Gn(#w)dxF7h%n?kE3 zD^TCp!}-%`$NdwOYQKcc_~gpau`~6<%}tQGW+N+5p)Tblez5zB`I%Im>(~DuJG(E0 z<@Ih`P|JgX!N>}fXoEdJebjKCnK!{Au=PKO(#s#mwV$g(6O1)vlj$6dlL?LaIcZZ{ z-2VP4jH}5JGlJHo?xS)J2w(;QwOx$y2SH)Np3$PQHMTllGN4!!IYBieN)Be~uE)Ffs9 zGosL1&ki&uWZj?Q!10v;Qv&%o^zjt4>-^ z-ud>*h8c5CfC7kt!N?xe8I1Q76F9$Bw*Gcc_tY?@i3d7jjajEchUJay7lR%7z*?Mr z>yp>Dzp_5GNiX{>C!tsgT9m-RVB`R5Ut9Q9>9_tkH~03|9ZK)HU-#NYS>Ia&8kk^U zFmeQqM|n8Em^<@+$ho$i4s{=XDxcmvg+XTr)D4cHgd^p&NQd8Dg>&=AJN2#GKBc+m ze&%L`_L3Yy3j+c@jXn6>KPIiOyl`4Uv&VhMrXNWqpl$=m3dq4q5(YCA9ogbJ{=8c5 zbL*q(fv}+apd}^@3`WkNu~G}ab@^LPGQ8J3#id)Z`i#vqbLT0Vph6s^05sI&;rwXw zv4c}RIPcF??mwShIB6r}ehpAZ6r|t)0|SGUlmE$w?$e{|*K*C!33==u7?|k!L^e&z_L) zYcR`DF=ly2*?!P`9>@exM?}i0YnIA$(}blv9bP*Io4EZ^;4$F=jUq8H7`cJA-6(sW zd3DF@R@5gerWp4tJL|!#lnvvWX^(Z6H~;Z6en#v|JUj7(u6&bb%RFkkY4jSk*c$D{g>}odi?ygRIE(q z->v)5%H0DLU{X#tiOw!fnQMOq+CEFZefZXdM=SlHrM(9z(Z+hl=Y0BjOHBCS2W{KW z426<2mz-G#T5!z3VB`T=oFF&5-7L*3FzUpKH^S#0&ueet*aun<#K2(W2?}xxzoewK zziJEn+4CaP!*)u=H%3Gyfd;A=7>v9?`NP9`;?y6-7Yn0HOMf&<+|E6sHBq<%R7Qgo zfT~9+r{F8?F_o5Ii% z>fy{6mMCUXc=CQ=@ZO?7CXQWynK&Wyyhi?@0SYOntdo)I%SWTJQW8*Iu#Bx!Ugb<+8h%ltDEONP!nPB-8rWep@-!ro-le zC(Dw`tQP^k{h%_Mfx##MbfA!hpF+firIO18CYZNMX5KA*({1m$2s%a@0CKE{Gtb1o zTpb1L)TS-#_f*gPu60T-13LZ?2%4r*_MH8`@WRz|RhhR8&sVU`i#~ApeK=@vgn_{* z5V9*-uIr(M^?{;Ef1bT7Sf--5@ZxMC$RbapAW-79@DnX$PtCjSH2K=$g}znav$yU! zSqWMm%D`Y01ll_6;k;>vyMq4F_>c0t6=GVYTQg0LG(#I0!JsNy%4zAM%(4JeuGu<< zby~ZeMVHxLDg^Zs85oR$L8AxOp6++k`GPd(E|-ybxOC%k)uktE1EJ$l!6o2;5?GmP zlE3HhhWML`GFy&ur|ZjwYC>8dA)rYH3%|%hKEKzD3vMSw{Kz*;yKPn!I1Mzh!N6b? z3R*wu;q1C^=2VYAJxeFXb9D*7cS^~dqy>$OP*D3?%ITGcqO;($%X;!HCPnOw1ry`; z?1dKQp`eMLV9$uW9R~t$IY%!3o~F5t@AT^3KE9w;k02{{fgQQTwWt0nSIQNkV|m?m zjAtWu-d+eQn;003!a=hT7Jg5yrO)!HeE8xtIVDVXs_8UE?$^+q6%MMRJ)FPleOCQ3 zYoh1Yk5S)rXWy%QEWGL=#GB!uMUGNVS8}(ksCBw;9JDmK)q+>K(s9NOP(=c=0yKLc z=&8Q&%lzo+w|e=i-|e^)KW%BN&1um5E=U37OtaF~him@X#dn@Hd%NxE0o7xQ%#)yF zAd#T9t%cvh-bo^+)<@>VtJmq7I4)SZx_JhuGGkyciUj3R59eM*n^P0=Z^~_zi0HAh zn|>MRL+SkB zr(v7|;?V zDJS+{{w#d;odN+zO0L~gJ!<&m%W+Tv%D`Y01M-c&XWt>owI{8*{(Or{+P)`2a*K4e zEp&7-2C|;Er^m26Q-NQJWkav5;p?T>9W|do>x)>>c#MT#l#>Pv^8w8%W@*)wKf+dv8+Bb=Xh z)$ExNyJhyK8P5?Dkq@3Qd6mHwn?(yzXg7=+3 zksDcW&inxRA7lb(6eZB}WbZny&({qA&^>7x+ zf3a4*;^*S;oDV-MI_~FU(>8*R9wdPV@Z3E6&#T>fQ}{LN*x7>rCuTV~e@}3Sj)^5R zg58i)X0^{WLp9)Or^WyQy%bRY!oqKJaCM3M%$25N&&T_Ts@z52VMN}J^y#tNl$yl zn;!&LRc1lmkSY&$!vy`!`{Y#$eWz@xwa|&QU3J(u0%SA;gHal&_OtNwICE@u$FXlb7YnmUwpa$>ui zx8&kshCh;z1A10-YBdJx? zK<**EV0Q2Lo~v`K(l?j0Yd)TGkk{4`YDEUf4HkZj6i<{NOU^zt^-x~ajC07-fLQNIjhQRNUCU<5J8gfvqQHZXRoU67rN6vbxDA6EuD4?s>B2+0zHb+rQ7? z-w+w{rdpQWLk*g$Gt0pNWoj$$5< z9onYNO#%0som&;mUcPw|X(fE6biby%-aF+`(0DxqgHbMIrZ{=l`^g(6W*@Ao+z_Yo zRb@Jp{WR#9SRN?4E&TMl3*&bl?!DNiFqLoRzJ43`tHIFjLp~^|J)AcN&F_kzx!*@` zp7tIs$K+$H;txS%Gar=Xq@3cf>p5QwmHT?>ihz_H>;8`u6at`K`+QK^4D{rk;rEI$ zu<^{+$n`4&(sa*d?b-)zaOOV-2bB8Smntg~@67e}+Qb}eoLc$4_(fJ4puxb|pxGA&2BQ*H1_lNrf0=#T~Of#QUF<@9bLL`f59W6pY8vAJ_L8RzU$dk1ZuJ~Fc^Us ztyuVF3V8_4n`FAA=;fOEDLy~Xa=hk(rs`5qkJZEZ)iSZRH7lP?w0p|w_9SKT>Me7{ zpksq&piZ%rQ<<}T#O!ptD~}Fletc|g+@F%F0d2CDfs&rPXZdA*Bh{UYBcGpMt1oon zO7af&2*}BeMrBLEvFZBv?>4K?T^j7tLbaD#TbVh;E`#bS1_q;Y(5SP8-&QWpzqx4( zA67ixnI$}N$rm}hJ)k)Q1_q-FP!;XrJbA9jrl#In)0MT`9e+>kk8SHY3mw6z0L_Hx zdv2Yqvx&ptv7}?p_doY@rUpDrvVze6!sLZhzn6mj!h1Z%m4hiU( zSQW^z7Je*1FB#>oI_?EF-qOa7`ZLIwA=dqnMWO8W1wR} zHJ~26wdVr0_4mJA%{(BzT60?dFZTx=(Y>I=3bNuo*bSM}`MdSYT9=&KE)lD|yXyNT zGYe>8UI%KzTli@N9Vpy%@7-r0_+Qj+WLET7@0?BF9kaJBHrIF zIDcAfA|E7gHiAkTH_sIeW?q_cCugZ%KN2(jiPFZ59r2(%$-rRL2w691ullnzIq1Om zZD*Lhm}e>L?K!#>H2KQFVAKRzH<<1AVYTXInU<*~ZLcHxc8a?_6^2eyd-vYS5r= z22InrdCu9uH|_FIQI>~i_ODSbj9vG}%oo%d2AKe?M zenC@p3#7)my2p9_v)xnfS0%6cYo8K#uH3`~I>Olssc}-K-CgMGovS3ry1iO&-^*9m zeoI61W-Fw|IsGMWeDa2>g# zdav!~)xBfo4snIMF%XF7PmWdj*Lu#BC$9@QH6^v)8 z-`v`77-F$sFRBML3&p@-)DEg~Ts;?WS#$E9|F_ml(vx-4>eumJ4}K1s0Rkz2Y@KEa zxaF~T$&Fp7l%hnUH(ECeR5XLqA_Id_Cup;bh2M@lyeY8_Mm3@**}qI(EdOnVdls~* z)(NT>Je*agF6p|{w&Gc@Y2VTr@l)?M{%wPt=3&$cY6VC+?O(7_&C9W!|I3*tKeP|* zUtqDj9MlN}SpjO~xOp}#-f$yt!p(C+S?nL(cV^Aq!*dXH$`42ZWHQ=1xKX$H=zXzu z|MYiRs~k1%>^=uAVY)$cDHeV;Dm+GC#UpR7E6dQj^un*L z&?)s^P{OhBQ|F&mdFz)%^zDT2+B(lqxlF#`2kI3tFc|fM&Z_Zn{_CZcJg3!h_k|{2 zsn%Qb>XaT%hmIBZfd;mvoI3AHoL$}A`KU=d$D*ij*~*_sbU`B*3=BqnpeDSVr&h`1 zxIg{v(ak&tYEvRNR4B`7f;yrg1&v@wW<+oKb(!n8Z)1;X+DndeEr~@>LG1X3Ojx7LaOKT;v3cR+0IKk;PGi-q$x zL+86EfZFy_PO%CXYglIRPKiDEdD6y-{ByZ0zJjVl1_q-EpcaU==d{;+No~H<8n|}c z(7X75zTR4!1ZXihVLjN9FJzY={-!FHcs5ef_v*8S+B2NiL8k^Lff}3^evC~0QL6DK zE6qRh-7{LITUyP&7Fu^t0uAJPIJ2*azSwYCW?EnF(HXOj+;jGnxCT(l1}et z8F3a|u3tk*KR7b+JvZ;E872nM*qj0yO|kG(mYBxNvs;AQH(&aECMhADi9uH;T& z+n%MfdHKBy&=%=b4zL?i7Z!YSRO4B?_nXLt{L_cmve)T?7LYM87)=9NVc{3>v+nk( zjPKE$H!mp64CBr46tIC7=HN?oJ)ED-SGS!NeMUN=L;CTYA9preLYiIXX6H4_0;mu*L$*{ z6FoCQrJSUbh-R6@V~f=1#k?#%FTV%Xu|}?i*8Vd=({{?9-xtYz+x^L`S<|NPVqu#_ zoOW&isN=!FU^Fua?8x9Rvza-?965&-DNZ~G?RU@K4R%Az(~VtxmW4@K-{%|=c;%ZbQ}hzl$YWqI znhP4)vhWiNV%qxlz<0B#U*Ul)D+-wVxlBNV=^zE5h9~G^%77O?PIA7=l%8w7ld&lE z{Mxn9QIxr$8L@az&!}BL|NdEeZnD*TV==RbW}-2BK`U`VCVU3Fp;mjDo07{9kIoCn zJhfWVgVMH(L1zZ%gRHRd`@KkFo@@x;F1_1fX$L2p@7A5X7*vrkFc{4TO^ACqGtQK@ zDVZl?sq-|s=7E{LXi;$AIyo^f1&=}{~DpU>MM10 zppE~9pqj_RZ^`y);>3Q8htazZ^7(%)nr@7_<(;!+GLEsjCO#ZfY$4HodJOa#ob;j@zL5 zeg+1kC7=d|l+*i*nq1uI4k`KU5wUKHJN2GG9k~oNkZa+0)o=eEE5rNeTVIrW8VYJAf=rmjz`$VbSrK%|Y~9b*Z~l1) z?bwyJeOLa34bUQJ#Z_=X>0f1e=Kk-4p3RrTs(mf4?V6jbxKEx{01by#pcNES zP8Ev|Pw!<9UX%6lyYHz>+s;f+{RSFsXJ9Z|1FBdp{M@@XuX{Oj&pKOokLig< zkA;4i6hNzkHK2y4hx4BwPbRJDVQ;HA>h$+T`ZaxxgT|oF56A@2>VULb64=W_bWa&gR(sXgVEYxa6st_>h4>cJ*|J+T5+asUF(@!IzK@>AnQO@Sonpv zdn^}P;gQG6%&~b>_}zl+hrXb3Y6b?Qb)a^&hw}!1iNxDmRqMn8b7|Ic+f_itOR5Si8fMES3H1avLy#zWw6c(&%> zE4K5tXB{`D?|S$}=ij^>1JGGT3=Bq_K|>uDez7}WTKICkzN^|g%}sXZt#>-StDytA zn?aijJ)Eztcx`pv%qKWZ@5Yk*>K3os!g`=9tTuxtLZzHGTK<~6??=qp^PSIY-ffoK zc8p^iG#oaAnkxF9pZ{vjnVlhh^K=PM8-vM}Y)kE(7+BtImpxGA&2BU3| zyDxWmUTpa5cW^?Cq|n)pJv-ls$?b%?VLNDq&%*EI!h_LzB6pJ4#GCi9)NgbREcAyi zcHIsd9Pn^%d6TSoT4{ycZms&8E^BgkGTw&7HiOZ2Q2RmObHa%dv47dzybBY$j>Ipr z$Z`ED1zmcyLmV6qGFwh|{{C=7GyGR&#uOW`__R-k(D8?zpgd~fC$g-W(Y0b#gw4W= zZy6Id{SIEd9dz3h1B21d72pcxY~rMlEi5G=`<6XtIkfuaTei5f&;hHRpxV#f^Zad& zt8#ooa#Hd+%kpP;8oXM415`#cFc|HE%$Vyc@AWnL6!JJGN%IjCZ%XLh!$r`6n%$sE z-okIi^Q5)?Z!2Fd3O+B(f8e}|mft2&8O^|8v>Q}DcsS>5k^5-;H8L<5?SaggHznr@#MGuT?bH0Vlci$kgjMSnLC4JZfM(3gJh@(_^e zF9EOX`74}CIo7Aw{*E~i1)cZb2U`2@;k+s9M$*xs@Y61bZ8uH%8abhB*DBDgBm;xd zzDn?X)?&$*p&wRWsP4b3E!4?4&4XhWZ1M9x(5zg%=j+cU|0XZ4>Mr)pSpVp!=2U^n zmeAGF`yjWF@A>W+X0?d%^it{7S3Bna4Ek!Aa0oI$aR8L`Ed2a7{P^Y_urTA*&L9Dn z2q}}b9QQ#xHy9X<4uB53@^Ds&S>BtK&&a%3?e}s~uH-HEE#HHxWRL>T9&0J5`PrTO zy;Dy`y8gZ!%=gFN>MZkf=xEXbP(MT2a~Y?kw!ppj7vi3``3uEW&-%D!8OUe`2BU+J zmiga@Vb$6_%g?$#-XiEPQSh-issrlCLy(sF*S~KMvgprcw|?*Fwsql8N39fhXjy#- zG%W4m%%;cibmL5;)s+*9cU_GAnc5Xz3a$MQfm-HLPEQQ~gkP;LIK}_HH+w?M+T0cLeb6*{I078qHf{}bmdIX9GMX;) zqj~Ky3)z`YpnfI;gV7Pt=}#7ZbvAYvcwevc*vh@^f6t2tdu4lLK%6f6< zRgeNuWLbOuu2xv{CgA0-d^NG(+lso6eScI5?T{XY++N{z#{1RQj{P;aMf5lJNjLC) zn`Z*r;l{vVbPTjy*1|7z$*wYu>yLhwesNCz{8~2j*LhFSATk4k(Q(jHEDvX$d(%(- zbU4R-?A@Q7zfQ~h_-29!M?eZd`ggRVt6 z3F>!xICm9iKkrkPmnmd@>{pq!)@SAEc4%3B614hH%ISNJ@wX#|ZkO6Nc}C#d7K|QPJ0Tnr+DH0TdSs=@AbPn+3NPX z6~%j9!eDbKr$O^t7JeU@?srU>;c@kShW;^TnOyhv|J*z(}pp&N<7>v#|fkSd;^y9^EWgc|~Y|_x>zUmr&Sa~1R z7iU2u85Vx)E#7O2Zv39AI_+O{ck%t{w$Z;pr91CVYTSSnKyLV*{VVv^*T2(* zSMLlzWKw+o)3eiOp(X8k(E2C~Ke=08XFfc;pnmk0u2-Y-CT9L`rq(Dou{B3)_pXGNv==}< zHFwXAI}*;UWLkITan7VEwpWaNrY$RgY>hO!02%QX;=WZP$zT#HC0KQNr91yAfrIv- zY|p@8bP42L3%{4kxfbmbTWTcGk$19U>2|{<{D+~-;Vyw%WFF2OXIgg`|7e|eNo?u< z%|A3b?KoUqNc&;EfkfBeM+f%*4274XSKP+tS>(zfthHe36_+hSR{n6qoyS6i|C zxM~&%EyS*YDt8ZO>2HyG=M8J-T>GiLdV+M-(YyJJpd%R9KyHz8N;5zBzQpsYWY^UU$d)t-I_ptVE1{ux3V00Za^q2lBC}C^$ zx^5e(jaQX}H|=?~v>zG51!6iQQy~=w|=Py+ka?h@HS{xO3KN^G$ELEUZk}{z$~lR zMY&@46u*PEBQh`;-3D2u@2OSk_)_MCsgO@XVvLu}AI{zwZfL*zb_X~%jpv^44Y^>&aRo!vUh{slg4e1?gh~H>V(pjd+V*e$_Do~Bfz+eQv;M&9a((DWGXD2y52%OA& zKx?-9yy@qj9fQQ?eb9bADX0HYEAJg*QZcy0HHC2r!>$W5GxveIvLF*cGazoB@1I;) z`oQ|czXMm#Ok8&2Tp<4|QBZ}-z+m)16YR(zn>Q?IyslPr`cb*zPaE6%XEto0a)E)t z=pm>hV&NC|<7G@pzT59SuNl{*mrl`8F5(5XBS8v4TV*|*C%>L?alSdj?W&BAN)apa z!-QkgKxGpHgV7^UgDc2W;Zhz`gq!gppC1bI8Uk4b9a^V@I^-Y)Az(Kw{-AVEwMXdM zC83MO_8&M-YV2!JX)tXC%b%R&YLs;uC#hzfDTwa2DPI+oZZ=L zYVPJ#C@mp|5a1B1~M z(2%gT=i1s>b*oV8Hh!;X@-k`djBl^>K}Y_dKx!O5hXx;GB}=odQDSSG-@8SLd0c-0 ziHoO@8i!$Hjv&X>fMs7jRu<-T-3*I4ZvmS4WMD9Q2B~otpILEtheyb~g-Y!+SCyPT z^J9?*D2PD{KsAn(lk94nrwe;CrcUC&P-2r|x|#QX4Yag>2I@xXdlr7X=I`}VpI4Jx z-o8PbVQ*E0A$0ZQvnAk=ydJPKW1+W&YQ357?`t4L@4=Ro7Li z*{|_sy3`P?Y%5gy{CZC+D7iB*7`*@;PwnBXV_IjC->}dm==__yuU%=J%>FT;kt~n` zP(wq?>7~(Ldk6kSst-2@S%htMJsP6B8Z?>)QUI!=gFMSK4Bt+dQktF`Qn~-a$0C;> z#T=kvXpn-JU`Mv)?XaISu|~r7gYfZx!d|+8$M=KgcNrLrUV)mf7Jh{-XQ2|*jJ#e=i&VLk+Q6H$anj@sx6B*Z1#G4YgSPUBraZoTE}jlKT}%u zPOr_IW8K)sd4IKm$&wd>pnfI;gVAe9yZZaI>&0Jo{nsd%{5HwdYnuJFjAhWFzc--p zu<#RWIJ@+Y+6$%7;-mU&?s+YKc9{X1VBSF5)!VrieY?LzT(M-*3(wgv{(2_LFN1c( z-hhfAeb3wF2@#=B?xq{WaO_vwZT>NONhxU1kb%MItpGS2v?t&2K6zQ!do8Ety{CWD z?UF@Qpr!pgPz`M1R}r`W%aMk&66Jv})?a@$KQFe95!wNH2dWM{oZqv4UX^5j4#)4sP8OX$fc+b?F4;6Q~&UaGty`qqWIvbJxCz z%>j8i-!6*jrN}}O%x6%wpzoQcdZkPJU19n6#80~ZX?3BSBbPxZyg(<_F-H1@r#+i! zYgqqr$~$S1%p-F%(*J%1wPhI?jJ|-@L0I^eth3s<{QgU!3Gb30Nxiq?e0}-`v<>qG zv!zUQ==@iDJHEnaS?cJ%J54K@0_ zhn_(DykC>R38sCMXL7~2LW5d&wZoC|-Q!AihO9O;!`<)PaB#yzk?=YgFH()qO~W@I&phS_L1#2uey^$L(@QYHUopv_vK(m zzOvg=y~DJux_V_Aznwel!pR!bp;a@e>(5}}$Nj%EeO<{detpfWZ{7v92Sil1K*#NW zf?8r8&I^1~udb4Nb&XGT)8+=J_3k{)Jox@Lb^EY4?6&99W0%cU zjX>>b1_q;_#~BzHBmFug&-rIf>}gV67qG+6l6B|b4--Ih%nS@hzd_w83%?gENlPwX znX*ah@u8?|Hu@Fkn_!!ce}h_u9?tsJ2Uz-}HE(bKEtIk(?#GNU?F-N){l7t#yp&V* z!o#1lU#=1L{rI^fLP4Q(F>4((U;GADi`JeW`nOHlckt521j&%L-Hodcp2?a3t=xY@ z&hg%^DgA)ISK-AJ-n&_g%zo9a+4o!kk|x0ir&##07u1AoihR`R`YF!-_wQ*7OG471 zQ>cGIapK_|rMByk{EEC+)yMTDYL6Ut{x&-v+OGZ!I>A!P$-Jzn?%2zSUlZ!??05Oa z!u)*d0Z`e*z+m(j)ERR3yj2w^z2vl#m|ohHeSbxddCO|FxI)2SL#kX{$@Av8Npa0zG%cj-%2^4}L1)w27 z4`+||UHa|m+6ybn#5%q(-m;%udKA*fF=hZ&EK*KO&iv@qUBxN6!AXVd{gF5}SL^u;%uvT`$ZN_j~qzx4jP;D>i0=>}>MX@XijHdtgD6DucG`T-olz7vG^K zFoQ-iEc|{uDE$2p!S_pum6eYH8;d^vd>@emKSf>5v+;KsLG_E#j7PRsNjp zZx$wuN7>#pnNb0GuGKavYs&;Xf(yc z*>h8f@su=^7QW5-X)@dXZnop*f)vHZY@iz0+H)^cCg=P}rqTd^o0_$oxh7rhdjwf( zV$25FsG^xtm?HD$`|7X%4q5f=zRf*9cPgX+G3Ed@*)05S#Atuq7TCP^KG#w6e}Tfg z-sLKRMv)j8j5$D4B_7UmR_ih~)@hx*RO4}I!MxiOg$jof_vrIzd)I=5d66 z?+&$ZtlB)GYWG~{b-bztoH>xmXk#wOJdUkeG;`pa8D0zLC+>JwG3k_N?Z;Gb#xdrC z%;Vh2zP8;|uRZ8Wp7Yh6J3Bug|LzGID`#LZ=7P-Q%x3tU`rED}v3`%3{=2|bqx_c_ zK)pne0#N(f+SB_ew|S&M%KU0R$BFKjf?noKI0;$BVa&}8PWESPZ|6C)%(yk#HfFZb zzrFc!hQ~pTT?PhY9>~terAPAfQl*oRdh*Eod3F`V_;T~S z^UK`C;>O)mpQ_CkaE5yB-T%7)vWd)?*9Pp!Z*J?han*3YJ(E+;*#7_OgtZ2%AkAiD zK2Y1%!f#$>hHv5;!N$+;-20C)-}*J5T@_TRGcXwQfjXuh&JSFge`%i6N)npGC#JGS zy6NwYnUF%vm>*PDNjY89IG&!g=kn(KjAIfDnsYC-S1f^aCyn_*D=Dl!x8IXF`(xIQ zS$Yi8I|{c?`h46b8`NZHU@!&^eKAJ*F(n!5{0=ioefFS=-N0%4!rAXufeLX324ewG z^=RR@T&=g~g*0zydGvdWnp3Jz_!Or@R=XJsfC_aF=el+IY&QP_GkU+z-+Wm4{oz>+ zFQJYU1RY4|?%9*_qj~RC&8idEbwaXQ&uO^5_5?ML7#NHNyTAdZX8l&%%hN5sJMp69 z*_$q>I1}%HhF2IEjDm26yG8WMEja>p7*#s#76(nw+BBpM~yetm?V6?Z0Tl?bPKZlu~ zpq3~|!Cr7U+;Us__jlC4h(Fb9k3_n?iMsXX6|@i&hb$z!wR_&F*+(Vap8oaik2t?~ z_Nuk_A>%N{;-IqH!}%=lR^8pd&X)$d2y#4q`^#1P@gB%Xudz5}A(@=2P~m(NKhdQx zwu*_L_^m&Gwiu|<&%j_T4jN5T_B>G_>w0vy^sa4U(H4&+bZ-^Zya!bzAO)Afj?`Jy zd}XoKtqkXNGYi^wvOlZcatWICBtesp7JflHo^+@=8$R^=vgyh5H~WtNk(7d#QIep> zj)(J;r~?s4xmHVmeZ?~`#pl*6Js|_gIIXcHXaZEqiSOdJz-p58BwSr9nM559gn! z+itC!@$OGjEc?-8Jl9xnYJP-_CK*eEM%Us!L_3Zz?t5bbKxMh>KLxvxX zWdgu%;GN;O?@5#3QPzzM4n}`nb$HK)MW9NZfx%c7WQB!aJ+E%SoWhh8v%p;$20|~s zNZzuB%!nDwf-;bYbMYJXHMb?+CGKdNbKYcL;OT!C+804eS~*Z*CgqgmP|c{g#`<}{ zB>u%}NjuN1Et&@!W@2D4mV;zHmQyA-a)Si#eA}h}=c7fJk8Pt2G%n;ISx^7@$&btT ziKWf^9`{sy*6&=8t2aPJ4+Dd-JS6MIe)rt<+WXp^5Jv|a#;V8=*~E*WEvIP z$$KtY_e$k@p8b?^bNlZNQxgOJfyTl>3P3COrJQu#?=e1gOI;8!CvZYhvWv`&KMc^= zQ~-6W-93ZSTBDUTHcVsdm{`e|&+WhD)MIElsc-}wlI}%?yIN0c+~0nQ@!bNgWo8cN zzCtTjC0X!kKYzK7{qwx$ukgAl*>2t}VP>7+36PbC#!8^3yNB}|o93m~b)}bGCOR!p z>~iTz&EkX>gG!(cT*{vHZ+5qA-+iJ!BEZ-ubP@N$qQ||E4ym!y0k9k1e%^kO-%mYh zYT>LXW7cHr+=b6U?MMa&V-?V-nuXtzx9e?%omRMBEn+b_Kb^zuRI4Rq0@PRq)NJ%{ zE~w@`=U%l>r$$vweA7P@6XDxZkf9!9m6_mqy|QeK%Fz(P6?VxGq zrYBCl1q})?Fc_k+pRs(fuJ)G6;E}VS3 z{L!UdH|(ue`4+C3Q6>!yDDcTDZl2=F^*>g2^?X&5`qZiS+rT$A%>|mG)FF3(?!JHb zRLq^-MHXLKR?l~pKeBMvts{^`t5FAztRDFf-TPVo^X%OzxcQA`7stA{Hjq_b#u}iJ zEf44JzP2?-rs!Sr;*58<|58;~Rk$2fa4;|!Yk*dJNja64PH~-4yKTLS-^+hpAJor3 zoHPkkXEQJuYl7NQ)}H5;>z6kCH3^<^qP*DlK-9$#_O75C=|Bn~YcMXP?OQo%#wJD` z=i1s$odv5qx1~dyNm`&H$ih!)DDk$p@~7s?qL2Ygj-dI1CKN+Mr_4+H+I&y2^|F`!BPk$v=7^=+haoWCdg###lQY zoT8>n{?EE3zVlVXXK7yv5rz-*E5SELFfbVFfVvMBeow9tA=(jvlDqu<(;!`7`$M z59K?FzwVza)$wVa(!>cGO=Dm%2A|F1;oSdt&bl>L1|Pp(pLU|A@bXgIKG02#3?K!d zITR_U8PlIzv-R(}b(=%pKc(&d`ERArwXDYapfWq&^YE#-E_rN|H{$zpmpDujc-ZkkzophIZf-#e7_N&D-3Qj7jf#g8y5o zr~fz%z7C3k!5Dlti-&VwYsF`sjPS3MY(GUzZP!(iS@j2$A3zHBF)%O$d(L26bXPdc`xf?~$8UoZB!jcJiSo%OR=S7}Soi z@Z+3z_bUI|$RATVj`keTReE*f!D(n~&=^!^dpH{(x_!OrdYhh}-ISx2O?%UPma#z# zQe#lXV(lrj;P0w1&o|=BmQOv|bbWK=UMmr3QEURqSw>rAEbMQ2|4~cgx!E!I;`)0Z z>!H0xQ%KI*bTIRjUE{_%FLJrcC6CNHYnCPqvYUay*c6hp))ZXdQmV~acP#Bp%jT~O z=lyP51Ff@6Avw!&@uw@b>vWPQJW{b?;Ixl`Oxy1+xCZ*c`MD#KZZk&u!m@Ia(EmpQsdct$C&X$;SZH;AUVj zwg3&1NICtf3;F2Uy!*(b>;`wY$y!k+Pjx}fBai}6-#6Z~DPBlgW&T<9i>* zA=Bcf#eRR{ECK2^FfbTffpWQrv(NX6Q_d1c?r0wTaoKJa?;({>Qjl4DV=GVt+}d+j z&@A@vft{Ldahu1f&2|v3NNDU1qsST{C*(7N^br7X>%P z7+olZ<_jB8^(f`E;aUFqB;K@3JTV!wJXlvBkv^ORnQJz-0XatBQ%mRM#cN!v=k33< zTHu$ck7&%obC6M1W1Ht-N6H-XWA|}6m?*aZMj!!S-3q;(3|=1VGot7 zv8Nze&t4ns$nF2MmWoc^6zjFAXs29sPsxV`8PJxw1E^ze;rG?MCv@-mK4kg)@(g7t9z^!D^)_DbD*j2u%cf{Q#Z*6eBn4VE!57(0TzE9oTc^0-VY zC+WsLMY z^Z7ixr<=Iat}fk7V?}i?f7a8GHG9TRAU9a}^~}||wE51<6|;6Z?JG5Ur%lf!&b!w%^#^m#4|_^JhJi?~2D3xn75slkV)` z!hFFyMn0obk9)gx?31tDPHIrD{sI{rG<*ecDD!NWTlHw`Uhg0C85J9} z1vmOv$S#K_S`Wx-H;3x&?=`Ad872rm>5tTE%v~n>8&vc#Fc^bZ=34m0a&C{l^isuL zK`_nXNY^jjHww9+Ha$oIWVPFs=`GCsA3T+hG_0v=;AZ}JH~liy3QtfeC*`D;_AxE_ z$kv{nzpoqVAIaMBq(U?S;tMZO5ftpH`zYwCk3(GZ`Rb2(pMF)Py>VItE$zJ^7o9&z zDN}9y|8s)gvKiccEE}dKG0ue+=H8&v-onoyTx3GkA%kkQ1NXKwfs#Y<}v#X+ix)$)%e}^oG;8aS#v86Xy)A{qmcRUw4_u60;D9eFNfL!z8aN7O*ta%SR7x z1~<>2r)4Gz_%vF{Sx-OpKOkm_6u%2-WfcR1aWE@5Bu{Sp>Jj+0)%U)6nZKhDtGd+} z8OTC(;}B5IW8ueo;AMz)TIs6a{8o9$l8r+^;}0IrTW*}2)m(IM@0*ho zea^)1unoNb7g~UX++zS;9K+-M!Nz2AeX6PG(TxlonYVLyz6~!-z}fkKrhEM4g(EG2YSx>c|1{f?%P%j~)**}p=ZT8vLd z$jyhA4-p`5dN@y+{>)fo=j-LFLbpUu&6u|4%OyRK-3$!Ik)VUe^gSnRJDQ=iT38*MgLE_;owUA?p_p+bAK3KIh+VJO3P0y`^4ys3kMtb!< zo0hGAz>;Hjf-WX8Q^Kjmp#Z|KL_mkuMS!J)d%~Fa`SAPU8 zVPYXgkc*|2RiujUDfT^cw)S-zY!kXW8|uwiND(wwYLDN~ISN-rcU!j1e`Tz`pt~1p zMI59E>YvFz;mcgJJ#HlxI&*og>_bGZgGQMd7>wf~MbO8Or`$wO`aPYI_l)xwf8X(q zfe%0f6CeekA}G-F&oYCG(CZH(+G`^x__{u?cks@GtjRHsha73>V7>QTS;Vc`Zo0ia z^L}!9Z%~N?P1i9n7$<=0ZVNwM#k6~wYCJzrTu+@EytItpYTyS|#W0i;d6KrG)plZt#M-A+ZEJIN-PaqC(Irk%(o&a}EF8+*$hS!6V4ZWaC88 zjF7eG?JWscb2#@sQvX)39H4jMQgz@&&{7+a6_6thWhb88?A+j&@I&ur`dyzZr?o%X zL0dt|pm8Y+Kk0%!N(wjfgJzkPMK0bS$owU&3vz$AaWZIIqKEU%KM#u-3`-0*Zn0Jm zXi_=PG^G@@IfQ}1I2qK>kaSw?V0^;V+kz$WTkYfa-4 ze%~^lowvC%f7|T7zRW{4I}7t9J3$f*492OTMz4pnLqno!!9LOF(~sVI;xaEZzx>xC z$h5w3Dk#}YIbB=hQDN{zmA}<}VPa~s-c#vz1yCoDfx#GTP^@Q+WAe*M<%_3ZmXZDt zYtMCwVKED+00k+4B>M$68ezZM0zZj3t=f}k#wqWaqz>{w1A}ooB-u~DRB<|Dv7h@z z{cFLKQbe!aP?QBFcaQ=Q?cvO@mM`Y{laI;k%uKc#raP)Bs5C>XgA7ozmvVY;U~KBt zo$xZ_n)mi8i+(uxMehVfGXsNh2B_3m_UtSbV69$qwB6u?c+sh}Xw|Mcf1ss(24suJ zO_v)+?L03(Ux<#X<5y?89l2K>+P}zzZ1K96OFp2T(gcmzs@&C(nG5VRgOn5T1e8>S!;|6;k zSQ!{`;%0}x$?kjXOV^ms*f{SbbSx+bvW_%FR6Bxe@^0piTW2EEzMRRaRnG^tL>U;2 z^Gp~R7%co&a~iSSy5*bT*gK0=|FdxK`E^#Hng*l*GzQ|~%)u*vv7z?;Sxb|5iia#u zS?)JrzS#$WyMkbdWMdD&s&W6fC^^hsV4p0RTXtxDd(g7C(7~cY z$ek?b7X3@sObwsAPrJc&{iQkq^BOHskDYQMXj9g| z1K+YQNZoq6GiLg4s3VI(QzY@8*Or=jpSrA&+bbb+c8Arp1Fx?2Ktr+^a+-(F{T&?| z{*t#>CWl(To!R8}S9=+B0J9Vn4iFxy(rctGr4nB{ZG z@eanIgHsqI{SN9z1jjzPX(QZbu{kK)_ep^|(Y@2eN3#xE$2I_HcebXXEO>8?Quf=)P2OX4i+dmiC?3yWN16>$U1!|c~In~}*56BRh7*HUlCEWM# z>q>qRXJ}AYf%@J0o<{<;f~O_AXPvR-zRQ@pz_ek~VbHWC1A}pu57?2Kf#*2yKluo-N$=bvqDxaD16{q+Y@pIg>eJqK!8Wj z?q?iiKYjK8n%-%J%75){tyO{6dQG6-vxVQoNp4Zs>)(EE2s?bcxfq*9%WU2M3x! z)0iI43!U_`#M%tbUJ_XoXLyQno%Fk2=zw+;$gz@6f&bOTmgg%=|1YG`@6Q*yTN>T;UD7~0os<^TuOR<8ZlTaK!(zdx5rL8yFF zh*Gu`D2N#tj9Wl%u<(1kK(3{6cf_O0m!9YQ?$2IymHFgNNW;4YG|}VX{QcUqT%8HK zTMMj??fH>>=>4XEKhOm;Eue`%DJMI_mO#m0;s5=#PB>;P`xZX;sxfr3sRiT~WzSHR za5dZACf&;?N?&4m&l)d1eLiRin1R8#RSxXP8TWtqW?YIiF_11>dbFW)u3bqwXx@T> z!MF`H8ExTriD|<`r#tsK+b<|gvbwX6x$n6sv{GvWO(}agUvMenJP$IzXLc59d~i{rY0eC7wRDMg?bC&io6Bj{y}u z3=GDdpk||#)8em2TE}a@T;WZq)5$AJx^#8%YiQrU6I5QtdTyT5enRGeTi>ZkHvSSO z9EIoN=7DNlkO`1073Q4Mb=3Wp9pKGc6MVhp)V{2y2FT6@<8IInNDIGB>c%M#LsN`8 zxX)Q+-z_uGw>bpzKLdktH>khm;XIE+-(PHHOX8QsR{Iub2Wf^ev4I8!Kng$!N8fX2 z!exoQ8)M(7PL@l0BxGQ_dc$03^PqbVIG}t(6T(dE7N@N7VX5Qdex&>GkP39rtQWKn z#KLdimVYi1+dpX9-rLf1vyk=8&uRuxAH+zT2b^l)DA_|@hUj1uN^Ha)z)G5Lqe z6lXqA2@6sHT8kp(bm$nre{?zT^~}<3%Wa!F_GbFdhYsxbg3?2<=j3lU?&y9O?LB)T z^~&S0H!a&H#6UYBpd0EKBmEk$B~Ey8h;wD^eK#pDpbH=gkO`o| zOv-6>rgq6>vx%na+7incGf-J@S6h+i%xj`5Qa~jS(|27*7P%T^4=~0*R0A9=#EI+xE~k zZ{El|6H~mPMe#&X)#Tx9=$KjbegA=<>7gt}zt^_;+!YRiCYXt!#*Ulk_IF;VrQ8hl z_V&DE3%h)9CuWIpdmOi*=cc<&m1-|AtYGS5Gu4Vh33+;eR z0S&)NIk|sa+Hmdmju`>3_rHo-nd4}f z#1lCblt^$uy>z?sDfKYl3g1d?PQ_(8&)yiRgVsGTFc?n-wF)i#ZY;>!xtO`q z^wWNpXX_?KwJ%XDg)X3)3YyRIa1Jj%cU(y=gKLVs;oq4Jog6oMd_e2$85oSGftIY6 zc`^xDG^o_=VOz9AaMrrCoMlH{%%L5SX)C~PxUu4p^g*4q*UDx~#8sDEbGL~33tiPS z1GHeo!cQp0H2&=2cT(0uKMi<$tLkSK9DsI6XMmOudpPH_zkWW~_W0~A9!_^|Tdr8B zym1C-89f7o@eI(Z%le+TCa>CPY|`5D-So~hm0c-rSN$qLOEWf@;S!1&;Tw-0ca${ z!?{O%g+^!c4ev)Df951x%HEckISmv*AO)b&HEYjMjex&zd}Y>j-Z4E^rf_Pa=%1q? z?|~FR)<1Z!ePJ18cgpplIqSjjO)M+=48B6wiOm7Ef-L;@o@?kgVZ>4K+Q!D=j3_(+;?ZDa0zHWTI^hOs>o1xKD2V511gH7ob;?0PgZwW*=Zdb zzR~r<6yCq3n_yOK2cI3C#>jXuIb&sN*0S#odcSAfI9?bA9bTC83>;Y&!BvsJr%Eg; z|N1L?C9{unl$`~r=wV)q0QfJdkyfZ(;x+)!4h{*!8i9UUp>eQOkcnxVaXxy(-$cO9W$Q~ zS^wbiwySo^bl->NQHe#zAhQac@FdOy2m+ zzI@GHbXz9m6fENfpgBf2PuF|pXALJ@NNrPj>r?D`I$QA5anM8;1B3BGdvHKqn$daf zz<;xT?f=Ivs5rXqbEy8V3~|FE&}@u_-#hkaY0tUuoc>au`TL>0?1Cb@8tBB|BG7=1 zhx6TF=+jRlvCd8Q0?knQVOT-`OlpGurRMf zWev1)Uku86)}A|Oq$s>#b-ymlf38<-ioDd`tv^5$JRlQt!H(pZ|8u`F&#V+4uKu$B zj@KMJ`W}MnDh3AQC7>l(7JhZVw(P%Ir}{DC%*v3*Yv!K%mHQFYb^$2>WnvF!_jHlt z4}+9b{=8Yb+J;Ml`3Flqs0GHrV7wGmcS$+1Ei;^4)u;1PaMSu@5hvVO-12urJ7P;g zvFh&mW@VT4wRN(p{`0kG6uB^Jxar1%MtDIcK-Sy8|8aGNpy%z+#~E{Omh9PYzwCA* zbch2yH*ev$WvlT9i)WAZBAVwf-IdW#B39}0 zrLJgEoT<|0X$if4*LXQ(J?)_#E_pu-4kqugXJq7xzOmz{*lcL!z7o{fvGBV(ohSC{ z8ufCy{f{kdc~9%DT6i1md(RQDj=A5_XSFc_}{ zMZ1(!^Xom~TB}Uj_EjeGb9T4^Y+$di+MQ;AsESh6f6uF+m0f<8`1;fV-!`Jic|S#NNdAMqMeK z;q*Y)LTWv9G-(}V=_NHy}3Ei(7RTbCvb@nVBP?gNUV7viD2YY5c z&GFxT=VpxMvEt3I4TD6}ds{$-I7mS!I2^9cZH{i|*Gt!I&B*4wkab8tsUGTvjiBuX z7JdhR^)EeM(S9y!=kGV$mGyJtzkUSG)-x~|ZvyQ;^l)b44Bzp~^rLiU*7M5tMe?jS zQ(d8vwF$K9&Dygz==HIk^W@Er*Opngr_SkEJT7e7<#@nU90hR5z^}F}#*EN$S zI14Pi@@UBh{m0Nw&<@aPyB2sv-b~Z^l6}2T#H*2ZlUCG?D(7xHe@BHO#P)C%3 z!FVUAhobCxr|a;RZmUO2oy@m4x<_nq(R{WaG*AUnU;uXH-s-aGuWd(C8m!mO_4BJ! zKCgctG$p{mV7v>I%PstVubJT;bAP&e;OgsKD$_$n@*|gm{0~w98Z`27E}eJWmie5Y z-J-^;{g0im%-WrE7}O$XU@+bdDvFdnk4^f&hh^=g@HV530kz@6Z<8D^L%q3M2keHb zxbtO&pG{+D{G6M(*Vuw@)B00DEwuDqlf>| ztIY2%I)GMxGB6nL1C7sF_)R~^+2mvSDgQ>#|+&Z0X~k`!6aL5zioCdul5C*voDXX7hm@E>0DD#AH zd;m1`XWwXCDHsYGPn8J_t%M9?l1kZ8G%w{V@J*lKQVN zi3^mv)tiX3K08Bfq7r|t_*(L+Na8SG>ggdXsigNj5-P_K>Ak)JmTNs!4v4`86Cb* zS+HUL5>OEgG67V8#Cz^4wx9K5uGe2VmhTCB`&Lgq;h6;O!W@HiNEa{Q4E5IY_t$)I z?MwW>;~w`)OdKIr90yrp;TN>5aRMngMsmuLuQLGbPvc$ z&y%;!c zZLs;>3!niSkOI&|N1$icDf$0@l`q`axV%~0=hd_lMNui}GO$ySgO%Q1=S$X{uXn$$ zL&KqccEK6BIS-*-xznJAw}s!_iaR-{gx(4;y9J9~+oRI~{W7*wlH3vmLS}->R9a$br%#1B3B7P{y(F%kz6XwU%#c>KdaMxx~ECmHrE- zgSsvt1)vn=;q0t#`S%8Eb!EWWy-TI%{_g#*-~?SKb`I3O*7tnA_S><3o8Jk(@7uj*b$O}0#p3J@8j!8i#uq@%B`GJBnZ=uJ zqEcTjKN%v>F+KQh?}Vq&lJ){r9p&M?@U?qM>B{D3ccW|Ozn-Ukr$YM^G}&JQ^)IBHxKg)IojZ%Qw)&R* z`{Fc%nk9!`LhJ6!65#CrZ2LbM?fsG;?Upri{Fb=!@AnR6$o5R*%bDP0f2B#8dD5|( zqRPGc-crK6zo%SE2935eFc@C}4Fy~Hg+BaiYQ6kr^;*eT@tjLm`_|qN1C6$W6o96b zJ)Bp6?w++_N9RPxD-ZtbZk+f>;D;}CisUM&Kvnk4oXlXmE-$|7ug;7#NJNfoA0_{FXJ{FPYx&@-1)5 zdGm{!rgvIXB|u#`kOELc%fmU3b-|fg=Cv9!Ytk<+`n>JLQJXT*-VX)_-0CmG{P;^`Pefy%Nnqg69 zySL<3Wqtas9-%gC$jM8_w?Q-J9?oy?INV#AAt-ga=Pd7vF6M>-5@Jw)Ot4d3ytH znaar;UYaunOgD;(!Df#);nNWjfY4(Lli=myt`=F_H59gh8f8D%)E_a8fOhifOy%S$on|DHk z`aZ}iDJQv0!n2bv)c%;V=G}?92#-Y5mIP3@fq}soJWOfr8T&Uq_NwjAX2wNaQWy2C z3$>b3pff=atieg{Vuw+v?5|C)*lqc zL5W4^=mn3@ub^&t2wJ`1;XJ+3P*(TD0pr){j%oUjxatpf?}D1}2vkK&IZ52Rx4T%s z;TM|_lkq{jybq_Un?WJSz+n6c)B(}=d}p!SZt1}@8`fM4jJH0$J4(sO9y%HQ2-4S! zYV=o|CoXoUvP^5r|0?Tam6=tbt}FwC@ncXKW#RYzRr}t5%E9uJEN*kUi5OrHQp1|14js4>SP?t( zlIwC!El`~eQUFS{fu8qnly*;%y_t2mYU7mN>r<*(avPunxlbS`ab0=(A^yhM>(Xnc zK8c;DG}m(aML|$wmx00fDX5IH@T-o{4-J&zd;U`F*_rk2*)nb%8$k1#3=GE4Kn011 z^TWma3}ai|IR2|WygucF!LFUUVxU?dqySXGN;$1=^?exBuy|VRj4y#JcbEBdEZqQF zdjV1aiY#T%lZMq^^DS3Y&c9mg_$U@(3Gn!WdM<_MTBea`=h z@tuqFe`=Oayfe9!9a^cq0Ie^Ua^jKu?o)JnUCh>Hf2SI7&fnqRz8spfUVu(!bMxfP zS~sJ_=I@R8^$Keast3Ad%PfV)#S6%pMdoW)JJq$b?|eSv>1!>YD-ECB>p_lVU@(3K z8tJs~+rB|@>GFTiZw6=2O5eaeU&m#aBdB2kQUEGYJ)Fa@|JK#@d!saU-)+IoKcf@k zy6d1F(pQi(i(GFCZM2AZ!ZWL8mVS=dk!x4an!>Dj3_fM|Go#S-SDuajOE&(q%G9;( zS{z*gZFs+i%W~YeQiA)&q_O&;6kt^EaSQp@m<$-z9sQ*n9Ke_;4|r z7+0KbH7N(pwKFgnzX8?V9?lAPzW*?r5xGBL`J~e3C3g#B_fG?@oB$~RH8cV}KRaX@ zC&^uM;rlY_i^xu%e8UCvp|SZEa#WXw${&quPyJ_4arkNzzo%l+*M}X@5(a!Wi-lk8 z!;HP2TyO8x-Sv;Xc)D9Yr{@}U9_JlsRLR4+d&=YuGPTOKk1B3B<$OU|}d7aH)FRq$?e_PWL(L<*a zPNgY>N>~O4;}4*Pw-$azKSVu0Ocj=XDkJ46z0}Hi%EArM7RX0X{_t?FR8qZ^d#TCK zbz65jL$uY@`CWgZ!_gl>&7?q2_lmnI$0YeJ{wm-;TKe2Cv^v{il=1#DHoZM*q8FJeZ#}wa|TYJw{z1?^5 z0{`*Us_FMH#Gzp9}?QE_U`nc5m`DC*Xx}YO?7#NJdf*Ly>&PO&K zE%Wv3=M$BT%8Pftta+?79~8tO1$)4QBo;!MpB*ZU+AShyOb~OwWqf|lXHeG#qyV%a z-P-eL%*3@*x%LE|x%ofMW=iUL?%$EnhSoR8?yB1x?k-4A?Or|m<969&9`h9AzjcB9 z&%j{(9n^lX@cVJJjzOG3bwNR;!))c}d|M}(EP>9keg{o_c{saH&U5qT_ur}iRwTfG zPQXgeqIsaXc9036HjI?hiYb}S9qV$}DSEP0d9u$|FKC%rCl-L;I@$>-LZIai?r+CM>4sUFTOZCyNVFF)`dIc(cCd-gi3^F559c})fe z<6oe5l#~*bsrd1sZ*pj&#J}X5hi~O+ z+14!QgLbQb^@1H4wk7lK6y@^$EiWS1YdM``wol&*4XEFsy4%99aYd%mfgei7R`!}a zoHrQT+2vP({LjE({0B4v=;3Vo;hOXE8H^{Z^WvXsbANlV(;*L9M*RV`AEcaCHmhIK zEzho4`dMk|T}AJDn^_8zAa(a2(3rWk=b0S`Z1^juNoMfhWxjDzu71J#ZfJ}259ApC z6Wfl*9SnVLzHrhM8MDW09cHHIf(9lS7>xgc>TV0aL%LT>J9~uQl>R7V-^V)Xg^$&L zXygAMsHx)N+_7+Pnc0MUV!L)$PI|T8qjZr&HZ=48164^D8&63z&zPLzpS6$0VPzQ{G!T3L<9d&ZejrqOH zp9L(EpK@X6V%6Y@+b4p`1qKEa22eOy`1PE;edlj+dcUyF+3ck&^LQqSZvrio1u1~E zqwKz>EO}(OvfkEz_fZ*p4nD8zD?sT0qyQ8bfu5cXGKv4z-R%hcoYr_~-D1|uWfMWC zS1>S`FhWi|?t0UIE%&Wm+C_7tFS$$2WM!t=gYJT5U@&0<)p{0w(@k`OG=emX)C|5j z&E2K8YiE%IXwVR(05tON;oPfc81=Aa=@XHv1<{Y+-P4J4ke32SmI*T`R;8SNdNr}| zELgjZCw_&z`%lj##TNx2oeT^n%%GK4fu32jwg=Y7)ZV}TXTr?N%D6KDKC+-bKS)6} zILYbmo!t8}vZF_a-Fse`9P5vVr;kD+%Y+3q%wXYHB-N`n_ijyg)?%9f3g$P3mqRkI2`gyrzqKdJo1Ux#v*t~FIIVo$ zis>`uUbUTdQuRvnHNrphPObL)2AL-{5DQX{Wz_0Pt=6JYd=g4;l3!XwgA$lHQ@%e@jaYdwXWwh{@Rco5uyJ{;@tin z89T~Admcb0fZ{~TsWedO)<1o#UkPi{?pys{f8D(2JmjQ46K+u573)9bi3R+4c<55;Ng}+}|ybD=o0d=F03Q=4YHf$Ieeo`PUCAVN7^IEm8|V?#85* zdo%Zc->Y=_=j`y(g$W&7A^j{9UQjXM;r#IZ zL9JqaPsWsIKOR1t)o%2fhyMxxwEM1aHbVw#O!y#&L!O*v_oIxd@N#sVp#EHT! zvq9OOfx(0y)KszX)BDEy?YU6@<+Ax2hhHpeHoGg$3KfauJ&}-;G)x2_6J9Y-mpHRCtCnT_t+iL$K9i!!{za=4yRZIjyV<8^S zvG4xPK0mKz*9+lvlcjoBLRVgQ0S(79FqjC5F)%Qcd0JXs{_DD;P(QNgg``2lalv_i zpbG;`gnGaUMpR}(+U=n2A9pW#_bNWFN6d1oCMX0M7)*pg=TBPr<>W1AiOf4c@AH{C zcPoYJ7tAi+2bybVU@#E@El%)oZl58@s(ON7=v2_5NWK3#x;=i-zQ2hGXlUHp^M_x} z3n`!9p9=nQFID=Tv(wsPJ7@+7WCCR9ukgC3g8CnpfV#l&dz$47eoNlj4=uz*L3z}| z@0wm$5%=m@UhG>puj!EU-m_&vA2iX5fm-Mu&YM>3`qR58&)Z#$8ZeP$0msF)CMWH$ zmzVH4sD0}=I`?7bjWj-J){_ERVd2+&a$A;8!I6Ne$%mP`W9CZ#oooz>0|o{YDNsS; z;k-prv%+eFVJcU#_FBD%jwbs2GN2YYNCBu*DCM+uPhm+{o4%OVdG)r1MPGzI*ZqR5 zz%-Epl~wVc&M{dVI`$o#71#7=x&DI_2DwRv&=e&d26p5xp*y|~72@5DqI(reG~T$* z?-v1OS_TFanf2h+@_prHCH;mkzclUAn6s~-S!tDLA7~5+qyTitlZW$*D-qLpGo)gk z_jgTvvwF&1uUR^f#=nUysLZzZ6!YN8amvh|C|D?+Cmvb632*qVr?=2mNZuyq<|1 zs3`Jq?lrh+<{P6Emu9uRhohY;^7V_tbL2O zb0{=GCf!WryTEQ(6S!;PJE4Ek&nB_O)xKl8qB0=^GU9Eb0P5>m_`U01^Pj0iAR&DwdVpAP7g(&58MzQjQ*Xxwf)txrQae%4;kOIgKj?8mcZb`knvvak~tM_&jEv&YQu!7o83=AfE zpn(btzXaQ7ypfl>ul`zK9aFm@M#6jJS;#<*i5_Uo+{3wR!=r77#2%`DWJ#6#$@}oZ zj>%1+QD%?{pdB3Uo)V9JUz)l-$Z&t%7xV1*O?Q2P2atZ2iQZXoiYj~I<`l%*cGl-w zA?uTwdg|_S^B`+5ObkGSXBK{KrB~uF82J4zf6!iC^8JaT)eTsJF#zqQ^>7Y4w8CV* z%fyCj?=PzEzF_+A`}YiJWEp@;eJQ6aLaHw(cm=xZ3&wc`$KTWG>d1#imH}wRnY-sl z{fQCz%^ltCr#5A;XsFup;@VeeS#8J;cI2Zpqx^j*LsxA*z9H$;r~1>+rd$R!EEpI} zj6h4UEc_%lJX_58^m&)zL#4KW=#GR#=hs0S|3;whl!x=N>n)*2JM^zximwj6xO!da z^gRmDMz0ZQgiqgd^F%eP&rU+;WwmA%h<;s|{o&*+(D(}jgNZR@>5*I8o$#BEqUn3u zZ~pOLv)V9xVK=lGGyyfdE&QHmRpt~+?|#JJ*S&oT9HEW;v{O_1&2&%Ig7)(q- zEwNZn?n`b`rFCsKbCaHxpIqJBE}qT+n$H6%fShX5mGpU+%>0c@*rpg4_8%)V{F}WH z)FEeJFfju;*22$VsdL|4(elW^)#ra~$Xa>%(ZlJ`CW;xTr15ZGTB>h5TRHXJtS-G@ zm)e~zlM6RO%LjANoU@dZ-m%K#XQbnU6_2LA@MpgEW%ukVkWK~$6LZk8biC*G#apMY zth)H;f9ss%CzricPAK^ft=!Ear{&y)dm7J;__QcIp(OnAx4piX?yM+&mH|o!3=AfgkOQtG7ksISYc|;MZ0qYes%v;f z&Zp@?Bg-0Og@vE8XsAh`-NbdVZ&>n++BWLH3>N_vpbQKq)}UsBhqL98eKy++eoM^j z+;L6qnS+AULuTH)>BhX&T2r}GcVgoteq5E3*m&+^EA6KX!*P5fn|LEhZf6yYx7Bs?V z;m6wfSyybgn_}t&JvtArJFY!giQ+koyr~cBs3;v<=OQi&^C-cs54~Y=Xpm_|SF>#Ld!C*4^9HNgQib}r?_ zR448o$hhh0IV-NcjBcJ+`#L0{ja~;(fCYQny}UJnBRjic{UlM5)(1_@*DblB1&BjE z*pZ4Sc3+www)w}&ch(i}lIq@G`TG)bT)BxOh_>*%V^wrw*&UH^kNofbQrw?roS6^` z4F@OC_=AV@Q6Y1w|M%7JO+U=M+3=-OWJhk~FVJ3k3I@X?Sr!H{xcxtL#w>Q1Lk!4N5uNhMy%co78Ak_h5%bY0!GBWR29`y*E ztPXOQsDBF0{w|Q};KsxBO%`$PuQ{)udC6$`@%DCENob;Vfm8>3?(ywxzWVDBNBqm2 zy*Icz_V<5;_Vrvq)j_al!0Frh zb|a&=sad^ztyiFJ7&k~ujO*mu1S96amrr|_H$K@NcEr$60h;XHAT6;8A^%MxwOJ$_ zJ&h9P9I;ZiUo{mnDR1HiYKcfWZN7F-{@J;@d;sV-|f2-&rMz+u66qMI#9a-qyV&m$-~((GgIS{L`_bo153QS zr&D)_d@0CokOI(HkhSMp!}#Ss9kDB)%_{OK*smA!rP2wsfQ*5`#1m2-817ub-tm3= z5%%`l0`IBC`OF|C$tJ<)Mies5;R1)NZ=KQet~2u|-5`#~IO{9nM>KLKYU9ctgsE znaRtn_inn}KBMW^mDin7>R%Q=dIM>R`G9hmg`e!j7|zUAhu>VLZxlXl2ncjg&4kQ8 znD{`-haE-1o+fW>e40A`%}^71e@?<94>BZf;sYulf;}x(&uUq=$-CyO#-#VNMQsix zPnZSSJZ0hw*(A~~uf9uFwept_uWDw zy$>QC&$)uS^b8CpexRWCaOUU{y1CX@>gc{z-dP#jA~|zk8h}=qF))~bmk*bDHnrrM z@R$GlULVsSdT;t%pR3->APa6y{3n6a!;J22r$wrd>@?VQOVs4wm8@G35M3?pPD%i zo`8BY5Y)a7^z^NMRc0sg^ITK+r5_Tz#H^ez?*^@LXJ9Z1ge-UAR2P=lOydr)cvLvkM=DI82-x~Yb{a?}&lHBp6gqcsS4eym{@S zE$K0V{hw_1PPM$n`sgFH?;i~6Ur0G6@4syS_)gpWJ=+b!563o#2kc)28Fe=a2K89W zJdf(W&SPVenOC6RbFcNzC#(Bi%Q+$GAq2AA#cuz>%ZIpHSKmJ*TrSAu+g8ya1I>D& zpm8}1Kby0PE9R$_g%pN}zvq~6doAnApP-{97#K`KK~u>d&K%xWU#dP^iskJ|R9LDI z={c)f7t|~ODFAiIq?}gmRZrA;rD=QoHT#zjQa73M53PcZvW9`ug`21K^e@Z)@0su* zrtq1#z32xmzZpHCF(3v8ldw2&Y`X4$Q)FN*w`BFxR5yMRrv8Z9dg$;%I4Fl%_(d!! z`aXB+1b)wOzgK%$4=q2+IUU-K3V#niZ*amoxA*3B_{_-{G~+-ud{Isku%faDLD-&{ib4LLOG{MAxW0!*m{p?B%kLN;f!zCG5(8>3 zDSMvL@3yrq@Y=A|@}gEY*DCSyV-G>YuM7+(F_0;e3HH~@0zwpWXGtX%M4mdPlWKPj zw1A9(!6Xh;W?T5hdj)TFie-8G(5XY&i#5l-Tu2v`A3zE~-6#)dtA6daott8rcUUCw zb(RHwz8kFonlk_?fJ~7T&-fZx-F2wkNW#>IZ-s@#QN8ofZdBYl1_lOY&#IH!>jSo5 z5tTNqQjE#s=$&!*FsS1JG66D}99E=owbY^MjFZ9PYdqC=cL%QVfev{kfP7=&SElg;V8p|D>b@j~r>0K!UaMEVTe5d^{X2#A(4JZXXfWB@ z^M@B-wdt(g;RTj+T|dvB+&lLHGbkM}FqkAj4u_QUJtzCg^qE1Okk7-QyTW@mzqtuo zvdq9>k_4)|E&L`O+Z1N36IpjX>+{FsI!AryY-oloT{cMqjWT*TXY&icPc?~=_0rq7 zfMM&(1wB*RAcwA-B!QM-S$nDmO6}jRk|4{XBhP-FuRrCZLlbn&Jn1JmMcwc>Qjeei=fCRP?Y zsGb6&dynbubV?7SUMwkv@K^cg@3K+A>$J+t2( z{+?O1uY%F4_HtL3?dh(MuD zC>DNtF6E5XTerb zvw(rYBoj1}BjsezK1F`f`}!j{1eh!J%y)i!r&$H5)k`D34nBsVk&wZU4Qs zf_JU`$C8Ll{hMr2P%E-QtpE?_a!0?(sat-{JE3kd`EJw6sFXWSkbSHs*`Q^^QceoB zTl+jd>AmVOiU{~+f5FYu>lbwDFdLM3tv#2Stf_UGp2>5S*J@_B{Fc`6y?mgC1p|Xg z4rJfKg8y&-C8P&0U2=A9{m~^S7f$cq2dYRI7)){@`wjv{k8}PHoc6^eYj&fkjlSf` zPqRQBFpvV!6rzW-;U-1(D8B`~o0s!`@MT%a@bB#r=jm^1grUPVhQ)_HG5&eu=f4{H4|Fqjm8x-!9@`3|~mi?|M@@GPv(UE%k$ za@}@gP@f;905ZXGySA5GGVy$Qn(6x+%js#EwEbf zaF>u<#c%H!3nkBl>u@=EfF}Gv3P5R6-}6qnrSZbKKeukU@GXkPBT4Yo&!x~IuOi5) ziTt`+fe*yI+}flYOTzY)R|)LXh4xTNKutCazatl$|9rU|c{=jF{c$$a7x58uZ$g^~ zC7=q{!?}JzQ`8?h7PnT*KOYtSc_QXqsD*}PNjrFhr$D&WJ&BgUP~(jc(=#M{(-~Io z0y&O>!K7pxII{j&?(+T~ol+8aYtKs^E48l&Cf)%x3m6zo%0P!JTli&mUpT?(b!(2= zJ?*J#&W5#RcWgi|HPYdwVHX`O<`Rn3-xB%Bd{A@o_YWCw4dcku^kVlCA=2anL0fHI_F*iDuOKh z5-j7U#i$-(c*baV-jkO{dfmwjUm zC(z`*&|c^)Of6`H&)rkaq2>49-|sbJ-4E4W?d7_|tR)VuFKYe4ZV(X?kGI;h(>|nk z0axcId*yJAr=Wzwz+h4b>LpqDg^JF(e3$EWz)^!uzkWSnFEi|Jg-#vTfd&sfoIPj% zF`V!)_Unv@y5h1|McujF(`Q3svmUf<*V^;otvsWuTe9oUhX-eVcIC}$`|A#>1{fGj z>XX54C|ID!{(AC;O_o=7ntc`GRNuq<64WeUU@&O_Enc$lTV$(!QS{%_k7@7M=oQp@ zzPxd<7}^18_yTV9-r?MS<)E&qW@pc-cFnlz6I>k}KOk;s1PuYkdrtntQ>pj&UFgi< zmA_;Zb9TG1w?b>)M#%9m?+%@-?q_wmwyghY!s~a6`{&<(4$a+7AS*2V4(wQUQB*(Z zi`mgC;r3;HuXpuZLQ{1!XdK4F`84mGPc6EC{2%URdc$HR`{vBeO32zIlV;Ewtzb|8 zcWY!>Jc}NkKRM6zz1*6bJcm5!R8ceJTB!Yfx^4eN8&c$s_%3RBlWh5F;!EgoQ!8lw zgN0x3*7ZlLpOsj*KQy_LAAF8i<&q6(1c!maq!rXu@o-j4C|Linz+y^sbAZocvm;BS zPe?-x(pFFf>+1PQs(P9e(}ULnr?fwQ^8I^e!Iz29o?0uUsivx?^R0!)#s6BYpJeg# z%Y`%i)enM8mnzVxo5)Wr9FQ)aHo@dX+ zsnv$RJl*_Z|B28suf5tR1FDi47)&}$!3pMJWM63WC2^HZ*4)&h|1K&eT3OKS-wB!s zweXuCIWxRKJs>hYHdG<{YqWyY?@ORaVqh@o1nrFWaDMiG!^ABM%H#LR>$wG+S{bnW zbAlp?fx)B;G$vH$8G8Fpv&i-3vY82q3u>ctH8?`&KvQ*B3)l_cX4D=uGt^nRdH?pp zW@}^r?FG!xkn9Fccv<)fhP&$Rei|fY=DcA3*-Z}B((%1eNA`d^0Upjxnt%HeZ8xz; z?sjF9-1V-_XZkB>wb%oibdz#&XN%mz+<)o6wv57hwQBXu%z`!0A_#opn6hWvqdzs? z?`LLtIrGo?uQhSWgYGY&AZB1N>6ry~XJ^xI`jH)Te{04l4coEqNzFHDcxDr%It;qtY;wHh9JFF{QckOI))S()c|{|_y*daOQv zm7j1*wCw2G#!PikBr!0U^h53mn(8&X((p#2Q~CYte5{eCzc$ug2X%fJ7)&OBI(rs= zujNmx_N?Z5DI^`&7k{WsefdG?{TC(^Kngva?q?RdPdxN#p=bLpdbdB z02*zUays406mTL`wJ<~FcUSt>>whV-F4&es%@fo8L}@9LK<5G8tr*n`e=< zNb}TlMz8(mozJ`V?)IkrYkz=Nv49jnHa1>4m~&uZ7wb){!|r>*)+Y`qEURI7KmA|d z5}EVR7U@(_?>XKxvf$V8#H&BUin5ATPkR1*Bw-f@Z9hzf3^%oNXPkGRCbv=5mpA-m zQUOcEV-4sG=`@fP7JiA{cYlT5QS_-`+57%j<;Nt!Xb#AFdz0y)j);eI4Rh5W?!w=9 z%I2}EEaT7Dv6o|lR!P%AqX@yCwoiE0>qu}oojxj7l@p&i!8_+Kw3#%0A2?M%PtMTZ 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

-(ZU8m!vhG+Ic4xn>i4$5I3 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 z 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

Og>&1k5 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 z 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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/test/irmin-pack/data/version_1_large/store.branches b/vendors/irmin/test/irmin-pack/data/version_1_large/store.branches new file mode 100644 index 0000000000000000000000000000000000000000..295209b4b92b5ba2de681110bd98bdeb7fda442b GIT binary patch literal 44 rcmZR802u=aFl1n0V98C)%zMr75)FcG}(y9%q literal 0 HcmV?d00001 diff --git a/vendors/irmin/test/irmin-pack/data/version_1_large/store.dict b/vendors/irmin/test/irmin-pack/data/version_1_large/store.dict new file mode 100644 index 0000000000000000000000000000000000000000..10ff4b264c8e9fd2f5547ec1a4db97b535e0cfa3 GIT binary patch literal 24 PcmZR80s{yzgmM`G65#=Y literal 0 HcmV?d00001 diff --git a/vendors/irmin/test/irmin-pack/data/version_1_large/store.pack b/vendors/irmin/test/irmin-pack/data/version_1_large/store.pack new file mode 100644 index 0000000000000000000000000000000000000000..0d8144a8995e366207015bc8157174bb24aa7cfa GIT binary patch literal 5563487 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 z zB5-9%!!{#h#A{IAA^#DCJ6`W!yO$9JJDxI&t)TB8DQBCWiXQvT?*@+SFb zEkAa@7xJ;5lN0Oy%^90vjM&m1B;Y}$CfC!77#%kGgn}Ji%Q;)#3u^{)JF%D=7@N+z z{p=2Nd0?Xb%iV4UUJ~=WyV4#TB`ZEzZe_A>!j9byGbWy_j7&Uu^CX>$ zt99bTxwx`+*|T$vjD7MayQ3A2s}>xt`mSq-qqss!T&goc$4`QrvmTZoF>Z})1XAIJD#4MAD(Xv<%(rCz z*0aU9qfjYE@Z&in=j+bc3}eKW-arnAV0PD^Iy%L#bR=RNI9rnEN;K^^7jFf}!9 zkzkOyU@?7igZ1fu8Oo2=JdY4n1h4Y5fOP-aHZADlTC}r}C8hLt|&i=n#20ShWPmoi^rn}fv#Vif$4O4%t z5MFP7^BGsb^4UxmG~}GI8ODe${eT<}!7MyK*k>=z&Ny^DTw{|a%e#Gs@7h6Si-D=V zqZYR>$B}mqCd+G6U2C}3=jyA0Q-vioRczT7(iU9pr(+PaVA;ErE0-_%>^-6I2gisH zRhlzwTQ0!PmKfg6nKGwo9zl0fjBiAUO!j*0P*?Fw{{)UyvE?(oIkT?uNnM%t()qUS z*G?Qh@~d2F^1sTc9A|8XF=9(UkQ4zT&zDwC^fWAv$io3=oky%UR}p^@>k z%@WE+{aQCCTo?a-_R-Wu86tCDfR|kuK^np=M%HXhmXITC*tVV7ao+Lg|JcsD+e!X1 zrT5&oPhhSs9Bq?;f|%I;Ioq~puq|-NqdA|~$SK8kZ#XB_`RDL~S>Y02CP+0BP9fVx zLwF-aw^Z_TdWIZju1QjxeP&VP9cOHYF=9(g3~=x#>!8|_9aT$2{9npxsM)(43oZ)* z-3erDZXEhLyloqA$*faZf&S4G*hLn1ijk)i zm3m89RR>uL*~tMNHO7A_>Ogg}aiowZMf&F^`z}=39{n;q?2S;o_ZN@8D%);>Ut)ZBT0B%rY!f*T?R~SPyJz#P z>Os-;*sTejR={?0CmS7>cv9H(xbVBN%=ufBHD}yc>!T@u4>u%S%116jc1OUQ9!QnU zPIKnW3is_YY8w~7y`@@T$XKSMF#E7GHp3XPB_%`xS$6Mmt<%%Fje*}vMdi89Ij!+d zTJ6MQY-nb|n`2%tcgv3B`HPE{Ezy}y*R&bTY0+oiYuIqzCWX0L<*roXrqaciq-vC= z?$@GI>9g0HxIXjHEPd1~3`Fd97R>um`?P&>aP5^+&lv@T6W89Y29dojVi|5M%lKj* z{#W^@X}iJrqcb+c7_lWoMB+MOJ6Zd1-pzTf50t{5EbV1B-Dc_J#A0l2ZYf#Ode2Og z|D-f`!lDpKyOYQKZF^9L_=vf)Zhs$qh>taQGkl1T^}^*{F-qd{OE{z+ZC3s6FYziv z*}{Jcjuf?j1$2myjXEoQhIfiOvGeEmH;b-%PK|ped-R~_>F3ui_7hG~2iOY(=I-+R za&>Q722atR{4nd6Et1ciu^GmQE$tyv)PfzS-uOQI>KVeAmFL=O{kKZ=`xek8--bq0 zB)<4Z;lq@MD80nQqdt_c+ctpd&Qc* z;Ls|GnR_=lC0X12s?X+sdf6G9VT{<)8zL3?-`KysH)!JPhPm9YHd~$dddm9nz7va~ zv6=Z(UvE+2pOp`)7}hSDll$&kRo;06lxEQpH8%KF@xj8j4pE`(%8h6BTxNFU-_F0L z$@pl~U?^wUjyS-YMMJaZs+slW^dz72BF)-?C4#IKPp1@pb|joaj^s~cy_%`w`_oIk zY3+*SN5LoBkIO!G#%35JwzPyuA)GUUPR!c(GXLBo8}(3@_vs2Y!QxIV#>VF6zh9PK zK6lYg_J~Dv0F$cdUEUdIO2Op}Y$YLScPp?R^H4TPSXdfW5W^>-Wz^(%}6OT0G7xp=|-~H@=PNb-cH`CZ>(d#B> zY=$vnOIL{0!vAz`pnJP?{W{*({qlFszlJSmoan@2VrgztDt0QGX$y1Rujyi^+q9iB zZ*>`7LMd`i?S^0H!usMqd?7Q_PS9~RkfnjFyEeiWGPATSZYof`9-@|P@v%QbAT2aW zcFweXZ{+Sg+o`LtB8R?bjtuqg{N)DsZ3jPZtoSuSX3f{&--TCYwIY!d(P?#fcOI!_ zbK;ST9`kY2-69%6U*A5N+a+YM`i7R8Gd9B*u_ZS|B3duNanbfd;np5bM_;b}hKr?d ziB*Hn?K3gHF)8TSqIq3jiYsRCyY*|gqqvCg7f2$4w2zsHSS84ImH~N{pv2@q^M7vN zsISbnr|y)(mG1TVr$eVP?Af2Z!Wo-kjM&l}$l(wy{^MHdjXS)BPcMqq z6!>Tu1Pi=5=)_`SW^TFuhnaq{TiI!@XD7T5=CLVBeL3xu{*UIt8WLY zrdI7kSr|``s_lFNbnP-5e5u!40~3cGrYPxcc|Pv`eu zYnqnZ$-cs>+xe7}Y^!ca`uhwyXKaQsVoQ0Dv;-oz#r!I|F+Ki6WJI{-lc|%;40sne zIk6a<85ty`@7g|%E9(2B?ylCkOXjXj-DR@QlYxbe3A%Qf?cy}}+GRG;mGHF_Eb6iF zwacut0y%VEsa(DqQ#G^TLFf6OeyZE1K5`iCse^)^jGgBfH$Y1wwyrB8_Lti(>fO3G zeWD@Lmq}TfudbYs7)?c>Xdq*9?3xm^^kG=JXNJl}1-GsJrH|EQ zl?0CHIPd(Fe-k+sT|=CIf|80F+XW`A?V8JwU8XgEeP3~JxXcnoXKaQsVoPrzheNQj zRg-PfbeGA8{#=bHmDe*{TVR_AUVQ^ylf~F^-=t{XyXXF{mc{|st)E9YPW0{J<{GVe zK*7g$!w$!#2*LSD}I6JYJn3x!BnaSqnvBU89&%S*k^_P4i&%_8UAgb!Q(+qFy zqAe6Y_x8l&@X3WiFJBvdzVLX*+)c5+`)E-0jEq!tXD*`ZX^<1WQFd+1{p;;V4H`9e zE!({49m-vpcRpZGMYj|8-xsi9beL3h(_!zF=W|~kTo~hw%`ir6=?$EKz(n|h%2>(P zb1Ox^F|SvcH#f;7_UKn977I&LQ>7JNnM@yrWX13N6sb~P<{#kg^bwMZpk)q;6A<@K zz7wkGw%feo%?p>$@wdM1J6Lv$4Rnq*{Pa+^dyiqGfwY@|7>@mJ!^L+OEO9*=P;Bd^ z>}FFZ%GJEH{5ioc&2wA-DdGr<{~VT{<48#w)d3Dsi} z8Cx9`SPlO9mcE|4a-|MW**VY(QZqv}@51_*w~KkbQyPPV4_9#gXWb_ao`5ihjM6Z7 z#KLcxVtdHP#$*XeT+For-8ZMNDP~!e^i=T4P0@`9n!HRaK<8B>P9UbB;$nNK0Xrgp zuN5FU)8>x9RJ}+waVj`!_~CKu#?Wld%;!_e~Eru&u7oxsZ1@`BcUNA?=gp zx{X(yu^GmQEnR^V3YfUQcFDAF?^px=PFnng&35^*=Y;}BPAsNIhKARSc`6j|IL$gy zE0G_hqNv_ykdf)hz`@1@-R;TZBLm;<$=bXUvD@?hBlvDlw#T4dpwLz8j7o^@Q*p+y zqYRj*d&7@1VAb~Qe6qfb+x=>Gw^4h5)I2ujh659~QLAnvkkB57!Ip(t^FoIMS?A1v z9%aBb6kABhb=&O-*5yY0vMhP$Y-1<)we8K+va3Z-XphfePiWnpCht@=dSpK+xLjWr zv-s$8>(~NkY=$vnOOoI;1}4(HG8@%Qt{%`+bNV!?Vc)0kFXFR6$LkxKxK%Xx`Mj=4 zxqoMxyWqjd`*-F{y-jjLd%6_9t(c9dgm&r2(|6s6md$(m;ptiRB$_xr1!4O0(a->=Jcg52m528C+_cWcWSRs|)<&4cR zMr`Q^oFKr&Q^(gcwi!)b71zG-kIh*Zzbma1M4VVG%}k6XFFi`D{cwN%f-UAXr!s9j zG{gGCAx&$@d==xRUN$CU2%F)D1{;$xWWNpDD-||INW+O`z7QKDBn`3JD(rN2TRb6U z#vfhL<;QdDPW+V7H#HePqeE=3>_osJ%D_hQ3PK7;hs6Hz$h=NIC3Z}drN3fB7Wc2F zT9n%wkkZhre)#Cn3-5WowR$4%9Czof?kKrCd*ihoi{5{8#%35Jw$ujkEQl=Fac8G- zQ(;u-xp=MSu=inRi!R-AVlgx@F!{YaVaE%jPNyufh+{#!Vz6a_9PGW?ncuk2O`}>(LoPpkYWtQ>Se2F2YBXSZ4+9 zJ@Wj{nQp7fw1tZo9oV?XVsit-{?Q@|6!>HmQSV+uN0305LELultDfR<;)3*S0siF; zJZ)u~4an6TQp$O6gj7UbnHQ*J@jg3pZ<^PP<}0rYCpACc;(Q8=VT{<)7|7ued}8{? zHvuaT7vGO^(Uku4S})_4Q3N>U7zlh{Yp%2^`iADW?p@J3pNs#`JD-HI$oV5T8+?)T z76)DBgL9{T{QFk0EmKKskMg-R-89hcz%)BAh1d{~#`{se&PN|y+EFU^!jfRK`LjFhbRD~y(9?C;*qETF>##1b zhMum&^5Y6@cnI4CRfw%OgJ>|3YRzWV{a5%|lj?ShY|@SW!SHKViE!^}!l~tR({!C= z?=3qlOVcjzv-CA{@VncjDdvpLFh*?Y3Y1PDIKZ!CjahKO>#H&0W=@9~8rSCDo(ev< z+hEuFJ-kjEQ$MyX{`HZj}RXyI$s&tF;XzQLuNFfrNAK60If z%F4k|%M9@{@c0UGfYZ6E)TH_nlX}|2U8xN2>Tb173!FZjzb(@aF*~VfoBv z?VjBWo(dlLroY@7n_-OD(hnp>fXEG|%~r~{3#7O;Zp@jQzUW6-y;-0Wi-n1)!L_K( zek~u^mH8$|Nig*s5!{j+xdvRz7(rGfvwbgQV={*<{$sr?DJFQr{rzj}lVKmZx5(P4 z8f^+>I5P552;28=2~e;yFtFY%hIO||pGZg4GG9w|CP-&1?N)qXv*L`Siqs2Fv29K$ z_w*vQL%#1qN+Id@Zbt@|ZLIE`F|~7F$*v>n3Q1wk*bHODmX;u%0FiGUqZGS;1g*K_ zcT3o4mq=d8jhQHiRWSdnK^#_LaZzP6pX8U-L6>W8w0)Rq_(8is{D&J;Dg|I?<(gC`}SN6>=zwwObfm$NF! zBCbX4xxm7dC9|Z|(Wv|5-#x!}o#hUGV&OGfYJdPzsqq(f{|DCFVz8GQ{szXUZ)NSU zVRbv5agg^EL%IIGS2)td-yiT&|CX6*q^|1eXaggXKaQsVoNrJ z`@$G9{K}G|$i`#}9iaVxG5+YWzpax}d>_573^{(FdIf7Z%YVvJ2;2YH(0&QFQ$Gi1 zFP1?2f}9l6w^h%1!P~~0-@d=SvAX7Y*}V0$&SFm?>xk4$r`XkINiKF5 z7XSbEo=UhU2*s>H@*0x3_}89&3Xc4y3-Shk>0Y{E<#^#^V|m7R%~2kcdbAwT!*oAq{6l8Tvm{q4H6??!K4PnTPI3MsX)GkI`8HxQww z7GB{ccii^O-?&J9_2n~vn76(tvEg&ZW*8&3bOi}KF!?C?e+Cn);0-IS*<@y`o|RG=kF%-pOw`=yY}N_g6W2xrD4Li<2Sb65_}MCQld7ic+yL@ z4->8Pv+{hl+Mw5shc|w8Vlg!{GZq#MTa>hYD*uAD zC*uVdUpT3;>4^h4-55beKiJtK*_e!={oDoT*qDqVOQ~3%d}3p=Gy)mU!1CybS$uY{ z`sIL(pLtGZ$5&=HxQj&38LTOXovj#paR+PJEZ8NgXC@1R{ldUDxKd8hTo=dU*UJ_N zCL|uWeLwd>Vd?{a!YPMsmp-@13fW&18{ca(eiCS4IQZwM>KkWlhB0DGW00T#k)jvh z2`07dh>LyvfHftsIsM;E-{(#&hDL^#n=kEMI%QK(x|r&5lXI&Qga72J^g^baAt{8N zV={bSH_M4~_`Yst?yK+%s#u@Rg6->OyLa;JpMI&`D$IA5%S(O|4L^LqueTg@Z!^4W z#Llr6b0y~hb&ZBpA`&+5oxsi7Gr4uf5u?25PX0?5g=Z2@L>&JG1fPD){lMAzj&G;+ z%g2T(_m92oaK>gBBevuQN>)YM; z&!}JJi4;((FuPcqD4la2v_p=(9l7jWH;{Ma7EE?9nY@0kkZ`;{U(iL(MQfE0gN`Pl zYkFem`UG8qhkr-zkV;RU4Bb8E(sC^OjIC3)Z`D2bX5;JEgwqqZf8z7qJNM_WN#KiL zt>(C5yL~=a_wa4h{&2vF#oWly#J@>( zxv1K?@M-mDjti9drO18`{E1vBu@Q0D1Us(=tWaWUS^R$I_t|EDCPsY`Ss%RR+IO~> z)Bo&1ZcDTCI>8Dhk~dirSjUNFZNe~WOFxWJF^;X5&exrAZ_$);3p@M1dRF8_#5)B` zTbiBQ-=ph;(uVg;R}Sizi_W*<3*grelyb&q7$dgi21-5CyUvx%<~S9vSfO$fxo^(Sp9}Asv*;dMs&?>u#Pjx= zva4O9AIdl`Zth)IL|F=9=WmDg&G9cOAKocsA8Y!po11U5#!C8?N`(ksP~`5+MNT37 z+pwpQ%yU&K^KG)*`^uNsh4aVewW%8&b;f2GBet{zNgW`v>lRCvfL@kZ%t>u!oyRG+ znDnn(fcHWf8~V3Ae8ig`-ncSNsW0K~41sT}=Y!`AO`vTb!Tz~CX-Drc=1>0>F3>6L z&@I1Mu~%qx#0C_s_{a3v1y{;~R538HVIR{IbeZ&aw!tgeGX{klr^j$ghyJ*diX&AB zo`H?nuygzWnbod(!0*Rv_1WisKHBr)C8x3=t1~vk7_p@vh?79%pXPbX&s>hmV_z!R z@ofDZ)~A~#{XvJT85wY8+`66J6sG-fnI`usfsn0Fm-U_nmm7wVIYV~grEE;5(7u$L zwEBV1rTfpDo(ox~R}%fGnf1g|8;#Kv0t#YmDTG~kzYIu@fq`HOF}q=zyf`Sl^0r5b z_=RgS-wK#o#c-q$;de+WnbgO!-Zk z?4rlv+fUdQ)xMB9A-$sY{-;$gs{a~zKDh9mumbJsr(oF=8<7LX?4l2$ODeJ5q)Fc; z3&ai>laRPn6uvE&YM$)yu&c5`VDmr5`j1gNh1SKm7KF0L+(Dzr{@7Wv8Y&du?Wt&v8b%_&;nX!rC?pby-!uMP6 zpC2vIz356`+ytGwy5PhG-RDH=t#<4ZDu}haNVnSUHM}UCe8~Mts^cW)$E^2+C#gJI=h4&G;s~fj@9?4D)YbZ&;GAhrl?`5$!7V@s>hFT;*wYqEq;EQKxDMl zGmiP63*+6<91Ib$=75nD2ZBrFiwwK&nl{lB#FRV_Q#uG9+(ODuUlII$R+8X3;5 z+d56=`QkT^)$EysU!_f5zVh%rViFg-R3m&79rBflxD%I>(YN9kXPur*`nzh6<@a5T z-TV`u(|rOS!M($vBv zc<~E$VbglHhgBl!^0o1XQ>IP13vM_WK?a!FW$v*tLfTL)g~_`=Hb!M%%bUE;e$Ldk`x!>ALPJfGC<_C0*=4gM5fq`M=p5>3Nygf3s#nrYhlsO`H?r{2(>5RywkE|NJ zzlD-Ok}qpI8SU}5+g|z7{yFo^b+2}~<~n0Dj1gN>f+P+QSuJsK;@1EMi!$A#3X|Ak z)AXgY+7r&tf-*l=1)FeV%Ao$%l(guTxl;lq5OYRO>f^Z z!xK{{+?9JupH}wJX$Y~)OF~baC7~hYe$2qpO7X?>{9P4)lHR;oZhglR`HTs6q|_o0 zU;oW6&C0gbeKAZ?*2r3-NrlHR0eKEi=ZI>v={>x?xvzhs}lJUC~Ka zy7`_yn=^oSaqRE)yAw=nPcpQq*C3y8gPd*@d*BUdY1Z9S;{UCRb-3oftol}rbyvhr zxx(Yl*bHODmck%u21GWm%TxKpZ4=0}W!AA@Y(GCSc}uh0Su->cVC@gWX_j_p-MO zgMx*D0smeSnx=`}{z4{`+}^04UOhuj(DL^`(-|#OanwA@3y{*poN{;Om6NyG*p*FR zUEboCd-C}ILT7A-F=9(S5O0IXhU^7X7JW1`+w(D;JvVOOgo);rW#BXcJy3*k)fQX_ zihN^Q+LJSZJxS8@_{_p?Tu6?IgYlL0361HOm+kqm(d-Qi>&*hgN3)=ED%ekaq z)dk!-oIVAmHKMu&-Wowk6I&)2pRbwXuT=he%{%)zvzq>+^X#3m8ODe$^?*_X1WSA^ z(MWjVw`sA%!jpe~Nhc-0`o;p9A22feS>6>G^kFsY&Gn0a_$tnJp0&+J7!M2Ci*ZuRBExnCr;d-ntP)Pq@b z_>}UWbhCCFF8E%8T=-y5Xd1GD_iLWaI1t#pCN9BJx^DkdF6Nmg&e#lN#Fiu>i3~)h zO;pNUeeZBL$45&6)_u<(%d_yF0}U4%SbVl$v1jd`*GpaJbxk|P!m{%4jncJ{ei5X4 zLcS@JUGv-bZA%OtHy^h9{44N>2ixUEyDr}DLav@hQwRfr%N5wQ1YnyFkWVzB7(p8|%w4mgjTz?K7h#PV4_WA9Kh_Nl(8Ydi_VuvEeg@jG2CjM| zbg>`n^;p=JCDQL>Mn0fuRq4u9A;BXv-YK49v~%C(;eIiM8#%S;GN~X%&+I71wOx=?D~GIGd9B*v85|WN&%6F1s{i834V5L*L1ni2cMp_rKvHMIk6a< z7?|2jxW6$h|4v22GTzCHKK!XUT$n5cE>B?BW+H8!X4i9z6k*-;Uhcfcm;C*e2lj<6 zKYg+sbPpZ8#$lT$0bBY&$)Fwg%WeT~haEs8i4*&p^Ybe(!< zl*}#RzEb6P$1;?;as&AJAM7Xz?O{jGwv+qi=UeZ&pKUQ=`Ta>Rwp?+>W*8&3Bne7l z5L}(DEVTK6ai_PI$HF@q`sdzOpN({4F)}bS5c|63s&m`}SNT%T-W{4U1<9}F;%Si3 z*o`j2+t94qp5jy7U2p6;T=k}%@0mkml`OMTc%XB~B7u`o3>dVVO3^~%1*`C?^ruBYzn7fhQl zl?U8HGKCEFvDv4xF_}R|0GZ>h*qAIJ;_RkY66Rn2Nh+{~bT))3&8c7YV=2Q&qsW;!ds`_m)#TbgBy(oX5L#5Kd<+( z`_nfn9>&3EjT8=c(`#K|auE+Tm?C06Ger4%Q-{y?XFh*=C29gFqWZ_gTk+0usc{}z< z{nlUk@6&Czu1BDC#FiEZS|y~~B_|kIF7Vdek-zl-`|OZ-PX6hZrw)WmY17Tr}CVPHQ!Uz zdT7JsqQ910Mp2+G3h<(Z-FgA6i-kD6oGM#h*oVoW9*!X!fi|Y!61PGHUTv(~y^*7% zY}MtOIKqj@`qOpp@P=FBp92ynO24_Z;!9NQTEmOZ*bHODmfRo-2t?j=nbfJ5Z)#;T zW!ttLuYTQMJ$I{=6N{yVnWbxw{?3+ZcP>9Xaz^U5mH|rylNA$qcG3hoWMg}pjmZSE z+JUv+l#R(0GGxOhD9grV0Uh`YIqjYFbar!vCsW8|5rI>8qt)j;;0Q+<>>DO2hu!um zbohpa%6m0&q@3#AVJ~YH6%%j1nX7X~!XqU9dJXcK0qod|A3L3T7XF$GPItED{%+Tr zw^7VMXZMrG&e#lN#FoZDX$FET(o5^(PE3)lT^<(Jwp>ypLH+brCl+&K6SJ6|`#ygy z{XaFnDC%3$HQS3O9lO4RQx0^mCd=E2Y_PqWENjBxdo|e|SmAp$nJ-66vmEv;VBnkT ze_r=~*|pAZ%ahbVdo|%@&R`nWVRw*+?$xCBunrBHGl35-vD{KJzg@$U6SJjBv^HnO z>W?_e9EUV`bH+|b@wn=Qn5H#X*3DRuKYiyp(={)iW;kOrj1gNJgQOY|>3b<5K=w`O zsr9Cgts7R&JnfRnMW-ZLMG3yzm=Kg#rEie-NWS3<_{}bmbmv-b-&hXmHe`uwOlsS>r$F9^>z>hq_y% ze}__Q%!b{i6?TyV+L+C@xof9~#NC=M`KQcCdba3hxAV3y=#NN5q*1 zV>65qTatt%G7x!4{HBca$$LE2w&qK?g+JK1&Sd-os_4v(zSOl}J7IsG|No`NH8XY` zH_TB?SdE;}a89thy(4k4F??{4UA=ex{mJ$^-|xFB+*%jDvBB`4{e-8rbZSw#b3hXs zJyx~Ty+!5lu~obIqSVQ{bdIWDQOEiW?&(b=oY36sR<%2<>z8R2zRlA9==v;;&U7tS-5BINyoc#Ke4IwrTN}e;a%v{8@ zQsK>~?eH!GTb6Hd#%35JwiE_RF%aDSEr+j#MbePRbu#-U z-UBNeRzK%)VllV0Fw02ze)qcCmB=20kV{*S=5O~s?ZSp!vLK)D#_qdOCE(Rywe())`{?fm z{98@R3|0Py_NdLxT)G@b$_X$*N;&IupU!@kt&>$y!*)jd=(=Y!ipsj3u^GmQEscR3 z4#9qsH>UqRv?C*w*ZSv+gyq&hlA1uIeZKFP)F)c!Bp(X>N=hkJJip)XtP_i+k)c6dquP{fYNsrkWOf~{ z_2%9%^9-vcWRe`x%wZPmhVO}B4~b`EvV<%tWSgk)URxvBt4-rV_QhjdpG=<@L`g}5 z&d0&BjBqfe7WR-z=$;7D*Y41%d)`{$BQUj;cd<;7byu`@Qq7_p@*P&$F&9Ssgz?_UM|lTLg+nKz7UNoCy) zA<#XC24;yZ5)%9UH`bl(-8n0uxJ9^=_vsRFYQeJTls&8$dC_Ufx#h7Z`qg`CyVqIg z_3-|>cFrec@Ruz}sU>VViHlC@lv>{3?b@xi;F~$q|M~~Y?zt!C>P5dqPAy@Nu$L{b z53F$xDmHF8pmcSi`u2GdezVtXamHpCBerw}Nhu)mQps`Ntv@yAFge(sIV0;k037zgb z^X0T{eW^hndu{)0{Vk0D&-6;1+OU)Q35Px6D#nHLlvGMXAmM~3-kMby>!u{cm7T0| zX!814*JmhOuOg+fCmf5vr;ki2V)@5?`)7Q`7vsOaujgkvV>65qTM`2$83;aSrHWjj1ip4=9=_cpkgfo{}ekNN_y zl-N)=>NT-lu6S{6iur{NmsQG7<-5G}Sq~~^;8R@eBzL&!(w&OtgH}qcRN1IUohdGq zMscIzX^$s06~|4jLhjrSZF#JH?lsDoF;Z%Y_C#tFFP-N2Z!+iIjjjJQ?#0}l>?6#Z z@!lDmVT{<)6(psANEXA#zr`yUHZ;Eb@|>Y<*W9b8GIu+%m|9qx3tE&tTI&7wRpB|` z-ShRBoUAU|%>j3~jUZ(R@0WA+|llo=7> zNm*li(aRZ|VT{<)5-4pzuwpug+~M#EK`L_#&*dJd{&$+aV}%ooxrLF*s*gP){51h> z1v(3-$4`saKJn^w3Aj8lgKP_DN&L*l1iPR?U=RF)2KIQD&bJ3b``#a9w)yn^pj^mS zyTg+fpzggJ9r$HnkB@^MBEXzw20f~axo98sFgF~FE%uiF5K(FGPUhpf80>a*O69t! zcb^ESmiU=1fzyuqq{`H2sbBkj;Dzj>jWWOHIAb%65nH-~q!bWY@^ue?YlekT?a3llTB!2U!PxAHMexNI zXa{4@lQRDydSu&`P&rw{%c@C=^JMhbpp-L%Ddi;gKo?t(elRvAlS*Wz943jIHv-qK zN!ypXq_MgyF6WiTht-5rPU7V{&!~)fhC(kjR;B-qd(iJ0S%0d~8Jl5@*wPp%%|NhE zD{F(s9@%f_Pvjb=o#H%MBBdh*x}Dp?GSdHG7tb*@`>r{q*Y=xjy)pOuyY-O87SIJ= zETE(Kq3q-}gpcKKTXdm##g2Ec1inW z7<8u|-P6z(z8ebvjCU`1$ZE$TB)xprbFNDh2&bVG@w;C3pQf?KiSPWsXt&j7S2upn zB2Q;*hB0DGZO~X_U|=|~{n)(OoS{3?6SuU>1Trs;Vd#0_#A0k|Z26--VTtwUF#ewT zuhlyiil4TX<5vK$KZagP$e#Ma=h*hO4{omQS;`)9G4siipRdg?`HrRvP~akNcqhGN zVNc^a=p@#>ZOy)xKeh4_hZIzntg4n;LpW8W=}u@AS}#9UcD2&)sq=Fc4r~lKpD5vs z%`ir6=?CO+2_ibF$bo*mC^b-WB<3uZnD}e9?Mq*4^6{JsZgCGG{1YoRftZ#~p!P zX71gBCy&g{HjR8cmp9~G|GW9y?uAVm_kMh+ z)xEUG8Jl5@*pdVd!~Q_>tJO+ZoLDT4EKEJSoVW8!n$-o* zJuxSdUr;_YV%|LPDSgyEUz9ydoo&M*4%>IrX2x>HG&DJR>S*GX}ak@w?F!)UK-KU zyQ$E-_l#fb#e%iY*bHODmJC733WAT69GiEz_nXtqGldaPd00a8y1%tLu~?d$81dUS zy-a34m$kFlb@IuEzB7jx<;+8=lX6-nB>v5I2syq#(|$_P;oM5y|4*vTMpFeSV2PcK z#MY~3&zbkT)3fJu>cQKF4P2d4R^2&k=H7jaBUR)aL`oI*}-}7z-;|K?nnU((;YICgUKp0!8MIAb%65nB?2 zBpMKTdV!j(+id|)#zRIY^6bm+<>uHe1Kq!CY4TqEPS%DUlNmDJnr&q+xc_u6t7-!% z;V>COrk~l%1KF62AQJ<4R^L@Nuija2=c^p_WX0d~=G_{->se4v1f}6b;{bJoXjl=I zXG2%tvFFS?EH3kliBCLgkt` z2}$B_WNbtCW$r#Gy&LE7Ze=&&;oa)ES!or~dMfMYZ_1wY(&2dGftcHae;|+OW^m=w z0U6$9PvhdzWv^mi`deLS6cwDSsZls-slsPbD=3>*8bo&0})I{&RWEva|s zXTk?jXKaQsVoPn1^aCPguk5_>#AxNL2(c*fyXjB&wog>ob7D5PFu1You-n4>e?Hk4 zNlWndXqnkIZp?xtA;@w&@U8-5$hL3x>hnbGFsQmDcK2n3s9izGtCfPkk7TB9ECk)$ zi|9&KzaVjk0nrN{hIcu{Gw-SS0+!mMC8uuZ2eD*tyKr{pAslI_#tL2zRep=-TJmHwvIUBr}{*QR=#A0M% zV8QCP?xg+NZ7csrXS{IH`*LXV@n#01Hp$fqQ?N-cw)kT~=DT-1KHP6k8DBemD!j1gOsgd{Q$`QQJnsdmAk`O>M!FBT|SE|X1UHpP>9aS~>=kHwd?-A*%Kw@ z48J0(VH&Oa?8r?e5!qJ;wKJ@r#Qd%N{ZPx7CEB1H<-iK0rc%RQco9{%`1G6T^)UwD zUOyMya+e|E%9LG>+#j5=8ODe$je*h(1i!X1zqK;(VaR_;AI2{e`X8(-nKg;jNe4F3 zm595hc=F*}!I3UCW6x4|H25!irKRxg;@0}L7iF$}le=+4pH4}rX&bcgq3@&vJAIPS zbK8#&e>FQE^|xf&HE%w-QtHy_Q#cBrW(A}q#Jl*jsaD4m>-f!Y#e-LsMSI9hEOW+Y z7$dgC21!03a@*dh$zOKI9&MLjXf-3C^u5G;Q+-eogQXkK7^VzgBaGIKPuT!@OBZV<8Q?@hv|`S~vdB^P>}^?{**O(Z4AD)H?FrpA~#NkdsHNJ-i!_ zl00r4JpL_6=Z*cL>g6hd42%XRZL;E=u^GmQEg^vt1_ZBOdO?Cz)jl6}*hZ8<9I=W0mI*<$nmfdXGpgLREB1XzfPOa)|U}LGUx%(aXLDG#c-9yj&cJ~Mc~$)ol< zA96x#Ux7WL$y;$}8WuO6d6Iv|O}u;kJNHEukDaj@#)vIRLJ}E>-1jMd+vAT4lNMI~ zdCT_pDF2+QeLhYsCT8a5$BcOOUX)w^I8dm$dFiv#j!n!_?;u?^$U-j0OTBDN#t=5c z4-G`G|CI_GqY21t2A26kY>dzmrOw6^`(7HQhc#_kwChzw0-NcVyt$v351+b>y>m9S z*UxtF7xertI@M+GX9-7V?0)F-p>SnTg50~sQ{=CP<48lDZ;!72B*%Yl0Or0=)Gzp4jYB{$$@4}150jAQ$WJr0Lp*)!!*nOdO9@{}Bp z%AVIcH=jRIo5_!yZhBPUWe-ZaIo@$s$$KipRejNm(}gXkGl+!t9CXHJ7$de622L_y zLQ(PK7T0e=eXZ_C-YgdoXHe<&kpfMc8kn)}(`=ihHm7vsv2tM(l~`}?hn0okbOT$8 z-1`@P?i-$^$X+MpT>ic?lYcRPTS?^n+udzR@3K%z9NH~KCcW$4Ck|bTJOsM#TN&2& z?YaEa*^oi)x61N}X%3HH9wnS|`r=y6uP5>x{XJ>f9^=->hsE>Tdu!)9V>65qTN(o= z8ZdEg#XgB2D)VozT57t1As{UAt{4LY_}n*(X-yJBOUnN2ovf&}cK61+yBK^9>4O(% z7(r?(_6g=}OeT%=q%JIgiP#ga={X8mZEpLCCKYMIbu zzQ^OpN5yuVG(W8_cZYf-b_T^nXKaQsVoO($fC7;zP2w*<)MPZDdDO@pT@$bHZe{Td z(43fo#qyw;%~8u9FLDSMuTNF3|6A+pwGTYSZVWxtW>Tuwhx)piO_NMZ4k+h;yKOKd z@6DpWL%rq8KB*qhr7?*8yELtRR`H6h7XQGkXF5yL)_k3*0e|U1HRMz=X%V*CXF|_Y zzvSjkH`or8@svxy+zgSgo6F`Ghp}b)PRh`q=r+>D;M_ zpu^ZKjMe?#|GIN!-S=Hr=bq^J`EAKM@2on|X%mc)qJp*R0vjWw1Yw_2&BkO5nLlMt zf5gUQ3TgPVop)nnGKZEpTsPR5ETE?cm}D<_=Dnpi%TjEYr%yz5-HgXG?*=8%y-u1k zl^YTW!>E*rylNZ1o0(DYRYAYMv+3VCZ5gLfuBpeKo~C?ybbHcQ-flf9VbK%oe!h7T zne>0o2WM=CF=9)3kYEIn3!4fL1RZDIX;oQpnn&JE*gri_&WXj?*xc0TnZmr?Cf-l> zm2+I`XAupza82?AwPvu4^{`Jnjccsu&U*IB6U##mtp9&>@7D!ui@3L}eN2ObXxdZE zu^yT=g9k-Hbgf8Vty}5mwrWM~>OK?Cr}I8Wg&`M2)3vb`L{mOJJN{>bNB*A+JU&xr zhjtlWcJ8g6;Ec^MMr=t8lw=@y<;i7_(pK;uENTrdZTZL*>#X$kg%gXZnWfowX=Bgl zOXMa!;l5@&yJGz<{=HUaxVqr%Gg%0C!9PwpVi5kjFyV~Hs@HXmv)kDgmwTfWKD3*W zpu=!7`%Jlk>VmIZx+qaFbYgmPq3a`t9eMFS8?Nock%ngG!@J;9J_V>|p8dqIZN}=h zz$|4SlMBJ3tsTzT3}eKW+92r%L>}6j9N>M6$@{!$&-^bNuI{TBVsZsHd!g64G8_)X zb)9QKz0Q?=4?@nYp38CRgxPbiTMVks*bHODmU=*`0fM=H zf9RZ$sL(TW+J0{d&!W@s0^)xG?w{JlYBSfqxEVX!w)J!tB?|NWA4b^SXe%{BS5O@-=7Qa zWs7o0(+ViCkv4@dVJE#pn)*+s)t2wjp6k-w`Hkih8|T|C?joF4mN+$B7qJQr3l7ux zZqbs+6!1nQf|J)7n_-ODQWePI5Ul+7$^C<>4l9nmV@(YdICVkw-RX8vubGL^di8rJ z*_ccqV=}C>0_UrrNi+}iDgSrfHaS)QSbxFyXcLt5G1}!}z<*jS(#EM}(unoyZ!FHN zd?&1zwTQ=fu26PDcGvn9**Mb2vLtwyXNgn#l&Qz8{TBBf?JboFQUCVl|Mp|;&e#lN z#FmmEX#+$~-L_LJ@cudL=liX1{Ma+$Ig9HxS0@%jV+&)W%XxzCfv>W*%=lbjV6p!4 zf{FbeIBS~~)?Ggm8;i1|b-lSP^ZPur4_|zc)rXQoNUv>HgbugbhMW>)$;-@3y#J-@ zv}cP5@ISp8ptHmYWhF6Ea|9`ctZ4ByT0SQ(D1OPxw|Q4oggjmuJvq+hjLk4cY-tIU zHXwL|+}wrHi{c*sTov)~6|eX9c;>mrpes_1&3T?o)8>uL%Vs$dtrY+^+{-1Tf@np(GPJR(JN6Q(TVT{<)4&H_Z73}Ocf^ZOn;n^S;mmZ20gSMzAu0*VIGTPN&m zdSSIs8rL)}z0*MF0xzU%8h&0 zbG#;l_SPY0ps}=7*wSvF;iyz+#7BO~-;X0{g^uq$|_ z{G~ua&A`A;WLpKLJh`qm@!lK5THbSY&KwCxHfq`_6ucpvLN*!*?{!*kr`GDT`pRpc z>+}2t3cs9s;*8BOMr>&b;$RSYnBDVy^l_gWtGbvL!9Wewm%+v>oS2O*3>X&HrYH5P zWr|E^-JLV9H_gRst_3)O7($8@rs!@qCJR%L84T>3IhPCd>Fu1Z@65g~&!X)1?k}O$ zi_-^J0%6~*#0PdQ1ML>E&>(>vE9vx9O7d*coHQ%oj`7i8ZcA4s!U<$^;JLEGjA!*T zOI8-1KBvAU;^5@98Qsp<3}eKWlpp~GBBOleAE@;HT;9L7-|6J(j7)W&KVhKrXiQ9> zJ>|W@!@7O(F(VGKhauHZtG|_-LpsXPrMFwP*cc&e5!iAs!WUVx3cZ3YvSf=q+mmMH zyhui`^0?g3dn>&U|FJRQ2VL}qsCovx6GXdo!@ku8y2z3S>1LLA`m?#qKObc>bBz3K z-*SIjA%{KTbhEXSqjsJ}#2lZMOPa4QxD+6-$~9-nVrOiIF=9($pcDhaPhFgMdIbF9 zxYa21f7z_=J+f~mzIS4=G&VP=IjnrWElzv(Ccn}Z=U%V>R-&@@8EBac>{1oBfLm-# z#*k8mQF{{`lL_QpX_kyy_@yfB+mqOs%pnaJ*4)i(Oy(KkDlyVXN9Mg3W9?6ov^Q$~<{$dPhv;vKp{0|w%;~Nu+L|?a&ObsOMA5+J@YzjQYKyJjLk4cY-taYnn2_p-jvnT zO)I4Ac#3Xjl}e_&7#{C*VllKdG+(dXzsjz9rPjBMw##uT%Veb4YLmd-YIA5wv~$bD zFI%1!?XQ|w==saHQGI&1;K|3+MsliP-+7KY4VXpxjZ5#{UQ_dN=ZfM7=Sv?PZ{C73 ze~3L*?EKhU8u?pxV&QkKAB}7N9RGUq-7ZmkXKaQsVoN`u^Z>z)uB*QXdFm9_b9|Rs zxbr-}t+}786N{;dkwpjlkz0(VT59RvMGAJ_$lkIroG}*Mf-!+MYh8b{F&bk~%=-+BJ+`-bzthnLU=wSi91w=EIp#ZYLIV10&;8mbc!W3JsjC zc)%xka=dV~^XY)u6zyr-`v$(Z7WbaE9Co>3>el+xQ*J zr`b7UGmH^ik_06&2wto3+im%^QdR#zqk9fD>AEXs&M0$YF*7$dJte==eS=P*yuqef zHis=tA3gk8yA3kJ2U*L&Zrui7%fNmh6uy>$nfogIqEpsqvtVl(*zTR&9XsPh(U*U6 zODn&KJ_$dx^40QJ>rv{n1NpGE3?rhIL$&&B^SukZHRpAe&p8(plkL;Kfqi+858*^~ z;NX!+vxm`lOEoxN2+CG`?^BRYP>gZLW*8&3+tX}JCXgOEYrQEOlPPqu z_@P;BOcu~KbjWGNXX*WiK2Kk?XG2S5+|@U3d!BRE56hHuXbW^ZB+J5l*y#{hdR$aX zIoxgc*tlOt8fZNGrn_(A0xQ*A+YZ7h=g{vd;Y}*Z%6jK6hQ}GttJrzZeeIIZ&e#lN z#FoZDX$FE74qmEe9o%8qICAQ)W|Ms^2WA-Wi)=jM!2SBt3x0#Kj$I zZh`m9c*{p+G!=nDlZ;8H<4lN2r#F2Me^xJ;f7$P~ z#Q9Ij)6Xw8{@X-26&(+~!1`%^U8kYi8|m3B%1$)~C+rT%J7Y795nFl#IUIt|-P2iT z;udnl@_Jors@(pI?#f0BoLG!Z%uOHe7c71JWq-%T#MMq=I(xg0T|8_;IqQa8NB0_U zy$vPE3GL)QY%S>Hp<2^D&#M3O_Tc*UeP&4P_M44o4n1+kW*8&3Bne4mAhM(3)yA0{ zE~n4w$^9T%bLFM=f`jXvSPab#Otvn%?m6?8!n$aw`KyXIUY~pV8*?VOGj9lK*s!0T z&c&3(uMeL_Hj#g+|0Br@`io9gj2}r2d2R_o9?MUZBlxp^(}w@w?N)4GUuGJ8ODe$ErHSo z1mAvf_h0g<&$$ez=7n~f_C#KE_G58kHnT7{3Rr9Ps7qhfGF&bxsd?{jgE;dTlmv2i zCp>{LGh4ac-hD7|`y0oTEAk)Qk$2z!PCti{9M4qbf3j(;uq z@Ge3oZ2S9;BXs7Mt=~!v%}X~gyKelg2RVV9W5ia3oPH1|_x5^p;H1PiZ%pU4{P{j3 zeAe+cXKaQsVoOSp!~r6=Ub&)vYyEZ~##{02u{&>6<*x~y?ZjecW@wO*r!2+2z-E!+&+fxRbne!0pF{{e*P94lO?2c&er(aEIx*z$El^+v>=pU(NSZU z^wy84y=@8>NU)#(0^O^`ru!MX2a;{e1x}D>7#P@x_W}u?+TPqJ`8ldTIDWp_FLdqI zF-BpO3x1GN%LRS-0*TWPR>j_2^5M8(QTRG%%XKcXWkOG9-gL%h7$dfH1qoUZDKC+B z=H{8U8Jqtlvh;m8q>|I+C<(e-&dltjCey@fapAn_QeWH!weugW{ghvdQl4DmfR`r> zOiA%){+w&Cde7dHaJ!|{JclbvO%HVYAYvX9%Xkbsya&a8NeNn>jP{@y7}$|3oORE4 zEZDY<_t6fv2iLxLEbS0_C!>v{JV8n!mjeGilv7U+`0-Bs>f>`0UX`um$~$_-8Jl5@ z*wPXxZ9s6b_-PgXDs6$(@|O4DE2E_@MU{!8=??Bs5{N@Wqa&S_V8tUtb4v4IA?ud#+hZ^qn>B`0xp;*hO_Kc z7_F5+5kbbi3Rhg9Jt&5id(5NQcf4_b`0AIw;6}?AyH&(=R$oO^44vS4a9lj2W{aOK||K2$b39En8e1H_K4xhch+{#F{knSbUCwa84Nij^n3H;r$~@7$ZyzWr|GEW#<|#;rcR$XVhO?_DzUl3u*wQyP1_T*(h-Y=$vnOG}Ud z0Fk{fE^WTRcxC0kw|X_d{Yu_67T8ESv6vbgm}Rj@J@ynTeSF8&qxj+6_j!8^94k>4 z)T~|&Ur@s|SpdGEhW*xN_<|ZHtz7tm8a575_<|ZX@y82a=wCc1zP|CwpKHCF5|+$q zFSC_FNm1~|FZ->t&;>Qbt_~j2jo&9-^#?7^zw8w?6H0p0x-jg>xgEMVQq*l7c;olR zt>~~9c8ZZRZU2TZ|38IuU4o_Kg9Fak3}eKW_CRR~f*&e;tSqz@3jJR(!HU1C%R$q( z)E<;>pbL6f)7fF?4Y65$Mw~aabprgnA=aayRl<;Rh%t8_{JbGn@qowdCxrfW{xsT_ zp&b6Qy^eLtl~h}L*Hr9xSz+f5G4VoAHKXq=Hw|hk-g7kx3PC%AS&nQDE%x!Qo)FcR zikxchCc$eelvES?q+80S+0ga=lb4xHx6`jS^1e9fjLk4cZ0QSE;6PGA!7sX7{a^_nCa! z7QdyutH~_g$9MHMsVC;&hI(1Tem@jeJI$1%=Rq*YI}JqSHYHEEJMHDE_=l(Yzuysh zf2Z35N2<7AfmD{r+G4(%AN*3{-71C{oCpbI9T_lV!hFCHv9h9iYMoQ0G^o(7z*xf*|B-^({gB-gTCwClR9bjKN+VT{<)5+rqi zNXbB}o06LHxVERNrh01$?sa0ZFfuY%7f-A|e0rHh*yYnp{<}@NZhntj1-T=Q zG8Or_7}1f&z5nfePsOa*2PR(HPk(7uPh#@l&s)74B^3>s;g~_t3Vw{V|Lu2+LKb)8 z^DII8Xr7g&O%69Fy<{SsiXK1Mr8tL8|LMtncV_=~w7ymRIBWfnGG}atF=9(^p!5U5 z;q%xmxh}PT$#4>N;WgpA(ta!Xt`m!qk&%h=uNBAMd{ui|XY{Y}wa1A`m$_rKsneQa zf4b9W-Y4hg1#(SB9A5KY>SRU_1+XaoLb*{Ubzs{d0vwGvL<%Jc_*bHODmhvEJ2}GuETrof4 zXp@A%%@;;1-`%{p@ki$y&}BSE<^}F|9X;0hz2!^|-K^xhF4t?FT|KzoGJ~{t*=+aCvWLJX+3xqJfM7;8(7Q0pL4dyM^k@7FBE(TQ;@k zMJOw6=xJU_qIRu)ij^=uCox03gedbiSg1B0#^|OjMn_`@?8ODe$T|rU` zh}=4Rlh%g~z1L1^Bp5QgEjGSm68i{rgrd2LolAxm%jB-hO=@@kryZKN^JPVC4LG$x zuZUx_PlaFW&i-yb8JRlQrtofW0oQJI1VGP3gj-;{ipS~kp6%e$Shg}?Co zET}XhgPdBd6&wCpY&(*{w5C=uXy%88O~tNl$f@Ps7woCU_ASS8{f&`JBJQkk3Gvi< z*LkDlfipJ47_p@*P&$EN#jxY|5A;X5MYC&aT>F$WO(;<@(}~5{(8%zwW7UfMMjdPO z@aurXilXVW!UF#%gj35$C06rI|CALI zzH`++o%pMQfopE|@+xO+hB0DGSCBvfkp|(S)+v8gLLEg-R@!uz9N5w7!45h>#KP>O zy7Y(U#=KJN`4dW&wd`;W;Zr@&Gra9J^ z?JoXt|Gf2McWB=cXKaQsVoO($lma48o^nx7O|3u4H?Mq-$%RX*b9HQ@otO|zF3)d`9uHZWm63`yUIT;v_;v&k3HdhpI;Sg|5HT$(Al+@oc2HQ zT6aJGtk4^0Y=$vnOJblT1Hr-KU2>Tm{gmG@9XM`QP)B zC&lk*Z(f`uKL7J6WpFWL2-(HPy66uZBV>Iy>yunICJSf_=4VBIQjVT>ZcF#BTMNaN zlBIfh*?U+~5)0n>X~c{H`_Dq8c{N{|!Fh*?23X)JjU0D1V-DT>30~vXNjLjk65y?K2-~|=G zmoBjHlX%+luIFpO7M_FqEKZr;oc?(jrJ>*Z2WnpO$!FXDA@3|7FW9H0wl*zxW?tiO z860Woj{s5{GS<9$v9Lzy9#cuA=49<3XXShOUN~bjj1gOE1En4amMJ@;yKTOT{+-@N z`}n&b{HFGv@^)f2F*4NAw~(4uCpJYr;m5qD2Za)xFWD-7h&e#lN#Fq9z zX$gW~s_|Z3ptVKi&xe%1-?VS;Vm%?m3hqWjm%%WKS^jZth-EWgY`9!;`O>p8#fQ3Y zvRobNanHdN16u|&aB(j&Ux@E|w${em7g=h5{nzdEkKXEpT-_kWJyShW+`sLV73+4N(!ObZXH}FlHp3XPr4mTIgGez|XP?(wpB_11vnH);lZ(sGH>}&8m`%)0 zqO}emVED3iRk7j}TZNO8-k$%?djZm7fwp6jP5|Lxi6G(xkc?T4_P6I>$@^J#MrO`s zzMu0^LDX6obEWJ(T)LGNp$Oa(&5txy-4e<$-mJ@VW!P?)EU&Y#)NgYZ>w?Bb&e#lN#FpAXsRx2T9{aa_agw&tt|JZSTW6`p z{90bI(}~%_(o{RnL-DnPe^gBK_Y)^F`*Ot|ywU}CkzgnMGOd9h@W3D^2|wV0gKf^5 z>)Q@}WSgmU=IY@zf%8mPSXiI36KcM2ux*7N@W4LWd|_aE`46@q7J2Mn^!{AIoetMe zafRsh>z%3dK2;xtyl;Sm?E|d&!htAoI9LuF)q9!8#0gsXl$qGY**^`qDU@O9jLk4c zY{?3eP(Y;7@%#51SiC>AnuO)g*%4aomThqhc>_Khb2l545u}V^xNO75WCA%@k*)DH z8tNDv&zDK>9<(&SlR542qWFf;M; z$K~9ooLDT(jZK$JT~+xM?5Eq-?zJhEp9NjPiKE*4W)mv&;YG_o}Bx;Mw`DJ$=_`@b&e&z>T-&e!`$ zHn`G)-ucJD8-VMIrNE4`xyu$Z3Di!_;CU>Uy1A0g!h=37oS{?7aPVeHgCc-|fjP@e z2FfbhCktV*BMxyuUc`A|V+7~8<7>B;TZS?-zO>zsIjEZVy9H8~Ko%>22Y8Jj zc-7sbI}2VE@1 zo-@z!-}LW(({&}%?=-fYQ95UTMD>3nj`YEQ6xNI4;9a`q)b(pM_mv{E916q^9u_*% z|D{{a8Jl5@*isTGWk9gERMJ)d*yNb^zZfM{e3KuPS3dA^Vzx9h_SRBky12ULG^@t~ zi-{HwD}A>w^oJBCka1rQ!FljCne1V`Y)lr=$%Be@o-u3l-rR8edZOVur=MZumMLuu zrH4}0!y&jGx;~S+Yc_OWB!S~y;RARyt$NNanfX(F=?>Qro<&FEH!w%eD|&kYIk5%8#iA5^K;HI{!-KL{kvR~Nw(SS&4#&CRX9zwj{Uo~?i6q4E=!sD$i>NEZ`5)KKZT|c+O6OvtGam|c`etmc=>^%e_x-=-e$La@Yd9e za0(F-Ilg9r@Yhb>uSebEuK#uxp7xBzz~330VT{<)5-4pzu4L0)5EV11Oz2Vt>0$io&eMDsyc&#~6(Ldz1iU^i%OLu}K8rfH&o zQB%t*uT5gjx-^WfRrXCO*Gyv&ivr`q1L<6O5#V>++y8!*cqE) zjM!2SB%nZ~y||RQ;FXPU3le`U`DVTKf1_^xC|LR2_gUp}$Nw z_fM-jX-4@@GEiL_;dblhi4UW77$~^e;O!a?xtFB3YrbB3?|tI{!`zB@$IR2-e>0Bt zj*G*QTI5yWb(qw$YPL;X@z(k8)zq)|G*!;lD7bn#%Nd(tjM&l@$l(widtY)HJvgU&{ap*2CD(Jn9VR1aqEPtD#$*X; z@UUxsoA{hLIQv%5yRsa;Yln=x9i1za6p<6iXorb`0e^>yLs1OY@I|hkN^DCnpN%wu;+tVw}{wf=RixX4G z6ce*pH+(}0dq_NdLkWknT!`063lS~H!_T^9k1d&@7Z!N=eAD2sd^nUXpiSaITltt6 zEO2MBHl88(U!&6dXjkBdnt}}E)S_GruY8b-6GhjADNBAVE;Q$6@4NYRW95SrYJV*I zoUs|kh%H@#(g_3$%2cdulMD3d?%2WTQucdmz71;{=msWp!^2YXrazcl-aOX`wb{r# zbM_&TY)$0JNfsX&_~ayO^Gf*SByJZc)3O6+ngw_uS@8Y&^T1npp%oNw{nI+LQ9`?hxPErV~lP$9_-we@b}istB)Cw z6PoHB>cL?Bh2NqBZr7MX){8Ukl!V`+!#=+Yc8d;6%VJwwt%NT*f@N=} z>uf&L>ov7_(hE=%Cr$xm9RmXchx%678k!(==o&ogEQ=WCNkwOGbb)5uTDelDIZTUP zYxI}K2uC3&6%BUmNo6O`Wai3Wmlqxk%~z8<=cKkMi_OLvn_-OD5*0Mo7#JAzBiDZW zwc^#E>+}8z9yPxH?aZq^PN2I2P0cmfS|dGA`hWH*)%;N_eg6pS^JIO{kRKy-UBoRf zHYRgOdg9Q0z{X?=>Aka;O0Y3mLYhG=XTDrs+R|^=@Ghq@V8+ec9jn`-ubP}gE@P;Z za5yx7aX|dUGNm564{n$zoWmbiE}Uvv@6yWot3=}3^kwrDYyKc794!az38#6vqsEkL z^9*%)H!ED#@zJ%Ju6EKHn_-ODk{BeALF9!g1$^f7`8RKMeiT#w0{FI^XvF=yf zL;_wZnAe7(T&Yfa+n7Vg2ztIe%a1Ft6T_=Dp$P=BI&ZiP-QZ{&msYb@$5vGSU48ZY zJob+Z_Rqb*hJ0uu2lfP_lbDopGWqXjsX)n9`@-Lfw68sJi;c$_n_-ODk`gFsK=4NM zb1j-nUZ`65oGG3t*IN3b_Gyk2i;1PN`Ff`b?GDfSn-0w^oc2y}lbRBrh>0fyJEDct z^A6s^VV=De-ooL~vx2v9*hE(%mS6GY!9AD1D$pu&m8%+%1NdZYCd%TveJ?foZq`~2FqYtq;MH3oOQ2+T!r7)&=fqEr6R zLhQ*$hqU~5uEnh9{@!vPz|>-}aS+Z$kd<1Zq%UdYeLlHgZI-tF`p$K7ky~6o;7Bb7 zZ;(>UiYa|c6Ri}a4sgkF%w=<3Ycfkp%o&?ujM&l@D4jsCycN&Bi>DL!UpgYR*+8pk z+DXPg%OUMy$Z80d%dKoo#t=4pWj7m>F{FB8Q`KismPZU zC6-5AeLq9Zh#~KlqjD>9N*UUf7KhPM=q@;R3eJuuYd~icr#NS+0gvQ_DOwg&+cVGf z+}dPKIHeeiwY1wd)$0lwF?C$HAI#Cc@vx>&nlm=T7_p@(NGbu5&1*k}rZdV3uHL#g z+}q<~&acZC-h(PFQ{$V#o<}uWgZ}5wd@}vwdJ)+pb?dZ9t+Y5y-V;%2MJ@d>?{x8j z;K0bApSG@Gmj0o26vr{r)LyN{VakbFX$_xZ=t|<*W4z5GHS;fu?0I27Q7n8#=`I|J z%d{9?3>k|F?SH-U%|%NMe_v&u=8VlSMr_Ftl&m254kxN9iqeTT?y;3bC~`Iako5%Yg3?jSRzrIV#Tqm)qQY0wV)Xd+@@AYrYA zv{qB_m9R>kyPV+{9aK#ti{@3KEFeZ|R-5lYNI91yl=KV z*C;5uxDvVL!(llQem)xVDhv*T>3(`va$=7@8Ln|o^;`Bk^YPaUJkbM~S}a!&mzGbf z=((AWcNSh^*I6gtwmuyKt?@x}#q#er&g{&)S_X6ZS+5C54c@iHK6QK{N^ z)>kG;Yk@Imipr@Yo~`=M*bHODmX;u?14O>5mrrFYRQtSXuYmczE{O}b^-g#@F&kPK z?AW5DJ#)J(mw#~2_vsE>&Y!j|Itv>AW5V3W!eRRmzT^*eAIn)IvAhkQ-FtU#sF`)v zD)O7lw)t%%X86zc7i`HN_4lz@{du~Mv4Hs!xA4X#zoI3kecrnkW%$p|9zOhsRIu1^ z=V}krdp~;irvIOD@~AU5!x*t8Fi?Vl;PY##PMM=Xonn?XBH?KAm(r|f-V4LQ#cJ>07#`tC|ahFb&pbZ?zwi< z;=^YnzSA4$=LFO;Dj^pv4vE-P$PvCHlc%hUdeHIeT;7h{P1ld?_A7A4W*8&3v;>Y~ zFtOr!%2u0mA}iK#Z_YK8NSJc{v8D@XffhARg00-MPSQ-wIY)U%M&)C<)VA7$QG z%?kPV!OV%-+{kzi!wbIT1?RtB{eQ4POw;J@TG&xXXH1ut;aJY0sSDUl%JO^8CF69qhZBEu0&6LNg zr$h6Zj%FMRF@LOV(pl#ij(k4`2U5X;lt5f|eKmg;cY}4yOu^SoFP<#5yW~;oROgJ% zFh*=i36wM-*mUmk+V#@M{STI3o|hbad(J$`jz~~9+Qjs6UF+dZTvJnyS43~Wd3o9M zyPEI0z)cqDnZHbORq!)^Iou|*FvFiQg`NMq)dkvUp+U+~nVs~mdw0^oq%}G=n>VcU$e%tlhH%m1_GQ%r z0Vl=xb530Mt$26q`%>vp^Gia`*bHODmc}5d21I_`b)wGZ&{9StKTAH5uwUU}yYgQ- zu~=Fd7$(%*mStJ$)UGBF)+@mj9eirGw-;mp2GRo}ZG@P^<1F8?)sh?UHLN@mHZjZV zzVBbp$RBftQ5y1ijxj<^r!;ge^Tk$=I_HNBr!CbM&+RyPP<21bmP_oVkEg|gJc0k` zYfo%2N*7$!oxftq;i$Yh&e#lN#FpAXsRx2DzyE&dW0t{>%WWCetDZHa{$re-<-}rW zWNzSo-Dd8F)fO>!LRzZFl)u(arUgo&fh6@DgOUfcZI0TKhSE*QHgR`EInF8G)zOj)dN)~NkuL4 zdH$JI@cceLjw$EVx2pe((IcFOe9vqSTG5*<Zpu^GmQEwzDD z512U1CcJCn@6|j}pPK3n`aJ5?YBd%(F&i5gEtH7%S)$G1Y7@7A!l@T(xx9xNCW4A2 ztbH(l(E3rx#3wNqp0eMVs25$HclyM=_xY`b^9zpeN?3V=r!c#H#H5=b0cZo89q&e9 zvKCtW^yv3zi@20M&11nn4-SvN?en8Maip7|P^5HInP#&|P9jxWFD&DaVYza&RG>hm zGd9B*v86C@k^vK0AM~GSM5uq>&3RR$^tZ z*!6Nz+XMq}Wo86fHp&sA$Hrs=ZTi@rW@9pej1aQco3b&PLU+;}n#IOs0V$zaLQeNR z(<(IDbMgjX|I*J>40C%M*Y!{IV`NB#uSupuH;o?E8AphRC^&Q(=+wlH7GAgcQuUGq z%iWt)opg@dg(#Hr6HY}TvnALaou0S$&7PZnBKRnu=G@CCTR5Dt8ODe$y+OPPB3b9& z*St}(uY6&jp3B!Kg>GvtUFLvlEm%YP@N`&1n&r_Ecte_@YBIbb&1|+D-jHSuHH9~% z8PAn-zB0+bpn3AvybTx3G8ygi`O^462mB$1h3HUcafFpX8`2!~9XF(9*(3bqhQIZ} zJziz6-u{2!cy4|8smptCq?)jc@Ukal_CtpVmXeF%_l(*CBBHM^c3J0`?h+E+bM*g*%XdM?o0wTTwe~V-O%yowc)`bnSX0?4?%ADv z;E8eQ@g~TJ;c!H(LOu+K*DGw!7u|ZdDC?8g7aX0SEz`BUYjDk95tyBbI08MMfQ-X% zXgNF4%=XgAUF_)g|8;UwGRLGR`bssHBd3;#|M1xfl+^M-;mSdoAAfN6I^h zW2r*8)9u@qlWO9Q(Yq~!tvum~ z`UIUAr{Mt>v@A~q0=2%FvUj~NPq~nA#B3Sw&zrTCI8sQoB2sz69{=yy@86FKrhIER z*DO&_Zdp9*yfZe#7_p@#P}+dtO8Yeivg=*1UrY0~SQ6oP@U;4IR&Y8ngtSapI+fX& zOd*RUSly&WOIPr6_Nv(|Uv*c_?$ovwmycex9!&?Jpv1NboFnEJv4`6{)4QB$SGvBz zpWuwmFh*=C2IO!E z7FV-U4HM1XchDy*G9aIO&4vYf-J>#p~|Rb&62&ffA{2%JL9 zA?;O$nl{8S0r5;#9xh4WuGE&bd5m-Fl=N-EYq&};+2mDByf5E-Bi)I`!r0X8fN*Bx zt*_fB3H0+zY+ZX?c5PzMQUB+UK)8{vb zSy|tR!dou`9>I$MS~V)%4O+ z2W{Mn?Xrc8=Xp{qg>a-UA!^6vK#iNwG=-RLtoki?b45b)d;K4_8r}s`J7#YuoI+AB zPdoSH&9Zkq@{9Nj;(j?KRW~wBed~YcEg$R(gELsoPwWY6JTJUJY zzEl4ft6n%#5_9yP{*bDN(vQ)+2TWEy)XKBf`t-MCxwOJFCKq1MUbOLQR0wiv$za4* z52aqVOE|oo^}oH^)$4l>uS%TXpYPT@jRo|%j zBI|ce#)-wm)Wk&KN7ju1x5JFFi~YHNPFa3vtN+SswWPX9xL-;SzCM(_Wd;Z!ik>_b~@#mIE!iaX?m>E_uJeS&J$-%?Vp&@z1-Ra3r} zvL!?=?QZkhn565cY8w`#jGN>{Vox7?FI_QQ(O6fzzQNzHbx+8%uN(hKIAb%65nDBQ4dgV+&hmS$sOVRz<&atkGP=T1kifvdBWayHkxNrd<@G9;6la5xI8pv4Sg-_nRqI5S>NzBNBH>7diZZ!;MV z&0h3Qc!mJsgi~<9YOBM6Z!_lFEs)9Fb5`ZV+J?1}|D3TI#)vJ6fszaaPiEV>Kj0tx zhF$4je*6C{y!XF6vlDdZt$}fcK=n1Z$FsMGYTaSY>*E*vx#JAOoq9y6Zw4VpI&1##wHL_!y zSb?U*s^xzPr;wsY>Tix8%YFRp&GUZ@EdhSlrzjjW4sph27$df{1W6qr^7!U&-yCJt z<#uh_yx}FUVbz(bH&-~Z7+Dw@1bq~nb)woQVVh{fT43ydW$;H%Tj``iw3R~PI`v0klm`~4F-CA5;O(0%>GGNJwcAQ1SnqP8#p;|i&) zl`MA`hlQ>noX|?WgWvtkT5)UtmnWT!CwXn3AGms}cbYRc!x*t8Nl+4lV7Vz8#i3H& zlJXN8C#1Y)y!kD{$q_j@;X1vMJ$ViMY$MW7Z``)==WkDb!`4m~nMc`Mzf{~kRuxO9 z26VX!EIHvlqZ;ef^x$tmJAa%d=c|9JcX6#^c&~}Uh7HS0=O8Di@>$p#(52q?k?Vzd zE^oVZbOx*ZN{1ic>_7VLb;f2GBesMGNlGBHuY7aHiIvs9VapwC7pm<`m>MhT0|quaSZ_;;Ul*!g3Pmd4wD?@9WzzqN9l!jYu^GmQ zExm!#4+QI8pFB4`KFx1Wy40K+&PD$gKDyHl+WBv2X==Zy{=>3s3v-tJm~Az&CUfC) zrLW*?mkpuA#nn6Wqeb79JUnuF=Yj{i+r4&Q`1R58{b*GM3RpG@_ReusU!J$1M7wnI zse+uW%TLSx2fJUN8J$EpRaAfTxOZ~Bgr~Sn*NcLsOPtx08`IgPoUs|kh%Nnq91g*v zYWY(aRhmi5&S!4d3RG9jaGxNb8^O;#TKj+i(qwim?96)-CbQpewaKWv!E;kb zic>hW#hNwk?rfC1eCj0NwGUFcQT@%k?cjZ-9TlhjjM#LQnyTBsF21$K8Jl5@*wPZn z;SjtxXMgp<-zOe0xEWMxEsp!rqj~DT6N{ypiHYOoGZQ)@x~_2;o8oplBH74D^C*s*sDYbCn+fQ#kc#d#k<@36>7GVb ztTQ^#XSXkD>$7g$^%S|xK}t~#S@4>u`kTaA-A3NoZL1h2`|}yyC|R+n<>U!xY=$vn zOM8&i1R_0+ydVF1#CzcCoYVW%+b>jHPub;&T(U40gXXd!%epyg&kHPEr~liwT6&8R z>#nf&Z{_(Jzow0rETDiyDp{JGNna+TBw6>W;BMGN;gH6Y9J6oknm^qcWphAN5xitU zNe4?lz7=|P?p#@s>9pl$d2*Z$PdGj}V>65qTZ#cW9D-LYYW}rE>Xe0HOnL0q5bupm zMWU`wEas+0#%p8CW2KDF6fK&>%dFS(&-Y{h3*djaw3YGDg+K!4abzj(UJ;l%OY;BBz8)HoRo9t>m6%hr@o3k z?2>n)Bp-g=az#lCxddrhgFWS}%njbMOYHg6`$E$gk1?Oxf2x6Vo-;PX7_p@>NU8ym z6IY1JZWb>4$h#zJ4s*Nvfh}LBZUc?vm>GOZ3JeasIO)lQB!M*=zjrP;GTTZ5oN}N$ z{yExOiP`Z#as3_!0eMXpv%SqNaYi{xItG_P=Xp|RlodcUISMb@Co2&v5sH(XNM=qyF6yd7R;l%`ir6X%Cc^Ah=ait@^@*jwfPS+nzk@ z^r@3-ozxG$nZxvQ^x}n&&UC36%v-SK>ijxt+V#f`(x849UU3aR&I z6HZ0F&l4Q=4}bV-FE3O4Wz*7KW}fpEB-T4)GmH^idV{1O5GhtMRXNsTKhNTmhkxEp zJ@1+n8@B|sliScJ@9ffD9vS62#ykmEo?GNxUb@Cc0lXRm+uHR01ITOBi+t?gZkrUd zP9SlALh_>ft*SMPehq;#r~ejgZ90)_cj#V=E%#sT%kXP@?9OH%Dd(6+dN&ndLJY-_8-&e#lN#Fnl==>&rR9dqRF{c>#E^0pYA zm;4MI$B!47II)-;T3YUSbLFIi!xptat8QCrMsYQwYZ-4i<=m=v*re{uI*UkyhXO(pIWZnfKs4 zY4e#@YQE{nDP)p4_7q~h<-;VOy-ONSY_M9hA#JzmQ8BLD&e#lN#FmyIkpUv7z7V|_ zBK_@i#QFdG(pFo2xNu-DrxUZGu}Na@e`ZbY6YZ*>*;_sw++iN_b8qKUC-o7$T!={`1CF+EM;#zy5;7f-O= zE#808`4wX*D~{wer42qd*!%oWn?StIiI&%EWTyX5{e0eX_cW(h&e#lN#Fp?t2?>H< z9Nf3U@8tH^UT1#37SMfiPVBnhPA3*)3k&0!YVUor1DgMsFXKzh|55o>*Rp0ZxO#%# z-hGj%o21L#|0qY1`2H>gW9<^4kMSIFGK?9=OH~$Fxf5Y33Zn zo>fiyiXQqjX7;LP$1o&b;;d72@u*a6FJAY{uz+xCnYQI<;o^>UpC?cKQ(%@l;jE7S zDc6UZ&e#lN#FnlgDFsB{(m%p8;aeo{C%;+d{jS|D=cb%q10L;xHhdW`%!S_^&+dO2 z(eS-@l8wm((l}2V=(O7PpxvuqPi>w) z(oqf9Rt1+P#*j`m$E>w%OxV{4I&EsMf4)PTv3GA=a)9gCMFG__`1}|dQmC?mbk=cv z>jSZj4GyEyB;;fLvrUa@R{N&A&w2Jnj^qEAt0>p;A~j`@Qp;?n_v)`AF0L?s@o>7v z-K$6ZzL+mqyVDt)VT{<)6(psA$W4bB*j2tZ97?jVeU(|*+Q~2Sc_Zi!F(bVlA>|CwOOH9`+&&X%oPWM-b)oik!DY2aB%ZE3QKv^%!kP0G zbLsI&PB=#Oa(Q)2tDEmS2h0hIHw7Gx6E1o>JT$Hom zq%$_d7_lWWP?CY*&RMKy7sY5NZPA`kzpR4c>LtxrZ@`5KwCBto^#y*nH=B$%yywg| zQQ`7_U$b*L931(D9hcXKF?BmHKP@@+I@K5^p%XN@SIewdQx5cdWa<_Qhv)3yt;P3jA@DAV{fYVXbDt%tNm( zvS%EO+F8J2_jZ}lM)N{vY=$vnOIM(D0>KA7_-^)n-n2e=wZe8)&HdNTGTn%9VzD$g zGf!BPyF9|ZMMzC=b19RDcwogTrZmVn3uJ7CIZFn9>I}!?u$Ft`O|RF_wW_(WIz?HD zZ`!Se+b4{s5KtgvTd2pexBz;l2y@Xs=$Rr&x91{{+rIr$Jm1#&w8Y_apEM$Zi?gcC zp3NtmLKe?wmphwm9npT6Ys7zM|Lc!^Gk@=_DeE-nQ@fXMmBxi@?>uRf5^@M%ZjgT(5>FYJGuSd2^zEpNMs%WmqK zdvwE}Q+HRp$hP@7PX1M)?gonxNI5 z*bYskU~L}Jsb%?T*oX?=L(YakYUwy#JE`=~Cgj~Y=$vnOIM(D0>QdxEEJx3+e%fWZPGM7HuZ1T;u%~{ z%oe6bjz4yoYTNk)^!|^K@yYg0h`JWC)RTdgjS0FWi(}<|_>wGk;?8URp#RV0B73Ld zF{YS%oNEL7Zf=+vHZ1F^l|P`%vp6UimLs9AYMjtuIq7+p)3yZ7XSX{SSG~LA@riIE zTIKy@Rtkg7vhPnC7V@psSekeG??kKB&e#lN#FpG32?#{`RXtlFaDs2Q#e?_1t`?Xw zT)62x(}~5z#N5#O_N?Yb-e#&7EK~O!l73M=Us-J>l`hTYSOYpP3(_cJ&r+YYU)Ui_ ze0S;A+rF+Z1uoRKCx?T^eCbg_t+9hGtU=Ug!>5FLt!4D1M5nq)EN;h~Lvyu1mF6=p z$C0?!tbmtLtGu_w?h`u_rm&>DnWJ^iu2}w+QZqZ9u^GmQEg6E66$DG2@0)y+MdNtH zHm?6iwwgBYi7-(@uC-W2mEg4&`ddsVR)f|-~rB7?uSvq4gj1gPvfusizY4mADyg}6dechYxPP(G< zUmBaq{PQHV3{SSql6Q0=8shv!Ra)o2V`hgm-SycXT zp5x2%mo`kQxBe_Xa?dK?Y6Ffmw2=X+TuI!QkbGKZ^PZyKD6I=`1l^XYs5&`gGmH^i zY6GPn2tME|^moP=+jcF7_w64~-4QTpNoY7oAADZjobY0wW;n-&o+9x^yaZS z6_7LpnL%QIr465DV%rb}pJn3MbQ3p_2ow>d?`h!J^cgzi#ISOY5W98g+|!Q#;=9$p&XE4-dABchDsn2?>;^B1 zP*Tw;a^T`WshVf^I%6}85nFl#IUIsd&0JgH>DoJCVp;go+ntl@ zQl;IsK{HO~=E)`5J%{wPZ-$f{u2_+-H%rBsrvaRb2sEHMw#viz>awF=c)+}HZN`(; z?^neM>aV;T_#%p>(kN(HHlVj!(zgN4@h|`IrmBDy(uQm|U)b;WjoN1GOE?v6?a_ZB zzCeyeE};G1xm)=~&U1F>xIcErW*8&3^ae>mAhI>ATj8)_P}`CFuQwZP3UvFa{Wi^s z#mKa6dBGMk%a@)K~RqV1R9HQLsm zy|EKO(sZvW}s&G}Oo9kNhu-OM{RbVg(2o?Qn9Yx%>m^C;}9X40o4=w1FC zVczkLBcWvOD~W=+O5azd%{?gWNI2!};z?Yk^`g?+=IG3fU!||N+dY<2u6X2(%`ir6 zX$+ETK;)V^Q_B;aeBJE#aA_3kao)KoHAU2k*~G;3<(JL-T5hPPnHGet__ekBRkHk- zZ{XPoELZMw?0#yvS0tpSi)TV5U;^3wkEknmNf_Z-SNUnj2G>PL zkNu5VHZ3LLV$ZQPMuZc{9^JU?b(8N)tm&3MFL~0FPq~taG^ny3AqLO50Ib6%hObcy-j{!^PyY?VLta^e3^TMVB%V>65q zTl#^d2oTw5*V6ol?~@(x^YCP~Pv54Qwq51`r3!O%YsJjTt89yo$YnkIe=<+hVDHE0 z?WAt5<2WG0#$*CXMeKXuurXOcy727n60ifdI8=Sum@FYn-Da#;Wmb7VN^-_#7$deM2?ts!&aT+T}M2m3a;A1uaOMJyVW0v zIwT!wR9$^_z0z~S>FLlP>3f%(P8|6ows_Bq#PY811`;`&|2ktcj1gPP1EnMgR?j$V zn5QP0FE#50*+`hEtXq*2`N2s9J$KI z2pQEOV;4i4Vdm@uU5Z8Pms`$^da%GJL^v7OwU^YMMMaDy9(fN-PgI_xKpIP=ch8Hl zLw?$crmrXdpHZ3e)ptw(viI3DaHOZBKJcE`p+9D;<+VRHEbCkP`Ty?s3JZL1%s`EO4&F@4T@cRBC)tapM7K`TkkESqfizgYeG+SH<-*Gm0# z<6rTtzyBSSp5SNZ1l(eSZT{srt_t7$%aTzG-~7wIJqf<~mo;}Y8#LR z=6yRaWfIgJuFuha$!!NmKInQnEF~1jaeL_IU-lzcm_d$aU|_$b1lwjsNz-aLmQdS` z?=vVwvEDl$(f+!laEFH1T&b6YQ`GT!>`y%Yi#AqI{QKd^`SAoyzGJL3~R_$1_t}Mv7-X=O(X3G8#uOEQB zWQLG_I){S<8Y!2vek3;^+DDqIysRK*}wHQ^Aw&7Uy`= zVm#fhwdMSO{g0_RqEv9N)->>F5A=#=BCc;ZJu~7s*ZzvO>r7YUPc8kwuakc#PpiO) zNjIlA6L)yny#bcNTLH%mHWGmH^i3InAW2#)bw{o3YXQo7*GHV5hJn*En))Cr<+2`4<@c) zHYPJj4Z|QO$;M;}9V29$gG?Khm2Lc!qL#u(Z$=g(zhGPML5!oYF<=_A27f%;UP8;QEJVl+LD@-6)w6hm1G z;W+=FxJx~TcM3_=IF-}+Oz-o8?ATiyr!VEcboG$~atgVihdqVd4BGu*RhZZA|Bqsy zmTkJzRm;@W;Ec^MMr>&b9IaqNUzk&Q_j@hXXZ6pXPP%qaXw6bbGvr}DwptID`j?tDI}A6dTv%}`M8{n?ChRXWo1_qb{>+=Bp-llg$*vI;^)_8%A6Z=omfoG4K0~7CVf;E`F>uw%VqYyI*xz(zru3CRf!R_`nYDm#$*W@ zTw!|oWc|F}s9Td{%rx%g$8weGKKgg^tLA750fjNKOJ+E(dC7s)GcceuKs)y|KK^qi z>71{=nr-^NYnxaz1!|E~$hAuBDdbB*y6v20=5Fu2f-km;7>KF*Y_c(wz2YdhYqVLQW@dT{c=?xV5tDI~zEK zm_kPWIc@~8F_}S{qin%C%O@`iJ^zi1$3QjC%tb+~tm_uzcDgTQpvrI>$Bi6}y_5qu zoObW??DOY!G=DBUwX}F{ti{)@#%pKcNFg_7!-vx@X-OSRVZQT7A#B2-Oi^Z==^l?H z`sX-fGmH^iS^}jF2zJd^PP|rbuIPA6_|2Yv^&R%nS)l1?OOq*~Ovh@rZZT6amD7ID zI$ePC<%@fuo-K6i6Wc8>#MY- z$P!LBcezaiFBdq--v4CPdx>>I>`zgVN#!4%u^GmQEro$n3Tl;P-mKlbFzf%bKQ=*-7A|D4gta3aK3KwW?+JXc zgzdBL{8O{+1C3wHsZ{+_cCMbwu}kIvsCL3TG|zGGA9S!}h!4%vGPU@tSo!A8WdE7T z#}^mR(*ERpO#=8VlSMr`Q{l2SnAg87VRm7d7sfAf%4GGnbg^iQ}Qr z$E#D=>U)_VJ$XD$=g{#=uVuG4=F^~hdZ;tfs;8%0^Dc*peX9E5pJ~aZd2R9snHllO z3Fjf={ClM8>Aq#e*XL6{PWa5Ka%TN9e(~Uab6;FK;*8BOMr=t8lw=_IGT-*)7kB2J zdm^8^ZvK+aQ#R{oayhYB8XK5-r%Q_c&52C%3u`((z0G^dhUMpOLW&v4I!xpPMK~U# z94OMR#>{TVJhhzZrD3XEzu30*?>T=DfkyD-ROk^Ahyz6iStB_7%g3oFbu1q8Og(Lx zUT9;#G|%e{j@0sa0lX1>-_n0eWmc8jZNcr~h0i8sW_{hlGm+mJn_-OD(iJ47fXM3s z^M09_q^-EPHn2wh;`?XE?pg(d4iqsle8tCm@v1|rb1+p71yCX$ZV zo{FY3O||^^v41^|RP#arsk||^JJp)S_McH><7-Bjo0FDp-Yap}8Jl5@*wPm$y+H8v z2_m6cJI-D-@F>uj_Iu`^BmB=NgYVcdwl(InPJevROX`hy)jc<+7doLoT1ef4!twGY z{H7MR1?Ct2%sU$Xf#-jqQET{3Zj+PeFC;Jx%T)A=8Cv$xX%EV!v&$!Ne7NIYe>kd} zHQG=6ctse>u{B6#&#N$`RJ6h}ODp*FttvOZtX=M}zR!}HBBJDs%`ir6=?#*CK;&U3 z+ofwoLoV@Ks;5Z56A-i5|EmlXWh zdnWl@5;OE!S6*q}wdO4YXSVp$6QBwSwg`^noi<_-oc~hzA~^P2o8gP#n6z@?i{RKe zMB$6zIO;#fEy;1zPd)WrN4hpS@ZBycx65A>aTF%+Twsgf)?J46v>#?e7s0XroCG~* zk=^$+Y|{Ds7w7??T@y!wdbb#< zFq!aK-&EbK;MAi-nd{h;&I`DGZ{l;tW*8&3qz6e%AkyvK)ZUOa*)8{ywdxnoU6*M) zdsZCiigz=^?^?mXYwZ_jmz8|?_;SViPo3Tx29y-_p$49!$hcEwx`bWkgW?6Nk{Y@D zobopucdxf5rvYX_yVhwCOdEz9F>2*xbKd5{l&Gf{hYBG#)vKL zL81yodfVQN%Y0tGqhY#O;jDFh*=? z36wST99qC_~G17g?f9|ZfD@&JLdOmC80@#AwDepl@qq`ftJI< z;f-e(N%m|F`g(H1O1rA={po(yCrP4dyR zQ{}_E$l>_z3`;rGzNsB~-#*7w!Tj1gNJ1Em=V7P@J2IZSa;M(pnO{;wnXJWExg{GC`# zjLpn+>|d33mYH$wDBJzG{r3BeJLSjf!Icu01rZ!SlaH=oZ4|kGnxjwAg=Ga}?eayZ zQ+$VL3i(-!Z$SjSAxx(f^3D5#^OWONCJWT>Zl8UmE7^oyW*v?c@^cMR3W;4)#AdKS zK9f`R+JVa+x7c=_J%7p>n_-OD(h?+ffXJw{-0Z|41`D~9M!c)@eeX0nd+l&yu`o6> zy;^c3#p7PbosVCFUw+v7>|+1+Vh?cHVhkC*z(MckF4LQLX$sHwY!7&_ zs_aJU`S%Or+N~iBN^ZmW`Ge^6H$m3^<<@ZGlmpEfHj1gN3gLoE1 z+I-nno$ajnwd=w96-l!1;~thWn}aWv>EBHyKp8+hNjdv5^GIGI7# zb+f*>&&Fg9S&YZ3Aj`&N4oO2CfA=;nNxy62-WJ1jNczU6pA5wsB07bmr3?rl-JbII zx->|Hfq^6D7xc(!cEOd<@f-G78`#1;qsUyW_Y|1U2u^GmQEnPvJ2_kjv_xyjc#J8Sl(T>9< z9MLTwG@KZnm`x207V3zcd$xa#&}V}v<#>Ck_*K(qo&zTq=#~+dhB){t2-bdM_$mmF z|F4r;Q}(=H_Rsim#zpI^e4ITMNl6z8B^FKw7Cd7!1J+NXU6n*mV%hMZDqZ5t*Jmcq znIA1ma#?09?6JU}SU4H%krK;6CM!Q~6?r+{%BdzcD-F9hU$p-1jLk4cY{?3gOd$C9 z2_ELNKjY)gGM6bht885u5&H9z6N|ZtnSsxes2O}|7R%y{a*Hw!BpuVJ>k|VvT8to@ z64|~NvN4%MCX_gtB=)FBNb%0JS^H}cRva!J2az9}Owg>W(%LC=g~y;&>?31SM1 z6P_))ljfU*be?))@N9CgchU#@_MJFV2vZ_b3i<1?Bii?vRnF}xf1CDiX9#C9u>IwX z%`ir6X$j(V5V=bE`;o4M5+;k%?Z;--dlakK?KJ}(YGz@UwPBf9Z&uJHm&pHh*&L>o z{hK}f!4pc*LpnKp6XAz+aM$ zN&R%4LZ6mf(+_89+T5L4H_I8DVT{;P8z}WaaJqx3$Bz`R`eX%_sLt*y(>2rBIY0+B z7@O65W$1iM&~{k<^Y@HxOV_=2uX|boE@iOXN6N`oXRg~JDY@?4o-HR*q!OmiyY%5x z`C;OlxSVV=pmPL>`$z}Vi0%M3arfm*PY-gKzKYF-aZZ<>WhjS6A=d^}6OvOD(?~XVkA}{)fP=7U*>coE!__2S=k_AenY- zqbl$GJ2MN9%3J*~n;o-t(|U%1D^EB%c0mu0#&&@u=?A|IV0p5am7QbZZS&W;8(AMS zJNg*-l-MEP+=U~xaC}|=+uD@DeVTGwb;H&dmmb7UtK8x0jLk4cZ0QP=P9QjM=MLvN zr}tcYuOPf^?v3>f+8&if;8FuR%Fm9pos~6vZn5~Q8OvQ6rX2b3{L5lduh<9i-{dJP zH8{D>!AALKd%$KE2WTE>085R3^$#1$c^G$E3H+Fz;F!6+xi7mFxzynLi>=h)_*xmW zzSR7||94Xz@4V5QEEv+bK;nQiHp3XPr5H#W0FkR1Ch=+A-p~F#EcxzE_Vb)NYjwpy z$7>i`h9%#TJUqLS!|+P}!APq^%s*8{mV-+T*xhb8ZtLRYx#nzsX2%uBm&>IW<}Khd zZhFdgb>D-*Uutmje1I;+#D81Y0G1l}r`*XBJUEqg$-hW;#jS@jms(Coo;Bpeo?3Xd zd365-*sS3*bT-&DMaH~)SxMmy4`*zKF=9(spmYMk&mTOy^8L@^;KyA8pL};%yq?;< zSOm0V&B8)--U;3VHSaEdUmW%?{DFSWS`CLpaCu?^>EE!q{$^vcgbc-T^0TbDv$uER z+k`7G=Y2?>%REnZ*4H@B!BC!X^2@<4B%t5`g#j#2Oe`3qHS_n^ZaJpe_GEfR@T|*E zHX)ZM{Jz-A6JG6qJzW`(yzDQZKK54VjacU5r|+kUIAb%65nEbWHOE~c z$Cdrgr)R(4owAxx>BM4aU}W;mv@z__?H5a)?`1y}6tiZL#^&1Zo(vppOoosY!YQc6 z#$*Ip9L3u6j*ZC#GWo+idn+5031m4Yhn^MuBt#CA_wbVt*?98V7@^~GsJEdczt9!3 zmp(rKYudGl_zm8UMNCXL{1_P$;R_hd(_jl2;7ektGwi}C=m0wjkvdCaC>VC3L8rQL z`Nzwi63Tgx>)ibA=UV;v&mr;_M?w?a2J2LF@@n%a`@hS%9!~+)RhJly*HC-YJJucqPUxBMnl{ zr}Z~KOu9XN@0lLszoJi8=r5CvLO$b}6RC(2{(zKnjKh+PH(udY`9JLfqr;1v3wSOy zH#=i9j1gNJgQOY|x$t$(!_C6FYV$?c+&o!vr17N1R5m9TLnCvG>z7Xm)`?p;^PE4w zWi6ji_on;4PT)$+5HetgeB~sk=*ie@<(7{N6tb39SIKVlwdQB(XaFs@8=#GC#CDDb zs+q$n`WQO?&rImbNg>8bAAY@f2rWhZZjV6y)2}aikD2p_OcME~f?4Pu?{Z z;JfCqdS$su-ZE!whB0DGOQ5s?!6iOPPydOmJZhLO_~?($N>3Bl z?B}3n5tbCiDZvU`Zb!4NlEWxPS*p&eo&AfyW8H>J>WwqLe|*iXV~V4;LMn44Qnp^W z7%!r5-u%&$Q?G-s)Ha`==+ESg%`ir6X%CW`KqTV?!P4a~=U9}ct&tRWesE1Rhu6f3 z#mwB&d~b<~dLysD*_^1Ua`WFfd34lP1%SI*(7_qxTfI1?Y>{vEa(M4HEl#An1 zyY04RC+RGdOCPvKG^bQJbZ}?%oYZw#xu4r*(mhhbGL}w(^6~Qqc0!(eFYUi&<#zjh(n$^WwJ><ubp;<52s8EbVJiHDtuVjk1tGDzZUv)ox}EJpf4PhB0DGc#xz7A_G>o$S+|t{BLw&^_)u_ z6P$yuZLo1-F*h_Y{XXNeVAjFg6<$GqBdVv19{3{l!VuI{h8`orusRNYj0mUPF8DDb z43R?cV?@}h`EP5>@=p3GGF{s1*VJ#TmH#kCihZVj!r_#=0^O(0{#le0ZO7!K328Cr_w2dekb- zJfimWOtq&*|8-EpVS@ItI2Aq4O7NqBh1&{58t06X(_AD+v*SXRKcn2E({48 zq~omMt2a66lPZkQos6386?a-PM>X|~Cimt^vgdx|NEOOiNU36VWShL(70pve3+8%F z-MYBz>7+Mm&e#lN#Fl;_-Ug9s&s}?uW^HQbU%RXN(!o^%FB=1UotO>H&E1y$((rhF zZhl{bZrdykv#zhTy7}Oaw;5!_n6*}fjmZMC2#-_M*=`SqO3P-|B#CtQLf4dMzqnW0 zg0>C}nL#~H)fhogcrY+xN4=$tC$+zV}ge1?Nw>)zt#uzb;HVhkQC7r}|C~=oKNHD5>SI z+oA1lHx_P)3$X}1pL(;w%16Z38Jl5@*wPg!oj|bG5g874Mza_5*989A$#}GI-i2xz zCl+&4OH=E!yR@VJ9NTr`O3f=d8K!@V^ULOgQwwyRCa%+}I5j6tKP~Vi-CHf>rSX{< zhxhB5xsB$B5o*kGYOaB;(@AZn?jCoC9j8CTlCh5V=+9!6oBq)4w!MzE&UdxpWV+ zWN(TSi>Z;RY4`srlS7po)7wiLKFIl0f8SzrS^`}AKsT4L{hkd!ZIe^`z!!EMO%~1A z73C-6R3A^%nX%5a>e|puA)MN`pqoor-!?;=C)A$ZCSlmOZ_=sf`&IJ=EP{N>gB3a@ zDnb)bnkU#(hz@6{miwQ1zpZu)Uv<3pTS+c>)A>ct&e#lN#FmyoX#;|pHqG*rpD}Sk zz14%=yVfWDIXb6vCuo-~Nmd zol;Znwd=FH)@*yiWr&`(y7(4z$G7HlQ^GT>_&wStBpu&V;*8BOMr>&b5>O!Wlv+X9 z$D3!S6noaBZoJlPXE0+CA*cNkg61gmk z(?AY7@`AYMk8}7mZE83F=F&d==Ku8?>mw&lDrilPSyhFc&mFQ?ZRzjnrE7$deM2})uRocu=SyW0Nbvu=N`DHyoVnZeS1w-tF|IOC;W z_`-1ZnJn;y;T#*L!WM=zm9WDWhO_@(`s>)j)hnzPBnli0I4b^Ttxjt2jTb|yPmRCJ z#A%cZTNqC7K6UczZjsV1*CQ|X1l~2h!nJl?JkMMlDaB|XyvwAgeYYZ|cV_ev!&f)w zCWVVwJx{cD{^*R&Fh*=?3X)1db7rna;*!30Zu@*7#cP{+UbftcpIy zyB4$7a3a>w5g?dOUCoAZzng1{+{fg z*kNh)a!n&6j?`lE1}U{XE-=lg>7C7?)531M<6~WEov(4GGd9B*v85|eI)Pv}UeLw|6u<2PsApz_DL(gYgPJwo(WDZ&=FnaD=aw8 zjw1Hsn_8{&=er#Lv|8~0Wv6V5C3891_csR8r-MCEwGgM-eb^{21y@)QJS67srrO|K z)08Tvq{jZ+Qu`cs#jf0loLbDK;I$A+YMJ!TB`tQ->f7d}(fg*Yn#eo*$Aw~NY=$vn zOIMJT0wT>GsrCG@SKWMxZ})CKksX2tZPg2%SWJveOuni1F1RjpXLHo@|5@^r-@j^D ze5?Z8AcigjeUbzF4DW*8&3 zv;;~U5d4zi{lvjijs#vW(jM9*`{y?>0)|@E)wJ0a$zt#CO zakKU(9{A9DcN>m0WZi(2hOYP)eAb$I*znaqDZb*H58?~6BW5{cGmH^iYJ;R75E=8z zz1{e4bAEx~sq3##ZJhsyY3?-8ETf^xe=&>s-`+^S-f=v6M`FPLteH)&0pM9iL&)_> zoVJl{Oh%A>`t1If*_ezWONrU;on&J&fv91f6&Txdy~TV}DeK0V?JefX3Nx#$jdzcx z98l1czOk0mwpbpdlYxOfXWsTKjtO#+D>wy({>{Cny`0xX$N*)28mWG=-G!8LF77${ z?biJKSd1|}V*{bTA{yVW4 znOT^5TPE5IIce~$@SdF2a(K6|oB~@Ea{Yw7y@}I)@`m=Q-{ZF%tahFt7Hd-bNp|Uf zof8zcVC>gI>nC=++na`Y3r5{6jPG46gO$uwu5C>#Jx}F^w5~udTkP+^TQDdo#O-qO z&G$WijWSy6PEClpFU!H=xXBrtVT{<)5-4pzux#z?s?U?o$zIq{bKtR5$p1b2U;c4o zHZ`)~z8`S3yJA70UQmFl)n7U9w+{{-LRv{h#L>{4j$3gZ4Q=wG_iFHrr-CbHZiwe7 zY^ie8kt(Hkfy3!|4!V+xgV^iM;YULg=swZ4szNDnKDD2o^J}?Gm-2}nlcU}~JYclb zVgrukYsUN^ zGS=aY_m&^~_#zjyli$?n;#DhyX;)8}DYz{%pRz+^N#u^D4aAK9ak{WjF#cEc`84z7 zv!WWpHb=IvGM@cwpU8C3)ha|D&xv*XkJxg{Wnjkt=+yIC|5NJKA%{83L+&4YY*23+ z^HltoH*!LAL5%;QB((L%THn_{(@uC$koZ%jRhe;Ll0%O(Hp3XPB}q^cgW%SZd9B+R z&Exmx=KT7W=@+5Lap4*03_T;`+B%21Zdo!$o|||leMX)1A;``CVN5%FsIt5@V=@OI~cuMGmhRa=lt zD^9m|61PZ^-Z>kVrB%B6KIiz)r(&EdPL!2O>VHt|_iw=>l~#LaCAM8!y65qTXKUWAP_mrHc{Q&>%$x+#^}#)AFp9poM(5;iP_k|^y|@N zt#l?S|5wiSQVI(%L?_D3`G{2cv8J=L!6xoKHX)V~Z=C?Y7lHNYb9m*)AyW^(7lHlh z&I>ML|9>YphBGW}Y*wrdlfE&JIh;;yDR`O0>2Vrb`O#xef=*=;>w=X$+KFF&?-X=z zX;e__x9t$Qf}ET@HQ;S2l;kw^M%gvj<8q8IwE9IB^r!ATVY_ItGd9B*u_ZiELV{p5 z?-$Zmx$h)jcW11aa-EfT%G;02oLDT(%nUy(J*~ZdK;C%s@%RJ@+p6|Y7A79xG6{MQ z3&-|UHYO9uQZA0lVm2ldNIAsm&B(@N3Ms2NQ13;EidW$mYn=SrRLN_%o#@@KVyz6I zE#&YeUc;qO;`Ek=-ituHHGn8hsKp_n`xmahVk0uMQ|m{!y8J}_8)tE(BJVt;LP>1* z(n(8}D#gD@zr?mdP;Y;Q>GDKpY=$vnOK*@A1R@WW@xAcaz35eL_V!BF`b{D6RUE3I z`3e)WE>r9JmptD#8|=H2_t%;$s?1vbCU|A21*C`1>Fd63XAbWgo|RWie=sm!@?-m! zVJot9v}^$dE2nRw6o_VE;AnD&p18-#GY`7sj^If1FWu1YcWKKz8pTZ|7q36zBU-w* z7&%q=w!q64lvH6fw?WZJ_fmaZW@@*1ZL4Q_UzLM1Hp3XPr5}icL1f>0u{`d|d#^Pv zD2JV$|MB-m|7Gu-Sj3x5WhmoPHhRNcAFrzT$HkM?0*YolI^!#5U5 zf>R5Y(>yr?yOB@x{Bl?JS-;8-2U&+XUjw-s_Z+zJ&T2R|gDI(TI0KhL%NG2nd7{)f z8k3)KvaL8j=dGr~8H4)_a?^`EkS^H4FCHHB)@W(2 zFh*?Y2b3NlSjL>A`$y~D05;lGcz>V?Ra95)+-(c`w7$UY;3iE zacV`bFSs>p2p^% zYx6^y2~I4QriKt`_)q;V-9aqxI56ni4Yj8TyjGIa&%?r=tkurV1yPPk!te~OI} z(j#JHeZj_L0ZC^Zb8hbw+5a--W~JQxr&$(Lr#S7eWaD8YXCWzPgdX%lCk`DW=)45S ztmDuY3?+-vhv-7mN#9#~UWoXG+~F|}cziMPU}llRF67b&d%}q*>DZxoFZ#De=jTMP zqDfnqao%Cb)OE&Y7$deM21+sz9C`3)`9ce>2@yBXx83&RdX;79+2O=uXliU+>u>mH zsfX9eZJBdVDBS(=FS?`440#}#jkz1Xkd)!F4SXRfTjOi^Kr-{^h45pN*d-SK?HR5q%OGXH+_LAu0YXyhAjh z1-!l|U}4iM7yNDOp;V2k-^^`NGYKcOsJq$?36m!{Kemey2&$2uqws3}=>{ujY=$vn zOOlX81|pZ9o4U$tY0v!3sDLYcXFHdPH&5gMH;4%=>tda^X2sz@);IjRCpSk-d^y|U zrq@5cADfZ8Ps6a*irGfgvMvg{Pg70Rm-E)RYJ3V}X+O8^Y~9SR1;>!nM9fEQwN}*K zDLM`hZs_zV)iY-3zA8CVP_HOw?TpPZMr^4Elo}w|(o|0K&_n0t)$WHYPP;EyJ?F#$ zZ6_9U3rouh*L6=`eYCbhjcb3vvUw?+T;J#wx{6(c^q5i;RAW> zhi1VqIOU8xrE`V9Q%qr+^V=S8(FI4neRY)DV4+I2N}fKwuOTl&?c6*=iP08s=xf=r(bO+vc5)bUGKkH6s230 zD3H8PyJYXXg=_LsHcS)mXFR0+;1peM4-j;7rtlcB?opvBL)P zc(b6LZ4y$&!;3xVY$nv*YmR!oAxTT*)XAIaC`V^uFIy6Qud(yrvp;pTpwO=R$mUS4 zm2cU&Go7&+#)vKbfYJj5oBnw;Nngdq`oQ1&_g?yD&C2+fSLeiHVqs*~=V?x!>cq;YdV*y~kQ+9f$w=ovBJGf&Y=(TI^y0<~dme5GX6Q(lFuk5zADmZ7r%Egt zcK#!sXQSv-iJkr#^JmAmvdX86zljOO%vh4MsAvLm@sqp_TP2q0D;M@vD#PGkZ0@C#8nNWWrteZq?`XEvTwlQaLc;G5_NiOCVd z53!F2ai%VZp3sK>Jkh~9Sx)RIA=So%!hKf>Ex+;KhrO$5z3Q`o>|gwrD{-W!G&cBn zP@*sI;mXyCv41lG&?hisN){k%9S>?-ozbDSB7`EQgI(qYE#e)Qa)85PdY zIV_((iTxI(z0Db$VT{<)5+ry)q>tzw#gk$t2RAd`OEP=S@#;qQlXXtaMyAHcLq9X* zG$n4IB=>y5gzs(dlClooM=5f$7!gIzaaH)O-Ygll@LRpvwsJ_giu>W4)U)2LqrYVs&-1#(uT7C~$e^V)X^mYln;&BA;Ku znG*!RXN*&GlFi&3&V~Kqw!8%!Z^l}_c{Jmv!%KpxB`1d&;v{zX`4yw71ueDo|J#u$ zY;6^1a<^fzLU+~r0OtH($Q2a!)RMFOvK2$dwdH=rZyz6%DbKlju{c-xtur>m7_p@* zNVI^+gI|7FAJc4Bw9aEc!GHS3k3UcEf{(R^p4G>8%L{&1AIGf{_*s2yemmf2^>I8D zYV>Vl3A@i?sJD!pG0ozL%np|PYUR~%OiEIxK(c0;ymwrRZ>a4tD@b)lL?Ub{;NH1UY-4y{xi$8Z3<+Is++tIU#(HWazjMx$q zC}BWw$&;Fk*M71tGFvIOX@l1nlgceS+?`m=EDa1D*5^$Z6)n8y(zES-lG-vJ6Cbxw zaCh7UGS9$SFkj;8&EE~-?)e+;Znh#fN6W;rCgu{+tbF_}Rov{?6i6PZ}@X~Vl- zo@=_D@)HtR*e9*`=Nc_rKoLRufH7y$d1yn0Vdb8X$8RI%Rx5We`kJ`(vXsu9$R7$h z$f>AU30}6Kq#~Wnh!^{{ZU2Tug_(Z8wAbj{rO;>2*bHODmfk=Phu|I4#8tNl#|q|p zlrU~8otGK>%J&Iqy^XQ)^4pUd3Qt%wIX*1@Sitj+QEJx%JLFWv2U_cQ;`p_U}sVFoRfttI& zUQ5JtmK}Rn*7x(mVKKhO2E1G0kR^Q zE|63NT{Dd18cfb|N7!j6sMlcL-C3lw(s_DE2;(tk#w0secC%{=!zc}vM??1t(_?rU zB@OwOAG|p6&o1K)N0WAX%nD*WvValgh%W3UQTdv*qnn>~q=;o}txiAwMejn_Uw-Er zXKaQsVoPn1^aCQjvj0j>-6N*vlHM6HQ7rn>pMZZ;omh-aOw5k@rWkOVFD*!qcaDXa|6Jaa&y%}7#q)#KuQbDdDunj@u_%3JW(Px+eX+f6?k$IbaM zZ;5!9walg84!X?Lxx50PeHQCbh_6pZ7dU^-4ItQ}wkA15a8zZ#rNe*ITGKY4%g}^)iAR3 zQnjz(O9MGrBG{OqO9Pp?ufmrGvOb#yTN=oA?<9u<=ZQ7Uefpud%u6aS?p<2MBw2)< zh&bz5pi2We5rca}XSfD$O-0j0^v5#3L(1{n_4mogR=?M2xx~GkCy8((stcRF>s2bt zE=#$!JW;pOyon!K>8z--JiJg_3=)(C! zOl&k2fg*y8Hgkg~qRpJT!%tA;&YhC_@Zuv(2}+jtqk@pHj_1T)gEh>Vm|2p&c+T(p zpZEor8;Ne;@UL|7Y-enSF=9(^AcsRR``b&$z8(zhQoL7b-un9YVZS9`L8-{h%veKX z+Xs(x=6q{)1qJUtnKA3vIbKi5tQ2HXAIe>2O{I>@49$2CH2bog_^`M8`s>Xm4;E^S zrVvmdV@)AV{m`9L*zPLhL{1@}FR?4X6zvUo^Rn}cSZb$*kK!X-y(*;2s%hVpa~0q2 znV$-dV-j5)`7c%5h+9u6qRC~Guv<%18 ze7l<0f|VV=RDP@7S5G|alInJ z)t_|ovQ~b-X3mxHxr;(Iov|6lh%L22(hrCXTlRFu`kdLvX7|kSxw*yVaf^1=UU1(D zcGYv#7d9p{=>4jXz1f&7A%_RB9(}&Cd40;#i9su`zS{dQY5k$oR-y0s2Y=s*v+Xu? zwwu_aPAFOrK~CQ(#FnY$>Myo(Q%0>1oqD-fRNmii!;vQ1#o&FXR;Cpt=MAmH7XP%8 zcwFmc<^O&EvgcEsu^GmQE%ks>0|c9-+z||@N#Nf9{ni`X{Oux4Y*z73%tj_=|6&hk zb}bKoZf|~(>F#OJKiH-fq3?Q-~@lCEm!sye0#MuG0(5^P#@^>7x>CR zqy}*(2W+-`=ro82u8?^)c_yRG1GaVR-8?6WJYcf${doapy(m&s1}Q;xrY~V>ci@QZ zb@_C4sc+D#D^7FW6&szg8ODe$=|K_`h~=t2bv*mUK7aj}oE0lwS@_2>Wam@EvrfiTTVE zhi)kI`WSG>nUz2C-zW6BhQ}5(qywEEXI;A%F+IMt0zN&?+1m!69%s|Nd0Cd%*YqRv zLB5m6M0oWI4*ofKz@Pfn8E5Z&==36u%TjTI&SmhE@@_hsKShWUF*8~#7Hk<<`X~Dw==wbQPw3>a4$V)|327; zD-P6q=_9hATkEA>sXH}m*Y#yP>&h-X4*f@`gw}rpw&9B8BjScYLhG;AI3X-(QoP}g zm-^zq!(nV|WlV4+vc{D-f6nE3__l6^%-SUvo5Qx=+Y0HiLt57C zXLqtOnL~Q-oRid>L=Wy^`xyH%dB=e)kK-lITZ?`$kuaM+$&m%(AdVbu=-y9GESrW$ z#!4NO+4MgV&#zhEN%6?~qu#)s+f*HF|LhcU3Yk;@pG`+eA#V3soab_WTm62|^;c(# zvQt|YSiW?|W*8&3v;>I^5UD@EAj-m^#+}cqan`|a_p9m`{NLlmY-(WCG3C{)_C3{W z>TS<6rb|v(C~@z57dU~KK)PF;Q#{$2ETNtEs2l%J?p4*^VfgWXbhyA&wN)j)~p9~DFk5ZuvjoBUKp$mPv|BaY||=<})7=TYz!aNR?^d>vXwxsU4iG95zQn*wJ^FJ`&!iPC=xy7R%(G@!n`{b<&ChONJae>^>Uq3{2y z>5x$wI^lZv*Nu63G9&YyG#Wv#)D0^R!YNVM=NGW8~tHWVQsr%X^C)b6E zO1a-LwNnss#%35JwzLFE9UyXk_79B{j3zrSKd5GHaQ(e(&6SsHoLCGE42)kbyk8yn zqr9ZzWti>#_WE`))e9@ZRgxj3ox;3Njg83^T0PCWt@>Ioc;1l=?;Oj#tk$Z~O@GDK zij1~dKtYUc1t90Fuh3ZrZ0EC~v{}|CF6i2_IYZ~U^?~It-rRC&|6dS{}B@2VjORvE{)x=Zf6Ho}xJCibID3InG{$ZfD>e zVXa^iQq(h-$YigeyQi8t3fCp?dh_>fu+Vkn6g9UDdx}b*$o zv>7~@b~KQXLc*)A2`o3-(mVHF+6T|3-4=rLW5keC$ov`DQ^|)%-8mnl>Nli#^)Jr2TDu z7|Vto*(!p5j11HsBVO1I9qVKNEDGBSLyt3W5Hk(*9wXkdXz}%9dR5Bi{pO$Fe4qCq zqEGQF;e@mBqTeTnzw2X8ImEgsJ`)t`XW43JKFb-KVT{<47$nhv$heo{MLW(nT=lxu zVmrA@pqIbJo&mZ4M9dLN?4T)66X)uvc_dLl6e%{5mhfc|9 z@hVvVNu~vM?ls3Q=r!XU);D405G9ws4qS5DbHTJanWdzArN70SDTl(2%@5ypnQ(Gi zqL7?urnt+ZkA2tE=*=z%&#%2?>9f`un_-OD5*{caL9lk(oJrFx_*ym^G(?;{`fOs= zRDqYE*0HH&>Drd&;7d{~XRpq-HszWf_G$8aR`9&J8Dx-#wN`|U$qd>$Uiy=b$pW%h zhEvr!(lh$;xy5t5rpI``)$5rWxcgfarynCjk^;m|2E_T+*v=6c1bwMx!q8pf96xKJ zyTmz_-J!e0IpJ4?(0$%K%P~|vYI4q#v*!dKOlaSJ^`qpDM>tZ;GQ{}r5``RPogZ0E zfpgEz+Srk_wyu-IB-hy)n_-OD(iJq;7#JA#M{?{gvpAC(S@7<7$$^NSFZO$`0mT94Ti-2fP=)M1l81^`#TiD?iPzQ-2k*Q=Rw8wT@(G zY=$vnOJj(Xqnr!rMD&TYrDX<{d4NdCT{%V)}iiHzx1H`m#X-d~xt12Yw1E zMO~>?)zJ11(OZ9qdPCXZ)ati&nJYuCKPd80u6?NVLS5lDa>7}45Z+KmNjU$f##q;@ zG8i6vmps)u_p)N3d&z5OY=$vnOJazG^KOyX$`6V=e|TA~UMloU^XxS}md(iR9V(ry z#2%}}#sobwlGA`?RV8O{;+Ob&|08AjcKI!Fe=NiElm`7SY{_ZOELeL7+dUscJvp5) zpI^C@W1EQm`yX9(^^V)KJo~JXlhaxO?8!-ndGoW4`#&!IB-g)WlSQg%_~xB2ov|6l zh%MnElGB^n3B9GIR|OwsH~MDIEz4rfJ8}0nxc8|2F=e*qLVP1o+XQoFDCN+Cv&bgLP0sNtx zzX{h}TeibpqXI|DS?`5ZgS`{jUBGallmB7P%gyBhah?~pU0>jg%`ir6X$+BaE|l*w z-*K{hD|h3%O%~r*`PN3Yxq(i#H8TErts#jaf$7kb>d?m_>vpfIZj@gEPB}&DVDC!g4uEFtY6_V4y3t>SzxYkN!dG7tPXkQkRMxU%QyVC`dZ zZnT9>dGdUKt~TY!^MSUSIkj&=Tg|L*n_;cyf$L+{FF%@d=+4QXdO`wk%QViMjgCEU zOgQCiY&rSlbv*z3ReMe2t}6Y$xYD9@{<2NZ*bHODmd3zQ4$a;*&u;%uUTKBW{K74S(z|xw64bU`np{@)?uwUI(WfV@My1<991!<@)AW*nVKv z$unVh2eXvU@p@lp{IC7?bWi_=GpW|Pa{ud|P8>dU73b!1=*o4Dr<0+}0Vz3?i-a*k zafa(BZx@?wie0Jm;oq*M%NtkS5<*TloAPxMhu^GmQEro%T44C+}MC4lKpNXyS{~UWNq?OK=7Jk?Q)Mhp?J!CAlpu1Bn%p{Ys zm*1{<-CK#dx50}_4Wa3Vq}>mkTc_TrRn43s|LW<)giPIqrAMw`{Pn4M7?nL+*F)0~ zC%uOYZ+yGATw%AZ&1B}yuivH~56V8_P(wHkZDUyOy4TRn{e9fcgCAnIs(%*XcKMg= zjLk4cY^e>Le89w~qbJUI9FNY+d-WqGj(^gfg^BxEoLDR^EY0uD`FO{zt9kZw-Df}N zY*-i@uW|7nsO*9EyEwPsgpV_G;9gVOy6wN%Mvh`>tq)yuSvN4oaoB3jr$KXP`)6ps z3u#R$b*9ZpAL^k`bEoRaX4~-ZiiP)?mo__d6y+}TegtNmE-rU*7@b#p++oz*! zHy#G>j(>VP&wKCuA3o053}eKW#K36=Ob8s5WLTAUUoh!p63g_MpT}!&TNi*X#51;t zT43IE?T1BSuwhS<f?-X^Ev+xsYNGfBd42Ph44xXCEau}GpYnRu9nz! zmCtyMs%LKQGXCk#*bHODmcqbE222F4ZGUxtH|yuD7`OISPmU>m{16`N#A0b|VA*8w z$$W*(pUAI$OjcaKvzaci>p?C%gAOQjq_05?DDUxt4=A%%tSc>ITeL}`N#l%AtdU=g zftd8FGeJWswQ%l9fi{h?9XrZ7aH%C^zhAX{hg|;BXVHNjTO_!b>^LosoLctG$DUgB z@)M<3Iu)K?nsm&ju&VEbTu$|4XKaQsVoO)xgaRharx|S#OkU%YAO9^$i}T61FK2F^ zaAL7AG&M0;HlcNwTiC^e9l`zeiD8^48~g;p(+@_FCJv{13LBFNbjo301sjtYq*KM* z5qq%6WsB#jskQMTxs&g&`SC~2LIZSm1wFYW5kxOzzGFR zxSZU~UlnZf^xz4p3+;_(J1^TZ9dKeXv@|nOygvW_M1`0ft-FgWRHIh3eCI5B3SL$L zy@iNf<{s=8BF+QL%7Z3}vRxDjuQ?fYz;5%T;(V3g%H$L$oCglT*7{*veNOD?-tb8v z7d2z&DjCTLd<>qd)L$X=IF(fpC4n4xhdqHzT)q74qFRIBXF|W}-aQ@f^YYBA`Oer3 zW5kw}z-a?aJWgFGntg4@p72G@mu0TrDQeBSam|Uv+|+*!8n!Y4n~Gm|o%SPTt~Ee=a8T;7$i`EbMcdX1g-{UX0? z^Ui=P83KF5Igi|Z=vq^6=suEd*5`CcgAKIBerw} zNhu(5aqG<&mv>$$X?`ZqIQQkGK#u0k*-k9R28Kog4=?{+ofYa8XYotIBg{l^VNfe@!k*XnMzOCXYYOtI?aaU#>pV9dycCPRL5s8BiFI} zi)X%j_-Wc(jl(wugf4cXoFjTX3tso2q?@IR6V_VIc)QF`?ewmLGrK<}d5O0;V>65q zTM7fE7zlR1%IbID<)7m358u`mR^4%In|(dsiN)C5#I$JrHktlDZ_TS`3R1#0ectuN zROSVEw2s^@;3u8g^d#1;T)EEr@%6-%$rnodTiG&((_8^!yzXQybj%lV@f7|o;1t$X zb+5a3p64o=E57&0b%~Eb{hp@3%pNAj9#-0UQ zUjx~k+wh9&65qTcQFb5(wUXJLcb1o{nc+606?4yP{}qA#nST6N{yRk)?g#Pj|Q5 zAuraHc>dV_x^VlkM+%p~y&*$L0%7S?Mr>?3yCrQ)jnw_u;%$3p>#M2ndVW~xfb65u z6aorlY)6E0o;?TM*h27#P*=s}_QzRv)mZI+82@3ilr3{YO+1dmdvV0yhdq~YzehBKx4u?9{o=Ef!_ z4F3D?RE6!{W2%sOtf=|Z<$1SO>42LuhR{{Ph%-Vt&tJoFMyTwXM282eMV3EAvtXKaQsVoPC=Gy@`!9a@wbAlo~S&GmJ>MnS^EpbxJr zK+8N$EwA`Y=H1$Pv|-_*3+b{Z@(1pwZT3W2jfLYp3C>G=@C$r7^sL|)_!75!_Y0fq zBfslsHqY0Yn!I8{)|4#oUm|oWpe|{^R%2l~PlCYi-2tk?NGPC=efqp{eL$~a$evJX zp~8P*@Be?pRfS!e2QQ#5m}7wv?~*bb3)@d75wJzUgnBhT#=0|CSvW++SdEv zDABI6BPBHRzmav)&bz)AgzH81Rkb%;?@8oy#%35Jwj>EjWFYdaJx}Y#hyz{Pf+i_5 zB?Qjv+&|pz#B63}mc6r6c*4#7VT((R*~)rDjVugZS0bk~Qn%A^UVDH@XE<*p7k;Oy zGF9ZzB$HFC;^&T*9%V8s_Y*bZVmAOd8G!Emk?N{ZQ_&OCjbJ z3m;aNE&D%v(Lcfo?dFZNrn?2PLRxk&?rTm|(X2j|dB2R&8Jl5@*peh9k%35y+5UM? z_a^MyJC~i~mh!G{N0TIOCuR$CqYFWO7uYLm|5~_q?tAoQUa}ACMDX@eCTPo^Bl8yQ z^ncFV8{sW`_U@yw)Bib6&$NyXVA*oBZ&lsBrCNf*T7FChei_4Pf(-8 zwNB_Z9Cpht=nd8s9(AC)AeP(Uc#TlatLK$3CU;MqvN2#5aCum(*%SN@*}r>A@I*;)H;vM!YsJ-tBLW4r~SVliS3sfZp}a zGF0=(to`O*=7mh#L;BAanp~kl!g=x)a|JZXV+KPi;oM;SF$@xDD?M)#~-_&n>u4Nj1gNB10@*~(h$eSWCm#mv6o7~@2Tea|GJ=k^V@(sIYD7<6)!Ja z+brN<3;97XO*|KY9qdHxVR9ocO_&^woN4p<;;v*_)p_lE^A~bNGOFT86VLsT(!`9{ z3w-7{ax#DP)Ac>-H`o5>(g*9Du^GmQE%iXs1Bg76>heSO@%u-9ZvVu71V0b+4O=51r!h5oc$F)FtSwU9N*S`D@ z*7sNZ0d>@vjG*1K*AwAq(s3MDg`Y{sl2Hpkla76R68ua$PSh(Z+VlMc-~K(_EONW3 z&Q`f_Ca=JL6&zi)*Q=pt(s7c0MFqB@NyLcJaO|q-%?%fly>Z9v zC7hz(a8tQ2ZKw@ zuLMsK?e#F3c!6)_p(S@|Q0KkmtQpvf@ZM@0{Uv z-W#qn!de@4Z81On$3%8U&AY&+jqVDYoUs|kh%JeMk_-eNy!5-JL7<`fdGnjJySew* zW+dN!?!;_iVzANj1$$;n?V3)x&ndUw<-W5m`=kz8W`cRbF6RfCUyqV?OLMQxi;elY z`y{kPj(H2_)jt z>IL((nAXnWoZ?xc|7Tm|!UciO*bHODmXsig14K%8N&W7qFHCG-zH#68vrF0*zt6n^ z8U!*hJzaIrckX|$E59!oPGp?$>z`{2cM7gX5$7jcDm97@`>?WA>)p)~|G891E#}{@ zLsz2q(y3AODSS9LilR)83%u?)pB`HMX)eFK%u@b@_yFXD_6f272PL7IeqQ+Mu;yB+ zp9PtZH_jt>yAJS3Y+cQDxR!xacwyPs z2lw5MaSVZC>C1ruS;$Yq;*valx1D-MTX(N&Q?QtS>eqLM%4-*Jq?Rwgk%}c#snwHj zP2*xOni!_@>a+U!w||0zov|6lh%H?~QVNLtR6hT;SyNE9>FcZ%J&SF%8OK7NfOd?cWS-iy8}WIAb%65nBoar5FefG&hK!w^JZ7OqNwwc7gg-aZTnYPAo=dW(IPZ zoOQ)lqFNKx6%_Z$ziGVqmd_p3^};eo_LGOyIWiBW9fDWhN_{Ake$5|t=6N4yF4r!) zcf5Y84Zk_Ex&|Hn*{oUTmCBB0-8WaQhTlkJfG`S zGV{MPHp3XPr94Pl0+GkQKjXXqFgxPI&mHeL)p-xE{Pw}YiN)N+%!u>B(|uPWb#E?b z_$&R7b8bz-_X{!LS_`(vnPUNBkMr*s_#S7DY4HB>|JeAJOv)XDjLV6)mTMUe zU~2hY2HoR~?Lb~m(hrLoxD`a3H|^v-TD0G5*6~TJH1lhZ*ubTn2MZM)1U7X0OkWgrfIH{cil-7+-w;kY ze_ubJ_(VeWq+D6cnvGS@byh4@dmBE<8Jl5@*wPpz)qu#Rc!ha_(hV-sni+QT+csuD znYiyexHK__tj}O+>S1HDfUr4=X0kC^LfXbGKX!e6dvLn{pObHU+8UJj`_625CwcG} zwMrAt|3}zC&SPNU#6Rda9Mi<1$$lcc+_#(QoY|f*#arl_=I8gD38#tw|6TaMZEnB# zPH@Ge$+e&Ed}#{1lELbX%`ir6sRt6=ATrivLqR! z@xi6_*UsnLg{*V}Y?Q37I%6}85nF15cosz7H`-=ce<(j&@Q!Pou$I6MhW@x>Cl*Uf zb7R#@^)0cNZ`uY=4xjJho^{qb;_O{;jbsR!73H*zWMeXd?kMuV%*JF4T@iNgBpZ_n zL=6{Kq{}#4b4h^|?Ji^!{iM92E4V??2;WF_Q=BWME*=nYX_Er%HxO z<(&McDJ-X!?=+3Ockm(hl*7eR3+sV%F*(oH^vTTGkf42zX-?HAB^WeVQ16$L3HKS9et5IJPI~Du~?cL8WqG(;kfatXtUX|Bb<5xGqQu1 zs)>P94)hE$99!wR*uszwzGT&&&u;s_x^8FAZj*AkidW)C>_8*03BW*8&36b4E$5FEPsW%LZ0qX&-|ycBd%HSJD$65Hy;VrXn(5z~0d ze!=w*eL<)Fug+CnYWTD@Z9Y;Doa4w<*eX>njy^;WJar#@l`5y>RyHPcNFB!-Y6@Sa z%6P7vqwL_PfIdt0`T1LxS$y_}2hOqlG_+5JZJQa=N}fSE5{Oa` z$yq#mDnBFi_cvL`ZSqsX*xuQHL7t#MPEVYyNafJG2(xy<@~JT*Esrjkmmiii*tB=4 zGd9B*v86mnS^|;veJL9Q{`K(688yt{|6n9ubgL-LiN(Ug(A-;6#B<*F7ae{Fn2wz- zW}Q?X^YARV9D-h3!O_+VKlGc6>mK~t3XU%y;MZ2LEDZB7n|){6vf01GHRilAPUMW} zu_*+dPlxTcC6fD81K)ne*7o7z`T;%ko0FFNd1QUkjY={jUvFD^t#8WdqNO#jLS%82 zL`W%z+kV3;r;31?6YQoNiwWwl{+hW;aqVj z8||w<)psW42B*x7_ZSl)nJn=E%RBgO+R{m)8A`3?IKTej*289ryJgK zcnyY@3RgO|Cm2pSZ!BC!Y^lRhB0DGVURQfBJ+;9ZhvacwPoVkM^BTT z&IDXlnB3yTVr*h&w52R$kMq{lC0~whl)XRsp|NDwbzyM2fsNu2v0RypKVa3z>tAF# zL=*l7e!gtGGxxyBd^XTB9mEw&*iQ98tT3d?WIC~R6&HUNY!qkk*Huy~&OeVdt%=Fm zb7aHu{yBFUYTsWS)^EphPOL63VY5=5P`8ODe$je*h( z1l#V+PrR1hu74_|OLCLPzJSI%D^#3VOpT1q-U;WHF;|{ZRVnBG>6YDUZ29BdRq%2P zBgk?KF2OD~CQHa7F!orbcdR{ox92(~Z@26G>8SP_w{DyZ!_2QR|+|eqYObxA;MoTZDv+y@(kp5OFtv` z+p_8Z_R@&2&e#lN#FmyoX#;})wQiK(H0$yCoRzOuF+~=&^(A#jII$QTnpyU6XB^vj z$+bC<@z+|{In~BZv$tD=$B0cKtC5+wg5hi08RR74YudR)&m~+7OevfH;i}9AQFCjV z;zQf7%Yxdtarkc7;u3uUThk7|ta!Ao!oYxX{qa2ve18EC#n#plw_(@juuOJVY9$ z;o_C}W;^%IkxAPpGfR94i`r+F@y{~y3!!xqLnz%yhz(R5_n7Y7Jdvv@2{JtMt0nFv zTQhL2D@0B=64BVxO?+i}S+aL&t3=DJIpxg9RF#t6e|5%Y7$de621+py+{jwDz3urD8*kCvZ7P*_4%ut^XwCn=_@Nqe^9&p*N@^{Xup2+RIt>wgG zVr*crpHK6OyZ#|_ZKuIM^YdLjC3s#Zdoef*j zfST*9mtD!4ad=9rQpD0l@3JPYoQAx3iwk>7k#{&%x4EJ#a>-9yy*Q~!b=Kz`^4)GZ zV>65qTbhET5)j!pIa0Y&=jUvO`2XK56+$;%)h(Up#A0e{Z1O;hVM;>HN~Lno7XLG) zixb$q!&ZTt(q@nePcB7CHYRgucYJOP8Pd}TjMKjqpDb3>LS@-RwVB|`*yU1Gd9B*u_ZlFQi9+eQ`zE{_a54R^vK<9p@j)#RTr1)42|u@iz-}i6c?JT z_hX!8vG&d$|Eke;GALm2udCov-GslLoII~|#@fZ_7L-V|EytsP z`OwU@e)eG@iE}@S9A0dsdwNnoLDc;CU>Z>-n4T0QCVk6pF#7FV^pM+j{e^#$@AFYc zl#v=a8mdU?Y1xgKnx&bcX;Uog@78_Wzq)txjI++z3}eKW@*rsmL|)!kBd{+On+M`>St@>zA_KeKQX!%><7CL05QjY5pT-g_roR z%BQbpi+;HG&^}9$HEzC|t%Lt)$^ivE86}aH1Y(8PPgl-J?wdyW?Y}Py;Iq{MC1LGSsF3RcJDcOhFOhp zYSHOc=&29*QGH&2U%h-hm)NJ950*^rbH-*EBerw}Nhu&QMB&cr!Uw;THNK{vGo5$w z!868d-cBs0<_5-BQ+`A+YE*BEW6zt@#_B1ip3#{pqPH7fw&?V(ciYWm#<^h2x~TsfgGx<&|A@{LaK>gBBerw}N+%F(*yF>@ zsrA@abW?ryHvy|!)}XI-;Mq**Ef&mKGVoh0IP|QX*QK;Hlw45LzE`{T`-Y~;Ik)BV zMoSG)P-5#;a~VvL0m(5iFcS!+d0S(Q~(38(b$}Ugo6x zcJ-Xw>~j}u1|laGqYvf z)Hj#ON%+(^XHF1&>YGz@(g7~r`M-DOSWo;`kZ8ZvLRxc!@H;|93zx}b=+rm+B_-&| zC7cm@(A2`AW5fn=FzLf9gS|mQLeXM*c+y-C#c78)yoHX|+v&D9TwP;MIJKC{%?kRZ zF}wA*oXoAVk6)d3yyMHN<8{Vn7$dfH1qpZ%Igc%}B2us4>q+ugIe9n5Z08;81;2mGKOFn_5>iK+HJu%{(45m_6JnwH)(P;1=B!7b!#mO( zGWGC<=3Hjq7yR?koM7NLrHo-iu`&m%{;eJ7574{x;W8J5cBDC}d`j&A&MWOdusDE? zVTo|nlE8EQ9v7KH^8MA3)024~w$jH`E^o)C1EIlNlMK)Gt-sPQz#nR>XXlK~Fh*=C z50sK1I6f}eqQmg0MbIrP&5+Zn#VPvrtDRUZ%#95^@4WdQJlphHe8v``onB^)83$rB zNbX2mx)*Yt`}^gw@26Vk9o%*^9>z`={d#V+u?q@(GCIOA}t)>s}qE&Vsav`746{!2AyY=$vnOJg91 zL-4Z2g%?hQ9-X_pCnssz&wE;|J0iA$x<)333*z_$zm#6SY@)ehz17lN@)atU6TtNr zfq5n_>&6T*)=4?ieAAA)EahCdsP_H`t>-4A^%f|=k($KTv!U}$B-C3SNrJz$-Uddq zhRF-?#hkqpqVhA1aB8u>Hie6QmQ}aSL^;Jq^}oO7B|OkQHq#lKVT{<)70BTb9KG<) z^Od}Lx*{1O#}{!KJ8;JS-0s9;Vqk2x`Av!O;vdY>TTL1yU;Q$0b#TuYqEfwOyS{2} zO{bgZ&(spDSE0OO$Cot7v(Ke_y=8lH_|;o(!P`^UX`Ox}sl@Q~l-*9V%e(z;kkgZ$ z8ob^@Dt)Z4*)j%9w45@bI(w<_j5CVy503;{K6J)r7$dfn2T4mHvazG0W2N!6@(0a< zs_#E2PEpW$w!?|V(8SV2=!4nE0`2+R)ZWNHK0Sd`TxH!=)O)y)j zKTig7LUZWHp3n@oq&Y=QPJi+2kM!42%dpb*@oGn$u^GmQElGls7z7vWowLI1vDF3Z zh7CL8mj}K`^lPtoVlg$gFgUMmo!UG#<;@NK&rG~>MQZU2ezAZ@d!S1w7>k48ODMRU zGAf@7p4Q$M_sV~5_A1`<2UhL)wy$h7g@6JXaYGH4Qxmjm$lkcGu=d#46-Q zzF4;Mt=vMj1;16NfSb_Jy_#GuUBv9wJhj`S7RybI+2+JzVQOr)ruV=`9qnd@ ztDB#uCdbGcGqZd;>2Og{2&i zfAEyUZhIP@ayYiivoV=MMxi;o9pI^m^Q3d>@y7{PW(vM{I&U{RJk9yMyLSs{Q8AXi z;)u0cLvb*X%TofHin!=g{&?85a~(4~(!d(Kk|berRn(K5#?bMh3CQxV7ZRCp@ls4Rx3B2I5ccq-!Zc7dlNwgu*IMLzN= z?5XYkEHtrwqg{7Y1=k{-;W!Y)0vWWAC7+)2C?TBdXm}edXduYKXx$aHCLPJY3Cqs`bDASLM5ZI%Vw~F5e}C zaMFVA<;<>qA!WC&S>KG(_{uMRLh!NbH?2g%Da7~k^7`o$k6t*~?(Fm0E2#eLx;qQS z3!JeT#)vH~K~e{ZT#`Qd~>t8#XO7e5x(O@ZiwX z%~>~{?`@bp3A`rM5OV4tm;V~O{l%P>4+K}gzkWO+^={1uS<~K0qiq;auu{@*;_^Q> zU&ra6M&IEB8;&3ReC5bb1@7HO_mESC|4Voq2C3Zey}aPrKN;4{G^ada7rr^3AK$hF z9I$f6W*8&3^aFA@1TQdsT~uPz5u@?_<f=frpNXl+C<%K*`0)+AL1n;Gg)-ZLh+p zRm*S%-hrJ9iTBC|F8GR1+O4gjdoA-Q`1{o4M`4N+zCJj9xnHOK_;n2i9H}Kp96sIP zdpT~_+Z9#zcm8>K^jw<8^~*}%@5ohWY=$vnOIMJT0wSa0{|4E2I;6+W-*|=RZ({oS zUVG@JiO^H|gx4TiB)EG-%&Kxb)JozW7dqSt|0sOT`>M@Z(Dl;vSVlqDaXPNx53p7U z9ePAu{>PNBIo(^4z*qn6c$r9i(D$Xz=UmjE zzg0W#?|8j|)pWk~bA50t#1PW*;GD6OjmaF+f947ksMQrbwE1+z;fhB(_Hxra8^zhD zA0)m6;R@4&E}dZiISIOSg42>0+6o!bC5YXw3mY0vKG-F`J80%#rBm}}`QPQkkwU^E zkxG#71}b)5bGPfa2cB)8x_zGdq951RIb$=75nEbt!FXW$Bx=+c;84L^VP9t_jS3cP4hymL<;E3}eKWmLLHI zA{D-}BzC#q*j>b@WYV{wHm~*j@)b@jmd2)LN#E9fKeGInZ>8#sK%c35S8sneu^wrX z5_y+OR0v{m4bmx&cy_7$ayq~ASL&U@^EL+GE}m$~eirU>g6<_wR33Da5?h;Ph^D8E z_WGFr<03PaipiH(@5#buYZ5Z0$0 z{>P@hoH-*d?{NAHFRqWWKTX9Bg_%!9P9ZUG;jI?b6f%eV=W=G(iI;obC8D3-eaxQo z@0K$*!x*upB}nQ3kzeiB=s78VtaRnP*ISV#VjUnhLEeek)YPc<_#3Z#``(owzb<=+ zf5l_gv%){wz+E6y$Yx1qv2OVFP+W1x*qAKMLFO@VD9dg6_jj(^=pZt~<^zl7Q+~thTFh*?Y3gmDI zUcpwl=)3Hn%m^}zDe(>P7-F|RtF*$0u;8kN%`GaXpJbmiiMp)`u@)iks*N&dlM+=R1;m|BwItz5}|vE zlRPP93KP?Ni4P@-d@&Pu`rf(AihPj*S8@-w5+~8)>>bwqhP&QhJo;(P=`*`j9BZXE zK61up7$dgS21!34QYT_bFK?=RJI_f)bM8#5cz1?CFHi%<)O7jmw3Z+L1OHuPl=Ex) zwC%-VF5}nW28Pf5z)N+DdS_0TR8 zo5E@6;jcp=gX`u9X@Ty@w8Gbf>Gu7m)G}qO#6dd_m}WB>n=Q3SIG3=A;#B<#n{5q zIQTQ;C98w;A5FX&&^sqbZevbiWfLgnFhYtJ&L_9on9L!~U``yjdvj$T{I=Ffq;cBf zC$2SSFU$-lZVk=#+fMynHCN_s4v=pc7}&O4;DoR^uS|rk$Q+Kn>c7mEhaQ`s+W16b5Awr=?efr!o043}Q~dM01tjLk4cY)K3f zv>?*#NSAxtt6%r`hOKSkJAQg`ubgwb6N{;#k&#s2Rjb*TuIt^rJ!8(fzuP|ktKVS& zZU#f=jd0y3#+Ci+N$vLtj_Tvzl-^w4mN@U}&g+593e;)_bLEJ@=8cHFPmFdO<|vwb zCZ`!3r`vyjQI7Mwb<1V=rd?N6w^GecCY)Mw{1@)=s1CgNc2^1SHNV?|{};ah{DI#Y zn_-OD(iJG3KyV1(;(Z^=0=6*yefWFU3uWc^q07v`Cxuwtspws)^k(b)`i?^eb9tVw zw#r%<1#ZHaLYl#Bzh|>CnL+2F^EA#Jm);?ib9N8c$(^AlMKYZ@A>tFq{%Jzo~rB+la8MTApGULoJxFu}#fGaQ!})LA?Y zx_PQGTVaMXHp3XPr6ow}0Fk@7+|mzzT3RMMjZ;Cb=w*bX?M@qWkDoBB@d*ayr54P?pQ46~6iNX#xZ~L8C{vao=g_mwT zf7<#yF|6Y&@@?H**z2K!mCFPEUeojvYMGm>t^W4=CX>gj-PD}18ODe$g@Gd;Oq4}x zKTkIoS$g_rez|>bbLpqMYaTkWSeO}^wx_AhSz7x4<{isrt-Z7E%lDkma0R6sXaj~} zbsVArBe#o<$r74aikjG%EFqJUY}NdW9hH*|+fp8S@KvpH3V5B9l-+-U`U!`tXb!Xi z!~R(m)_}R01Z}`@!mqfbq)H;az@cfvxpK5me1q?i=O!;6vn*jL(Qy6YhH^qD_JmXP zD6RRdoA3cwZ^p*?Sx>ngOvSm+o{b(`eag}$$w-0?_ci!ZM=4`cE-!pbZ_>S>>hrTNmF`1iSYKV z5`OgIf#i!*k(rOYZgNUBS9;)5FY7`wW&&p24N(#A0D&Xyh~H*v_!(^^u8Yo5YnS)ozZv zuznvXJ&|&FIak?7T!)vdg)6RT%qm{ad;5jYNtFT?U(2hXaipknZrD+s@WacAo$e;k zks6LEYH$3MmbNWU0%>R8Jb&|N*6SB?U0-mdsPZhN6cyFJEcE&3;-=PT5AM282s8bg zD8=TC%`ir6X%C#3z=URz!P~q01ugDO>eRUqdH;#E@B8DR>23oH*Ux$j{)_*AE|u&* z;rhgvGUwJZb)y_!E~v)FWCZDgv-Z4WV={rXd^j)hu`!uIn#>$}R%}crkcJZHm2x&F z3rMq?tJ0Z`5mL!QTEX{8@W8Kr*0_MGNw;LR(M>) zF`)@fxv#;nz=T(KQj}#4Ut>m>*I`K<39S-w|4-4QKX1Qv3ij*lzcy`u?X!xd?e;CR z_c>!Tj1gOs1g9}D@pZBI1JmyTF~T#R2l@(1mwoo|pNL#QQF4|r^Rj}S!q-phgq&Et zQS;Gnr8i}pABHyKI!CK|4YYv5zdr@BZXD5fAAt>}&L5%gwk(a#5vy?e{Qk|+sVl7) zsS-{%HQe4MZ2XM1$FJ32Z(TC8ym14!pve|zY=$vnOJU$7111jMznS-{=g>CwR`uvp z7Hiam!X8yPF`6;|pLXfup=0vD?7l~DFu1qfQsuohsCf)jolD%h7cqGwy^P%6#`^^&3pI1l>%NYqQ$)Vf6?jABEMkP9YY83fDdfWszDMyXT_=e$UoX;hV^8dtUI+oSAO{Wsr|Rv zRwW$$uj+v*R=66Bp>tOFFB=o>*&?VBBTj zyf&_5=EU7jLc=l@HHAXwuMnFjY1)f_c2Q}8xZPoys&yVy9fLsY`#hr<|A{zbGmH^idV{1O5b5Q$CB%bCpQpJ05 z3=Pdpc`J2aY?ivnnRTD3?b%Q7Z&J?7j)2PIZXlr9aq?V4yw3BwnA-%Ty&GE3@HHt)ZBctZVCfZ%&8DsS%Yw~^MLQhz~Y)5&EO zHPU>b6*xu~>*ld*Fj+MpiMZdtd%CuP*3B35CL>Q&;oRWVwz#mm;P$$MYPpS^mZl7| zzC2l{E+$8{PEy-m=tLE^-uN)@BzYf|@Vrvd=D~HtGqP?@%(5u03n<5kAf=YJAMoCI z(~4~-T>o$P7pfiGI;Hqp!}=NNc2CzjV>65qTe^az6cG7u>(fowZskk${fKPLty#OV zT{hw_a++XxJ_Ek#jqM>HeA64Je{7_VXWNEbR#wiJFRHz{>JarKYCEWe_adgTMf^y-k6eOu z^1w?Flr*tZJo)M$Q`Y5mS}SJxuW;derM<<)8Jl5@*isKDH9&CQM8C)k*@*?mA9Flh zP$nFBZR?eKCl(V^3zO~rzu$Sz{JnR9pyno~)nAUhoS3;3d4z_Ixf?!0!*JOKK0?FR z_!>S!!`1Z^F+y|g0epmp^QH%EgobUeA!39^y|>>a^yRJl{aOts%Y1IN`m77g{3=49 z#tc{2f9MDe{wWD6HHqonm|3>v<_w?A&TCDFTt097aUz8O?w=ck6IyqvUfF&FpYyu? zTY1w9m@E0_)XPnJ>x|7XMr=tElE^@0*N=MBUE(SG|J{>GlgWz<-qU+}8t6t<1Cz)+ zWz%;n4Mnmz6^bQ9USG4^eB}^wlNi@Y5L~@}Y_Ri0&`yHzXb3VY4->xR7arrO|IY7A zVt{etu&ly*GoVdkI-LYzJ%8GnR>}Jb?7KHzS$T4rZ{5Tz^*B;dFXH_B?$YgF_FHUN zdGT{SMTOOtVKZMpUWt^I>a?`WPYUX)P&>@dT zruMAH8ns9Ti6PxOc%`ir6=?j!zAb5pI+SGpvV*Mtbm)HF?;P8#wrjNSRPJW%+vi<$-9eaIVoCEE~q)ua+%H<8$6e04Ls^c9Pra@!+e=%=MF(-dt z(~D-+@HtY|p?qwUkyFl;NO)r!sl1sa|KRZb*RK|<)#l$3Z_Lk#PwY6qn$;PbVT{<) z7$ntz$XWcHI=w-!KEHCZdEe4npuK4Gy`7+2IZTai`CN{dJL8ogE&R7ay1S<~;78p) zc_cq#dk4;0FSD$tWdqOh~H25NXnZfGTD_s-kslRe3XY`0U zV>65qTapANF$m_#UD2q0=>QGG~{~pJGt~=Vwe0A%)1(Tw(9!wTHhFlcQc!E8Jbe_8XkZZ^D=ij*# z-by4l8|S`nNOAVUVi+T~v;+w<5UG_Aba<2AZqq>C<&ksi`VZUw<(vcFHDfl>p1JL* z=gkSm^S&OtasTQ3B*{h9;O-W5ZytwlB7AQiXUlXpCS%A_3Z#3!xn}J}y5~FL&3cx# z4O8|9?f%{G-#Eoa%zFu_vxV*OMk>!@(WT2i>pE<2UK5u22U<3S)a;M1h{)2}JiB+n zrAD(~g^A`Im4wsKYz>8Yg-x*@*E?oUx#TU%u}JengWy|dY=$vnOKqUk1Hn!Tdlc4K zi5%5`cCBV%f|x>>ZJC1;i?NA;(e?0dzjmZMC7L`-DpYz^IhRrSfYfp6Vu8R5+%9Xy{UUqnQ)4AqK)8oL# zZU3j#wn<%yFBL2`H}$P>TX*jL85}8RZW4T?dA5d?$EGi7NuPRFcA3VU=~fqG72G)4 z8Jl5@*wPpz)qqHS2`=GRtJu{TOA@aweOn#XJ;VBw6N{0hslo2ejO8L}5t>#DTqh^E z+uSUCveFEE93Sk8=K0oYx^Hio?~8iTw&hJ=7Ca$ zh4J6wd8+pWr$0YG@B8`fbt+Cq`Hk+hXdW*NgpW0I8nDdDE1#ftU$xb%ZerGyueCz% zJKum#S)xbdXJIy;=JAkk{LHI+r}X+N^P9*A_iu?mFu33Tjq@FHLRZ3%eHYf{*;LcOx(C;$SS4(KTew zD-ArQ?|J@IQ*hv+t90sC4Sc#;d<8o4LxcXip?Mr@r?JX~;D-vLrgw^`RtUU9xkG-5 zB=&T}b$_FQ?L_s%n@nEa{+o5g@;YQjo>%x>2D68k)>UDJYoW4F@+-dR4+pP8h;Gw_ErnxT!E27UOQ-&{*Su`wA#yIV_c zu`!uI)s*~ZV={xBf6l(9SZY64gWir;8yc^FT2?j3VrIwFF2!Lqen{75GuJX6=xrSw z)t3cyME~Eln%T1~`YZ2QcI9l>fYT`Fh+6qq8xLw zq8MArvMj#%$?=TXwA*W5m{lo$6RxdS_^UD18Jl5@*isKDH9+vSjJ6kvmBsSEircAf z8I>D!CX~ixa+kS)mYA9uEYkKfTAO7Tc|KXm;iF>JgU%Cs=RxW!=&;|KdGG-qF7ZF` z0Upj>LTrqXi3~2bF!%ruuS7cEN>#=FOLsCCO-)NNFj}UgDQh{5N~JYBU;{k#E|o;y zMXc;xWs_UMd$Q-NZYQth#8xV;I+~xb+=A`(-Z?+DLfM@E@yXdq#``&A zGmH^iY6GPn2>!aQw6h)i8~mnU&bu$*H~q4iWEX$h;3jzJ zp{eCl-QOE8Toi3FySNKS!-r-?64$!lu>GStK|GMq;1WIt8*`>))%(CTe01)!C&%n? z2)R)#A~I`2-_L2w>QJufz@D7eN1X0+|I&YKh3dJ5mjci1TdyH@&h4Z#Hp3XPB|J#r zfyf*Gzmy2wny}c{aD$Q1`S^L&y3>0=vl0g8FI6rS7`}*#d2*unPR#*TUSR{X|HKqY zTpJCs7fB^alG9d~u8o;t9lvAFnyW1jbf?}MMn%#_?|~|kf}U^j3zrYlZe*1&c5V2| zb+kdw9l1!_I0sviv_4|4ndgl4Vd{NR)55J5O3Z%CDi!+C8Jl5@*isuP^+2$7dflz+ zA9{1`#U%NbM1{4ioo+P)yiCmO)s;okPQ^>O&d$y<&fI@;<;?@?QQ&5^8KhcctrcNo zGJ|xxIG6rpW3qsBwYWBy_6J3^irf*aSikYVSZ&*zrZq~JLWj~gGuP&R=y|0aKWm`} zt8gm2Ll0KrwAP2E7J82;CjQr*u*h(Shgq(V^n?#vH=mgA{Q^g7*?bBx|7XMr`Q{l2SnAttDCo?!NgezAVppK0V-6E~LbPG>zF`X~R40oJCvV9d?dQH{l(2uC0sV z9d_0|-{!Q>=`r;9^!Ve{X+M@5FFG-S$;NuL%mGCM=|?1UZQTp)uygqz>lIY_cIv9o zP3iVUCFk!=?9NfUXoZ}Lwh6$?9F$bl93l7MLVo9?ABP&+H(XDyed>ECz!{rijM&l} z$l(yY`NrlIFDDrFhuh6A+ZUPWyu3x85t3G*B}AK>E?H; zW9Qw>i`_SjQp)z1u=0iu4Q7;-;-T$#Nmn?y z4l;tI6prN^*_ccq^$y#`X>3epkOniCUfPuOnUaDApHv4q*tF7drmviybC$C?5Tm5 zASkJ2&a~SPYv)O;obVQ2rOsj37&CRJk~22L7_p@*NJ;^buB9<29IXW{#f}AXUFPF1 zT;uqj#fin#%*f+Y772-ks8sD}=u3Pk^)P80mc;yys?>N$V$6WhD<9*I@-hDlz zU0U{6*N+KhH!WwofR-OqXY!IdDP&(hbniIQ+P=Y`LiW8`fBdqs_T-5lU!1=&^I5E| z@Ir0m6tZs~_7t*)`P~T_xd)z-JUtET)}LF!FZEQ>8Jl5@*wPXxZ9s7P8dFd4<4teR zRIdKcY||OQx@+SjNIHP5!(zY0!3MibiamqvZhbn(`NQd}m?zKf{lMgK%_Kc>A@QRr zTnEabmq~F(=s_=&BKBw!!~pNG98K}HXB0niV$p0S)pK5ped`>};?}SbP6r2;eKlBq z@o9;Rz~8U+n*Kjy*DvbMf9QE)iMm%o0TdG4Jj|D^%!;||64#i4p^t7aBI z3_ifHM|+)E{rv9%|LS6gSRgZEOWO0$IW%*ogeFTtq?1{tj4>izx{E> zW*8&36az{D5Nvj&r(oHFO9vlK@G@U!Fi-JN+=_KhEEa|qhKg3wX)d9X+N_0@X{RT9 zy}MSNmx;WXfnjnx?35Y~(YNr$46Hj^V5ih@9cgzr**?uiVDe4>*w|0U=c&heHcXu` zQqm3Ak%iF33}jrIj96`jJ>6WJF@=5J=?p$o0oHSuHpd&^E}ZF%Bi$T%hLmnB`i0Uv zA9{UgzFt~=CBQI%xxRI>Gd9B*v86CbngNk3xVcu{S#;apTESw$YL!PD%;el6^J!;#!Fk({#By7$AZeMcsx|B`xQe|r9oT_|nW z;}-Ci2}+9kWq-iug@knXS*E3#vmdzdxxTegamHpCBet{$i53vqbh7u8Tf?f?C#oyY zwL~YkxBE=xb7C(K z?oE4^xp98FV3CAeE@4kaC+h;=2H#2Acv`C`{rHr#jW_)`9RE-e5tb*Y<&4Az%3rwm361X z5%)?tWjt^w*vN3+^Uka1iT&~qc_l9VdEP%-&VT|LX*~9HA@p7;&RJh&KynNW9B=fY z>x4P3dBIvd$m6l%Gt=LE`7ZQqk~vGo$CkN2>-fjY?(0P&``RztZCXp+O3=!uRW>V{?wso<)`cZADF(r;u4N@c8&wyLONMD zn7r?5W21_c09bbo1-8*Kfo0NRd8Jl5@*islI&49>dtBdB8tq-2|R>+k1euj8oT5-`mCl+HvQ^TTC zzQgmIeGFF5zP)eN;u`G}*Oo5=kN6rw`srMkB-t1tN3^j%$z@}*fJ_gt|Ezfb=&p#x ztAx0{7gm_*Y~%GjGF9mXIf;eqk}<5&jJOkgBqx^3VvjCM&rv>65zBJWaM8}&Up>Q6 zE}=rI%r503C6-oAX%5M3kzc(+K5tK*G-O~ozjwMbHp3XPB`Z)ef#4;w`|mJDCtS&h zKJm$5u?1($j8$o%ZkUmg8^?FG&fhO5pN&|(jFYi&iKtogA#h@WU8#8m)UARh9Mq=I zWya$xFQ4}A>@(ca=`8A?yK(CEAU{TiM9k|DM{pPGN`f>b3P@=BJekct@s{eI*I^xv z{zfJ;jPt+i2_Y9PS7yVTJ}9Y0!Q5uT?MWUBS8q7|e`2)brL#`Af}F7##)vIlL7WL9 zOO9QfH>;hkyKKSdfEP{Dt&Os3q2P`b^mtHW&O%}@I03)jj%|UtTZ)vDboJ@@^G$OU z?Q3VTOc9by9hN1_wG!xANL=tumNad?Tsly#%6Vd2gVjIrlHcJ6Us$j8FT#;lt{q1z zSyV12oZ9g1ZodD?4ed6DZCQDFHDS)!3}eKWsz9j(f)lP;ZLZ6BpeD#HSK-vJz3=e- zY15rp%*+kV>=~6dNtxPb7ayuQQ&ux^-Fz7%Zt%b$bbBt>jRlD9xm@?yVB2#!zI=dh z&t+K{*88S5WouSLymign4ZB?SPgk#dzGj$r!Efw>ZqMbS^2TnIF8IEr+uOMge0)~m zs+uOC`Z<&P>vmkF3{uLu$++ZWq{y`?b2uJ-IkH6IU0dd@-E4-=*bHODmc}5d21I7c zar|)2EThdbUP4U65V9%`1b3h-pq%$7c$A* z@N2g75V`Z_n=>}Uu%Ey*|H8bu6@oR|#_O_(z7R=f{+ z8S$jkm0vsP-Ag$U&R57y9L~yCHYVuk4rgFDVsz)OmW$ER%R66G?RV|_zI)?>JM!C( zs~j0kETHgayWs~L|GVo9YvP-&LGHsI#hOLeow>Oy4B$vI;)3~RCiIUIro*(08vR$0T&R#mj(y2S1E zSHG&sII)c=DgcD8r7RBWpSrxpSm=eX{NGgKetk@V|2v+V5Y zSEpxgwO;upvS$c1i0>B?w{ea->t)Dk5XV%Um+D%)M|-}-F}IVqJdfX5%JC36wcK9= zZxExTmTKKI*@|f$;ac17ZatAxViVUG>F$ipFh*?Y3X)PlB**G06_sX>#F=+>?Jixm zwaEO1{TC+|OCv+GEBE-8z54cR^^StQSWd|LLsZ{X+C zav>e5g?eUyg+WEuzqz;h;&^+R+>GN7HE7-uqOXuRH7YU z+fGMkY=$vnOOl`@2EldWoQ1WG-yUeP_3$mp5My4xKa|ah#mvak=&kSJgirjJ_p!G= zv*ds9CA)T_a~h;rf=rPzaRsw6nL#GHxE{Y_W3q&9q7yxL^~>9>O_E0(m?eY{%$YLt zh_i6pD}t%z2?sT%LWg&1c_lZYhGD}5`Q4^7H(c}Ui$5o;6M$SSJ#ogKS~ODXve_Dh zM8vWz#h<%JW*wZ?ZS0KAFh*?Y3X)Plq=$!fVi><0SI4X`&s_gM3DD}8>*>T|W@=)T z|7g}3%ghp;^zXT5l2boeJW@Kn1>E<74FNurVPi6aq#Ty_r(nZ@Y^@M4HB&)J&YwQ)Ca3Gg^~?-9960D#b5hG7#K0ogw8_@V0B& zHNmG(%0z7Wkbms26SJ|Yxvl<wMr3*5j0BsR-y~<)^GJ~wnVfog>#$*ZI z|HgCesO;Hkm-hTw)Rt-ecjGmoqmE2^xUQRDg}Lz`u`ZOpB?#B6W@w9;BhLrA=MC%K zQrLFc5?O*!m{=}HP29jJ^XSk|tM^t@>#MJ<`nukRa0&8iU;f7Q<)=j_cy+#ys`XrF zDAjaIZkaPS!x*t8D`-MtU|?AJJip$(r~0u@!{^=HH3#w-bX9jdu^1Xz8dw{sabLgJ zyxDjjXJ?6$-SZDJ;%mVT73dC0t~b-+J0v-TPs4Xea^x9xC$O`ZIn7d=`tirI)h039 zRU9+!4*sGAky^OkY#f}aEU3wru5E zp!)UC_Bj{BKIsf#VtIED)(677fqw`jmIcgrgR&oUs|kh%H$m5=$PJqG5&LbM(W&-LLGe5rAPmw$li zx^tJ@n3oiA+?sVjTO@ExSN(`dHy?SROO3Iem``Dqv@=9y);!UV{;F&T{tCG!NaTLj zUQamPd<-=Cu~Aa`ihrDtjvAx??6B9;A9R*GV>65qTM9#@n{mbB@OydQOjHxI{Gk7~@V&`aFC_g}FXE!*RQO}y${TxY3mN0%f1E6wee&l_Pyan4 zU!1WS#)vJkA(BvQX>2W1$kL}1n1w^`M7I2Y|DD&@iN(;&*yPN91&adRF3pQ> zJ-tS5zP58g!UfyW`9pr3PwDaHtzRt?n=^kor7lo-dHbs7g`db})z`o9ksFkRCeYFH z@$qsU$0^2}gl~3Pce?5`Om@a*7$deM2?n+`4DgXYJl@W*L%P!f^Ii>=jGq9j!n(GY7bYu-`!pCtfaE(M_SDv-9zG=z`Gv| zA>%t-e?sB=emN(pOXV|c5jRoZXp^LnHoxmjuS1+g9Pv{NTz~S(-(@wtD=6vLiy!>? zIwj%@bMJz!f2;)0a&d4Wr;tC0{ohCx)UTQisVr}%-E1QI{3@S3F(un{)SIkTluUj zzhiDKIE5HPI$>P@%GsDqA*qGaezNMcZ;z*2amR$dd3o(Q+cG7C%IE;fQV7?-iNx*0 z8{R2|_vbB z)iO++u^GmQEiFM(2Z*$3TVlSqN3$mIR=bS`n{}|!zixX-XB@g%*k}%Xiiut39&Cz< z^T0CrigVWdw*d!uUaeD`b?Vpm3G+{NT-G(N-Jguol?r{y2(pcV0ci~}d~Om^fN(R+ zgiSGxCJzQK|6^@#vVV@<{B>6Pp3{*Rsa4gPFZK!`B@b?f``DAm_wVJ4eg4f{mYML) z@7flV_F&@-XJ>4NF=9(dkf;KYpA?j?ZoBoe_TfhFIsXg(-{=)P+>G2|Vx!K*z08Uc zh+R_Zy{r|vFJgE)zOYMQ@?7&aHnq@r7w8gAI<#20nRdWBOo&rGhfj;e|AyO{iF1S` z-k*)z6l;GqNao^(lLV6!H?y9*@V+t&>4m%7Rq{S%SSS4RF$tXMjLk4cYzYsPkRZ7J zy8V{p9laZLJoo=T(iXza^7_+Z(1|sc1_|7028Xp4-c>$&l_88HQ}I>RwLEb97P`!s z%{~>r%$U>cD12!#H!HiK_k$U|g3MKVz7unl8I4v=Zt`y)-h~f0t0HV^F|h}ole1n+ zG%+<*>CSAU6|Yx6TBh>)m5g63^4?8u))*{>4>z-(Xt-75kNW+J55>B*?;1%qF00xU z<&4cRMr`Q{l2SnAgs7d3(r=%h&$oHDMP=%WBN_#tE1g)3ElkZDHgbK~={a@gsx|k{ z+S^J+>^zl*QY>*&fAc0cyJ^9rmjCBoq&pdj8amk>%PSGE30)8+`Ol}^MJ|>Q35}cmC~Uxxn^`aEvtom^ zF4K*y$MTjLk4cY)KN7#31FM` zT8`aJC`w+J`sBHqxVlPK>yH0d%CsllBbXh{_yp?tjpw7x<5Q9KbTChtYSAME#9xO(9~{{tsriPhT2Sg(J1_Si;L3F7DNG zzgpMSKl^fRqD1z2J&#p~pDQamV>65qTe!7OH~pfMxl`>~F5*C43{I-AbTCj_5O=iFBTpG{}(h+Ve9Y`sU0 z$6l%ajSRtC-Y;TU)NO;3TIkvjp$tnBOeya&6f^q3UQ;PmP7XIxVWs7WQ0z%SYNK$BO9V?8{>@4Fh*?Y3X)PlWYFel z3y#Z2m$x5OF6KGea{=9pP|`l?xt82Hl+;Ws>Rd^hV|LG32s^S*#mg zws6HALzFE74htOQosVfewAgp#7f;!ig-Zlu1O*0vYT*`$f|f0uds3hab(p(mLyt0N zUsVo0%A5mxY=$vnOIM(D0>MR04NASuI!kWm#a|HKd)u;e#svl^7DGcb%h;}E z`=2Wpz2-NwZ9e|M{OYtH{E4KtXSjv(klQmc=L4;z^KIXxN0iU}>~58O>44(uVcDJ$ z>Y#6XMuBO{=3~sum!E3i*1&&!jVyEBR42lzNa%K2U1h*!?r$eAeVp;*?%C;ED_L*3 zIb$=75nFnLq#zKvqOVo7W6$|t9S^OhxNlv0R_3FDzY~j*v6<22_&tA(uH8DjcH`7* zZeDLH(jN&zE?%{S3?6ffYr0@NEmUr|aEqMd1UZ_4 zfs($`5NNkBXHHXlGXI+M?OkP?n6l#+^Kt*Xfg@Fje1x}Kgl=C9V$YcR=7Z<0L$UsM zPp9Q^hkIRf#%35Jw)6uDS`Zl?fRV#5J`zqFO#S{0%?F&vlGN z~2<;rzzG7oChRjBAutcyinL@hQ%-mPmn9Lw-)@QTW7$M8m zxh0v_`zXYOtv_v*JmXAK>hHv*78z#?kkb&iq%^G0G_-rzSZXAirlF(uSx3B_zK9x4 zGY!i+c)Yda)_deDTDXzgHArQTWUkNr&ws=dL)GMSwKDiRYurw)`&i|S%`ir6sST2T zKxBx8(WZ#9YJE-(`I92tMV+Vq#)o;KKUWKYLF0W!dB;r3Iw?%M+Bio3e8#dV z+ojJLn_-ODQWzx7fJp!MXa2uTUVSy!G{w~7)3{zS`=*H-E@@H!Zzo0 z-;(`x7OD?eH!&N|6FhqU#yMwfhB0DGSD;V9{2tjZYC2}k(*fnQ(0yIRA@j#ITKM6JY;6OK|T_Js3q z!4{v(N9M(Uxv{^Jcm7U^l&wp`ov|6lh%Jdh5)FvdPt*ImhI6an+wJ!DnQrT@*%#NA zIk6ZSnHeQn|FaCuJ1w)o=*^tzVKFL22R))82?u(nfaX6oCL?Hn%>Od{syc2JKQ`Fi z@?4hg1^H*|xPFIkjPcu5tjjEH9J}-fXu~HWcMK9w>IV$UsDyZ!pMxrVE|2x|L&)dDCN|f%O8fAl1v^+LZY7+G)V``pt4&Q6t-Z=N z>s0pJnxnt%{V%U_#%35Jw)6&aI0Vo8VK1nBpu&CixhZphvwMr*6<{nOW_JVgdUiJW zr4P7wH>9)p9cBL$*RMLqMMT6h_gsOU@D1$ghFjwtsk0G&Yxsn+T^HP2E%HXM5dr4xIRTg>k^7N+B^W!Q8jb*bHODmck%u21KrC zf40O?D4O$Fn1{iN%9WDXhO;n@B3;HurBDi7{#$iJ1)keIXo`3$i}&~jw>0zt$G&u~s5+}a8f zpkQTS;7rt#gs>mk4=>A*3dxKndzU3gCLbUxG)MIakgu0$r7oRHr zm9ICi>3{JJXKaQsVoOU9r-R6EinCsM&Zs@ilA~7|YToqCVu|ToCl*6v6Vn8(T;)c& zX%njV&iqi$vEf@DL%?NXMtHb&H4t0(x}LHznLt`U#EtN%JgksfTd!d*{rZPZv1)v& zU>nm6Iu%8_PJ?EIhXx5vDz=~RDx3cg*<%wdo$3ymT1{A#NI0SC?&x^@_4W(Hy2{Rs z`?K5r-ALZ?!8+L)n_-ODk|ZdJL9kwkNouC_mkw#UXAH>^kL@n9tSxk6F|{x-Wm}y$ z>v_$&ZJie#U%9=j(^}5sx(VDBq~yGWS^?I*HO#$I@)()?W=hqKhj`3$~Aj$b;7h)1((oo6T+N3SASFGZP$6b?6$! zZ29oEtiKXRYSDiNZ#L`h*f95=zWjoJrE(t4^Del}QDDoM^2HgOVT{<)6(psA$jMB< zHcq>$_10m+^6>AmCJ*=RytL7Y#n{ZisF^v$wcX`=?CJAd%V+$vQE@J;y@gyX5woM1 z+i*X;SR(G^z+ScZ%wPY$na8dX>iPWjcGN=A)x9VQjb=T2Zo`|fVhMh7;4m5zs*k!h zvGdf!1-A1k$$Xz%iYw*uMeC|-Qm=3%7LyvJQc2tO*++Jpn7fl4PF&sJ ze=S0+bXBf1Hp3XPB`Zim0g;uG>jLLbTb2?P=5V<2XUP4COP4M=F`FA2ev_OJCl+IKbHk4%C#t+o345RWcs$zsVA|sIir=}whf*3sj=1HvddYoY z!6m2pITAOgbjQiFJA6^O`7L*}1OWvr(k*->@8sgPWY~v~7-TZA|JbPJ^{G zRVN_VRMu+PN)Std5B}ku+O`a9TNGN)PFQz%U(2=BZf9(UF=9(UAcsS+yW1~0&UrTr z7P56e)>ybyvFzUe>7Yep7Us>Iea_c4bgsV2c9C8rS{r@{Sfh#R8uHf>u>r!fW9BwK!V5;rq3?(%a!{ zn%PSw&dk-ED--2DAxikZx&E$}^B-TIUx$)DXxG1@Yg2~XJ_A}k(PL#iw>2}5*UAmC zttSI`8u|_Gb=DeHEjod+3ekQ&ydXkJAMFj=!IB07*3?_2d&gAQkGhB0DG zNuZPg!Exfu440 z3Ald+Jsy|au>;pWisUcsm9Dmm0s1R0yjOL8!;!7G{nQXhEsl#w+($w8)UxUNQNDZK z8$Pyqf2%wlusYsV;Zg>2wdHshduq|@R<(9e`|-_e-$6zTlN#B+Whu{{u^GmQEnPuU z3W$6iIs+4i-fg@+u)l7D{hSQn%Qx}4F-D8K(sRMF1BDa{HCtJXG`*)J6He+)@2 z&_P1yZSX-t&YU3lAR(vbB!L#)lG5KLTGAt!G=)&pm)rRQY>@CkIc$&+ z+i~ppXSe7(q)hLo?=i+%nVCkP?llQX&C3mc@?K*~rU&8F;=--pR~YYh?NoJW)qxwv z9fy9ZF3o!iN(~=-1O6f$<=>; zSH3>E=w9ud{VabZmc`zK)Jo8%uj>;wCL_q~7R#D2HYQ`p(r0!DRyHO}NQ&a(52)Sc z7QVCW5KC_Ddp4^Bg{z%o(v48cnL*TQ;dcGU4+)kb&}#X{l^(W|``D-J4F20fJwvP4 zy*tj1Bjvcc!dopa+|RDu*(qxLMTaH+`^UonokFMFZqz$tGmH^i8iNE6h|JDRpTw=V zxbOGMimMkkyKAIZU0ez}=)lk~f-mlp zKjLstNYPPv!^-~TWgAM`Dmp<6F<@8hrL(g!LRJiNdTe52GKMVWVct3ce#IW=jGgc+ z_Bdqf;aBW&*{&~Bv1mVDer$T7SKE`9^R2XY^{?BHQrys?5zOrs4!xd;=t+jb->eDu zaXNqfER$|W^X2IFd>fHsj=~(|RO7V;-mF0?ZanI~1+_lgcl*7_Q$2tAs?*KB_SZwM zIb$=75nK9#q!s6!Y=<@3zoX6m&kWiAliI&m~EFPI;xC;%Qy@ zFStvk`gaewS%c*oVQ!yZ#2tH18KntEu?k+F-d)?d>y_ zzG->j!^J*>2#+(Kprtv6kfk}yj2vuCrjW)9=h-cF#!2SqESPV)tWj3e@u-RMe;{-j zB^``5QWy|>8@T;;L(>7ayB1NFj#|&H{3KPhZB`feU;S^Zt@H()emdhw2Y#>MjTDbM zP9w=S--#!lICkmIUwh(#$RD4Q&(7EkW5kwXKq&x%x0V@lY2SHh{3EVc*5T5pK+Sn9 z4NffPCYDBhAHwuE*8Xp)d;PL#-LsWNxh+o*Bah)xG6&8ba2Pg*hc?~xL9l7Xso$U6 zc6N*ZG2y&)qx8KU>S;{0tDXYxLdWn1d-X(Cfg|z#dY{_fkKS49*F0PBHgfeEXWQ?{ z2`w-fUf`f4v`a2-tJT-GmrHNm`#AmA>WKdh$1gi$GmH^il7u8O5VR>T+CuU0{%T~ZiDJIG@`|ac7X|ba z?is89+L1Kz)|oZV*bHODmV7|T0fKq6_KMFn6)fLyCi&L8!&+@AchaYVCccd<-gt^; z7|mRs!u|c+?eYiGe>3yA^ueVGbWVyp@)0p}QY+77-wCf2J?l4BEN7Y0ofx4;&pAWA zIKi57BL9#*Cq-7u=`fJ$Roq|2Yktq`%6$&kUz3CEP>Pc%`2DZkD8)(T;e^JGVw0rp zvL(20e(#98Jl5@*wPpz)qu!DpERC7+V!<6xMK1rem2nwEdpyromh;_EltvE zSL$o;>zaF5b5mQm!B3_a)eaNET`%aa2sZU}_^t@<7@6*08jAv(8Rsz`-QZhPz^{Jc zrPle8mqNH>%%Hm>*e$!DyCNv;g7bMKc>n>bd z%+&w&uf!i0Pn5CZxCrRsDTu8#*rumO$BG#kP&Qw6cdZae$k8eDWnIhoms{9$_5qHI zgcDKRs$aWx%w`$=Hr-$>O_I#~GVpjM&l-C_O-M=JP^#@1+HC+wA$W{8zM=233a416@^b zWbxtnroC~e{zMym`cdievCURQ=!h&hRlp8;OPYDTUF5#H)%#a>I-HktOX!^Z%)h-pRt_#W`4tW-4Ewi;z$)q*Wf+lgaZq6uUuZI zx2slFFS{(VCO}p=AbqzpHp3XPr5{L&0Fml%4a+7!EX`t^D1GRw;+u@QaiyY8EanEL zmNq_W)A%2q;Hvz=<6dTL{yJfnOAGRhQ`H6djMGmZ_>2?Rx<~LCC${r$@EIrWl=bi# zCpMGpIHs>1AJ2x}oSxvy*ukjQyy(s(NqUzu+$kraGfrGIyZ3>c$fXffD`hrR+r~?< zoT-|0(%0xV*TK_U7ERP9oSstEs`3IZXvaCvNw^-G^h*6y^TA(&zRuVTW5ky7Kq(1= z)vBlG=Nm`1te)`UOT~+Y$#turUv*+OvM@Sl5n298I&}A>v}ydYr&-Ix6+V`OC!Aob zuG0R)S6!iN82@&0Hex>?oP&56at)WV=l0m;Z}LVhod?pS<_4W%Vy=r55f? zH|QZsT$#5yKwe;A;HFMhHTYA@y|9OAUMrktZB6{T;K`~l^JfZ+y5mSKnT<%P<+h=n z=cR|DYuuOZu1vd|#4UR{JJcDQVT{<)6(o>BhUFR zMoAUJWi$@&mW&A&_OR+>-xrCNvk%;3>D=tV0BxauOzUMnLhZ#H9*)9`MpaOZYGFCD_Rfr)BOmE-`^&U}Zi zd#C>>F&g-2nEud6K zBIp0O)V@Gw!|b=54}8=XHTB=C-)iQ>Vrgt-=4jh9)#P==gttxq@?OqxKAf{zA_+Vi z2fZ?pJAW1Om5EJ)r>-@AxfSd&Pj%ID)lc(6&$#@dtZd=VKLWinaiFGuNFT4ILD{0> z)mEBiB>(byYsmu9mbjes`D_1PPn*4{&!NwW#lq6SgiB6%n+mJIdb14|_bjup zytmo-F8Ev|*m68u1z6{ZD=GxhIl6TV-Z|n@Ux(-%6`p~2ju_9CzgXgY)p*^qrze+w z+xYX!hAV037cN6dPZV^viEY7f7e0e^j&=z{@AlxFlEe!M7_JB(J_rkG8hY@zU{-L| z^c?C|v^@2_x3%U^-mUrkt9x;zry^%~3nuqs_WsR9Tk9$(eeu>YYkBUlG5`0vNM~$@ zF=9)3kbnY_l8vIfPKIiz$t^IL|5Z6F|F-JX8=&!u`2?-beo!&*nMwSi#7}Tr=~$%qITfopQKK z%wTmD$;Zu-&{I;&*~s;-F`h+pq2$uch5(JeuWBgA6eE>HCACN?=lDz$)lc&e9sA#y ztN#5r3v+$Qx=?3qhB0DGW1utx!Ruu?+?YNyEt7h-QRbJn(fP;iC(k*t7?~Panz_Vh z))xr%1pa$3cvO?&^S47gbdl!;xXVDh3?NH`Szp|T&kHc^l!PCu&OW~jcBnc_%VI$V z!&uAkx(Ug8YbBXdLxe;*D}Nv-BJQ#R=)3@dD_-HN8Ahu!1_o|x=3l>s67mc+_Gmdh zFI@OF(lfO)K^eLDDLVwO&QKDO+_7i>_Pbm0UC?XfYmwN-xl>{LFK29qF=9(@kOTxG zPduOcIg;;eZE~gG?T3#(+K8HQ&2nO~G%>JjohHTnKee>%jOE3Jd6)dpukpMz1$nFw zQJryD%qF!u+xLFwnXWd*IYOPH0XZ{z)Z-4t=_02mPI^>l6O}u_lMPe`4`QYVFET#rV#;Y?9^E=Lvj@#B^-m_6<@izJ8@uA=b zv>~L6#nm9m#$*9qDpU1(`}H$P$9@ZaSvzUHm>=Krnya(LL6=G+4*8?QOeFr%VD4&G zXoH9I?-J;CC$3k`umQd|8===zapgHducu;t+YDPOGwZqtB)|}(!F1|kotEuWxe>JD z+w&a{5~PKmyg8TDphGx?RGYAE{k40K@T*r}oOXVk&ykhYCT}s(8Jl5@*wPZjvmkQg ziMdl5vM+l+S5WQdRa1Q16F>2a6N|Z#q4@>Vu%b;39O+l4WrpW_Dw(8S?pOmJ;Dc^= z;;!X|Ew)2D2iLajQM>svzZxk)5ZS~@GxWE>6#`O|YR=M-*2N}-T3}eKW z@*rsmMCN^;qj=Z!RY08Jg=6W~U8)_wQn{U242{f;diH1^SGL>`ELx-?6)CyX(Ese> zso*v7BfO!*kK+*~N=r#s&O&oxrd&X;`MB#wD;dd-NG4 zZ2Y_RxFNTmzWjp;lVUfftiQ}#TuwL@HGbcgE8`Zs@cU9{feX*?WEu#FFb4KIV>65q zTY3Yf9|%?{7Jqx`_uJyU1t%}RGQXBp+;!OtbOOJr#ex#w3Z0`X_C3#A>c3i?&*_L_ zuK{wOoxAx0yw8qje0jd^iL<{8s@?bP`R_Nop(TA*LDZ6Ao^qOB!TRiCuzS!D2V_xg zd^wC&Zo1`8iTM$6A@1{+*?0X&{F_BM<+Ki667?|<_hnEBeii_3|FZ(F?oMFc3|xud6j^`q#4tdR-SamW*8&3 z)B{Ql5WIhm!m`sV3Qq4Z^F8R!vUrW++mlS-ng_aylWp!l_!W5U)#u@(HSAgH@X;C$ zllQRE8V+-xW&fn*EpLVF7CEXXmEH27B}>$=54kza-601XtvUY?dW1gKJxim_VFr|4 zn2wICmL9W-NeL<4D(-)zr2e{S6v}7~Qc~$CfH#L*49(vhGRPFYxI@8vu5XEAWQJRp zu&^^W!x*t8Do8Q`kw27}5NOwN@d*|P#sYho2Tr49w-9K*O zYJSju7J78jyON=s+;qlf7$deM2})uR>}zbLeM5hf_r2{iHBwGYj(;Tn z$-#-m!o<=dzf)~qte=-rBG(_2HR5h1j}~3H0dCJExI(3!CpZ13Vv_s=TCm&cfVIAV_%P#+^;hiP2-%g8ODe$g@Gd;OuY6w%xu@SIZ}@Q z+^-(BbM}{WqxhYe%qGZN5##qg~3**bHODma4$X1Wep!E!i?jz3t6` z2Dj8-appXx#g*w!EM}HQhIbtw{dl~^W5Se0=bmKFQ3&1@D6@x{GG?L}QW+CFS<+R^ ztWB$9vB&1Gm$Y@B#D&qT_dW1s%tQm)l`)!yk}q~2TQk?&X2;)O0^3R->26CPoNgwT zs$^PviqssMpVuV3@KlAlJX}Y%Pn3X z>9}}eclw?NZ!hOxiJ&!K`1@bfE{7&(K*t2Bb0E^7SkdDkc$LQ|g=JU3jH9z_*S$L& z*zmv;IXz82ime=)SSr@AL)$?nf(*DwXTNLO_25qn|&&L%!bqKD12=NgXGBz-==Lku=Xu?Vy8i)Z_#r@ zz1OQa>0UR{H%&~P2OX#3T6_go#=!SnQf&pP(gvGWH?E6C{a1eYn&11rLH5S^I^;Al z^(OW-v3PmRx0-Y2$DZB$HEOVZ>r|ziy z=>;A3jQ5;Cca@o@9oT!^d2#gnL#dHb#j|fVw*9clL7B#kFhWdYPT%CMaR0)egKPp% zHz`KE@lMloZdXb`Ng)H?73ZFQ20D#NopoE>^jUrLvDZmfKq1jYa_Vh?jN7LlZQq*8 ziz9_h{|)boPb@tXvO2zR(R7#F$(LLA&fsRaSD!w~8Jl5@*wPX>aexVr`XWzZd-o^a zUJd89cy?Wyu{ARtbXS?7`5fcT)>?N?|D6B1&m(BRP;c)%o3VSDosdYPr(`6yTiD;HX?DanT2g{etz0ZHhnB~tS{;-;tHO|-!W5kx+ z!087}6c#^`^L@U&VM6}eWnCE>;wKvHE`g?_j0}X76Es?8M=m^bckzF3>G}`8&l?~I zQX3hAb#l*An zbWJVXbBv)&MY)8JL6?eBY4Q@=pbRY=zDB!Ng)R&8d!!wFT6KxlM!S)6gScl!`$=SaUC(7z+;^CqN;?6 zZR6K|p|^jnHR;<_V>Uisn%`ir6X$+ibzy#yhitTbCLU(o? z%+z1D%ermz{LrbOBP5K?mLGI{{4bbE=PKLR3c1fygv3|Rjz{V;k-CgxK_h(8I-5y$ z{T^*qXHD&6=TsCt2-Z9Lg7Poqgw4!;_Zz0?FrJJ??xW+3AeUFh*=C51f?1gbRcFGrLh*=FS__zeg3M6 zxtDTQA4ss^TJi4Xj7fW0=w3c8dJRoaTv#?iAT_4v4WaTW(E8H7r<2`2@3uOW^;=}` z#kYB#e{rOz#UAkTX~7S?t&ozN`6n(&bQl!}*q=nvD@UeYI4P zjmaF+^x=H_n2pI2(r4%FZDV7yv;-T@m3eUDG=Yb-B{F_ z5anKKjc5Na_i#)&CcPmlfBmc%ub5Q#a_Qmu&L3M`AK*whOA-5j7yR%j+x1g8O83Xy zQj?XRo}3ggT9%;fjLk4cY)K3ptzaT?cD+uCLwR0s(gJtWdm3f-pN(!fu^1Yf7(JWq zw_@4V-N|?V=&J44zGp0HaT{`&HI@c6_wp#@2DIj99_!-X(j7BvKJGEmdcdN0J^#f3 zR$I$UhD!rlz;fQzRM9&g{pmBC?f9;L+1|4`mvCxXzMf~+%>%oi-94B-w|VELg|%~) zJe8xJu^GmQEnR^V3Yd`ZpTYZ)Q)ks?wVV9XQyO_ht>oiC7m=BnBx?$JxqGpEm~nK) z!OW_69e)?r&q1!XNE=UnZUwS(|e~ABkeIrdlNF1fwqQ?x@ z%0i!LL_^cf|rb?W=;bj$IqYcs!M#}3W}=9y6_7ci{+4<98&Dt(r(KjJ%ot;S@f zrEAwc;(vVoNpD^M&uz}w3}eKW^1w+6OcZY8bo1?9qNQxLbH>xIo6AkMt$GI9JY!^W zQ1G|rJuRl!OQfQ%a5AlnYhDqT1|Cy}9i^`*$;M<3?Y<{`h99NRz52$IOr7kaXYcv` zokNa_NITwXD$vaFQ zd-TDjnMjQswp(6^M$W24cq50+ZwI`Q!@Z8}j)1F_rS=w{OD!Dfb3eZRnR7DBn)<~I z_c{e=BZp;5J?uO##EHYhv6%T=F#r0c`gQ!MbETCgR^3M@R;_Oj>`txSB z97{#7^VFxzO)D44ZQrvpifXB4LnQP_oDrB>VwHLonk|Ba7P*P*ZMzy@`15QM%8@u5 zreIGkVg7H6n&u~6=+2wVcrHQ2S21^*kTW*J7_p@*a6$nSeis`jUAeRIlBa<=w_Mw* z>eo~E=YWo|Ff@5Cx3z)MZJ*`=d6N$eESuYdyMt`NsRg^E-1tPam?QFn@~!JEW+o)iI>ZfQ_f0~ zxpE;Ts_h9^9`G_KA(t&ksb$k4c+Y!{?zZ`lp8mL|{8r+$!bZOEDej-wW;HltGmH^i zx&kK@FtJ{q@6+d_o4yq%pI!3NXpRB*&|I58PTG3^jjq+AVpX9&LfL=??3HbYd4o(5?j8GFt%ba|X^mDbO97%w4mgJ2VL_ zh@eliHht>D(4P{UkG+)3D=t65*>1+tk8;<`mTT}51SL&u++!B`{o>EXEbM#RCUfsm zjk?hB#u=MojM!2SBv3%)J1I#OhtL`P0SC6LU;cNwGv~70ALJ=+HqB1tDelVTy293v z56*j8Gk8w9=D%%$n^V9bD;u`0hfQ%0rBOMl+Apo1pXT~pe6n=kwZ8nV>4$P>BbN0sMEq_SaY+}qx6!;ssD{2A;l_pIeES;BAbjLk4cY$*nm0wCDC>g!%z0kyz-1$*;( zY5b3jtL%(HgDaMn=hiDpED+nI%yaV{OW@Xgo7i5{Bv6Bu3A$643&+KTJGLWVOc;CQ zqvv{_dsmA2GT79w1bbUY1zkIXIJt)C<>Mncsk~Z$EXJ6r;@E0?Yr9z*XTJRA-a8FBsqC%6o>Vs8*A1Da zwRJ1&BC+TH?UfH&SaE4NV>65qTcUy_6AfC$(uT1p(?cR0(H27v> z7FXc$3MunKy=cSX^Kx%`&fD&bD8EYdimvv8{t&3f6^jFQ?GsM?|j@` zjJDZZb9>I^ue|Dv%`ir6=?9b^Ah@N{FfN`eg|l@d4qUWAs~(Q+sfenlvY3s@1bPRW#D_oRB8EgA8dtHL-bkPDYDu{C1~zs4x!)* z&+^BOX;;>tUx*_W9lQZ=`RrxS~rg{eh@bIwPX)7pRTYL;wqudexd_>JH?NPihR zA&oSK!hLun@)$~xp08|X`aY*{J1KFG<8OcWRB`rso*S&`d2Vxg4DCbCyqG zIluS(#%&^EWpXE0;7Bb;*pO1oI)|>DsV3sl%dT+DiJ$VVaLeEHEzZ~sW5kxOK@TQ%mcR}faB~zciaJuqy!OzJ9*f~1-a}Z8KW19vdSVIYZSsm8tq!i9! zeQWc^{g%#;>bC76oLY{V?Ca}WE0{BFjjv5H1N-V`rX^E$c_Z!7 zHEp%*W7!XS*`%aq#V_SC`2gC!WNKhm5y*8r)AQeCSGLaZ14)h#X0km4kGsH*7(T&^ ze8lj=14q0s)W+X5yRTMvG0Y>`uHDWMr92_MWqU#$cEs>VZrLvVrN5$TTHB8c9z1@| z9lJh$x_0e8atb*S25;FSl_$qcA}X&{?3w7g#N^4=H$US1YuT&sdOBk>j1gN}0;LTI z-d)F0Az3%cCcvSm=giyfcGC=&|8Qb4G_f@1)%dA=;Mnr*PhYbhDX2NQW2)bgd>ZWX z=RT#+#$*X;{;;d}zL>86cb)Mrr^jVq6ce=L+*HHXsnMw@I^_x5<&PMr89qgkPgaSU zZ)eG5)xA5`W}m(@QO@Z~J>i6QYJcE6JAcc}{$uej=TdjvWP9}Bw4b3fHp3XPB}qsk z1Ci6G%TCce#JszWXP#L6f+H{P-8m)U#A0S(Y*h1j)v8k_cVBSLKK1Zx=|Rt_^L7h@ z8_Oh|Ny2?*25b)thq=#8=F@vruiAL5*pt^Ic2(K=-<#5#D5cezO|X7A;!Kj!)(->M z{7`6*i|bH5Y*~X!hCC?#7#P@d=KWxqzD#g!2zzI?^TVg*xBtGFbzv%wM0Az~-ugMU zzrJX)V0BAIq_E@9BIA2OvODHkPj$v-7$dgi2C*JQHfil@6pH$Ae{*)m>pA%|R{Ogt zuLrN)G(E+e`lseY;FBbkeac^d{ZHEUlK&UDK7(Fh$$joF`~pjk-A~`o+$|}e#Ij}H zSL3Xhsu^PZt*@F!U@>#Tv)#5q$bj86XP2yrqQr}b6jUD~pL?|yNoI=j4 zor`q7<8i{_;)TCrHOF%f|J4oncgz`^VT{<)5-4pz@QP-eQqvo*4Sf2#?`0NwsXaNd z!qAD?(%9&{^zY9Cj-Tw@qh(&!H1537xK0Ri(>AnA&W&RkgV;2?Je^(>zPoBmf_M6x+nqbhSO&>IIgJTkZXMBr^2GA7JoMKUDH1iZGfC` zF2=(fLP$l+d9|H!cBgjEp8JteAafh8|kY1X7@V8Kk=D77x`7({?nn=8Jl5@*peG4`9Sc_U3$Jp zighN6oMw)HrS#kJ_U#MlPAtZTrp7-zRfLS5?%O}>w72wS#ZB85J@yv{_s$6|(!5&h zpyN@0C3n8GME|duA$E(`N1wiPY_zTd1vuhHRPL+Op{WJ2NRwdioMTb!azpFrn8Ke0 z?`<2tI4|83aglIpxq7MFciEih%1X1A>5I&r^^0LgZ~nen&e#lN#Fnl=4u{~fko;LG za`&`fZDre;`!S=pV_woMCngIc{fTuxXUkm7Y#TjGvIDrHjIVFZ0xb|{GJ=c@b6;Q0 z#$*f`17w%`&&Ff|*?hu&Ycm^@DdcD@uCkA8Oy-c)cwAB@Y)s~m%_OdNyO1h-sJfr`0?@`}yJP zEjZHC4JCN#bM;c5oYe-CIybREq2pJoVw={eKYhgFjLk4cY$*?tmO$i$pFMm_bSBk! zvm00}{QZUT|CL7zotVvy%=M>zI&$IK=FiJQst=#wSh~w}w$U%pOgMC76Y`p0?wh}H zt@+(6dg`t~OUmhsnPn`#_0f{P&q`6#4RxA6w?wGB=9ly}SoCiCq^0T2;#!^?KPB(V z!}T0oGpDu)DIlktTT$?)4@$cESEZvX7~q@cX(g;;5S;Tiq*J8O8Jl5@*islM#XxZO zebt7pb}%>{E`|5@Pg`xcaNn6Mnc zcgL8G$sAHBaibiLb-H+N!(Pvr9}za+_WpKjIR2Jp-h&ZSf8Ftg9bALIuSHJ%b?~9k zhKC#DOw)JX3N^Rf@%d81ZQ_GVr*f7~&z|Fq%`ir6 zDGZWkK&1KIgv>7oZ!BDKl&SN4&r4r@E0@cl-nfzZtCw@;B^0J0Y=i zhrqpYLr6`<^(T~#$s981$9*q*_v9zPWo^DJ;%k*$ers*v>OQa7G~zo|-1k~xD}E8j z4PzT!9(g58K-#`!pFIYGld_K%oLYHeMu)@;lq(hPZNXNu+?k}scu^+TS*lKt?-6It zyG6g+oP@fau^GmQEiHl41_T?*N-775I&9e{f6{pOC6B*{x73|-VllBavRr32r8>HO z+v=5XCu~@Idisp|6K+2sDFjl4pxn^%pqHUg-civ{Xd+LTfnmt z=({8uF>lbGfZJfVy!gMwL37(557@ocLw__|}MNU8Zxt%Lh`Pxl)rphqXvNfyo#8mHTz>z8*y@9u6A6%0u zSTJFJP~46c7u-|Ld`%oIHYT2S#%35Jw)6vWFo^8xJJRZ@z0*a{vm>y3e{|B@R>p-+ zEQSUqhVDH(PDmW7lQOV1UOlxUTF71WO(D44FoEtBcyg4D$r5sI5l7UGJK4+*mT7m* z)Hd@u=l*%R?VIKk)R}+*N+H}&?!(R}qU$;cs-+Og1$L`kMU$&$J=+wbxZKOry4s2j zM+$k$hm=Ab6TYm~Z>W0`?kPCglS`{qcIk@y&e#lN#FmyoX#;|9r`2%l@q{?@UU!^n zyW`6GP7jSvCl(VE6QirE-&)=23+8xy-cC;=)Za$TZTY?3k*$lvV5 zVqs=vVcfTI@u`aVt9mkm-{T*v-F-(6vUfH#?Q-p_QDtajnn+m|YB9EI|sVGNpO7F@d-&8;I9?$72^49ZRFR0^4MK80E zQqhTq1-g@)F3TK9j1Od8RGJ*}{%4IdHp3XPr8iLef#AJsHe8-|N;~t}x1G!UxZP}G zXa70{x;4(s;6l~c^)oW=&hz^IY=YRGLI;5*ibdd2TvO<3-?abm9c&zry%9UuUOPX1 zqEPTPJ^9DMYftk6nwM{%=3Uu11X9cESm+KmuFd_>9c&ywYoR;XIF;RDcMN`ZhTSnp z@6^(9JUUUy_1?nXS*gCI(*A$b-$7tIOj5qPPavWEGo5cn(fp)qEp4&ZtB!TPHFo!w4Q#{ zwL7?R>p9!*lUMuMb8wU)Z`UEEite?CCFCkapEtEmx7lQ!uOis)x!4(-VT{<)4=6oA z@Wx9YTpsG4uDKiOrCA`NSSXTm?w%8ip_z&KRE~=*EyHAUICB5nnLDth`HpA`{UNG`FfvqWVqC3uAH0slqeZbYd|v zG&8QS`th=6kJ^El1A7>iZ#=GEb+&y9IOPx+yZ`*2jS-TzxC*?s&Cs8{?6cph<0cCn zmo91hb~P`-ZN#LTFPyX+yKiCNP~KGDf5l<-JICOZCXeSG(#Hs=n=gLXri%MD%vv)0 zK?v7wgEJRqyeR0*a>iyDBeoOs~uYs}^4`1a-Q*;H|7Y=$vn zOFf{}0KxU$={zaZY^DB7%*z zR_MtckdlJ?hc&L$;%nTM_exxFSrCWPhKH>tci%SUEgt5nMeBth)<@&YV$C5zgf~sSO^ZHH6Oi z{mNuxGKI8oInQpH(0b?Xx5=}&?_C(}nI92o`&=x#0VRc8hOLI9?|Kvhqj9wB8RPE* z{c0w5HQaH3o$S-I#og`a?Od>>NBO>c`W_b?Ddg8CcpvDCU*y6CcUYI}^ID|5*Oe{Sfi64YCgMC@#@u-- znMW>nKIhCf%00kW#3eBQ%7Rt9XplVqbVHY&a3^hs9W@v12HO#W%P&-5VtjIM5Z##d)-hB0DG zNRXrfB8{F;ke_d|^ZK9MWL661AZF*P+YH@7)fKV|dxsIBH}JUmu6n0Ms9 z5&FdYziCMn2aC=2=~8L@GAyb7WcC;Swbd|8KiZyH%qEsZAm`9x7akw*sJ}_ zrtV*;!~BD&p~C&|2<(ahN){~9r|R*$=yLLq%7--<4=B0$mxd)XiE{8E7cBp|;Z+Yx z%8{LC&zP-klN+z|cHZ6Z(GSnt+dp&0W*8&3GzLmD5X@oklh5}-tbM-jf9t4yl2uOs zthA7~rf~|Y!7rd??Rm!ryMUJS5+56r31m?uhn^K1lL=(8BzLe58m$V;JbtM?<1YD8ODe$ z;X#rTh_qc(9yIspsuDxB3kglt$)TZ2KZ2ZCObkpd5(DFY$VPORl@&*4{j;?Z_}0yT z2+~W!9Pj6023?^JEtFn6^X!jqS6(ttQsOknPVt3qMNie#r_ra{q9nEOF#FPKyq{XF znkv?qY3p)a-Y8B`*m5t@=T673mw7l+3v&ljYEfaAmFhU(3m@USM5dLG$84do&RqH=QWUO9rv zgNJoFUx2RX(Y+@n(-|20JedYP0jOy}LNf9faS|BA5 z9`+Nk#tRRk{NQ0-{zO3jo}6UWB90iYDo2G7&enVE+RoSvW5kw}KuH6FFBbS;Q(LdE zYs*-0&uPQ8) zgY!lIRgq_Fj71B-NS-=+#h~fodEMH1&e#lN#FmmEX#+&cYL?5+d2>+Y55uMy!Lw7f zLR+tzIyz8iTTpI@ntsJlwZ0%|~zehi~a0A>%#d0n?5ASv4bJ^F2Hy%lL zU3UK9$#xYhC(g}^DXWc9QVRuj3=i)|*tzT@ua0s4YEmdk^n$P9V;&aAk7$dfH1xYC&^779MbK(x!{*@GK zvb&?hIQO2FrMeS~g@KvzY@KHcHtYsg(^?k-Pw*O}q64ZQ2j zt*Zg=I&*bBMRc8|-QZnk&YK==(5^G`sV+PMtmm^ukKei8!(S+KDMCKM+Fx7rh8}$? zD;@!PSl4+0{BpjdSPqziFI*T>m6b)pokJJC+ut|%aOg^(yzIlr48}_dCp3Ynof|`y z_cUx$i(FrGG3x|l-HEv8-<`1;#)vIRf|3{nD^-=AkYy=X0z6B>_D9z3B@Z;WQn)C~<)tw-%7X4Y5kxD&$1 z9FpmdQlinW{uAneB{Y%;i-$n{_uI6v?gMwLj39$}JR+bf53+=cUGtkr@71o1ZI?GK z&urXS%Pgs<`#$&JXh{SLVPZGa^N4(a9Sx+m2zoRSNA=~JX@$Qx@Gf4yY}NZ^#w(_A zt=AJnz9XFnsmeo2Afob_wc!aGXV2*G7vW&y+V}kYPk+y5XKaQsVoOROhePn4Jg=z- zwYq#h-{iNlir;+J!YSxIXfvX*;q~yU#b-ZAFuvzLubs)XY}$pr=dCE&PR}Fu19?0B zLBVn+FYB{<9KDTPE>2HQyVRy%!(Qa@hzpUwogUk;@bE5jau2Qf=BcXraN+7>YkTMJ zoYDT!un|X*BVGt^a*N6@vA>WeWn`CJ{QqC?y?1(j4TqX_oUs|kh%N0wQWJ=DJ^gUL zd7)mtpZ@trB}$7NISYTrJ24xXnH9-8Y*u*l)cI;Fr@dNP#=K6C)neei1cs1NVNN0r z4(E~df*n}K(y}si7nNBX^b zhwPRQ21(A+F`2T-ob%=wgal4-#%35JwloGwH6ZeIetg(6|EbFRzJ#jr&um*6btTWr ziN(as(sHu#zb?17(@$i&{_0HO3E48G*uMsxattAaIWKxPp z_5>S~2~>@x`{zgba}QndGnn3X*S1@J#q0JbO&^fU9K<11qxBX812^7fH$1YBpe-RD z?%O82oTeLj&0#+Kz~3%?C7f7{42(?=dX%t4JUS@!EsZ}r z{PFGQeVV%$@jpi4%v%$rj^p()4= zvpyM0LfaX-iS6C8^fYs|b3a-PL@qwPaQYsOgr+bFDWSc1`fXK?uVK*h_TAoHOD0Rc zi>^KGjLk4cY)KN5$Uvl}o9VU-BFlcCKmT{rfdiAIb7m)QaAGkxH8%gGW^m$nz~2D# zBMhA!7d6*>^esCJZXsdWZONmQP0Vh~um$_U_CMLyJIAb%65nFl#r5^}>qIEy@TihJKRDZjpvrS|JC3c)-1)Z5^Z0Wez z=W*bM8&g~#eVDb;^h4z5Id10Qk!|R1ORiU0@ZFX?DxmuhAQc@a&$ab;-M8f~7r1}n zK&YN{gi-C=4KHE_e>a~;=dlD{)&ArxZ zCVzBxp<+FI)a+T3$mPkvce!}fenL-_8B+7>9Rm7_QYkYkj~M25I;QEJ44!kc899Zh zYrwl)Nacwt+k^*JMT=CO?mDfAcZyP)SIT*LVU{yC!x*upB~aRc;DEC--!>&LDq+d& zw9rp^(fvC})QX_HMu75W9W-9BqLkT~aMP!=a9hmER z{=`b;R6~#QhDY0)8{|<225vqb*c~e~wn9&$8KUKl^6!QGG6%o?N?NeU{5#h(Q@07L z{~)It?HTa$1|`+#`Y$pUyZUoR@^^_nZ2RY&Ys>K7;Ec^MMr`Q|5{w}7v#}Uow!$v+ zjNBEo_rZ-L>abh+yH$TiDw8vyk?DVtpJFecV`I*(ccJ(2`$%#j|keKAODB9+h zywHzbNfk|=BA08{&n=hGqI+`E?HYc`>Cl{~ma|MX3b@`)?)Vj*H~FspEaU^xcyym* zPflOYN$RZq#*#jCFh1Ih4U@;m;TF*P)tEt{-b|DoF}sBdV0g#tG}6_dWZMM zO!xl9Fxu<|1uP}ATRi%=S~zFEd^Y2YZn{46rX|#L-*U!g7$dgy19CV7d;Geqs+PR(W?xOkhpLwc%O^HoG6bDYZ)wrt zz0BC;+CsjWzBau9B^_xwjyz%18q?u1yarp)!G*dP!f@u{kc-~+hjnLM4OQ6xNJ80b zOBZtSL&G+Z;Rh1ObcR$LD0}76@4Dhn!XGcKc1*b-X}m)~{t1qRW|RhR1L^-&xVDR# z;mR7jLg9VOHgf&>**t%@h%+|B7_lWuNFoD~^55<6p7i^fEl}RRsXHoWvb0T^H0T~~ zGmEUfe2&S|>D-Th{$76|Lf5nNiBBoG__2TtHS?I*w_1yz+f-}!J-X_qR+rpAX$Aow zjnU!<6s$ZZkmU7uQ-w*5M&c3m zDaU+%y)7xS?U}rTd7ejFi!(OE7_p@vki#MP!I|p9m-~~pM|8|zVYS>ixaj-b2Tsgp z=H}n~Rt9sf4D1ct9M$ya<{3AwrQb9_T`K4nPhw6M=P?VtT=Png-T3d~CBh&1C#kVK zYMC7?6KBCb z736ed20#Co2dOkMso`76TJt&csd}uU?IXiyd7CEp{%v)}W*8&36b4B%AoBD-r>&iH zlGvP`b9cYZd%0Wp&Am*}*q)h*#4cUyl8Bvrxd-*@PnaCyu@aP7Lqx*ivFK%EvV^Ye zF$>kn-zohhGN#Jgl2h%gcGv@>`yo$hkZ>%PkFrK`3{4ND6&dIGq zK9Zit;w`)tjFNCHWdgh}FBbjvc}0?_+Bb)j4IIX-&e#lN#FoTBNd|&frk$I@e%#77 z=A`J+_fEI6e`;LP1SJn9ESs#j;*PN~nu7Il@7T`9WC882_q|Cktoq367>S##D486m$0#s`_0ja}_Hw~$8C)rs**ewC-z#3Rnm7l!T*00^ zta%DjPe1zLvfVXgTHb8OJjn+I8B=yTV>65qTS5XyF_Zo{TkxxlvO@#u&Yy;mlfpS`&Xh6^VWIl{v6H~k1GD8PO|=pJwfr<{DZC2alQb% zR{20V^q_j4(FDc74PQOTqkqf!oRdUUoBFejuU@VCe8E@!w#DqpgcFo)toaK~wagO< zxBXsTo|5EtQrtJ*@`f`u!x*t8J#bnA6Kj-Stg3bD+ah!2f&JBeht@BZww?t##L>)L zbZf=o%R&juOk>vPiQAjmHaQ0Qfu}M_TW!I{WCj^JFVg362-i3 z9!5_Nt8EIZ$~w@z@}{Pb>IHhI8Xm_Q=!hTJE@9{ZGPZM227Q+sIo0fYv$C>XcH0y0 z4a}{~sXR;G2l9Qxk!l=oBBdJE8`Ty~SGG$}Oz<(Z)8W)!SFuXQ8Jl5@*wPmw)!d&f zDl6~s!eri`)hE5acZ$r{e{|J}#mLgkaxy>1m0Rbgw$?1(R=dq5;mn1GaB=ViIDsqO zd7L**`}Lf2ew6uER@vzA@WA70-PzSRnm+WXsd${vKvN5s@Gi(H$$N5BV{pp zrFSO7G>rg-+T#5mavNS72{rdQ?nMBiPgRkfN^Ghl!BFZSIt9VDEw8ODe$T_I9S_tyG{ zGk+CEw<;d|FL=34uT3&zHMsQxU5EwhJ29C+CM>y{tlIJU~OF_}VIEZmJ<@EdSB z`B_SsqRKCQsr;jVMP91@;Hkqo7j}TIfx~hL@t`VMNKPv}9(>Sa?}=SnLt$DmitO21 z;{NjR%e)O2nwj~sYSk5(2&WZ~#Lll5KYu>=fW>W>fzTU?WjPt!_S!pRGmH^iszRg{ z!<%8Y};Vt<}vx-@Uf30)?Alj3qDwb)PV6wH23=O@A$=O zr?yJwGyM2;`0>G*RxW33hB0DGVu*ypF8sN+ShVT8{Es8rCsI`GzWvcF1>NCfVo?6} zy>szm7Abj0?@BePsa*``pXwr4N!&>HB_N-l#N$)^x_R1*M%I6Vd+%tKcEm)wd$eVk z41wmZPcO7eBKE!nx~#H6Ztm9JlXzd58n#8z^wXr?c<~iWPwhfE-vTMM_?&<@cRdpS z*hE#nkBJF>G{0WB^V22e$2#)5&e#lN#FnlQsm0;Jxvo8FS~spO-}>?5f=AOgGiNq9 zF`F4%P8QKwl&n_c_G>Rw-R34L5}3%nxK6w=_~3HZduWCmHe#g(VAiRpgq^dHCAEG>&? z&N-gRxQu5e&(KUDJb~QM8(LW3Hp6acnROj{Lkry#NS(BpjBnSyzR{M9=y4{^lAC8%Cb(q2^uZV*bHODmXr_)Wah(-ui58`$9xO7 z+t&56be~Lo+Y%=hQ)5Ge&-NPp+oqIkp4RZ{+uy_MU72TZwMTB)aM$v}8#X+_!mx%7 z>yun~!-m^LBjeBSPwC-thc8{c%07GDO_#as&}w=E z!=_~qPV(>AZCILmz-G?+tU3i}Y=$vnOJazGvorR_mq`5pl^cvp`1Te?`y}19y5PiO zZf0WPd3Hxe$JHRGr|Bu}OvYWA@9(uiE`q``GQ$(c`5jQe}rT;X@iW#9r({hWX-tsw23bVTWJ977wmNJwR2$1R_ zq|_3+@V4#;&CN${=Fe*_ObOO?ajQGY_{tfZVT{<)6(Y6lx1G2mYW{YYdyhH2svjC1 z&wJ+J?!;nbW@)MYNS2lB)aC6T8@8+p3%Ovh=}xOT4c2J!gjXS-SL<18@bc332XPV0 z^lMiim}tr!#eNSZq0z2b3ZDX7RYCfI@!&6(yq0{I%y{`B=Ew}lc0PhK3m;*8BOMr=tEkIhqf4&d*w8*eea|0 z6D^*V^|{Z9#njxyB>L&Jv#U7v@iONGF4`8<6J>R={}Zm^9-hd@#0>ZRvMTke<_UdT zm(%!adE|8InSIA?P*Ty%chI8=c<9k=rd@Fr`Io-KJ!Kyb+}!axG3L5;z}&?8lVKkW z#88%4AQe|gsVFMoWMuChHMRCeolXwaG6Odj)oPT$VzjLk4c zY-tRUa%?h>Y!h=-=;pXHXXSS8`&+Iw|4spwKgMPo{ia5@+un@UtE)0LF=-Am$*B77_)_ptp2~!X1uYxoN&U4J3O`L z^ol(tVIHw5dlYKEzw^*2%yw|bW*8&3B!);h_diz6tl?;6)hqFnYRo(P+*mQTv^Z(o(DIq6|TR83=~2}m3b28urZlgfQ{ll4BF}o>9%uk%6-Cq z>yw0k!pfdk&y5bgurw1(WJ6t(gQc0nldui8CMQe_wkC)4-q-MM<|z9z-j`S-FLCYg zC)VUS-34-LyHPfVBNa0VAK}fMxWlt#=LofM-IR9y?b*JePWu0ZDFHW~u^GmQEnR`5 z7)(s4i&yQ<{dsGuUSjOFee?ToUvcLLFE}@cEI4P4ll<1lePQa;i?jVXGu!j;R@q3j zOlBX+B?V8?Dd_d76wXC$WI8NAJLTP@zcn)Q#v4E9-pQVM14l`L6!%GQeP4RKx?z8> zIOUi1k!Gz0>gLmKxH@Aqj1gNZ0Y^KSu+F?cRod1^;_&GV(doZ;?q1PbIme0F#KLrC z)Ze#X-d5Z8s4W(re`D&xZb9iAkQxS(C^)}eVPk|2@1-1LV={-7AMD*nVYeD`oStb| zJLL)AhTbCwvgTjqpSyNO*WvGhBc)}+lX4$+t6_|p1URr6xU);3$%fN65w=gkXSp;) zmUGru=#5hxZ}ep$VjS1Jpoai*ZQTo9fW>Xiy!VYnD|2PkSy`q~XDu_=8Fi0Twj(E- zR26v31SQ#UPHCI@Fs9+y`sXSW{|B}`;*CqV>x|7XMr;WT;v^8+`*!IH!J2lN{+(@t z=63^byKNWEaAGmDFg5KdYYJ{!ee<7oX3x!quWZt%8_LImdq%J`+iG92F&RTAyyNWH zm`ounih0uhvN4%K*sRZH!Om>smSmC%WBxWrZ-4s>d+mx#!l&w4gA5dq%O0L|apF2g z!=#l$wX&!3()|swvn;so{rz@YR>i1xP4uq|gcDJECf}d($6bMJB{#ATuA6?S_i3SS zsgE-@!x*t8H&F6{U<=8oxs#uHTAvQQwQuUe97SeP1G?p+#pW_8KEs4u1= z^3%otS7wCno&>IuUVx3q;F2Wl@f)A$BXvV4vj1*6E>L z(ZZ7%W4S5$z*V-trq`Glk60dW|5cb1uoyX2WY%LVTGBJm7k!p{XeD$ya{Biw=fAv# z7miJCcgAKIBewJdNf97&#oo`$5?_e?-TUf0`|OlBpU6%BXFIW28W|faEq}B1zEbx- zF~;%>2W)I2?{=R~K(3N_vLj$s689Zrc$LJBa?vi^zxC^vo`~MoRNnj{j@fnf<&#T5 zm#V_&5QcMU!joMDtCG%rhgL~cD@}NJN=gNkPCu*@DSj!$`Oik5^3>^s(@pkvf9bx$ zu=R%7>U#02#!tDD&Z%W|I%6}85nBoar5FfKD>IxEWKt={B^e~4^YF(x%`M%j;89^y zE)kof{xa{f4)jmI-m-ox(_B|2cI5eP?(3`Bn2e$A7rFmzOwhdw?6)=}_9~Qpgzr`0 z$(;b-tH4qJF`?z*yKPPDBH6gl>3?UKzGt`d8Xe^N32Bvi?kebf_h`R}fq`p&D72Bo zb*LWN$l*a=Kw*BzYld)n+4+r1@%4%;7uP&rAQ6uvMdfkA`$gH?t9S%2q7I<1!_ z%tGprpz6(^|K=)h{b*<*P za+l;AY!^4E8XLLfe@anpf2FPd4s?J7yuhJO^5DsT1RZ2ST&u}5yt~c$C2iAJIZDjj zdLf}}{jD8ezQvvRiz9gyXdoqzw+mRe?AdL4@Pue5X#sK9}3 zPr!b@4f25`JVlJ~?Fr!RQ;73z_>7Es8E;B6{>s_6^o3^5$J-3Wv2^cK6-h(4C(!PE z8@e}qs{7vS?0qiJ=dJ!BY;xO#Gz-=qKjidOQ~_`Jprj|YXIl&Gmv894W$wrNXYrR{ z*+U__oUs|kh%Mzo(h`VV^J}iI!Gw!B$?LxT)ApY%D)>73vlEN4xv}LG@w);uzHq)^ ze_UUlaVKADT7>6J$eo<&tZ|ThNF+BEGX41F&%Qo%Ic0x`qCCjjW166cJ~Fh*?Y3gR&kxwEcI-0nnjx#b$GTeqgKk*g7uS?a`MVPs_Ha_M>byRyGi zq#hmGC7b{Ih|{aCz2MYh1|6;`t7l^}gPfPeA$*#R$pYFNf8Tzr&hzfs2OnO&c=O{Q z^VUCI`z>#xY-Snkjbom&nS!9eVPGJzWCF_^BuyK~jr{KAX>6;~Lf-jH-=FI^^D}SH zQNpRE?8@s&Q`PnetYFw_>ai%~*>VYX5v4iK*bHODmaZT{0U|rEtvlj!LBd6m^KSF~ z;LGu^IUcz!%jF+7x0dUb8+a_3k`_P>EOJ zmrhw}xGY*lIE7Svo3Z7|B9G(w^Yc8kyWi~XIxu-9_ep1LhB0DGOQ5s?!P|7wbbcz< z$0cN%KH12zA@npKvy&5xiKVg8&UB4)N4@ONo}YVhe$WhNt_XoWwV-A&6P5$?d8*E{ zFKJ?O~pBs$RlsB3gF5`E9ztS9PiBx2Gg* zUg=-g;G&|LLOA7A8yLKn5xkP8^}l3-zkBJ~x9d)qd~kKfW*8&3GzLjEATm*H`Qnon zN^klj`>WDTfQyxLmN&epT1)Y84HHCTWUGs2k3Jx z{RBTipKZx4_yPKyCBNZYy1CUlK0bK2=yryTftphl(|eh1vo7y@Rydl9K+(WM^2tX$ zwaU;L1s?rd^V-Fizdg5zLFGQ1x6+vtx3iTGTp^r_YRe`^Z+m^!EAUmsrX&Am7hicJ z{g`c*Gd9B*v86YV!y#BPLy7M}+3Wck>r|yQOCHv3ejIYgiN(Uw#8koeZik=p60H-? zvzcWciJ7djta$@2e+(frQG|#6cf1O4J4+raP6~0x zW*8&36b4B%AadD*rWsvPZ4ndG?oN?kwsnH)Q^|NI7Gnzwi=Y#Q*YgSs^+oJzeXa5Gu_Ku^He`sYk177H_D z(*UFLg2oq}0YTY;hOBva0+|oL{RgS5AiXBWOTBDN#t=69OcpjKW60rH92=&xF+vg! zPxDqbMo5{&{(Gs4O1k?C%SeVu$AZ;I>^-~q*EM({r=g)e?#I)79=6Mc9``694+|^L zoXHnie&|W7X3J~=yDOi(SCs1FNJA|O@NvJ!JEx{j`Z4+UFBazeMHi%_7MW=}tN(Py zW*8&3)CNgEAab|Wd6BtWCg<-um1&iDHT%UR)|=BoyD%*c{HJes-Dz@s^^IF!S0ycw z6jq6f69Uy#1O|+GT7SaNT4Ov{{?qm0l;&A{TUS1rX1!O?eU-A`+zuKfoHpSB889Be zgmZC6;GLyrIwo^C0{`AxdwH>fbQ{X{U8EtKwn(Ie^Mw7t?zH|RuP(h$X?*kj$78`2 z)9yNBGmH^i5(6a}2+p1KH1Jf?x%SzSch+fEvCVttSkMbf9!yw{#pik^gX>s)erwL9 z8?qmt*m3-|;Iem-YL2$AXAIi((P6|7@jMTa+YJUVeeCe4_mp}O;BB!|s`q1Uw9wLL zEwVTYmX1oK^x=81;%V4q)@a9{(-!Z(7Cbz%K!DO>vk_Ic#)4Ip>;h%N@%lmmOa~V+$53}eKW+#m@EM6$ELy>sz^{*raCLW8UW%0e_w>KlXhY#Nwp9GLiE_nIAV{T?RC zT1y{s>Gm#n1`jDiZ;Ix)X28Z|37K@@>1X)wvUY=Y+JX~Tdgtg_ESY)iaDeZs(J3lW z5EHvdl&4<`x_$z&NR%ftW~o`5xw3~(`D?uwet2_%uJ+YFXKaQsVoOUPheNPHd5*~bn5YxVH)qfN7rs&F5o^GxqvD|NP5UUGn}p@Z6>;WX=KCm=4e6 zXooF^)A`y;bnQO9k!ofxWqh@{(gQiQV6BKImyV9<5UPmO*S&poE?8M{<>g?lQ|mVH zl+4OnM>w@i-eBmE`t#N+`;`pk%$gmWIBtGi&{OD)%`ir6=?auiAo$L*79Y+z4^QpQ znDFSUA!FJ`af2OBEJntLMyH+%GjA~Zy;)_&12oB2S+475MaGqsbA$sF3S zdHa}+$r3s(f!ZHelrTBBYMYr<0N0Zm$$9gi`nLRgi=1$X9>~F8%uHR3*&iR?#mu4@ zml|!+`yMQh{ZsnawXa&PpCgPT;Y@uAFJ>lh;QhJlW%JtdoU*ug3*Io@(XBf>>7p|> z!x*t8F-W2Tk*2<1g$gpB)TCuqy?a>kNG{L*^eiV93qx~@`#;X)sxMoAYW;@ke^1GO zF+02`9Q6v0>4$c-5;0iUen5um0W%#bI7Zw_irV3E7@=U)2-P%Id*}{n%3cVG* z-m6Nwm_(mv`u&jM$pT3nsbcznq*S3Py3eSr>&5;XZ_h<*n0;`~6XcrgjLk4cZ0QH& za0q_xaNyJSib9!Rp<5H*Gu8j-y?MgRiN(^?%xF!mM8v0CYXbsb<*oWT-|*E&hk5}> z=Lj+^%ro-_e2AE{WjY&dh?sfyR@e|R*Q~v;A!07Z8v;io{xQx}wvya@PHUp~#o8!| zJ4cbz(9o`ucxHZr4G|-j+t6p4;nkP8o>cqzwEq5^CKA4vcK%nEnMybf&2s+WJwv6I z@8Jix`B{r6gw*|=b!E;jXKaQsVoPn1^aCQVF(>=-Uayk~QPTaB89L=_*V4a_oLJ1w zjV-OG9@`)l{y2qcU)Bi|_SCyQ22&nD(h#)nnIl8$l=w}ZPbQnXvcH@3S$%#Ha^eu5 z(oM6`R0N6!GN#1mm?5Ubb8J^UNjfo&le_2BzSpAMKY=$vnOK%{DL$H>HTT}zz4C$xss~c9?l;___TsYN<#oW-)L}0yK z&e018=WKa-OoioQOC;mH>JLZ@jJfNr*kBiE{^UWNf4=S!{QPsa^KS43#ys<*=l*4aC(||vx{AS`}cEZVtO%GPc8Yk)a7+EzkxG0!x*upJV;ss zkqWY5n)we&P!po&~322LVtpJ3cHE z$dU7Ncz+46No~$K@rU)};%}QmI7S9< zw-rl?7T6|>AF*5ba?1Q0e?R4*OrbAMhK~%QBs6!im*p(1m&)e`$UiN7W-`(A*P0d1 z*bHODmLwsG3`ANmbJVmnZ~N)Bq3_rkWyZ~|=Y78-591)8Lc;LoJA7#l_om!y)BRt4 zOKPk?pmcTX8U5t#F$&HvkP9EIz44_suwfj;DI~+LH%?){%VcNIxv2Ap;}7%g2-3a! zJg{SR8Opw2q%^U#9NzC*@N4yCnWy3Hp4V3Ko+-+GS*d!4v173_Hp3XPr5;dffZ*lw zHya+Bwm5KfK3`F{BjDz@4F5AuET#s==3IL>SZ;qRE#gox?Gxt@1&@jGhQGko6YO}| zHWtqDg-%g6Wt#wS`Pov*k^Df)Tk3$x!g4!=h3J`l3Xty(*+NB21@+|1_vfSa% zV8_dDe+lbV!H>hDQ>k&<@5DJ9zEw`ld36l`mvB18%7&XFw_ldegqIp9DdgNDUe5Tv zH=o`AyxyAa!`7H*b(R;Lu^GmQEiFM~je&vT#^x_Geu{8jVe9;2FpYJ&HrEGE&=OH| z6SMmrw&CVnFIH@KDB}M$pX=BO3op;2WfPa4%6$(|SL>hyRCyaU_Ff zn~~$;vbtuJYgO^Le1~MiW@Qg-i8{5H{UNt}4?lL1^LoPiQZHd;x6+l^;AHbGKEf$y z<>mAL7k-+(vE$^6g-4Dqe6(5ay!4`_&e#lN#FoYoDQEJ7>5nB3-4=fPA>Z}L{V(4g zEq!>Mm`yCrj%rA{-xP_D{Q9>`?027xmJavRnV^mo>?m|xTf=!)uOVh@_}kzqx7GA6 zIUe+h6Nu_Mtj=M+yd6hnwfZP*YxrnoMR;p?_l8g05n_3+9~#18E)eto_TzWCrb5F&ncn zSweQ=@%R*`4P1cd)9RjIkoj6f9F;KFwi^8VOAwWl1Domh;Gjm-KRlCL^NW`9lJBFhr;-n-oWV&GZuK{u9= zb;LXyw9S*|$9P)y^~zNQ%~^3lobP7 z(_4p6SS{aw^Or^ZrW(SjVnYUF)OY@~im^YJ^E_+b#l-(+zoW!OXKaQsVoN`WRMDb! zz@S6o=Fh_2ztfaG4c{^9cb|p~1w*D2kXM{D)NO-LC*WLhK9gtZ4)f%RWv3i8qSaTd zw7zQ9>V}+Bkh(^LskR}u{Mh6OYxt79;+(?r!~J%M!5eRFu15X)+1e)8%)-Pzzrm4G zHcf(;9~&~>7e8O(vdH98oYcIJ995cMrfiOGbjD^FBepb!NGXNV5nX$kmp>A?ZOJpc z%Tk5qKvt0X@#!W<2rT|+GOGG zXM*;xx$m{Y2KPw5JZhNto{E@5KC=FJ{nmeb&!1=)iKBVTN>NVD-*O$^dqPP>;@x7G zoHxr@-^@CoEB*FPW1`{ziO$#zW5kx+5Q%8HHM>Y+cYS(+EWh2&MH}S$UR_TCRYC@q zCHuIP4!qQ3m}V?zel$qKP2vr&B1$E+ZNp(R2G=)MhxuM6$R}R@T+w3Pvn_^}MGMci zQ?N>ik~I*6zi4qWtoUsE+zCwT*2|$WzN6zkB(g( zO(CFwCbsh7+3^6niWB7&ERQAg5@VjVC+Eek4NrF{G@eoQ8Rb|Sq!hA~A1Q@oxwxH_ zd(8BBPI8o<^fHx|vPZYhcE)BHBet{zaySGZ-M8S#-Gphzx zn46iZEB3{hS9Q*FyLREY|GIlTGZht2fXC$wAyY*>yI!y{nL@fZoU?A1m#z)9_bX-) zQ#dKm5i?QH;Y%239Tj3+ZnS1$;D#Rt%d?va<1knpqxp8Vrg1k6*b}y|fADnw?V0U1 zn-=*Xmm#|i;WZ0N3SsV1nww(lSD{s#^COBc`OMD-cX?-QhB0DGOOVt7A|0m6_^i}= zIY0S`;1BlQF}x=Yo7tUMOiT^Ty1d;a9`Ud0V4wZth4s(-FSB+Yk_C^;LD%{6?BzmS z`xJ-knEIV=KfX@>UJ(;!v~b6Dc^&)ZwsTP~%_X`Av{wbX&KLhN^&_SSq_wLo{%39d zza*2Q#r+%Sa~AVWXCs_&_GT?TwugVauK1E~FD#AHEFMo(I{uN#8Jl5@*pe71$w2Uw zDSW|RZ!dqlxx4(Bk$#%v?d{H5PRxephW`RRccd=fGWnxJKTXDZ{fr26pSy zjIGf7xOvomLJz3n{&xhrJC1wHZ0H~g=bjYU5k_jn~-wZ)H+WsoQmA{h88OBc1kZh4+z%a5+BIz)$yN z%PdEn?is|37{WcaAAY(gTN`L)40JWt!Gc!FlBL%5v)go*^D8TUx$`#h*qry+`$Iej zJ80e?8b;~qLjG>wlH~mll{&7;rXN`46K!kZ#;YezPbv}@r|oe-p{tq{mQ)Hz3|%D&ojS%FI^Zx_w;o5 z7WDYWVU(Ua1J{_pSvYm!n|-kxw!S}PxVk{}5psGuVvapMW$d`*dEj364%2h<_8#z) z^m+d7-3(`JhB0DGd62XOBFoM{Wn?+Gxg^=yWYzK`49?$9m$f>vm>V0L>fh$v#;>lb zo50~9y@0uS<~4((GT>Gabl*3d!bUbGBS<@$=a>K+lQCrQhGlU-8dFa=~CtIXuU-hEB~UWA<4-h2gnpuTwr-NdL;dp7;8%kyFmG zLhLDLZ?DNQwjFkNzxU?8Ufgx~n$+DLR?gTAW5kxmKxqbomuTKG>f+m7=)2{bW7_7G z3vTvrEdjT7%pj8h+y}GSn9L!q9j=7WY)s~m=_Br|wY}#*2c@-__qb}Ex)@h?c>UGH zx-jHk_h{3Yfr00Q7xaP+E`ur1J{8v8wa7Ep0UA<*>{o=FvPy%#zSUD*op$*{G2t|E zqBTRTHB{`5v{qtwydl@7b5>iJUY>BqW*8&3)B{NmAoAL0jgTU-(}8F2xkewKrg3n; z0xypfi-m!S$+imr@Z!vAr=vZiTZPy(gG`K1IzdVkNSg)MrExr`;*c+mi`&^Q&0l6> zuvWPATc~@f+@tB1s0YKsd*d{0*AQ6`QB<0os(@Y^N69J~657cxfATDOam_9_<%Qoh z74cb;*WOJNLQXlS_G2qePPG1Pv6D&8dcUqIH|*&7*?VR=Xzu;xjLk4cY-tRXW*~T- z-NLg!F6o?>@^*8(`;;eU9+Sx)Cl+%9bAu%TOAYomPEB~=sI2fi`RES6ptYaD<2A;R za)#&33^pcHNZG=^!g@~Nuj={_8?-YT;!2X`PZd4M;5bcL*}`*X6C1>l*lvd#irsFq z$`-$b`U5kLUr))nVs^yn>FdwG|F_&EoI=h#Ed3G@Ei`j=Tk|<7N#8H$ANHK9UG0p` zFh*=?2@>!il6}Ur>kiXb^nE>F`FK;OGuxEZ-|9{*#wHdo*ba>5no-!6Ddg>$1aqNVcW6TGFub8gp#D3jUVIoZ2y_nWyX#4bz|Zx`wr zv?=G@6=+L^hsZ->vF;!sdCHoslrt^J%c8*0GWFZ{OM=@zDYB+j)*c|7a?VSC=vpv! zN6D&YL6cuA#9KZbeHprIsxvmj7_p@>P?~{Y-e2X`mh68Fv!le`ma%nDtvoZ~G`Ix8 zGAF>H`QXR>(2(t&pMRaZd~=_W=t17>%!nJv>44f3(!+1oi08r=Y;yvg|29u?vcGtt zwC1a|lUc6R2VYqGJHTYb#*bHODmSP}j z07M=*@YpWpv|!P>+%Nb1bM3i8jP{m0v6vf~8@yYV#Ij9n+xc^=q~7s$s@@7-^J_0; zLK?EDf#=d6_#R0vaS$6)-*9a-gzu4L3xn^GH^>qU=VxoDOfNproNsY)R+bpUh(a ztMPaB{&F+^KQS8K&e#lN#FpAXsRx2BH2zOED4+0X0&9g?SX^26&&i>OAt?pYj^&v{ zcqb%dqXF{az=l3cQ`HbMFW1V+L-5o*$gC8ODe$ zRYB4Th!+qJ}439eFYeNHiW7Wn z`#-*5IdY}NbG;3^0EUMutEfgyrS;t5=WJIOL(AKhbpZk;ON4xt^DU7pEu=(r{RX_! zx;i;==GPfbiK&Snzwhgr9QeEOpoiTlXKaQsVoPqIn!?dmVkaHQRmy zX97>O6N{yxfid&6#J<+ak+u7GM|Jylr$?QC&GG>}07GE9iRb3V?7KhZnB=$Lal3WA z`(xFuY0uPH&J1Anbn`Tx=_b;<(F0gLEzY=|YPb7E*0gTvOJd>f)=9h5wfPiU%=8SW8WaozrjsJOoE(LKE0E$VZ}i=rtr z!+zV$kSjqs)gF5)y5r*(%WoT-)UPc0bU*(t-}ORKAH9^Fu^GmQExm!#4+Nijb#Pwx ziv{yIv^4%(iLTFL_`S``iN(~&!k|dzN79O;>y0+FB&=# zd15U3Y{7cVvUJTEf_Dj*ME53~2`gC?deKj8f%W5>;!BKG*^_eLI%6}85nF15q#qC& z{4I3j#Ah3m*RK8X{K>K9)qm$N$aP{dHncQ+80#DQ>+2L}yQ!VRI-qt#BTrP? zD!`6`;I5dBI0oX@E%-zwm-;%yF%S1opv^($2-R(#+1 z??uR`wvb|%S{&)=!2@_Z=-z~D{c+!8{wOCudv+-BjuoH&J+pvK&e#lN#Fp|vDG7r2 zGkWJc&f6uhxbXS5Fs|JWF`h5&K*wI0nVdVQk~rgLl(Pc6_uss-w~M>An>4_~JFo%b zM>~-Rh!wdrF30J-%b4DhJ!8(NH9f71(rE{|NyiJpyrXr}s zf$f*%Qg(+gwgKN;3B5{}$L1+wvCa2u@WnPGC|eZM9@oXuECe>~?jJ_B)Cz zqJ8H0ZO4(Ko_vKaw&58~QP>X)My|ttJpKAdSn*Z%RmN{er#VcQS$%FsHsKWYG$f!U z=fZJ8^DWOmtqeEln|t(pdfyypY=$vnOM9TS1i||%t_#!{asA|eS3lP)Jo6;yB_UQ& ziZZg4&#kTMP*Yx>>3dJ}`&4C-gR7@s1D82Q&_%@0b=jEAA&VopV`Tov2&#%*`|7(z zHfFPfKsxJ$Cm%sK6k=K4N0({K0qSq@Ja>m)-_4y}A_)m%Y=;GtFl}k8Xl}rsb3fK# zeS=+U#re66CBIQx%FoN-{Vk+g>1jwrN!{whZjLf{l1;bl6r14JfBrz9Gd9B*v85%5 z(?R3}ueI&80w)9q|>y?i4_D(D&hQst67EIekR-gBqU416gXJNbKYQP%owhPIBgJTw^A zc|9F^<}1sTdf0v^#K}X5)e*y|nE7?^QC5rOcT3hwcGGnhTs|(Abp0@L!g+lcTQT!; z$%6+vA?`V9?-Q2B6$UO=SZ!Xg^p7((!x*t8F-W2Tk-jtgxTbnl@2s`jm%4v%-U<2N z>jFXhos10LxCPyCWOP1pWu-@-LQN3onQixCQ3e6uZo|6foag4oc{>6g?Vqt?`rrGz z*G%z!@hENW7V`m2EpIPCyGmSG)|}IB5Re9y()R5sYK>M*Ar}~nt{3l_`A@kg_ZM<% zdB=@Cwe-ziKkvna+6LjWopT>tW52PKQT3KHHp3XPr7KW6f#4SlQYMJU{+s!=P(gX` zjOl@Ql9~^KuFW;FF#K<$R$t@Ner8_$c^Bc*JKVceok7J66Le<_$_e)GpWryb-ldVJ zfN6i^g3oh(xU0nvU-x4^u7XlO5!=Up{|~ye1?vg+@S~-%&NU3jKDPLRhQezL{nEbb z|5@=(`~!Q|x@{;2&LAb64=(UN_RA$tOjM>HyD>@X{&CjzH!lBPxhHLeM^g&8QpE^|wx!dAuGJ<0dS}&S5@0sFe;|spd z*bHODmfS$e2ZGPIhc~J6Nq)a`c>RP8r_YJ3^)o#KT2XFf_HG5=w~Wx8uDOe^-q|m6 z{I&?AdIh-C1Us+uBned{H1Fg?y=j?deBMFATqd z8gf!d#QJF`i(VCo^R};#iavk$$TqXUFN9Obm({NgTsVGdZ`5AxYi*m-cJ%*WKZ71; zY=$vnOG}W{0V2yTSk>N}FZA#A-0%&ZGvB7Zn8sJ+#A0b|WZ5YE{@v7N86iu;k|R{@ zzHBR%I(Zb_n!$Ea#^@K zy|LVLE&cSC*j3=v0_|dRT>Ka%%a>4sZJ+ z)jr>D+Ep~KVabPbJA>5`*)3Nmh4Qn3Q;V?)NFxLH275Lp3kaL%*8?^t zOGwj(Ymd73t+>iL-ls)xsY!R5?Na+0*P`l4wVu+iU+iG}8F)rsYWeeFQNU#DuJ>7A z`_4!w@BS8e^K~zBYWZ!7J+(;kaW$J>&`bZFDaCO;*J+WQnEr8RY=$vnOIMKK29bAT zc)zILkuS-8s`B>Y3p<8wyE~7A7T1^>s=YdH@-*r46{|bU%CUd_UKW3AVJ2$I;4dFB zQwA1Sm&hy$J|VcWV}?v}<)5!FW=(&Gqqh310h=-yt*r=88I&D6Gj&pCaERart<$aR zANJcloPcuLEA|xiw_V_3&SdtFC$8^qHaa2^^Zvi)71e9b*bHODmi9nt34%AI=5KY3 z-l4VL=&92mneQ#R_mAp>rwq(GLS8SQ!M1)y;+Ej*{_>nl%PmtDgZth_kOep>JD~n2 zurZlHrxH+iKt0T0Jar+2)wygr^N-TAHdDD46on4Uvgm&mo*hv5M{UTexdeJ#>wfRL zoZ~as-McD2kKd z4y3k1-igc0I191A1$8H`6r0ia*Y;1c>;g_z9M63B<@P0^i-R@g@G@@U2L%cP1F>gJ zAT9c%cgiWBeCf-@4S(m>J6+xM#M@e6$&%g3<9)o0zpXx{!AU(3O| z@2qfRg)=t87_p@>NbrD2)x=+_VJox_JoHYoqsJ(G@ z?b2H(UVi?yRONgTa*vzqPbj>{&C7g+*Kx(KghxA0p9?spvyL~vVp30qF7YXZm-!v6 z$Bpe2Ju0_zhExhkUS{I=E#)73(L4s5`gPHNud&9SKx*gkvdCgjAs4k7m49{CKI6If z>ul?v2Ie_YKQ}pJGmH^iS^}jF2$qznJ=uFM=$DUQAM0kvmD{TV|Ef7L8yOm}`}%C> z3h9n3eRg-2>Za|VF#T!31LS57CC8BPvVK#1-BNa?Y;QrmcJ*>i-pbwlDp{@A6BI8S zKeU;HIF@lVK`}7kI6Ui~-q+GurB5!*=yX{4;J|_PM{AOhuL|R3%fp_aLUw`rC z`|Yj7?}&{jU-NEy8fLg^f5HQ2Y=$vnOKza#1HrlHlP_}GG#7Y_R12PAKeO=JQH4vO zJ>P~Fx*wOPJi6ZM`nuexPO4f1Rjo^CA1iGZ=$x${YOUROAUap?s^XIh^XJN2g;hm+;0%vT7F=9(gkkkPpd)IQ-##hA( zZz!@4Nj?2O|IwmPE>0|lMwUhnHc62z8?}#1W{cnAo$Y?Wjp6J*NHGKHP4VE^&cMsF zj*ZC#q6Td{!}_-#g-bm`9FG0_9~W3NVgi>l z&^vl~`M$vK=;6xKcraVymwG_ip&2~avQC_rG~e?&4`oJb=%f%{em>|OJ*;n=p?CD~ zP-p2dkuy>#DWr6{`lKn*hHEUCRsGnq`MdY}tZOHnLilaNZd{vX`2FyueTG+lIDEL> zc(g|Lg)=t87_p@#Na_HQEVpi!ZZG08WjUF(X+i261%Wy9=YU6TOlGfmV5yXU%Wk2c z->gg7FB9K0IzklL@3I;`xtr)Fw#4EP0FD*3t$?<{kM z8(f4cOPbj6^VsI; zpczgqb5=vKGsP>M1>Gt|_cZip^>W{Pw=6#`n7HoYwWo_ikK_m;A1KQ!yc>HOdj9Z1 z$D+H50#>~L=6~CM?@$6;*i~n2hB0DGZIJW>B7MKFDt>xy_i4j9-9Jq1?!|U1s--%y zn3`CaTnw}P@&EpE2hrs-_Zz9q_uqMRx%usRODER<7j7kpVLujmx`vQV~a zeoMYDVf)UkYdRTm!P@=KrdmXbnm}5Hsnu8S zS6aGtTb{nvI9`BU_+U>sqF+oFn0HOP@NsGX5u?wuZ`9vk^Yz>=XKaQsVoPG6Bm=?L z+}{0x?5X)4^G|5H@cZgrQ7|%eVzIEWG}lv$SS8wL{p~=Bj#bGGvxRL=4cXv^jUi-G zfmi%2@*(FxpG=wY>5D~c!p=?)9gm>*Z!RhR96r?(wTl*B@#oM3`8eL_%R-_8$2d)r zS2<&tVdta_q3y4yi7rcX%_}iPP9YLv*oqd>FX~b97O&)c#H7L#ltZ($mu{Gzptp?WqTrYF&K9>G`1btO@nd9wA6`P8 zCNXu&7G5b%=%fMF12iFh*=?43uUd_)9}w^?}u`%Y>M>J#J~p`?sO7e7zHkp@peo z=TiB*n*|%)ubY=ei!AeYzWS*4Hgd}0mC=MBw}xjr>S24srw<*O=4lDem8+l3*uP#Q zKyJ{MIWo@tkYFKpI%)vR9M_}s!`3U`XwXyD4gB#-{Z4M@qAcW;Bh!Vg%#jKZTOPoA zphDL4+x_T{Z13+%ch)z)amHpCBepaK2_6u+;=KKzA4=TOOD>s+I=FMsc>d#$Ae`#zXoI>Q*oC-f+)*3eLU+Ltzr_Nlg zm7D%GP1YHkVT{<)5-4pzu=7hlmUrU2H}7xpE|889d?>EE_O}y@xuu1n@vD-zGgjKUWL{* z0{6XkA9`g~`bPL$&X@aTZ*EWchn$K=2ZtFLxb8Ybm-=!4YKFFLxaNn#+BWdx{CE}S z!-n;^Z{LW`dp32K!LOZ*n(UaqsMMdi`JVwtDpL3a9~_ojv+U?Q2lghrr)MXL_WJJF zx-f7Cdzdpe!x*upH%JNsk-ZP5eD9eWco(IPPL*CF;)Odm-!w{kR(4|XOU7K=!Jk@q zm7YQ`;^5lc550(k<0q`l;Z$~q4e`<8HbTVt5h$s}D(|b+mvgH-x!w!w=x&&~VBdnN zlX0XLWd)?v@~^X(BmLG|)wy#0n?9HyPf!xwC*_RIFh*?Y3Y1PDc%Sd|c|RNa9G9*A zy!-tTVXF9Q(B_-+i^aU$l*H=3~oSt}9PDF`HYOuVvcVnWg&i;=W&wXTPm_;&!ZS zMJOoYKnG`drgp*yXL!|(;Da+ftv}&|GmPiTcOE_WXz4HRh%Y61COpNLk8Qf=Wr&<^ zs8c=hs(Zr*XRzH-h-EV!{<+H`P~fCw@A;Bq*z{g zyEDg$#nRH)!cV=9b@hq4AzzHQ_aEPP^t+KrIP|nxNcDugnT}U83x4_|?j;hjSB3c2 z&q?q5p8m(@{?29FJ!-COLrz4znk`gVB0-m4_~0shf<9?Zy?Jux%id>iGne)S+3olf zgtBl8sqjHcM4H!Tys_Q4>Pw;WOjUNH35Dx_to`>!7JiBa>cHdzHtLr|&c0we&0CQQlE|UeN_q`Y>Usws^JIvoTpf zu4F;0wv?v&**^(0UsLQnchAW?t8N+p;CMRBQ;zmYdQ@93f8MU-Ud23X!A}!Cu0tLH z8`<@92p2y(0%mK@K8-U=E`J?6f3o(AmurQlJmqr6W*8&3GzLmD5bSq)lhb!ISAhdj zL7&`T@zmco+En4hVrgn(79(UgFU#wg;?A$Db}!#-_^WsNyGlqO3o>#JTwyLCE~?1g5Vv{&`1gwu`DJq^LM zs4G|3gjYN*YJPNZ`IpZry{*pJ3}eKW!XRk|L^d1GSI>`se`jfoPqq1+$NsV@Zx=YR zm>3%y6c{sxB~+LnE^91e(@2uJwO(q&CvZE+5OO^b!{l~0Mo7iRA^Mh$$sE!QV%^cg z#t7-W^O|fgU;9{;C1BIkx+xNO{_mYQ$LBcTm61~3@S0o{2L&+$11FOa?0mMj-O%&d zh`t6K`xxPy4}~{doqlea>aS^G5Z~@+q&6`HN4hZ;gO@i(_ohi-WnE`>z?{={`qJH7 zUPq?w%&~IDW*8&36bA7Qi1d2GTC13I=VL?1bH)ww(ek1^J5$@t2gh00yq1FS1zfZC!Y_qkywUN%vEfdMlc@#! zlT}4)4klQY&X7VbWe~mep;$ZdT57}E$?&tTd8u4G;YdSk_sPZt4U&F9F4t5}|S5Ws~T%%IijA^K}(gY!Oc_Mou}19@fCOhk32@p>yTL4ie&T z57V@MQjOD4inZA|UyG~5Z_fUgYXp8?OvjOOthd4IC(D{zrNxC$o%Su(H9i@h;92td zpT&kH&e#lN#FoZDX$FE9nkF~9 zd%s|+RW*Z6^p+^IfPNfnENuIs?co92e>arYSgcbHnH8b+iy>2KxvI*8B8lBo8$6NI zjqN-58Vi(kvwTM3%#!QAs`0vK-}RcVt+UlmZg9qC7$de621zp@GPPRvZ2IdDq9+Y& zjHLMX*naBfT?(qTEQ~rYii+?Cn6F{zh~vL;v2OVx&%H;%?HcH5=)CsF;isWOGS$!vfbwDs!fl9@tZ3lD;2ha~nc4xVy-Esi}$S=F9Jw^k}Fa=h?mK`g=q6{);abbb#w5 z=pm3id%4({j3C`4p15S#A&}fVwzDx=KxQa-9bcZ$=M=vX&2w*GyXBYVZbz6D{f{p~ zu9Apt%CdU$myEGDaVtuxYmg;e_Ml`AA0l znaTYsKZ{uI%W1u(jg?GKGo7&+#)vJ6K@ts!On;}#bM@jBuAS9=f@gkCo00Q3#>a`p z*xbmd-e_Tf{K-m3+n*aE@_bpi?);YEe~$H^gCxZq5>GGY-Rta(%`ir6=?auiAlR|8 z@f`ClhdIs7kLRTy7o0HtxaDGmH^i8iS-75UDirmyC9< z*5~5K&n$jfvwG~?vVI5Xq&71XXCJpn=Xv+;NAn50{MaEoi`~i45mL@T$`+oIKsF{b zNSVXy(FI?H!ytLmaI@nA*Y*let?0KQMpv$QnTZL{A=Ka<+T{$d#}e3dX3Bl&KpwHD zBayI?A<%sHg*pE1bG}^MWFa?|^G}(f&=lm<;&C6|;6+I-^8(Y4@_92c@SjR}fg?KX}l_%b=d;VBy&rJNJA+t8w*E}e8 z$?qU%Y=$vnOG}W{0V2a+@7CS@P&DABc05OgOM}QfC7=6FEM^Ag#+TUndJY8tJyEt( zy-n)<scsd`dvfL4lw|Eccp!>E+;`2rot zL+r$)Qz^4uZGU3yovH_^f)RQ}GD|mKv3nSYoQ8Z|;iU{p8cL8oF>iO@3C=f{BsW%2k_3rqh}T~ZHW{wv_aH+$8FW2s9m(oU>X;&Wm#G&VGANLuu@`LE17x$Nw$ zjl3&t4@H(Wf?CAT1*5nwdEpIAf-e~5F$+Do)L{BtnG0(seK}LI;QBF*y^fk<)K56P zfi)Z;-!L!`xa0-z(Z#%^cclg{;q-bQvYD8w+}W1X`upg;>#R{x-9^X=C-4yVgmc!R zH_pMMExj|M{;j)DOm)-z%Rim58ODe$i9rGxL{5A1{~?#4fa278KlbB``FRtRvPzv; zOpVM8g_R%AeR+0{gX790fnT%A)cv>w-8>mM*q962o}`U;=#-8gKAcF0hLjco4S<4WERjG1K})fWpT->ywLXD^%uB zauNR`h@8+uw6Q0&pA9T=Qkr`#O8IV;Y`7)#*Zrugw=*`w7_lWuNPvP!Zib&O{cEEb zKPH9W&D;CdPp~C9#EHe!($eg2=G5rw#z6h(RlyA}k481kQ2W{rDxsJRAqfX*F$HfJ z3y#GU{NhJNB&?1fPENU;SGK}-`jyOe7e-7AJ4_DR2cyAaiY=atUHP{A+t2$_X>^X` z&%wMuo=!N@O;|Dqv{vDD@?7O?WAh{TSjoNm6-Qs!a%fCEbvo7=n_-ODQWz-3K(O+H z;Qrt<`-P?CE8Bf7Sl9SnxOA@k&|$EBf_9V%2b+*@S;Q4jFt&U zrII;XMdx+Pay}UWvDoI<;V-pCaU`6GIY^cmT_=ZNxV`0(A%Ad zRNH5^Z=;)>+XL5i`&neegLzChH!>bVP9ahI;8hYz3gLJs+#m8w;$Y^FN7^$S18!JN z4ODiHh80LIadU9Goq!jCrb=Nj>)UT@1m7$ zZO&@{y!rR6Fr?!JY47mHOlM;cbFYd!P%P{SfM4Tro=>@-eYD@N1vl~|{iuq?9 zVzApjL9VAkRoDdLTGLqK$dsW!u2c zp2c@gRd}9T`+Q#w=x73SqqFNDZc~^M%ifxilaQAZ7scKCG#+`W4l!FEcoP-iOV@c& zw>*4mo_f9Ed9kwF`E$4b=ew*o(kc9coT8BCxe~3QOLeeqc^GZ{FfgEOJWmR|c%4)3 zS*rY9MR`XC$=B5)F`saxsKlA@#!tNawkzHO=4_hX z+Y=S>HoJ7$CQ*F`&I?j^%8*k_@^N?_hLTz)FYQy~IX%5ntL~yzLb}GR6(0?LIb$=7 z5nH+fr4tBV@}om~@iE0}iE9_!^L#f1nwFQmabhtxv@l7uc-8Unk9FHF?acitYwY+f zcy}j5>M&?SD0Kme4WYWLyEiyZZksx@u=UNP&c2+PU!_A(5>e_dIyQucQ6f6LS5G9< zM9@t1u6IF%NY0BM_opZatEcf`Pee;aw6?$g98fk@a>jvuE$@2t(u%{Ku^GmQExADw z5QscrIz6;p(39(}_0t$W^=#c^9PWA~C&l)?kd4V4GIq$>GF|fSmQA)s`+6V# zG2ona-_3?I=KBrR{m;yIToci~Ea!~PFh*=C29yFIxY4=z%F(vgoP`UxMa-Hf)Tr7{ zFmhrsF)=V)AtR)JUdychY@=y%8?e+_N~0S^G&Ya zuX)}tT1>WnLQX?Nyg{7BK2QzfuOhGaey`EJn|M0l{lmqH^#+w(T!hn5R>Y*X|1V`K zm!|z)EOf5&(R=R#VH0I%Y=$vnOKp(!10qlR1#xUS+pgBF(C6u@ckRWjj0ZcMn2e2P z@kw@C?{3)VaM!wPnu{l=r>5yza2W%=%$IY6 zCjm2&(+B?MEpLt|bVu*dZr;+Mj5%HUM@h2LoH?L`d5TBhoWpYtF+9MLK5{DHWlUDY z9|7KN2Q_D3%a#4T#BO?nqPgU{bI#ZdW5kw{Kq&))PcGRpS!*Y2c(>C&?|^p?`nPph z**h^?8X2frR($yL@Gak3j++`2V`7BOY@Y)od5N{B=FG#irzWDtip zFOc~H|0V9TFE_2Z@T&I2EWYSv?Q)Zl6U$&POnCFMpoehrVmZ!)ci;+>fU~L+IsaDV zeC781)WI#hCZstR`F2EJqzVZsvE(iNw4-Wv=fQnVUjtGLc@-;#UOcLs?u^YaMr_Fn zl2AaTd1A~Czo`*DEWSq!4Hc%e^#9xD=)_`SWM)z7ay`H!%K5%l)4}8Gg%bFmcr|SV z^{yEWK>8S1Z57xUA?bs=Vm2F-F=QnmZ$TX!lPP3^lS_Ra8!(4g?SwMzc` z;^pp4sdekT6*QH58~2kqR!Y1 zW5ky7Ai)SC-(+0>EWae}_LrqzKbQZT9ULIcbR9D91eveop63qR{LPbc3_f4U-hC9d z`J3bP%$GJtK0MCWJ(sd)Ws|VzJ~Ky63)hj-4dN|22c55^!J5(a5rOA7)l2gihJ3mI zFZob#b0lXna@ABU4DSY^q>h=k(MLo%B6*mOq&#AJ{Byz-){TYE*bHODmX1K_0)oq8 z9-AzS_73idvegT?+{Mm#W&L_577J5L6ZXelKP;?gwBETT{CX?zLc=Zd)l5L84U-Y1 zj6vRZ$6N9SetZdg5HI5Rl4JYfV|i?CZt&wvc!ct}j0?sE%8D zY447%O;D})W^~lHb?WxYlUmN$3}eKW_8_SVM7r&)%QX3)bF2EZd(=yfnuQ7K$}5~$ zj7-cdH=KRSaCMLQv40j>k@*^mZ;Yx#OCTL8NCigXnQpx0cK7467ccH+Wys#jZT{lF z*?Havo7N#$TD;{Eu+bU3XPFGt2CG5a2okOSc76uB}yD{lurm-A(bX z1XWtl1shy8K8mvg!=wB?-?v+;K0k1?@gXM~lrfdf7|Q^$ z&0-FtGG=qQ<_F)$Va`Xd1xe?fz9+r*Wx;&phg>mneJCV#)sNi+v@ym z@lek`^xqkqVT{-k5+rGW$O}sO^Gt7T4N&;AsOa0({I88_#($ldjV+8eoIjx{yyN|W zxfl5sy%KkGS={%l090vVHj#O&7m?aTKHS9_D9%-5FI<;X`rsZLkGN?wH*#r1mnL%c z?%~%&KFY9h?v`mY)cb7tB2o+*PdL; z;>Vs0mm+6uhB0DGc%Xy?!Hch~3~xyMnNj&zsO3&i>Y{h={cGtXmwASJ+(N zxWIj-!`+SDSL31{P2tEbwKNnTWW`GDM;fiLp=r~l!DXA8Tf~Z^@AAZU&YSt?L$&$; z|H#EkodUdAK}iQk&Wpx8VY;SsOX+};TIrIE%%Ta&&e#lN#Fkl7rc9jlhvoV=Nn!h|R{n?nzA&Y{UW5uL1dnNUrbgOJNKceQ8 zdPQN)jEP&3%ZAaG2m=Fe{ZHr#`q(bu#c^)UbJ>jgo~`TwyZvun4cl_2>3`I*i-gle zgGtHK-Aqa6-eeYhU^pD<5caDhdj1t>Y=$vnOFf{}0KuZ`udC_pmH77kpo6@y${ek~ zB_&KwEQXfm<}HqLQ=1knH1a*P{K+m3y(Fb#PaDV&OoQ~PE-PY0LKmQF z`JYW~K8Xcp^5@QXhjA9!FHM;JcE+KX zJvf;Vh2|`b5CZ2VP6DcUW$PX3$$+B*f=C=_2Dwl4WY-K=Bu>7$h#MNhWQJ)RSR9= zz}vAFzQTcH_fzkd+d7+GD)~?PG*M=ixAdgO^+BM`mWb0E5o0OCIECaLO{D__k# zDt`HX#!hZ$Y=$vnOG^+3gUHe@)$e!3j0HF7{f&J%)znbGMo86(+1%7HUB976iTj?6 zr*H8qzBt|fZ2>QRz!i}pq>0PhbsllZ(fcQ`LypjPq)bcU=;FSA`-PwN6&AzU-Iql9 z>+c|!EJW8sT`$Pqk-|&YUNN2OA)(_-?(d$t_a@gdp~E&|lf}cowtdHuZo2j0z2c5< zRZ>#__rKR*S)>?v$4Z1HpR&9yzx{t2`-CfB=T58h zn(D-2W^QP4KGk#E?jw<@7xNykd@_MK<%8uOb#OfdU6jeOd?Oo^2_zA*U7W_oWCj`F z->ol;Awz1wk%c@N*;vtsn} z3jY4+z?(aJaHN*r7^KvaGr#WW0@Jx0!fYaZl8athGg=i}J7Y795nH-~q!bYOsb-Ck zgopR(xuq+bjE=hO-#CBeVkZ_ua}(3W?=o&h{$5nR{GU$Gt(tRYYd^)?f{Pg==mfPO z_Uqw!`%T%HEFe8>_EHJu$Tw%UPyHF)u>Z<<|RI!*bN6-(M6IpbQL%10`rW z>T)Hca@p!4Ug^W;<-6Kb971My?45|5a{8yiM_o`-j`LSLW>-I%U0gYBhkvcJ%Mf5a z|H>JgVT{<)7{rSp^46YxH;bhg%Q^mSfAn^t^-dkVV_!l2Xy}+NcfA#CSp(-!9{89o z*SbgWWerShA&6xS^OE4p8rV#--7eg0o$$ivah>+>F0nm%WQkUnv9-1Mtq2*DR+dzq zZ&$TFoLEdu4UMaR&Yn0R>J{;2o5x$EJl zGxrm|2yA6gvI$_aKu$wb1hADn6VE942I&23%x#H?Nb;81x!_N_!p=p`*bHODmf9fc z2Si?MVcfXe{OC>1nveNMEF!l2-CUvS#B5<=K6B?IL+@*)Z;s`Kr18F%)RKD4#OKMt z$i`#{Sx3b?^(AljrJob0R?B|6IPYuwvj2^&U*~>AE?7nzGUQyD$~%o|THMN=Q3v0> z&1so&UCNScznP-4K8{2&O%>jdnRw>dmklS**YZ1l{_#IEU&w{!Q_2cgXKaQsVoN@t z!A$=r1PKDxx6RPYP>EfKNrMW8Z|TGBG9j5!vB{UWcWd{!O(@xjG7N`Q zI3T5i8M?<`Ecg3$syQ)P6j(;GmH^i$^)e&2$o9xF+Kb-FCV*T?`+TZo93T( z98GXyu{1EW_>$cy_3M%5O;@p9*A$O1eiY-_$O-OF!>%brKFf1X7<>|dLGq-=_iN0G z{fF2r_BDi;R6A(BU$;MUm^V%46u>3{Xt^$P8_S;uio2HXkv9a^!=qxVt>z2VF5-wt*jX z#jUFWKj@09>nZ%8D{g5w_(4~kH$7knU2&h%haYssJFmrQ1)oz}$&p^kFD*aH*{8lq zUm)v1pK6YG-aP0*SHrSc>b&T-GIVR+w4YWox#hwlOTS$?^E&)~#D$F-b%2Lm9U;)4W6; zeL==h%2EjLLU!ma30%J%VYeiRu7fVNYO>}cpm%Klt_9=y!$P_P3E&RHp3XPr6owvg2?~uv5F23OE3Nk z6A*P;vg%aecY8Z079&Gr)B3ds8doLcNnCn4H@snxuAD3KjPe( zPqMIcXL!r)`uo*it#M~u4S#P!-D!ZoMg`7f`&c)W^SzIku zF^l`!PZzlqJH9!mV&>2DHt^(f#%35JwzLGX9z-s`%+f#khMu17W%E}Bav#cBCeN~V zVlgx|Hf-;^Yc#K-K6hh5ME2r;4ZnN#SapLY5TJ{}d6$-_LoR305Co z_Ut%p|6CrlVG@451~1|y2TC@aES~_apID~U!|Eq2M|EOd3{J_aO>CohRBkHcNH{*# zQjN#Gr{o#WuDUtF^}ypBA8l)p6VCE$*b`1pm~8XX<9p*Lp9{A(P0LvHoj=IW8Jl5@ z*pe71$w2TulyksN+WHz<6I6N{ypnbH2Yi+Q3iSkF6rDZXa$(Z^5E zJpS1V9>%jU18e17x&FraT*-ScpYt~>PCRE+{8r(g+^f%{6%HtLcvqf;7AIt_i#gra zX`(-$-{g6`zTvxczg&B_Ws3->ij{8;H>yv6U$@rgSYh4!nbVBDlm+H|bH-*EBewJd zaySI*mrUyF+F^P7&A!WC1v9+7UPRpL2HpN;X!h~WlB*X}ZtAW&F-7&5{1ofiv&Hv7 zy4#Re3s>7>_$n%{xMPS_RI86JRo0E0G+D-ez3ztJAv?~Ba(D~ur$OaIXCdyOe5DP)gOWj7_uHL_{bzn&4|)|~yK#E_$$GaxIll*O z`dIrJb`j4INFS;1dz|vG=G@79^=|9jsVl@&+$JEWk9Ahq(}$qApJ~pG$t>B=(k)%4 z%N*Mvw|cMhd@P1BVoOP&lmWqCCj3bEv5i{2)%DF)3kACwrT^VEoLDT3Eey-A>{kqX z`|NRR_fbAuMZbR`77N@UeIUqeBku-bHYQ^To1tzS81IPxDsTY$N;c zrA3MMeR}%RMjwkd-(U7ILwnzfv9E2~)de4D*Z760oP2q^n zQ2W99(1=s9Z&c<@yy;Q7xb@<+L$8t3%BEHD@&+ZXOui8IY0`=Jr|W{|?EUqrK_WW; z{wil|hB0DGRUn5$@XU9cE?Ta2bqUPgpJsABOs$)7hAy~1f*vwY_|OK{Idu~i%&g8W zG4iTtRM+7D-70ZZ#pCOUNgZ37sc>imqQ`@hI&?ex4ZD9AS6#943FPy2Q`s%havwQ$ zY&n5Fbp$+bU0b)2Iq}Nln9IT^RfIb%)6|@?8ODe$9YInCh+N(7lD_=n|M=rlUiaGX z@Nss#cC7>5TWV^`5>#K9bL!0t`>c)!C$qMeO}e#eIwajd$_(Tsy}a8N;#ktV=~ub^ z*W>4FTYhAwEYlG)jr`i?O;#1OZ8sH`^iqA1=D<}!m(895hG7#)|!Oi)uPut2J zU!+nN9E=WFf5Mu>iN(;u!opm8<%Hs*wr2afqT?Oq4>qqa*t-H}!r5^PN5a{;x5qgB zpY{9beRX%OD}=HZuyd1lh|rENqX|c0KD0jKoyN56#ah1O3Gx#c^v!y?H0$$|dX}6` zI1Eq49s-djEg zc3ul$bY?kLd&`N%#K^#Mz2jof`G3B)$UJ=B{&(iDh5O8Wz9F}2cy8ZkV}iD7xR!o` zw`zEK*1=mfyt{?rtr~8%j-9~)E_YuiJu8u4wzi=?xPIeuwo2sUhj+wI0+2B#vs)LM zig@&InOtmFei#XS<4JDceNyT|=}Qr- zW$%rwoUs|kh%LQ=(hmeXFK;=sF*I*_=E})#(fgwRscfEp#fjO%z~tW{As=Gzx6DuI?XF!z_)b! z-(KXz!gIY1He-b4OmL(_6Nhn;!@IW#Iv>FOt62sT7hLm0Wg#q{3tyn~0f;lfd8aX5 z7TI;OE~U_o!>ZJYY3B}&mUV?FD94Pg;pinw#J$=6=2li{FUw&%Vtx z#~GVpjM$PD#7Q8sYF6drT_vaH|DJ4|_~(CS{e)8o_JY=5nVSl(*u6;e=Lg2?ZF)_6 z{vYUmqBDsLc?ATIP#$~*1djp}d<6tgR}g#!1c#m#Vg*F74txa!kKr}g3J9L?D#Qwi z{cZl$jYjA1KQ5ZL(O0;dLG_@$&5f7zNoc(L7r<6P!1p-~&PEYg39bFo(bDRBQXdRf zhZpKvoQsm(^yM0ky6u1%QbK!hL&@*c2i6L6nF${P71(Y+FIxP;8Jl5@*pehDi9zt= zbtMv^2Nx}snH(wh{*~vpb20x>PJ#xX6azg8nma~j`u~`)5~;Vgd)gkE_HA3I{$=Ij z-6OA8#e48Qbe|-5b_sN!B!zwM?GyYQ6opngS53OhB>bxTq~8iFcI0$$NDkhsLP-Y= zf6wRbEa>zocvK-2elorz(|r0`XKaQsVoNcQGyo#KC2}}^$rdFQ?3w(0#fg$vUt`x@ z0WG;Qu-yEiW~I%W_v=!Qeb~!UH!s|~Lb(~V;FHM+(yKx~>4Ep~clc3wJb(G%N8#Z) z>EXx9Z+!C13%LsqZV5cAb|HOn%}F=pk_D-~b3~A+lOBf4q6Z4wJIC8L?b@NW+Q@{3 zsW?W9UHICQRbhlv)RBUp_t&evh`Mr3x=wHM#!GKsWW0JG=ZwuTMr>&hl$Id){mftc zj_Haq{GX}AHb*bfZPPjHTi{L=ft_z0i7LoD-ww2{$q(X74c_}H@|D`Ev}EQo?Wkc{ z;vDmYjR+%VuHoZ2G$?Vd9c!vwTpIb|$cpxdy9M*E%aui;T-bhW0=5$8NI|HN_OUPR z+oubQ#@wuV^M@&?RO+=eHp3XPr6fq&0FiqZ3H+$Ix1FE0^kvEO6#k=ISiUTDVlgx@ zGTr32B4fce#uzz^5Ife3<`+ZOTrCEt9O(ET?}`D~7# zwb1!&PGxu4d^S}E`p9b2DjvE$>ucV$YWw}d`zNhkq?#pCcNs?tIrR$Orae-yL|~h`1j>01l(a^8 z&m11Y>v$<_jYO>4{x%@gt@g~L%`dNW%l&Bc44XqZO`Q2xn98Di-Nb#ezS``b*-tDl zD_kjm?~KhbMr^4Elo}v7$NK!_>rehmweM!1r@Z>r?MS~1YM?PZ3yZ*C3r|iej!(|N zw5ECezDYY%S2Zc2)Hdg?!)hDuJI3%M!nr@chaC~lQ}2IdMe)3c@@u279Zg;FIIqU# zR=>(c!FY^&r&&^m8uDf2T~o@w*ykEuHgBz~Xu z`e>I>xlQ=6C~^uJI<*b&Ma{uf+x%qB|6k?VqP3c_@o`7$FTNE1Ehv|zBeh2^M!;*E z^JZ=rogZ-}+_~E8m9g@q@rN9t2}kUlu^GmQEiHl41_TELyEl3)cKws$a5-W5VRuE5 z=ZgcJSPadK4c%UZ`ajz)$9_bWE%V5Zi&`xrdTHR2g@kogyq68l^J~{xi|ZcV+SU28 zjoUL?W`Ez~LEDnO>QcgkYq3!!_g}r)dXDq$aV9oy&U6z;5*bHODmc}5d21I&zC%mf^dw$yL&r?&E zI=v_VjaN)^Vlg!{F|7@_xX)IJp|obDt@G5hC$a}t&Z+~qUGmH^ix&oyW2$uPk%)eT$KSAr_$(NIP zz0$O^y49RmEDeo}qvrST;52@~SHD(DT+7Y^Na#%35JwsZwaDIoG2?@80b&|517qXdiHgA}8h*#-B2 zj()H(daz-m{(4M44H_bzwU1y+Fjw67CDr9d?@v&ppzx(fUu9 z_?`7E|J=1_@4`{f-OGl}EG@NR205C6fp@f?W5BUE;=&4}y^q$|SnCDm)=YlN_%Y+7 zbU2O_b?+2XJ*Ois9kY?rXlYhU1hoHp3XPr9DWrfXJ9Lmv{o_*gTl) z_&7K1q_|J=-Y{EGOUT?Lu*z+trBzu@`Teys=YP2(a!`cnDtONu?C7coi)+h`47Z)T z@^fkb;rqQ>hs(XF$P9$qY8{gT03*zVJM~re}48yr7_EU`lOErqg5ORPo>e zyqrNv6}!H)bxxDlH>rQ)$2KqB#I7T%{I@eU!x*upACSW#I5AK5&XwGErh%p_o}S#p zXjEV-^~H(B$jsQt=W<)dnb;pn`L}vgUY!4)pBu{Qjod!weY6vC6YcexZx0-nc-&Z= z|LXGo51+G3530963M8T2cyxKReT;ok)!xO7S>b!K#pElvucYYjv|hrb^ zf{maBz@{d4JY8u~3*X#toR|LVSr%Kt>O&G!h-$Yyxy`#qD!9k@W8C&t5h6j_!P#Ff z2hJPj<;jz;G;g=?KG@5}cKvATZpP!LMTt?5=3EJwu_gHwa%y>M054BaQp>j|CmMLK zGAo!bt$3>N;;Ae9`M0;7u^GmQEnR`q2?R%;i9I*r@^jn2f3Ik9tIUezVAGI*tnG!& z7P0tMvoRS%*1+&;X0b7unu0a*;ymBubMO+s#TMH>$sA9&vJJX;H*y!B7jnVE`SY=eo^W=>`H9Uo??X@!4YdC267_UeZLPAnFdhK5%U-um`^ z&E*OOEzbMzzFOYjHN}h*JOm6~%D^zW9X7ed8^!{kTw>kP0-IdoeQENs;hgCD%XWFe z8*e5pyWF;BD%*P{HqcmF#!D|pqL_d?vx*bHODmck(30g(@< zXx48%^HP3#{VQ3%-39Mr%^pWOu^5{fn%SJW`s6OdEsa_8bY8idhuXeq-Jc9vbVvNL z(7dm6;KxFvowAr^qZU!9*!Jkk&alPSB_|$*D&Ag>oSx`X4!v%J4$M$=EHufdEYh?b zV*Bm9#_-GgJ9AdA+qszGd2?n)|4SU@5K?-2{aC=kxUTwYe5i}@{o(@;PS2fN-4Wo7 z%`ir6DG!vAAXqK1MMXJ!-E%h9mo*D@5~s`yd~Z!!s^N-4943yIYOHjQUKiM;QMYjM z?wp$cN8|m2E^yL4)x6y^{8CM2b0ec2OBtt0xB1#z^Q&iT_ZdRcCC5F=9(!kQ4(VI~(q_9enx9$nWI*ZqY?ASL$;4$~iHc7#P2E z+Y@d3uWIh$52sEYJbF3l_`hY(Agy9Z3yAmqC-_+*Jg7G=<@1MZPu~&TDcI^A6uD=~ znZKtd_6~u>@_`$=whHOSrNLFiv`&{$+EaFR-<~Qio~?c+QCjIed4vkL?b^U9?bii2 z1P;sJn-4nE6@C#D(QTbimLzVX90Ze7v~25q_{8&Lhu)%j>zjVwY1*-ZBeHbaGaL!$ zQ$4(`^TBO$t!!0;{uImaE_a>>9Wde+PPZs>#%35Jwj>5gG$3*z)6sLq>~n<0p6pY5 zFT79Axnjl=&@u@#b2+`gnQ~GAYf~-PhS|B!{Qpic{4ivA2FnGsUn0^NR}>sQBDSA5 zL(Wx5-@8yY>}1*?>u`T5f-T#m&a@JJI@}gV))i`1U5AKRXw-Rt{Pi12=fiCR*R>j6- z0_lo#gRZPKg%m&R1t;L!3fLBy7njCtd2hw)a9_4RPlloO_4TTKpxe=hT{*-1Z3=8# z0pg$;T9z|n!nW_Pvz?q#YP5{<|&$CmVu^GmQExkcf5QvQKeWh%<{)OM$c3$?$3nUJ@sIC3t#A0e`YBF`>tke6q zyDZj>6ltGYX1Z1OEVDMGoPiulgfa~L9 z$1T_}@F1^==$=BBt-7sjf1=v(RAoX2GcV6Ez6ME@(Hf)_@{LkCs11Uz%bW*8&3v;;~U5X@>5_wm6)^IUW0oIRb{+f_}^NbCe1XJu%p9(p+V zYv@a(KFR8p4F#EQvuVyXOg?OjHj!dwK{-AVdkXojeK>so9p=>` zMT#>`f9q;bh;`?@6z7c1Fh*=?36eTMq>Rk#-$u=^LbqrOYA*{d#}<6PG=iJq zrTcN@ghQZ_izr(D$_?s9F5QckU0WypdS3EIM{#%4+6Qyo3sc^{Qbca#A|;%^De$7@ zxAtnYe8V&CO`)7kjq{6UGHqE{B5&Y~%`ir6Neq-^AXt$hT+Xl3-fxCvtjNfo@Q3lOsj|83#32~0aB5vPSq zdcjT$=h>3Y#j}T>;aB(>tK0u(uTf%|&vt1ZC=nr+SN#u%%_dO$NMB+X%nZ$Tu-=b( zU9)c6+)|&A_^G4Y_@3Sbb}r;Z^nWG19gLEQwpagO@iukhXH^rEA|nq+dH${w7o4#f z#)vJsK@t#%JUh#&$g+8xfuWQA=MMpwAJ1-(TnE0?*zD`!^UG#P1zlIzxn!!gT>neI zyH}qhCnC1F|KN#;kFg1!h}g5#;faX*%nVo};=XKQ`8r3TGW+YV&~+dDq;i>y&-xZV zK`x2-80Wwe5&lNbXi3C?a)5}$^-Xg({x|v7{&{cF)dxwYW=TeI*b@;S<2$61C_SxX zr>po)zKS1=p|=hAyEa+n>~O|r7$dgi21-5thX_CqHV>jZKRUTqgP?2|Y0*%uc zm>JdQF7_2)n)hn1nx50sNB3lA6)b-ONkoti6c5r3fqcxz;b(T@ydh8|?(Vg;!Y!TUx6SSq zAf+Kb79&_egqntU>_4dg-p_PrjoZN|%T>R-Fn4S`>Ws}WMr^4Kl72v>@&5S&*LJSg zznVT<+Ri2Uko6PkxuCH=Q?u}=^DTaEwJkf=Q2%&#SbXOj509UakzvS?4Nt-xHYPL3 zshxam+-yvikbO|xn{rw6bZ(tgzu>z3-P&8`VyeM!{L>Q&l{kECs<2ggqir8ttMWc9 zKkbmVL`pjaYFEM`~e9Kq_&*Ipwo!W@&!DdC_gN!QGDFmJdM>oUs|k zh%H@#(g_5+EGhUC;VtK`dCu0bF2-^Cs>kA9PArxthDK@{makdgz2LXVIUX}#xQbaJ zy>BUaRh~KIfGa)@OY^5n3xEAzrDbjW{qCew_gy3YKhPe@se+Fq7<#S@&-6R6ljzAg z$ZF!pzJ(iPtG1@6zvY)@xnFVqcOvq|Z^&f`M;TJ8Sm&a$NkS`1fAziPvL?z*t9RV6 z_i)B$7$dgy14$7evixMzgy+sDR(ve)-RqgeQaO2B#C9hZ3lj^2;OYOKoMJk2_yd#AR}ZQ953zk#|^(2Fg2rgp+Fw%}DaVq>y|7AIW(Y)qDr5gW#H<-XQ4br>2WYq}@K zu3?MIl8{UAmZN^c;p57LUTnd$?Gz`-UknWNoi8A^D@C=0Gs8{j)n1OXF89x~%G4zv z4{Cj!g}liCIpJ`vM@l#mbAP;V*~iggf5kp{_UG^0ekad=?~KhbMr=t860{&vuj-uF z!}(8FGgm*^z~l9aBV$%6?4yc-P>?Ca;l+avU&e#69yCwq%R8Q<5>hfbdmSL-h%5X zpL}^_*Zz{wU6I2Uo%ic`7xGaMd^}&_O&F9^lyCmv(A|v4-A`q6w1X%62PIv780(D9 zFh*?Y4dieLmfuu;PuXc()5^%kM@5ehthOtiEAPZ&XlZJhwkUJgwS_Dkr4x<^vL9p< zW=NE(2RC7iAkAPtzH@9$CXl%Uwu{r)n9QIZ^0@@AX-Bdiak}}M6rI1;m$boc(Fdf;icjDVyt3lH`5RtY@dhTrD=Qwe z(8aG>m0A;bo)Q1^q~@aG#y@|mW^qx!nBfx?gH~2Zw=mIR$cDZ>C6r?3?SYL3f3hw= zuiMj@#i8oo+TwVABXYtKjDZ(3C<(`G=0Bfg&Zeeig5Uoydd_F|YRUb>&e#lN#FoTB zNd|)N^ZDgRDfb=D|92=Z)^%G{7xRZI-eAfu|I`FZ zI84w5pnSrnumzwzDaYUoK-s&G!WMwC&Z)awlDx2!gTv)_(8Gv4Hq|MoHZLw3Dd~n! z*dMk4lq#n#qNE$U9nm_gRwOH*JHEtn>HErC5t~k@BBvYSDcIA^HQkL9mlx}m{oOQs zXXtI8?@kZzdpKh=j1gN3gQOV{8EWHc9WEDR9dl^vvMPOB#X_0TLryFfX2vE;=Op<0 z6DBZU^?e~!e=}iM`y+)q@Klr`q=(JA#et2<0y53bCz>lJC)xfcnWr-Uack?9hN}CS zu4j@5R|?@1Z6|wC1pbnRrYR)nYi@X4M9HNPt2qL7MVEP}2kqL5oI*smVNW5K;*_nF z%yY$mMOEx~S+^7aYa)35C&1T4fR9&%u8H6i?}x96 zU@w(u)HBL?xPR>}Sw-WeofpG@3NgIg?Z?QFtN?Ke120tu@+hgEsFR5J#8<%9M8F5~ zXqt%F9FIq`2A(UpCY-gX#b(Ci&lB5DASWX6-`Eq;1v7oYP25-I7-mW@+Pd-Rl~{jk z7iVmSF=9(@&{$(&U^s8&kSI8z)#WM633o%0dUl=r`g@(2&5R7@8%({(X1)k$ej^W|AiRkL^R8&+r*CD)AcO!FB?JeX)B;|lT5&7j@$h!1@T4Ti7yA6>duU`sZOm=X_W*8&3 zr1TC-~I&EVelnc z*yf^09~mZgCY=e($)JD2p znv>(iVr*$-c!cfEb=H7PKd&>UJ8Mg1Dk9HpVMW@oz$X{X#t7+xbN=LEV={&e@Nlhr z#KvR_nNh&AVZmi$``w`MvX~U<{)5~P%8Ncf>fMXnO{d2;7e2XMj13DzetC|{)@-vi zqCQTo*LTi}kDSxoASc;JFg@|for+aFsWoq_@7G6iD!x~Cm-d(>Gu1g`GmH^i%0r|l zzNZQTLeq{V#+L05Gpm-_sq%l~LnjtXb7S)WtyJ^V7S9iM&N#vD{z_9twfIpDF$dl7 zDJ-Vopqr1&*KNEY-Y4C?H0#Og=+gC#PV%SdQ|0j~>?P`;8!EM%=w0Q#jgOotRK2PF z$$nQG+4IbH+nallH#_ht8pEqRM8U-;cS^8h=MrWcElUQGm}Fi(k4667*OxeBGmH^i zl0+o5iO0VeuRic*(K6Xbb}Da{#{T@iXR{NFg@L)@W7)@Czi+2K)wLJb_mQ0+bJ+OX z0&w>XdiW!sG7lS*8Kj6}?rMyh?DBy*!hc@(Lq*r6oJvdoy}R2zG*bwlvKsX8N5s{+ zi0&C5y;I1Xo%@VLH(e60%$HcXc*iTdwM;ALA{Rxi#) zUlCGCq0ZP0W5kx05GkbHQ_AM6wCJ~;7OkJfUhP{vrR@E6(1I^RQ%QgQl=;?DkGCdw z{uJvsSW^2}u$hvgh)-3Ih%>kDJ$2U4+07GvW)*+Y8rEs`a;IlqqEkXs^`L4|G{_R# z@}n~|G$@W8FE5X-G@D)ePFV=sO}^6w)vxvePi1nO^t8TG0xZw zW5kvu5ee<+r?bo5vbHb!^=xBQzH6W1m5WQGoLDR@%uS`H9_VT|-nnot&$<22=czW` zYUSGk?!y^ECNg;LslxBz{Vvy*{k9Y2De5F12u>08!+v;VvJ7Y795nF0Qq#+IQR-PFbqO|`t zD8FOMotgJlbVaNav$=(lpZ2z?Zz49TDjKRpt$yCO#AT=ZHsmCP>l$Z1&D*dfgnEth zVTrqc|4IA`Gl^{G$}9bQ+q~nM0&>%PXm{oKG`~QT5Z!0UIO|k58Zyc~ulbukW!E$V zgJ}~Mnc_%7TCT9J9G?c0>iL^pdg2;W4LWU1!$N$D4>zt_?~KhbMr?@1!h-{R&^(004b4}Sym&xZ>|7;uJocNi`u zoK|!Sr*&Q3bFDY4=a7$%@R=`cYnD7UYjMVA7$de+g-9!lYW29*UACXDvnB_baYmj@|L{U%dKg3IPQ)v4`vP>7~GKIoyqOC8mz1(9!2y?FHv8wk}a@ zy1M_LMXM0u6rwkIMW@T$1-eT^BU(M@&5?Oyby;Plqcb+c7_p@#ki#MP<8{w+`vw1R zvA@5uUYS?z&1%IpGN1#nElrs&=T!Kx2wqtv%G7vKTA%;s&$o5BTF-n2Iq(x}adqU0 zYdyCyr+kQS>SpBs+`oG2VJ^kpmnPk#Q|sBFZ8*1{BiGbd@Lu@YA|e)gY1ujVO}s7A zw#W(1;19g@j8tvuO)l|yvHVK=rVaB;PH&hxJL0X%Wi}aSY=$vnOOlX81|okR`?^GK zo}`8h&yo0db7paVIoQ+=ITUDbx8;BvJTD5#MT&J2v9=U%RN`~>^Rq6$>AG*{ z-#$_EGG}atF=9(4ka!1?vT=Gk9W%cwDqC|i%@-Cru=x7Iwcyz126V-PMD{A zBX0rKI%@q(G^O{>;lEd%b~tNBZd<$JDss_4Y!8XgToKO}(1Dul8o(aXHlvTv3Pt$y z9$U4BUHHUZyP)fdERN)1o(}IJ8T(XxJt1F|(RZQz0H3i*;qCopGp3a}V>65qTS5ZI zJecUdb8^qm!;ws~%yMI(z@A_q;r3Y=$vnOK;!= z1SVpO1@pS3`1!lnaELW-SjTkJ*!dpla!dom%=aJnW-Wd9jJ@ySjvqBj1<%)|P6hY5 zO(1uGu(^VkEklNk`E2*?6T8T9^x#3IQ#uQJS7bc3Uv%dh|6u3}@!8&ho^3(woF;W9 z5~$XE`Ju3To=#ASTkCDZ1nVEa)tr{-q3npTV~00iP*O<7Ocsy)8+nXIS_|h?thekI z4l~Jc#%35JwzLFJ9AHBJZ?;@+=n02;JSJE9Ef2p~v^Ds>6N`zVx$&BUwfv%OwoE_U zjRm#*f6Q&Z`(G5?sI`P{)3bkYFm;`Oq>-@m9+5;(pH#kW9hTP_XjyLX+5f_`+ltyt zbP%l;x|bXGV;(&$tqNYQa<(=1@ZUGn_tw0cfn07Nr3wdGq;g}*nfR1Wsr|B_ysH;n zT6`+<)z73Q&e#lN#Fl=*2?9*0C+b~L+WOGNbp3^=dLLS5964aW16;?zCXsM#3TH|T zfz1H$PF@P1MDn>6#&P?JQmCPw_kX@d+xVwuj7$|vhf(?A_zgM(Km>?e+pMN92^^b7sr0(EIU&F>^2B}kcD%P?wSwOl) ztQG4l9?Nu{J9&+PYxj+unG7W!JmtsOhEkf~b5Vd^xQw+<8MrjDYtLoV^Y;VGwww`s z{db%Bueav2KOm|{}N6hnngwE+>ym(?`g2t1cxBbr83}eKWdces6Ow5>} zuf|!XQuBVF*tL|Ylca_IEM#+HF|xEYs&2}CcJl5@q3Y-VO;;-4Jp7*#(piRX^5t_g zf$y8bv&naYS6M@PQKM`4Ov`wca!dQL>bWj7sCL}^p!=pqOtqs?(x0Wo&z6>S=kEQT zf0oHwG|z~|k#O9mAXPif+xGri`~Ck>@A%c7I}OiCTKs?X*BP5(jM$PGIL&~GR{}2t ze&(ObhDeJSG&e#lN#FoOqNd`=W2=48D zzxw@2(Uwy^oQAdAe;HLxBc{2+{b46#pUXj|2V^>zZFFb#==X}G{h@~dOD5ZEU z#n)V+WlCY671#6VnDYCB@~eY3wln9s`SDCbPAOjBu&0!!yQ!0BBq?Z4*kD{TwX3}L zt=_J;&e#lN#FnPOi3CjaMF+l0nKY@^bMEBsBDR3lZw=l*a$+$zv@~*m!Q{H;Ptf~& zjmAQzYdz=h6Pr>1-T-b2-RO;Ux;dZEc{V0XNTY_gt$umVH2d{MyTdzJI-$THnl{IjrT;SEN}(V#|<1ulGkf7zJKAt{7o_tR7Je@=K-f0iX< zOZ#KLsI!OT-ZMrcw^-=1sAa%Y2%o>W1UOt7c#=**XMcECo`jueQ~y&MBFkkkMFzs+ z-k&cEVd0qhQ++@GWwF8D1x{DDHK(q3eB$F(l0rCz_`6N(Nv!?xTz1z2K?Y5xbvqAC z_YE+1#%35JwzLFs5{OJ$o}GVW<@_?fjMZNoek|3Q6WV(TQfff<!23gC%z{~s&dY~|mR|s^zQuU0-aySc`Do^3fa>0;HHg_+1{A}|VD z9pmp-HDS{m=f3%ODsBp!ao;YM6FJs~E@`PW!%y8KTzKn%iR|CEu zg)i6`e(^H5v>SX8IOk0d*u~4-r}W_$FZ0f8;SRl|R3KWCladtuW{<3?+2f)MW%Mb0 z_=0_*%UJk^W8u@ur&q|r^zE+I8pc%f+>JjbRj?u7)WU~7p#>j)xx83?8t=r(>XsR$ ztxZ1~qUtLyI%6}85nGZ3B{2xTc*LsACw=l(may}idB3=rn9i4Gb7CvcSO*-~6K^2X*LFKeH*FG5Z&h?!`l z8O6|Tuwn^*ARmDl#gW&!KCoBI@#058N9&MRZ#i4F40q}VeZf&Ig?@y0u7eN%mR+j& z>zI3K;cI99`CA`V3x7T(XyJBtdqN0=k2q&Tlv)~C8xj&q( zel4!zl**IVYdrZwi`5yMVT{<48z}ieus~%&eanl>F3F#~r(D`+c=g`P7YChKEDa5f z{Z&OoEG-oi&n=AB+)?0_wQ6S5BJc=}DP*w%=en0{OlFW)5nmKP8&el4?NYdwvP&Cr{F^sBIMK+Hx-NNosy5IchzHr z76;C}YoRk0M`?nTCSqC~g5PqlONdR_a^mrVmgi}?VXStKZ7jBoDs0Sm<;B&jwfMEcDQ+Y{*I;(?$2Sf4yP3^t{CvOO|~G z;kt(!`UoeFxW$KB{C~_#YWu%*^|3^${~J$yI(){>8Jl5@*b)*rWq^r_1Lcp*k3Z=; z*UpuYAN`GO`6}H{PAnGYMwSn?uGI&9W?CsculJCCQpN0=dg~t0sygU>sI2Mi@Pi^e zHo*^y;5mGN4R%ljPZ1-0nKs99RW>FI$Y2d$LQRU%=KZ&9t2h4))IY-cz}Z17_!DTi z8s4S4)b5z`B}{`Z)8<- zk&2tR#R+9S2e0m_c=AO)O6T~>jfcy%e|I}$GmH^i$^$1QFcBW+_IdGHH;$GCGY`$W z_~g#9*>e|z+qux)YNW25{aA~e2oq?{L zqf>L`>z9R1YSopC8cU70I*CS2xi+t|5V`C@N-N3o@a9U~;+h#Y3~zLv7$de+1x_Yl;>h&%|C<+btXLU3ou_<7Tl2KVMseT`*5%zgv(j^{Y5$Z6MMo*jo7DEFQQ)W>ZyIII{Tyy&@a&&NiuCQ$(#J8{?Q$J=zJ;@+*`%e(f+ zE&*Kp7(#kKT$=ybn2aE;VZL-jHYQ_8mBb@^0)9|6m!&%!lNqFy%&X9PQ1#qp1)cv_ zFKR25NvZ9r4_+CeGg|zB;(_#Y^7+!eVFy)DW4c+aw9@_)Q`+_`bFwBkPN};*$0i6z z@smCeUi_p+oGhNm_xi~vf9_S{A6}eYGNEDR!D?r0hB0DGZy<+5@S^1^{I+(j0grle zYkD%)CEG-$u5@CtG&44OI^(^%bZ{l|<-r=l2`BUV(m4jP90#R#X}?HH z^PBMh>@W8F?atT?W5kxkAc+P8hT-yu zf9JXuKD+T}vPfI&*QI-)Cl5nP6CN)sc)H=s-T+HCoClV{(+z9>Tgm&ZwX5&79xrI? z&pY`+%X=Q9{8Mr!t@yG}LemZDlUBpBZLEFi$N8Hd4L+L)?pb)o+G=lN)zdQMbd$pm zZyO^OIGNWA#r1a;YSfiX&*5rjEMEMv`}*@M&e#lN#FoN9DF%Y`CrmVY@igY3awSKq zS?k>crng-#JF!@pni+jHBY^NhwPj+CnCA|BqKCWb9gvR^z-xDKT^sYzC0%A(kuKE;AHjDTh{&2 zQr&m#{YgDXlOxR@$KRQon-NYodF~qxgjowV$?->MQoeE0qA87uNSI~XD zV#b$n0mb!YQ=J2%ov|6lh%Jdh5)FvlUh~T?#9(%q=nLiBj4WY0R_t zH6Q%cGCq2z15XFNpt>^qSRa>JpRB9oo7}hFK7=D3l>J6Z2hJ~-O-j%FmazWnM?w8J zdVdxk>N9l4W*8&36az^EAW|pzaQPuFdmWMO^Q%8=i_Z^#JfRhIk)?&1rQ7+auZJDt zP9;PX2k9|ii~pf<6I2Z`L60uytGEI`x|~}C_U-VU6=eupNHemQF-a(Hpr_O?4K3cYR&tK|J^)wE%DXkRX+Vn>0TsnJSBjJ=& zXZirV z*O7TnEXIb0#(Ft_XXJ!-=Ej6AjN9uXps)3xF9_V+g)V>KtLB3*f8d=H24C{P`{cI! zC#I+Qf+1kJ<)A{b7lqPP8I?KzASh2aSiy&yjQMzw>D64`RCbQ-H&Fd+44?%i&C-- z(0tR7tdnYO5Cgui|2?Xi_3my=OU>7#4>|JKj;#4rjU%np_QUI>O4G*$m*-ZN8~KK(4^GWD=st4ggoMWx-u&JBTyH0UPHHeRuU}!F2yeb*YJw8;L1d`06v%EIdM&O_zVIsKY+*RA{x5K;u%@VP3M-H_@YH zk+%Gr-S%9@!(fU#=ZyESZ${;>ors)T>i5D+7L?S&^hs6jzV{B+%X??!Z~KX&vIfhvNSPtH_UZuIC(Ld-{k-I zKZjUVlzSKcgQOP7@CvWeX*MP^$kHml#%b_vOguit4?cBf6?o5byA`Aqx^a8b|Hkt< zJcGY%;cMIg-NwYVxgWY88{35|bZ+k=mn{dbcV0Sm_IBv)XGQ6gTl3s5c;Au0ky;vG zBb6h*IJhXe#(?3AP|1}`%FbMg7C%@0o(=9h8$#1c>H;<&S z(b=Y8LXz5JzI<(pL#NABGOzgQrv6DS8lT;y`TvxKGAK_(IUf;w%4y43;<9t5o!3(} z-q2cS)j3;5-@UQk=8VlSMr>&elx86KD4VqfcfEG(;a&f7w0_)m_!D8Y)``W)$k-&j zlby5Q`v1(iJ$~2q$}gXKAlRUcyc>!~C=b3Him$^Fz8i|CD+sE&@mBBVhJ+5{ z%p&|P=pj(c&7HDMyjZ|!WA*8yf)!Vu*s34Py?|WHAtkhqi||^mEu-++vLj3De@LyX z41Y7D?<0f8+5@+pu^GmQElEOx5ky+Euh`6F=qvb2t}Jl*&aE$Qu&Bp@PLDP=YPrAX z_>{bbH#Mr3uuYJST$@WTYR;MaLM8JB&(!lp z|5P4Z&)T#{WhkWk|HJARYNX$7_>(@JM-hB0DGSD8Lv&Gpe1SRk_Q%F;ixdiCGUniTWeyT%?Gd9B*v85$Q>Hv{9RGk_myQVX&lnzdi zc=%{TaDKbH6N|Z#iDjf*!Lhf@BHZoC^(8uMuUFX^YjkvE;dcS<%Wbp2ojmi7#&X?TpPZMr>&blr|vPt9gFgMkNvcThShO z!XJJ3BhJel=EQ7iX+EFFt&G*v&h&r#vA`RgKww44L>c5FgeOmM`=dX% zB|Hz=GDYrid}B1>*=GuikcptqO$=LU!@7vR={7Wht8B zjLk4cY{?Cjd>}aKoBOP|QHGd8|6;J$J7o|V^QCl*5!3yZ~q%l#V;J-B!%u(xu_ zx#K3+o)v9H-UVf=0NVw{TfGRr3yQa(4!#SDOMM-D7Zl&rCipHW)<0Lwc2?SHur4Zk z_q*D{Od~vNx@J@zz0(ul)H!7LlLl>iih8%XL{5|0@n}H6k-+4(PgNT;P-ef8($mzR zNa^Vqi|V3f-5;N_olAaZ&+pW^e)rln&e#lN#Fp|PX$eFsbw|Bv;#k?8mUl?KV2b04 z!_QtPII$R;S(um1*3~_d7_|AuqD>b9jZ%ynJj6x7)fV(jXx?9s;Ois!re8YV5cR8Z z@*K}~ikEu~3%pA=3O_(yA2C2fHhk0HK-WhM(RR(pr_;~B;_!D!%oi>!5b<6ls(oGq zM~Q=!LS{%idM&)BelzNn^a@q`jak2hvND`+IAb%65nEaUr40y<(AHNlU(k~A?cIr; zysF|dA*D-pJF%FWni_xaoA)~D`eDna$ojo0d{gEwUBcdgRN@eEK{u}JarkC_>7Srg zARwlokhNX)_^;KMH{STv2ikW@-*)mWK4^)<6PgCwcRAG4lcltN@(1Nd=F1%{cC58@ z5oOU6kt3X*W@R6^yV}U<@ukO_;VsMfj-{Ni_|28;jLk4cY$*?tmO$jWzn^E#RsG}K z$S)eJ&C=TZ(UfbM6N{O-vBlN8nbwY1Zy%T>-+laA>(lpZ&Eq?fhXA?0<|2jw=eWR! z04clI%c5RbCT^BuzKGVg{rBJbg-%_sagr6Q$EE1?!!LART+--66jf zGN-UOuVl-cZ;71H=3Ifdw~-32S=oC&pVki9xk>44zt(n(AFSPdy^1c**bHODmLx$* z41)Iu7R>6Ea+xRhit~M!>)uP>jb6L~B{WMDv0IW?YxUc%Ed8hMGIRU1SYzc|XCUou z$T8KVU1`cUZ*9NO1=T$a$+HuWue_t}Zop3TDP z=XY@gh>6ax53BCk=Q0OJ8k#QwZywFc&RE@>dwPd)?h~Q%`%`6J})`(;pZj=`#L8UV@pee*N0~{xkOxCs^OX}@n`LylIIoz zeULN+*}uuR;3IthCfCwW@co;-JnP`gd3bjV!}o7;t97^?o$nHo!7t(v<=ph1zrwJr zrN{s!715&!HB72JzJ=V-&e#lN#FpMb=?8)frPGDCS>)XN_@b0iH20QU-dp`FCl)g^ zO9Sy-g@UC!XWYn6KJn4#6hnt-lvpEVG6FKZ%yq>Lehv=bVsrR8I6OZ#y;x@QB7M&B zJJ!a>&i$Qe3BM@hwe-FEQm5?oVQT{?GSXm)9DBEah2ixm)h+ z`>cUd&d_0Sh=!ecY_-+WdgwwhUMioe#fMy5b=YPv|GM`Vuf`tTsQ7uY@-ma>J;sr8 zmL7xGRtw{rq&s)<=07ODx+AA1d&^IW=0XDxXKaQsVoPJ7Gy}oi*Qfe89DF)!0)OEv zE46f^gqflnotO=c44==4acape{;{_?;A&vp&(N>j5#PWG2f9rh`C3B0PCP7!K_Uhfhh@5% zK55@WL$ACrr_x1*SGT@6aCYhawK&qv@_$I_CYRHw`PlW$FEgSQvu_B^3$JXN=;e&f zFh*=C43cI*wvzLnQ;ooF0%C8a=QRRzD)dA(IBR-A>L5u9=a>!+0;VMm9;Pc%lX z{^BEc9%IP#tH`RKT7NCs{&u~K#oY&$UpEvzUplX`C=5BZtkQwkPbjH{lWRf29ksJZ zcjjE^_%U($oWjcM>z%O~#)vIlfzk;C^M`Ohf4FK77QsJ87~M&JO$40XikL zHS$BG15Z{$JDsn-A-`kpp7W2-@h;|e`29)LIUPBnt(l5Fp}m_hQC4-;?t3djg`8&k zr_a7CY$M~0%`ir6NfMICK;%N_EPrDmYcZ)Kj*seP-Ys74aDf3l0&NQIrt^JaV={wm z8fW%Pf8^zQyr*kx+-$|@JNq40w0or%)Sy&PL#F%0w=Pcz6aWkitZ$ozAuRkCFHn1* z6-xK%xX@g`sJOV+DDivSo~305R;Z_V5>5x}=GuEr30wA`Wz!WWt;C=^tTB7~|4(zq zW*8&36a(=#h*a^~z3;bj(tVB|BL%*jFLx{QFqVLJLl_#AIzKnK)^%e~oXYEy5;L}1 zC7!n418&zq8^k;-ixB&)wAZu2j+y0E`3Y|j^KB@*a9<_FX6GI2<=YQFTFhc~*Kejf z=kQKBd>bY}8^knCIgcKjN-%EH5TXy7rY>HZFj zsjT;Z+W0$salUskSVj(2dPE)CSGB3-L8T0o#V>65qTMC1u84zi!rGKn>ouq+6VO&Sv;!P@z9y&LjSd1-< z46aNI-k!O{+<|}QcGstMs$#2m?)U_*lc0-vcohNuH)rhBH=U8& zg`@64N+H{WV=Zlxz`+87-ZEemsV`prJF=9(gkkkPpi$Ze$G~O4EK38&7 zvf^CKJf|V%~d!Y)qz*`iV7In2pIC()Q)aoxsLq4xM(`sWTz6zP{wsMMLw|>`&LN z>y4SB>MD(rq7Y@yPB+-LD{OamjFveJD8qZx_IQ>boHKp-|G9tbXJ2iNJ7~&pj3Y(u zTnaC9wg<;vlNS{fjp1r%Y=$vnOM9TS1i?bGPtLgq324u(|NCfj zgxgygUZ$1ccCgu!6Io4FBHbIlI;7n>so%%wkzO<%l%k*~U{kUZV|U$o=F4o+zI9A) zhZt9uJWmN0Vr;o~^4eb)z-WRZeoZ*{HObHWL2U)+^d zvU)tiOiV%icb313WP7xBs{00KY=$vnOOl`@2EpI^-U?n_lb{~3Y{}Pjuc$RE{k|zV zv6veem@t|hw%oU-qo7w-CT7xiWb$6j8&k$~zDU?ZDG?M(f6UrL0Nr8qZE&miCU>H0#vUbz*mLq?`jY z;8otfxS*h($CepWA8gbyJ5j;Qo>L>YKHM3bVT{<)7$ntz$m8?Rm2Ql%y=%5Iv7)q& zx0markOpXDmVtrU!w>6jPyD`VmYv#S!5 z-GftoyNja#GA?3YmF>;;_9VRyVHz%F%b{-AY&r7Uio1(WDHOZ*9c!?tNnWQKb7)um zG#SDv4QY;ml#I3$}Oo zuatdyQ9OGkI2}N{TO5zQ;oU9n>6>mW$#Uuli&1_$k$1Y(g{vm1-ESTZu9AZ9$YfY| zOU4+svmAb`1%ZX^*yg_JQ&Q}R-EqPGO{$hx#}B1V++r=q=5*ugZXG!UFDVY~dVZ&L z@@A=fbFF@To^0N1Q6Iiw>wITyhB0DGF_1I>BCVgK8*H6k)8T#XcHD}kZfuNsNfJ&h zmL}$Ap-ch~yPCEy+njr2Iro&ED-^ZF{XH2N*_bRLT`9g}vqiQ|bXDqayk(%YmNVd` zsfME7=bI?0g32uqzGGWqmj(^*(&2kP?_19=w(e%rli7m4bJsH8?!1qqbU;cK$8Nj~ zk+&&{e0A_~U7^y>CC?W+UzOPHjLk4cZ0QG-9w7J&|2l@??}}Sf|IGWI#Lp@?$yKuo zeBOXTZQzsbj{gfL*>*66Gb?@a(0?xno;rY?G3#amzioI|v6oB#1Rl_SU&JbP>NGq~oQ9q;%V+-!mT=(b2jE{4F+_`#iMHC@ z3%-8oDt@@SboJYEi+SvRuW%%slY;Q#-5JpcTP$@YS!@y?esWmNby6kLsOmArEZ zabh+yx7>DhVuZ#{&b2*-xA|5#njx39NASq^bF2)gx?7jfzmb=KVs@8u91^xW?V@F_PlX}>R!@wif#xK`>Z za*=d)34A#ON*a2*sbE^KVs(H2{q$)y?vJ|8*1q29jLk4cY^e>Ben8~rOfjYai>#}% zK5lov?OFLDDfP*DCl(WPWAinyJr;0B6{vD-5TC=dPtPyxiuWUM8yMOb;yYgp?+fwt zGx*4AOGr{ z@k48B=h6*xR|Yt&%``aI-R8t%W^Q2_zh|NP(!ga8qSwv(8#7OTqMV?Z0&;am$>~ab z7w5AvLOR`Orz^Si%BRd&k@Nj%WbE=l$>$+za!+JYsx#WPjxO$mRcCm24G+=Q(a$h* z;X@`fFC_foXA@n-uzmukoiL7sc1a)JIy#*&`N|#3wO>A2S=cWWo4!8bU`O9^17~c8 zF=9)SkVFO|6@|*4?|JxS8wdZA^~X2Ax77N=k`B5b#?(Mn?O#hqPV8*f7We1NG=t5h z7cPnf7e&xr!+cjb;Jb!-xq9~QIpVe_SxD1$BIDw|(1h=K$8M?(iWG813ASr^Xm-cf zdoX6E)f};r_FfucGy6xv_RSvJI8w-!K%^9M>ePgP>pg`gf45!x@~@`vc}G+ z(AQjs@>~`61~l`LDT@^+Ecy{Xc@nQSkA38%rMiKH)6=zuYYrtm-?U-FubvmF-wT#3 zu=6}Lt=SoyVT{;P9waS+NZU;_rK~T0I;E-QX72JuI5%(iSg|1-}D*k72DO#y><4FFU#>xd8FGi|HSouau?>|NKm)6 z;1%1og=fE5ul$mx{cWQ1tCzPq%a}f-Zs~BwW*8&3qz6e%AhIc%*OxJ@JXU^ZYy7X5 zpG~u>=UIRjVVIgO-M{&m_oQ1l=MWq5o$!mc2{=zRct3`HL4w3bjQ?aN9)%EM~|*ts$TewaC*91 zRej|=Pvql!UegNex0*1Pvwstj(R0RT7$dfn2TDm0d^cCAbGKpg&dUe)c^$V|&BQn( zUj(wl3Nir1)wURZL_1g9G58Vf9D(27wYY!!=_=B-=jl1E%_b3>3z;b&Nha;Dw!KICtpnx@I%6}85nJkk zqz4eGp7cn8ar!i+81=7vCeB;ck(i-!!imMg+{93Ff#j)nu`1OM+bwurO7#B|`2VaC zGF%8*{>T1G8-D5lXVF&psRMjG9q>~J_#URiPaR<0^DS%(=f%5DE_G##X0ZM@+qB$y z{bJC8l*tMpmoP9e@DV#+NY|#%AWcON8xi}+^(FpjE`1SEa%k4}!{4r$Cp{7^szOdh z53gWPMN=Q%a%MTT_2<8v-buaIB|1Ado)B@yW*8&3^ahPJ1_p-p78?)lVvqFOziG|> zlDxnDoI(GCoLEdO%q(onM3Rqu^HHDDxHbLc?pHr7+yX?wopd9}G5&1d3)z^=q38HN zUVBvc;$O>yd;ipJvj$KPPTg77^2Qc=np-{`0ra z*bHODmX;t+2a#XqmBkv~I+ej+B3vO-+y3@?)v0gDqkUN{CbQY{T=A{^7q3oO zIyH9LzsGUWKm5Gh%IH*WJv|Q_6-<~0ZOZT__rOl}vb_Nt^AT<51BDL*1Mg*T*blnO*d+56pIUGMf>)@p4~?0hE{Gh=g8p7-;`yJP;d zRlRjJ6cIgEvu4c;CZwh@YdSmZY)VcKP`3+GneiMx06&|O?}Z%vY)X#fs)#Y4gqj!1 z%qQgz*57}ru)i~Alip9+FIyJSJw3g!7=Gy~CQ>fq;-Aun zV*f8ndYZSa*`t+zD*NY)7d0CB7?oOhCh0n3GmH^i$^)e&2!0lLar2?L3BSb-A3MYU zr(8jzZjs7h0mJ<#Lc#o-g-t< zX2Y@YnH4*q=jH6%Wrrs!2K-&-dn!D&(Fr-JycNP$nZ0`6CGVY4YNz}yc!EQ_OXz#w z-Yu^oyy_&UWPv@SK=Wlvn0*&(+nx|}VpPeh^bH%lA zk!`k|@EXqr6EEXRM11dF6Oo8Sco?Q1e3xrmF@1H4U8k0Xtq|)!ltlENbu7PhYuGw^{AJtAQrWOXq`z{~IT-f{kc7~3qqg4IQ1MK$y-aruVs5o_y&v$F&{#>s4rDnveAD$b)<)j0U4er8)l`RJSKT zTTr6;IP#yCkGs#SH#kz%Hxu~i(Z|ZqZ4(2%ugPa*X8N6*E`OmvT;!a!Gd9B*v86po zY66iz?ko~Bb7Fl}Tq9L4e(+D!4*L&3omh;`&5V}rRbu^r%(IA9V8#8MjejyjRz+AM zrznmOHHhw6$s0uX><2GAMR6V55AU9_wSi7Sg$@b`Zt7 z7^B{h18*+z{ZNOcC~PZSNpEux?=nhy(@S2B`#IYfn?^ithc1XTpW5n%{(r)nE zA#pFqZ+v>RiSg)s|*Kz9Dw?*uIG=QDz2Gz{j4JI z>!M@k_p^`Pmo7mry09m-U++_X#<_?{Ft=~WEZlW$kM%o~RaqaMu^GmQElENW8Hns= z6|ju?92+5FGb?1(lsyd#J9K6u7f_UpA2A8EYVsNE{-WwWHQ?Nawe1#{jxKM`uEvpW z{+xgoP*fT}8s6z<uFes6{H?X)$iaUzbh6HOqFi5#J>C3OpW7;SCgyYO_HEoB z>YQs9#;KfGv(_1#VT{;P7%0U+@Q)ddHsn(ce>`~@!={+&GLV<$MLu-d1u}`I?t-7v8=bKk#)vJ6K@ts!OcXPi*m!HzW!@P9Cmox2CU0Nb zZt28gYH4oh+dIW2R;&M3P?x5#-1mx1uWj~_8?%W%h>oAp^3~}t?N73FX7m5L{`HEc zoco5ndBP*5z~N^Mh8;vl{fg>_)2oS5|D3K~_e%)umb%y&9A?FeTv1_7H~fq8tIH&!?0yIzDQ6x!M_0kifvde9E1Pllz^R zO^r-u7aP0I=}_5PX3^ZeaI3Z6w)Q&6#R0~UGokpI3)z?~AZ$*P>1<4vkP&XKw#7>y zb~#K|-R$R~`#kBTc}QY_w}~Q3VnIyjliVTWXYPU><2~{^WH*&(S@G^`xb?S~e*^#b z{Qt*xX!c`IEd0zzVI4Al#u=$0fA(84X#N&__VJUwSGV1fu$NDru^GmQEm=Vl3W$7H zRDaIpLx$3umb)wGc3yvX(f2kls1AZ|X=Yd*2j9}nov8!g(#$>c3Svuh%8w0y-OLo^ z`;U|}PS3X4@Y3Y+1gl1rGh#3NfHz)fT9)Lk_@A+UQe>b^ zk)7v{uHJ~k>qm?TClA&qs{DI?_)g_sG+$50K6*xB=lu2=&z!Lt#)vH;ff5D;Ti&_J z7?S&A(p#U(H2bcVt)80RDSlou=_{(!cUdV*Ap?=T5Bw0`%Z3IpH{tM%(5NGiHM*5`e-5| zXS{kTPqs|VX5r8A1q*_kuge|N4pY2HI1zDZYNlUlh`lXv{a&}eMyge%?Z@&@LeAI> zW5kx+APERWc4dFB-rc6c@Fdo!(9u!xRn*RA(1ASWh6WZ@^(Wps6_@JITUV68sQp7X z|FJr#PX%56jAM-lKNk}*Ydp>`SkUrg%I)S?d22reRdya=ZJxW2-VI}ZE}7xC#-n2I z!O3y=bIWzkdry1ey*eo~xotU8dgAA*gf)zj>nsk=!~O6fA3jw*_>d2Gz+u>yRo>v)Y)qDrb&t$u%Z(?x zwchAYDh@b%aR1x=J+9nmS3jmtLgVLw&3_Ebgl4hay0X^pZUKvU(gvG1;RS1#m?Cdk z<>!IVf1oBb*1Dvy)`Lg4O>*e`^?uIr`8_7vraNOZj1gOsgd{Q$=}~$zqLSz8`P)04 zS(Y!@l(J&#nHP{c4tklu24OZPV+fm}ZW|kuF=R_KpXO~gMo2rFr+F(IBjn5=mPr;N zVMm_5^~veB|8`)G(`t^_%1W|&$WWt-gB)Xv0+>8X=N{!Tk9F344&?~Khb zMr=t8l4w9=pn{FLe23-_oy@x1nukKK*6iqh=)_`XWMTeGt&Z8KMKXGxc2p9_6vLiu z<#;3HBgpuLGWVo(?rahrYSR!5i$S-Oll(gjdn;j3_t(}X$gl^o~bGYJ-(P(M`1vuge7k*Jc z=z1V*mp|fIF}Alpc4pq@bsrQT+BD?olruZDOMTXh~IiPtuW{3Ry7*X{hib9eBzwo^;r2`W}f_^ACMjySvxHX><4d4O&Z)n{*q%a$;oQJQvG|1vf}wh< z*1fHhZGtYo?*yj_=mn14&fDM@I5LaWvoTph`#O`Oqb?Om{QJ<)cuzX>&3ca+b9p|f zqMU7stpwqh-bCUqh~YdCjH3kk!1rmJ{>e*+CbHa8_kSoqX#=ywLc(c6`fc{pWpDo2 zo}L_kjz8k-r;V>1RyFK)#%35Jw$uYj4^Y`yQo(awwoBK1xe`+? zp{j~H35{R&!2mC_q0Wp0j)XQN@L&AtZ~I~lxeR`?E^q46s^R!RIHAdf-FrB-F*8y$ z{Mo_-MrUI=dcU46?{daw7$deM2})uRT)+EEA$RF}_TZp|ZGRO{*KVCs!wu;#LmIdY zliS%Cp>kV{_UW@l`MF=9(gkkkPp8D~xP z`u_Xw&X1Q{H8xyYc3ER{fTa_QrGbg%~-H5R=VMr`Q~;yDc4LTLft*74wNO$BSA&WN)2SEvAEVnWr2=d6r3Lqz zQ);+c?HYlXO`U(yI=gHV*bxNe?fc1Ee!?tR|l@V)MMwF zRKIWYgpQyY4IdT3DFk{VJHIYJ{6uyR%?EEIGM4sCZPVHRPXDPqpp3}eKWmLRDEME>M5*>f!~vMSb6fOWr|$nxX-vN}%8W~S!X zZTR=3E;2JY;;Q$}is{R|NIk3B%En#;ZhNO@13JJ{_mC z>R$WjSp~|R5Vm55->?NbqB|6e89JqwzYG2fW_f*@nf6zp;a%q9IbAA+rZ`fI;eMpl zQn>ZN`WFoHcj_`$xGlUlRi?VuZkIDQ!x*upD@aNKkx@OGzl!Pto0hEbKC8}gzodKn zLvbe-GXn$j%DE1!zjYo6lezJ+G-gW7>Sa-9c)_U!Iw!=(cMd)$#CCBSd`^hpct!=M z{2m4G2(y?+B8$(p-wXYJRga%g*+RS2!f(6@HYY@tBaE?ipy`xa&WjwLSoZ8nwKebZ zi?<*Dkv4Ga$JK#0ev6b^?x;I?d;{EH)KDPC29x&hZcO z1~0$q16Zv@mF-A4I?V~LLWT`2+g?A^wow0n$aTVRwuUeq0mJQnqTx` z+2U#W7N$R#sy!5(u^GmQEnR`q2?W=xKIhTPop|NQN{*ke4CH5JsDFuaVlg!_u@HZx zqVLbXSNQtEwQgId23S5ycUy}*&q$@~i1@Aa;A^{i_qW;I+t9IV>T#x%MRGSZ^(>gv z&G)j>C!z6MdBElw;nxujqlEV0A4A>yxSm@g%X1?v8m(^pdbq_HN3mqJ4=JJD$oM&v z<;d$v?WreP-wW6%eR_N*!x@`ljM$PSB$0v0WgoM)G~b%xe#LNw(z6qBBECoc4V;(_ zO^uC%p3A=M(+%0DvnpYl{ern+UTsz2`pgKj%7L%q3LBFVoNYkgiq4_fEV z%Yq%WzAg`X&^rFfCOXw;95ufLJ)V3OV-hnyd zJbaG{iN}iY%N`4vUm2CgDwFK0Xuo(`VwzBD$8D6u+-R7b>@L8{AtH|z8B)pV!o4Rd zvp+>X&42UyN@B*>V|fNLlL;p$d$&AAuAZ~1{{m)hFSU>7d2ez2blX2?Y=$vnOL&l^ z1R@Xn9btN|ygj;dOvavHmFjLqvg;kh+c|m8>gOGm6D_}xw8Lh zO4_b1cl-&b9LI*nS)9^L^}kE`U8Q!d(mSE4+5h0DGd9B*v86Fknt|Yj8WmIK`z=*x zUY*5$ENQdE)Q+52PAo>2rj|iF!XDqKTNPgSe?{Z;R>exa|HZpO+bWriAPYH>PiNzI zjzpZL^_8g8*&3>EmT1}EI3W_tb9}k)vpuYW?++lSC`99%-?K<;lG`~CMl8zxSqaXDja>iyD zBet{$NlhSf^HhVcfnNe|iLiMi3`xEJOR8oV-Wjjh$~@7&}& z8?g#<^r$IxDHh)sHYPJj1Bu^t^(Ci!F2AC_i!;q@%RO`0VE+ASoYBZBWayMR{H{j_ zQ{(67rv10ur+mI+?Uz1bBl|yro&NT=gj0y?m(LDyzyHgxkJ_pb)3-dgmSb`969H#z zhB0DGOQ5s?!FLt*bVeyNIw!wh#Kq0E@^Iv#|5L$TcIXizd<6>dBScu4Yv4zSuZ5rf?aI<=-vnbO+>ZKn=De4hF}2bJzx!F}5h7UUyh(4t;H`%SS(<43w|KfjkZ{gy z@x-t8a^8`h=QmapP7@v+n#T(#s{iOZT&JO#`RVJo@~5-AuQ_8gj1gPvfusizc`@5! z;oriqwM>?Y59>!;zyISZU7%phe0NBSBzCNoHfiKk*M8&FJIExyQU z!b=9eB?+k}@!(jiT+mnXN=_>B z`Qv}Y{i*Anb!=iAomh;GO$~#;Iy_vs;NQBf(;vmQvxk>yR0SMHZkzCXe?^@0N#ZpO zOaiUKFGH69kd53GG}B|>$6iwowp(vOo7}K;yZL?iVQmw<8xRn~$RoOxQ7V2J)Nd-d z{vGr61IJ&xJS!|@d__1#`Q*7@%X`)H*5;O~lVy3HNXX7^hqd+2*bHODmi8d22}DX9 z@i>0L#rw(EUDKDJuWC$ii`aPs)Y>&S_FBBLLo3ODe-anNESdcp6&v=J|3*$x95_yn z<@a+Z=HytzGqSJko7o~3Jg{Z%(Z6W1UzQceF(UkaiO>|qhvnp0Vz*x7-(*YrHm5;b zMp-SM{rfJ;_ZMdx?ymI&JM_(2_Vit;;vt&H-?>o{XoTo-(%VBZp_=JZ{+f3wax z-QbMPFh*=?50sW5coC<5@}i#-s*jGVOxwuvK>g6t4IiACO^l5W{a<)?ZA;}&yGatA z8yHudI4@KqfV?D>m<#jx17^aPgtG4W*7v+D?6c9-It7~*^>OmM-|voI*p9uT8%;zE z4EXon@&{~!E(zs*u$R5Vf>$+gZ>0F^U%UUSmIc&5l;cNEM1ic>6Va#3%txP2{r)ih z#poLJ0E3@tkD z@7>uPr|?vj(WvyX`32T=idF)!L5_hD!M{32J@_u(fW9I#W+DHmxYoN|Kgot2AhdIEzIj!oB2 z*s8wqg~Ae+x6arMW5kxmKxqbo965i*6qeysq0 z@*ZE2FZ|>^-oPaI$$LCzp@(>%h`ic%JMxEfT~}Wh%da11N>bD>SolLFpeOGQ=h_LS zVEMV?Lqb;8ibFFBI;A%sP_2FI`!*Xnd4$GcD_DZz%O~#)vH;L6QcD{I41Lh5d=~O`D2Y%zFMa+Kna%-F9NJFf+3hW%|hy5EJ-lz07~L zXXRd-<$LG1dor-FF~LrM6*h(KkmC-9KA;;&DyXaN*a?>@9?dCr5(>w#$ ze|6rxe%eS$H~is&&>eET2j4?4hv73-gbY@RRoSnKh`s4wL)N1uFg;nrz`)JM>RhLl(D$$CQym%F zoS8GTc0K>}r|*no5*vwTXed+t{%N#@N1LtO{0L!Bf^WgoUs|k zh%JRd(hP{a&G6*!iDftbl+032nKSRCi9z5SchIV1lL?3Be$0F?`s|?UK~5CWkFgadk>}nA@jN;B%5A>Qk_A)O@J#D&QCykojLk4cY{>_d z93a>#&F4a<$oIo{JW8DV{r}g9WSp7@-jZMlX{4~pc(XBCK(1%I?q& zwgb5OQ&iD$GS8Qdn^lE`))*%+?DdH0LB5lYA1NKgzJ^Z>MV_nhI`*_M#M!`>c}WnL z!R(U2?9dg?*bHODmSP}j07S+~2Yr;d^zqT{MwZ?4OQU#S8W(apv6vbgnblj)e01HX z{@}~oRoB8q!@i1Z>Xad`h9GrS7JvK^_=%f*7w5xH+(cWI)v>2$vFN4txy$CidhI=Z z|6a9(JF#?1Xz}-8t0C~N${L~xZORK(P2mmxDH|$8jbC0qC3$NC+UhuCGmH^ik_06&2tIu*w2Vx zGySAy*ZG%s3VcUCs2sV3O6o;QI6mTywm0lOKlf`Y@kdVTiFj~$sk$>Z!x*t8F-W2T zk$+R$zJ>3!mDq78P<#I~n<(|09w%|tR4igV(>5ACW#`#5!}vp^&X+}ReRm37+Cu#T zgranik~S1;swwPo8mv1wG&%q6wJmtLWnos=qn|hmkd&!N>0tk~q{C|5=VAh7^QH&i zndA2_Hoeywn_-ODQVb{sK(OBDi;HzquKFdfW|3IPQGD(}kgFYXeMHRaJa#=d_zBS5 zgfIQ#mpvB#tnKLEzU^r;93tlT+H0+_Op7#FI{)+I8u~{_oqRqnCHzuW`m^ z7$dfX2T4jGavDdTfAPu39VOd*xbwx!Et5H?<~cE28d~fSeZR}@(e#GpUpd-^)|=gx z`CQ!rp7b__bd~ut_OdaVS%S=9;A@=5#$*Yd0QV{O2y?vf=*Pvbvu?b9k0jp8eJsb_ ziJVvlK^=sp?BUP2HrQLqL0>IGG;9T4>_4Vn`a|qF*WZxyKX4?LOhI_rllJ7)2L+d3 z&NtjGS?+Jh={~c3zHAD!Gd9B*u_Y@8I0#r%QF?Jdqfe&Tp+M0?rkl2H)iy^lrVgEnO_`~oL5lAkUr}fkLeQ?mj;cqDXqvQ3_YqN{#-F`h*x<+(_p)! zroZ8Zi1BS#fwpe=hf;NP{*#OLq}tCbC8Eov+ae$7@Jtg$Y29E?HMzyB4?kJK&;0Gg z>K|3-XXQ#rE7Z%}aK>gBBewJf2{I7*`)=#XxG$UEOg(!vf?K2c(%Po4)18Tbx)7EsYGOpKC0=`EUFBllx51HLQKXVAWjp3_0EK7d8`4H?!tW{HXao z^qsch_URJ)=W*Xpy#8mzq?^LIv`aUt`KJE)p_`1Ny3g<)p6B-ERmLim;a}{>@;<&4cRMrDe@g62 zQbL`v8ODe$C4o`~1ot-e9e*{;CV&0J4`z=)DIM(NJ=yNWVq$4-8J(uHKdvaBi3~(K#YTF!1%`8-?cDh>FGOX-V%-)_P-_{sp$U1>Fk7e} zVnfrbJopk%-X>l)CUeLZ6|Pl2Y)s~mHZ^F`uxjD5M{C7SbZY#VP%W4eaMEzuapZJ^ zR6td@K$m!8J4~9A;Txjc%R{MvGLC%4vhL+okE`P1Aupe0TRP9%vyO1OsaULWI@Wgo zs*S5Z8#(Tqe6zRKsBQHlXKaQsVoPD56a&GAk5wc7ep>S@&wc&-MTHS;440FboLCGE z%}l0<@8DL^usA#YvdM4GE9#K~an(1#<2TSv3#_#w@J$Q+RW5^7W85XXu32!Np@%az!x*upD@aNKk<&8gncmOMK38{p=Ke40 z?Xn)3DLLTr8zV?b!B^78#$*ENadSU8%En{@o%ueP&BkO3>8-ODoM2uE6zgci4T{w!e6rrdgL^n&O^%1ePHYVgy%%~-c=>vmx|{w z%9Uv2NGmmek`x{^L)cEhD_hjpko{jE$;1luzAW?-^GuNZ-}ifbctJ6bLax3WPz-gLB64hzwR0v zlQ|@{@Qa!-Kf64Cl{7<+6jN`w+;Rqm-_PTeMo0TV0gg1bp7i zD{J=tdma0GWqV@!@8>8NN!Dw_NBdAxi`uP3qvGU@hB0DG zS0IN&@WD4P7W1;dNNaz$qi%oL4&5xZAL~J>#l*1jgXy%DGi1B2z3bTjbbU(Mvj3@* z!Sj|zkg|ohdJ!9wIb>vyzmY}G!LQ`+=05iC(jQa>Ev2tmu6^=w&bk~%`tx}` zJ>MsZ{`U`)NA61Tk$9&qf3q6AE5(iTPTM;@pB>$Flm6&Ng&1pEjIj1gOs1SK&DzSP5%7qVP`a+32gvG;5bw^lay?sj4^HZ(N2 z;QjYpzFY142{KVdm&`j-T`x^I4_@eL2vcMe7-)=FChJK6_m1(I2=_^U``Dwnm}7?9)?FDHf6TJk|Kq-Y zN^G$7Qoevv$Ng;|^+98R&~;Y~tK;D7uDCOG;OnmV+n2)EUGb&-X#Za(ohNcve%8tQ z!d)AmOx>u;dj~n;P^pLAz8|*k>eyD;x-0ksiDB8pZcDwixZhB3`U-=uk3;!lzniU} zigF+XQgMQma5`A0eu@70Sn1cXA8&<36Hb4!P_%zw;*8BOMr=t8lw=_I*Nmp->oqSF z9X?#V);Ui^hoPv_&WYK=!k9<>z}=5Owy4&}yqkOXSEQ%bo1_GAXUY)Lnc~v?2ftT? zFWnG+uLghTJ@~yET$b+eO_aO}t*&*>-JXGu_LY8&tK#NZ#M6{))PtOeMmtjs47_`b zpv`0MU(GU*IO3WgDhpvD4zA|!{0^NA=WktE!|=!Yhk4amQO=I1xAI%2L^gf=groH7 z@`9H>9jpc_o9tLOh#b6crQf>wc8BXMZNma*Y=$vnOKuP+fymxRR;%75ZaTd}`eNv- zG$VEMd&_S)F`F70+aynUbYR2m;KOpRjPdO+`)xTGR)br|hLF}Ve~&U7lPRQi%z1Xp zd+t~U@mzbBx6kA%&M*naeS9j1G7&YJK#&s%e~%5Z38d%szV;B--=-NaU%vgd;GDL2 z=UE*b38V)x{@cMS!n$p~HILZ5UIz*OX6?4ToRbQNoUs|kh%G6Bk_H4{TzqG*iRCnZ33Aw-bx8rLpPTIEC!<&Oei!vp@J;skj+^>ruvBttZOcdr{7^NZ>wx|d$45x)G0qlo4%lkAfp%F7Y8k7cpvOl zt-PdKWFPOkaD7ptPQlt)Gd2HjLrz6~8{th~lvMPxt2**3FVLWeP81kbZ;&)=j#@ zuQP?5qPBiMvxQ^H)VXC#wjC4f@P59zFBD~y?nGwnDQfBOewXLU??f4Q`uk_7-^;%v zo44H=n_-OD(jFu=fylTJUWQh~S7wf-m{tB+SjG&`^lkUJTbKw_HTHq_Zu;%Rjvks}2d)$P-Cs(X_z8$$~Gul2T zc=Pt8Z_vwJP?p|Ah?Z~m^=>(C|8CX#mb$%f4>R(iEWN>=LME%`ZT^3?sKH$PVMIn! z)NUQ&NA>SIov|6lh%GIF(gp-C)NsmhTW6}*=IQMByZ5l}M#o#dPAuk@CMKJ_*Id~j z`Q_}iqAid6{yEwT^Ew!UI##eHTZAt<<)89TMdnIvg?U)bgM3qN^OVP#HsXcB$mwQS zw|J&Xz?R++dC@5eEuMzfFdgRE!qaOelon@(V(YAn1-JXv-AvbFCI zF0|u%rd=_4&75ww1F^H~oUs|kh%JRd(hP{az5hWzTh4)}%QksGQgqK=wP?f7WuS9K z%uUn(clf=nJEDBEG0HCN^(M9#>XOFDbrt_~Gxz~oWE}2!<?YPB9$Ka-o28nLv)=o-9@<(TEWTK)=~s5Y zCXN&}eLYf&s@BnRuZfXASQh#ARGdkk9j}W1LuYJ;F=9)5ptJxl>F`Uvc`Q`1S?3G;J}Z;9+qSbfsXGhHHX^FzXEV&>u6>obqF zB_&5LUA;f$g1E4u$tu>P&e#lN#Fly>=>bGeclPPU)Puq5gr)^IhKWnZ6`h_+?BF z7|8_%|Lm>MP5(U8??{0{m(0$#b3)*XzsGr#-L>DyPWonHDK^XH6plnO`v$zAn0a_Z z_tzEMQs>v|vilVK$uGB8j}V^fjLk4cY{>`WU=VpdI3v{SH1`yyc6YvjZFaBaG>p66JEj*B(U8`uuof!soi&-!mheSd5J<%_R-jEL8j?edVojRCJ@>$>J@G&hUa7 zDbVdLthNfU?JeL5ZrJvgf;#y27B2O5i0v&?o8a49_~+l=ls>V#xW0M*efG^-(W%;D z))UzZ>0R>h&;JVD-h%B;7Jj_TJgMD8p<2na+j}z;*O~W6p1W*}J0NHp%@n}B6i0em z5QJ3n>}lg^>UmjxRoZUOr=0NGJipGOIA?5zF=9)3khBCMPxzXu{P~`e`@H4C?}GiZ zDNg5uIKWL5Ge}v&o>;`jWDZ$q#q-i1zI28`*(jy?-u=|aNq2`DG~;g#XvyM1%N5l$0} z(qgBEZ1uI_%?vL`NprKyq8XDxIUinwOgs-7NJL)y!fL_^> z=L_VfF9<$+OR{LyE)fpUAtTAK8|C=kvobU{-yTK|$`R;uu6)`R!U9b9qkOrhD>Ep<9Z{A+FSoWDox z*e%sMMo|VQ18!Zs!B+TLaH*?;LCjr~^K)>dkhO^Q4@){?Y~{r`JKuM%yL$P#i_Nuf zhk1IVov|6lh%GIF(gp-?QnSl?81i4Tu#>@at3u{H1k5A`7=0`Uk}n-vSTbLKpJ# z&09Mu^Sh^yQK`{?hNWARKd*oN&&Mr>291yr7We!ci=w*^zMYbntsv(&&GJW^x};W` z%_`)$-#8U}-2Vv5)Xe|A$L(i$x2V+B|L+e@61(Ay%`ir6sRR`35PTz8DsZ-~@4tQL zm?D32yJacAKUxjiM__63vHFnZ8S$HYR5wjpc;kF&^XxbM#waDl<~&>_Mb_NFuRrzD zD$Xapuz7U+_{p3nvp){0)Uvr_5SA4D8;cSH>x^Bea{22NWN|-S6vK9yQCkr?wQN3& zJ+)j~Qk_&2{Ho@2Shr;TmT#BYcHHc8#%35JwsZwaDIhZ2EtF^V@mWLr^u%CbH95yC%$UqA(^A**Y zW@j(ENA4aa2KJ3=muj_Il|i>u5ZN~6-@1(j;&QP=P9a;LVoxC^Q~m7~8~KBlKj5uLQEj* zae03|Vq>y|wnDb=OP$l#==`^XMaojw+Cghx_p}FP9)n@{jeq+M%rmKIHit}u;kP}z zt{zLBCTpMm=Wn)Ler-{h++UO(0N7K=4tBT5!=-O@oY$wdK6ug-5hvoZDWlgJn_-OD z(h?|bK=8)OcX}DR6TY5W@7r*Z*So!IOT$?w784T-qdWgQmpQ(0larJ%lKmKSpC|8? z*A#FHf$nW&`(B6`pxyaEQSi#-ZI_?iOZgdockXkk0RF6t>BuPrX)V(*?!EBu{3QVi zSgQ42E+^e``j&1cAbo1toX(8+`_TqVnsAgMyENg`Iy>0sm^{hdIL-Lc^(AL`C-Nt+ zzV}bK)ft;%jM&l=#1kO$L&NVAGu7>srY!Mkms1YAvL`0P!HLDl!o;Ncv(u(6es8{f zvv$$XShD`ex(fBh$a@>9bxh12CN?HZXl1p(t&#oXDpUCbSrQ5SKf)(C+6L6_Izgv| zwnqlGw~;FIhm>@aX^_z7?`D`9x<{m9Px?|`uCLFVZbS%5;YetECLtv>xeEygq8F@K zc-)rd|B@5!y?ll5?>b{Mj1gOs1SK&Dmi=6QyK<^DhuKH1NhXaty1$=oYI0(+G&eTB zxlOn6^bc?6)8gB6T~a%?g)_|J0?kLm50KfHP06CU*;!xL9CXfn^P=O+nQ@W z_vGFOSq?w$gt#qt#%35JwzLOHO(62UnRATEk3iX@DehacKc9N{LvZ+y_mX*c zwg*orJW{=Wy5T&RbJtF}66#LzAGpp8Hj81jvCP20cYZo-u{V4@4FAR=?QJ)n8YMVL z_cbQZZ<;@sgIjoh8**wnC65qTe^Zo z3y7>d?Y>I(mY$kH!VJH66Spk4o>{@|#A0D+Z1(MpCr4@4)~Ctetj=%Szv;C_&ih>C zijLG{$@vexhHv8M2+@OGlfivTA70V%%N|qx|5jYa=2Xn0(mV4_FShEI&p(e+(a~^G z#9>xgMF&3z7O`$~$hWx#HuCDuPy$Ug!FClO9q7q_Gz7;%u$>O>@;<*B8+;1AouqB=$(f#; zosV3d4eNAsG!MF~fChav-FrUneAO>@sa$Q1WoUTWa$i9K<(3TW1=P{apI4oneW~e_ zz1NiE+uVPD{!}_abH6h-!x*upFi4sKk&H4^;tkH}?E2%XZ`s1n6gJs-juYrSG($sg zw~h`))$ONMG&3w8TZw&f)YZ=gS7*?rSNz9&a4o%Z2@GeOY0l!mpf>4!(1F5DpZ#XZ zjHVV)a3d|OIlhearC0s)a(CP~8@ljzhu)b`q2h2(-;HYsmomp6o+`L*%C?=iwg13l z7S2nz=6f$|X>rD87$dfH1#&n98wi(Q`zacDJp10ct*o8-mo7_B>~mtaFf%Y@i!4rz zN_!PE>q_(9WrZ~t!fVb!5({*==j1M2L&-i4x?ya*H4;Ue_%m!eV)sj(@gleucu=){ zPF^0IL&*!x54EvOpVAzq@{Bci)4YS7k3>*T5IMz%t?hICA*<}C|J>QX%^P!npDUQV z)Lyr&|B*8`!x*t8D@Z~Ck!wyx2VN{Ro$=-A%11{FA8G&JqZ|)9n%u%JK;y`=Z82^h zyeg8h1|i#vjO=|tT`%ZTUgKv(4~b#Y)wT@*`r&(Rr-hYk8H&(+k36c1GarSs)ceEBlhHUCicfnBadIlrmMfU zI`I5tamW01^>HE2*bHODmheCc34)KbOxr2LI3s)CpSgnVn>u3z{+OUS$m{!fHweRbyYOFVh3|IZ)4UDa?ZVT% z6}G;QWs=2{PdgPpJeQo}d$8eE9M_GoX;XbyAQwqU!`MS{Ea<{~==whVi*RT#y11A* zVt>U7uOwE>TE;M^=BSO+_NU`WLl-{4$AZqpavC^)58(T@O!sK@%(L$|eG8j$v(g!x zVT{;P8z}Wau%2JS?B=UC?tI@}$?W%!@qgaJx6_!W_g{(4~{`u^@iKEW26vl}tC-byu+2?~%BFUCgJanuB0!x%3z| z7Nk-OojB!Nz5{xnGT&AvHi(1ynY-AbtRyTK64GPjaNttQ+ghi7-Yj` zbx+UF3rA|XEQgd@PCWU=qEu*^&h|v_z+OL&AjNy08=bKk#)vIlL4q4Z?tS8s{aEQ^ z?9o!E$CEDKc3Ki1W9!6XXkl((zggj=$Wyz0y~j7NnKobT%e}4L+fcgbSH8pU+`!#M z7i%~;acO*g{Aw2NjhDO6>sqb-ya+kn(4~t$Pz|4}g2Z*v$!YlTDZaUKDm`N>OKEh| zs<}_>)%UMK8AC*>sgTmm)iCw)gk7IIbb9=cJuVXXVY8LVW^TGOHp3XPr7%#6f#6+* zbxMtI@5(*hw9J^{>OGAs>-e*rSS*b!O}3qv%luI`efg7FpVybTL~M^ZCAAv4rsBD$ z3a_a+Tc#swD)s5Gnu=@IURX`Ve_h|KD4lQ7suWgd53OTMqMXZ&$~mKkPa5LC?g_1_ z_;lo;`!e|v_j1rO4GFgWSRD}?@UE@}S-5LqrU$Y69J=bT&v+wd}OrKul@lrD+ zYK!jtn?;K`ov|6lh%L22(hrDi_x!r+LaFbapr=y;JjDYlrdVaJbz(L#G<|!yVbMyV z6i?|K-`gd9Zq?2W(ObbY@>uTk=D%4yP5zn~Pn(W~&W!Z|`+a^fatC{YR)}J|Ef>+0 zp>O4Mvj^H7M%?F(xTz4a(Gu%K>A+P^;WxHA-b`oR+IUFsQ~S#+OVgfCbHb58ZtjLx zPS)h`rS+T7weZ=D65qTM~mL8W1_HRwiJ*XIPxo<|^X~zWZIWy3Vhh zm@P~!C(6cVY)j3F{J6dO_qEQWk6GJYo2<~=J<;6}NX z1t}5TvxJvEx4*2;IMuFTw=5xVR$QTScJQgR8ha0CY=$vnOKza#1Hn=?+YGwJ*0xL* zOFpmC_WN(k_jOWEET)D=mW<0Swr3yDOpiF>!|6{qc|MRQmQ?^pX=uF|B8@Z-2QUv z79L;Z(&s@Dd=v*I;S_}PtjelqLk~CNf8>qp zaHDybrY2Y}Xo*Ud{d@&_YIem3bo1ivK?aiY~W%XJ$BKGmH^ix&oyW2o99r zdd_Z@^$tx%{cDBQ8&&yr3%HzE%q)ye%f4@FPk$%wn84^`roUC^?53Tj6Obz_z6BrQ zl@-_0Pw+!y`JYt64~^yBEet=KnqRGTk~^z>#k<;s+UYj@XT;o2Or7}&bae~7sXUsB z7#R48?TyCjHi)7e@$g&+HE#kae-oi zjFX3--GC+{{*6UOufL?*NSPE~<6wWzeN=Pu*I*Md-dRYi>H$Qo% z(5uiR+BMDh=O+I>SAJb%WJ$3(d8Z9iyUFu9g$jFd=-lK%uB42{WDirUV7AHT9OSwd0~Z(IF0hlPii74iP%XkNMNXv%a|wx1P~ z27hYd|HMDoQwwX~zTaiM0^BXr!f*6$mh|)6{0Ze4V(g{KC$FM{tJhNgY&bb__S{96 zINT3Lidp_~#%37fbu8%$l2Sk<3(JMVX2YwCBqq81(73zp))RqSi8w1KrX(s=PHXpQ z+3~SSwcb-zTKeVu`>TJdVlC;EoW3ZNS~;;ndM!( zF@DL59Kjz>EG7mP23j%mHpMQ{xx<)SpP%}9drW%G^DI!c1sz}J{{}i=6j~0c8^I6a z;^Xp%k1z8l>AF34i1N;Sel;|D^4frP`f^2cn{XYGPsz0Cw;t&DGN1h~*kyLauGtwn z)1t^7tiAEyMGv?w_*5$NK{v=VvvXI{VHq3==i4QC2kXmB8#SJ}=l9ML{(9_&fyUFX z7FHYfPj|*<7$deM21zs^GG{(-AfH01R-pa?v2S&n+xPmpHiNF2GBr@B)BUepnjq4h zwoiBY=37@h8a%FeGBB|*!LD=pu^Rb07uLwkW#M(RkF8~0ReY?sXpPeLmYJhP3n++* z-V*WSC~SuxatG_j&LY_ixhK2BAGZlaPdySiNkl`Ba0>bH#Uk(Coh2&(ay2VT{<)63F2YTs@0*N9d%l{^n2XpItoLJR!$DYzt_IpM^yvS1S8l*(<{9 zdn4I5zL5KJK;c{vN*zYTf@S_+XAvDNqOR#(n!@gK>=%2f*6GE2ZrnWLKapqMUpkE# z{(26p!-mU(W#kb<->d)cOkQYHtUO2A<4H@R;wsmdp~wmCcPxCW3#lmj@rD1%Thr>G z>S+1mjiPbM=Ns&2ADruq%`ir6NfMICK;*3*skf$ZCa^`$%g+6k_i|rbdz+yXi>0ZV ziHhUV#k-zFa(tchlu^LwPt*?=W_8eh3iwub@2~K!>};WaY)mGQ#x&onJT@j%Gmzm7 zyiL4pOy-bYJ=ZE9HYRiEEd5`z8{a-&e3bV&%;5O8uQOv;q(5tag=_EMU-yTv|ogi!On8vtF%Tw$;j^F16>`e3$8|1@8|NPEmi?S28v4u)CsR z#&*%TX_wOz*RDH7(azWmW5kyBz|jpR-i0c0ygYxE|Lf{t&aj7~TE@?N&x6`N@SUNE zWv6^@COCG6UYMx7ZL{Botkr2}LciG=`o#*%s^O^EhF|LV-$9LKr`S_R-CIG`P5&=E zpR?)R+lfnWA9#K?Ux9Gy_|SzRo)0N zE(_ebLus4Ib)I$({?2XF^BEP=w*JDNq68QZFoE65z&~8d8(O9)_FE})*)GVeKP#!r zdGOaQ`TGfH4-rgJ0!;E&wbWl^ply-y#E^od^G8fPyBlB)6)BF95cnrY8XzS)KK(IEdp#N z(B(WsKD8|9$$3(;E;@LwtEQaU4XUA_i()CbY)F8^BkIq-+YC-Knk3WBINxdqpJI^BWubTJBfyaa-4Z&C z($n>d-H)%&YJRfdz`-s9NsiyD+UzKo&LetQ0v!91($mSMM=a0(c6Z703g|nvdZk)h zqe!STHp3XPr94ndg5dO=lLC9xdi&VTD>uF}zAnNe!E+3<@&a;*0XvH#d^-(M8$TPK zgsywmrpp<_Akgwg{lPu?pj^U-fRVml8E-vByObipH3PbxhAtaFk%tAHKIY_Zn)1Y- z(RTid>=cXZ>>p2{Tyut$Qn+3sr4((XD&*bHODmZl)7 z1Vqj|Bl)~|#_(^-rTuO{&U_l^#A0q_V#HeHdZFjOv~qCm$L&8%kN*6%<*_32 zN!tQEhrG6##wgBYxwFpS_}(OG4n<$*$LB^zXh6YA$(k+!o;$PFT`CvmNSk?K&V-Dm zQ?oX1UAR6DsXh|m`41bR5kN^5`M;GmCP&3vS6+X6VPZ+#opkRz-OktyW5kwzKn{oC zUs9<;+*d?3*CwdTZaDYJYqeMSVJBu&bCVS@_H5!Jix)NM7$3?$W@~Eo<&`QpQ9$p` z6yUp2;G<)D((2dpQ{G&+H!lx(B6aY2*zl=TNG~b`_&!4Kq9Wt&Oyr{C)0~a!%X6Bu zlP0EbTYb*mI7aaXFOEdPFM?E5B&@VO@S9IlKtDi?#YtSDfz8$HfipJ47_lWENP+;7 z@^-u}FAOgo=8g~9d#%eQ{^s`uH*t*u3vhVAXEOPDg5b++NFN1$zHUMow{T=;@dJ-P zlk`sK75{24r%xFpAncsPaI(AvE@Vs~)0YCmHb=N`FMVA1ujBgW#I2_H zBJO{jC5vNY!|2Eg0|VkpL;>M2*p-Ob$LcOOZaVA9SZw#@#}uvI_x9Y2liU1;aH{7Bc1Wl!aLTy3^DQFP+mSk|9%AP z;HrEC#5Y1Wi4XcSli*X30z7vfJDyu&aBYW+@2uC6&)T2WhE;eX--#$7{s3P2prnwO z2P+Q9{jjY*VxM?RX|-$Eo{j7EoUs|kh%GHaQU{2X4L@^RTx;3fC+1g|>MCeH`KHRd z$%)y*$h2%r=`oe|>qzH43oUHmeq z=%IXkBi~ov=GJ5Kiq6;!W5kwXKn{ms zbK8>Vl6O+X{zkgXZpu%N%m0|94LU2p#OMuov!7AZ3z3^#h6a{rg0g~ldmM$dbs^)o zJeU5!$8Y(VkHe2c5>T*%9fyQ^G4Hd_OAJj7r^g=FJ2lgM_4^Jv`HMZnrz{arh=7jY z(&chzz*DavrzHPwy z_Y2(5PMNBDCBN@!Sk88>!CLwVD9wRxV^U!m`O8vtqyLJ&<<%Z&DjeyEESm}f9Fg6O-!4Mp+S@-2e zcSC)bUh&bZVdiqz?w^Y{Lg_|fPeZEedVj=Bzyg{s@YTTle(vzqz+A`n!&d{dwYecy z15fCZtu0)W^ZmCy^9F{E!P|NTni~Q@XK-P;*Hb_<4z@av^s9=n9HoSqSs=YPPHg{b z0NX?}eK$9%-LBGl@i}n8j4O^x5mVyMBc~|Mz3?^>Qq88G{q9}c?fBH&do7BuY46O@ z+rGfe<(D%y!x*upJxFQ-kuyKfI{bJ3o(GmzJPntA*T{S=G?4`NxuN%ca9shV14#dh zdBtQlCUeLta(+>h<_A(=s&?j7WpW>6SaUp#`QP*>pRl)+M{b%B(4Gdp?}JzTxeO@4 z85lU;=tJifkgl&nZYK*e6$dVyetx^l`N{S>)@)LXu)2vdqpf`rdzuh@Dg1fmT5;~| z2;KYB8#YG$$qc#cjLk4cY^ew0I1qWhC@fYhiLK7h_+jq6#>Z)EIqrryu^1Vdn6A+X zj}lWny;-C!uiHiMz~WO@6E#4k3~YrJ`6GS;x~o#(N!Hyy|F0!wijv6UPan6ZyY;ov zJw53jA#ucyzGVzq=}GSU+yk?@gS2lRP}jNL;G1%Vt>6xF8Kb9&Jw0*z98ieAQY6GB z`?T{P!?I+h^-=4bu^GmQE#-ky5(K+%iI@~uktMMX3$F%lnkr1Lw)JUzOLW67Y9bLB6^{z#tuaDk{sEyD56= z-1L??4a?X~86US_l`e3`W*8&3^ak-5i2U|z_4+im>lx8S%}>|9T(G`;jqWPsvgdX_ zxw8!dx~qhrobbNWFx85&J|xmV{j=Z&i<~sNry3&%nwLFvPc?Rvc&aw*dZ;FSo?dxj zf+X7x{bf&)%O0b-*i+4kE{*kfxp$ViHr}{W`bey)z+%ldXKaQsVoP73^a8;v&lp^q zt6gUoIm5P7>s?dV;`%iwomdRb%?ytfsZ?1UXz1KM=kH$Qzgq)hVs~r=kNKEF${v2x zV{A-jkg*;9pnGgg77(_8Nf{fH1w;+shB6=59qU+{R-AjFUBO%N?1!GjOAD^y-PaN@ znE)$qXxU$no;9L{ww;VDPJYy&*y@GVV+ryPEL!y2Cm*IV`+kCH#h%(|X5*DoPn zy$dDf45B3!)EO-lFgpcHIa4KIH5L4xbJCYo;215;iCMdS!l4fPS&JSkDXm-3b<*h) z^5$>>q%y}`5I$OHa$Ujw&Q3l)7rw;1ycxppjs>)S{88YH%`ir6X$+KRAb7j=snoL` zr*9cf`Vjn2O}yr!yk9D$PX%eo@FQJ|$MRqr88uf z69@MgEVL15pLOaV_)2n%O+gNx=XY9fcqTr{GugXC>gA^we&Ez%4B3}0VD*oU$pXS= zWv*dkvV;r^vh5Z)=%KsjZfC)1VF{60+uEB$W~u55pp+mKjPnUtOR$3+&cMKr?Rb4U z?9s+HR!pb5=UcdYrBdbbfKBVCy_X8S7uAyPdHa#)vIlL4q4ZmcA6bJ<+9XXR(uX?P~Y_cM~mzMZvS)hLC;^|JFHdOy-cj zkbn%wiTP=lnWIDlH+Zj_J|)?;YI&3}=zb0&N9P1=bzpn-1^z>?S>T&!3cY55=hrV- zI>0|VM?vd#(3Tp$R{2u7;u?4B7I7*2FAEBdiC$TNTx!@xV=FbRgI6!UZ75^)=E~Nn zA{Ae~$NsZo?{Yh1GmH^iiUFkn2)^c~_pbiY(Rb%!Dt)Mmt^aLY@)p2Z0=8%Fyz}^IYf)RiFQuql*d?`P=@9qv} zPuQYmB+{sKEp58w9@(tt)Gt5;?EPRT7#-URJHcpp7a(6^%FPyZJ`+ka)l@8ZFm!#R z`}`N-gkwL&`$phXhUyxR;^a7Q|b3REvN^Jlur0T+7 zHFv|>X1ei8I(Uy*4LXFG_<7 zBG?I_yfT{br4s_qd*Mqb*k5TQmQGwY)awwta&*nM^*fCgYz=PeE}cLO{tntIESE8C_UsyY&h`qk>(7ENSRAMHpvxtW;3mB-6j^w{~Jo&ePIc7Ea72rY32- zHievg@6Bs)h55p5_w>w8_KXKe<9PzE-(llfi+tm-;$HK{T}qUJwaz zcpTdO_@7O?27>^j_v9F+e>X)}eFUu@hF`-#m+cB}0?>j8|8DIe)wf>tXm^=zw!r!S z#_24@$L_QK|GEAIazTWYoZNEZeQU=jQkxB;T3_oFAHDi*i+hLm3vS+bQO?*5W5ky5 zKnV$g?|*8%x_Q>4C71eNWlr6cY5n`vhX7EE$jmTIcxV2yNfSOT@+&QgPH?yreo4Cq z(q@LXlReznm`ouXS~$;ciDR?6X|*7{tYt~>v>)G7o+(D}MLA7mG=(6ajxXSm0G++$ znjZ?Cy~Hv4QrF(TvrE`=()202_DMyW2k&9LUW+4zc=RKskgP}IX(v{B9xi2-dV6Jp z{;Gm>pQp~)3}eKWmLRDEM3xCD^#)E|ej;ajfpW(AJ#kJ2^$bod#zw~GD)oy?8Smct zwcw@U$BLM`EThBr$ftgyw3)p!aJ88$`WzlOv!^7y_`KLJcXL_(5wZ8E35P13ZUL_* zJZ}*0{%VoRx_a3oJYtSlD1K8Dh>d=Q+2_V#`v? z?68G-^Q;eeL`px(Zx4TRl?H8Ks-zDApM}tt46(-v4`3UZUvgbxW9x}!IZs+$>g+?s z4`1}WN;rM^yb$u!40+Z2_Q~zqJ{A`7O!~Bj zwB|EJi_F^hL8Q`&+1$c1WncGqj~koLL{-Wdeqxz*`$5RxWk@XpEMW#HpHJT`F+;+fQ2|XKaQsVoP|SgapBpJ5_`Jd}rOc z{&o5O)E|n(Lk} zEpR-k*ni>E!TYN-rnlxgA{RG8IKER7Q!G8khyg*Jw!H3{Q5lSKoeO0=Ad8ZWH z`CnIiKg;+%m1C5B=#0%UMr_Fq=X>g7o7}SnJflSmC}6Q| zxkD5!0-;+mI#MV_%l<&2*87~CH4bb26r`NR7S4;m*^47pgx)|ZS{%3Uk1qH0S=so! z&`#Rb{7qKytS8Rc3}eKWen1X~U`8IX_9vdNteOKPFW$*WI-*~<<`?LUb3>EY*Q}>+ z%lso>Wm@U8vmy4K6tmcDP=kk*#pVLx8*wc*Z~MCU>ka;UhyIy9e0$lPGksN_-)|h{ zO!#Sx#pYBR3mhg*9+YzC+f0sZfoF%8Ys)e`(a}C?z3U=7%0kcxEqFPDlA_}N6_jTP zK5HoxePrTu^y}0cYd0-+#%35JwzLOHO(62zn_bslFPSiJ_Bw`>G5sOxuX@$CgBD{M zo2yo+Eeqb-cq6OszT}zc9IacM6K{YAZ%iReCU`G`_PRhO!3Cn26E@5=Hd?>4McS!; z*Y!P#2k!;kML8^Z=nUQnM9D&zNpLE=!4Ibx5Jr86XyIaz)^>eW`B-09z~Z_K*r zQNhddGz+=RK}sP}K1gNGrCA?%8FHteXIppHm$&<+({C5AmCo18X7gt&dPw;Fmu$?iwi0Al-OVo%z6-oe!VHo^SZhVt zn9Lx3@I^HOF{)o9H@@1q)t5t+HF@o_Wj9+?rU;Y`r5Z{g#vZz;W{{c_!(Ibo+bJ(fYmk z3trT|vUMr!bqRF1yCse;?O>XPzcerl5;Mk`1raPRm z8ODe$y@4DK!G5oIm%I?;dv;{<&;N3|QnQ!Xcxr;i{a{New#&koQt+>Oi5M1sAOv4Z z!DAL``1#T{nV)i%uac9>wtcx=YRC}`s*;iwAeJ!jy=R5(xul@cB9Jf>IxNgDYyn+L zfwV(zxHMXjlZR=qotSB>^{qR4{rShPJWMt9OnNJ?r?cGaRy4Rug09@--e3=3xySSC0et12K+=x-DKCr5C$>-eXZO6T!_=Jb zA>$quY855|Ntd82wnkuTc_Ojm$&EkHZtuR-+rpkP>u%{Ti)`f7lFW-ewM=kMp1j`1 zoH=9l>!|jnG4rxx{&+fLGmH^ix@_e*EAi*Bn4%Q@YX6l-1b!HLD#!oWC% zvFu3PkC6G?+*dDb<&G=WSt`T|?+J$YsmZu4?V}o8C8FK15zR`g+?^ z-Mlqz$f+gO8hdJ)AujS|R*BQP%QA1~$)8x}`#&)`y- z=74|k*B{%>UKFy%iN(^)#7H7xrUs|s;{N1<%d>WxOfYg-&0z$plwh~?FidV|V}!JP zdBa%Pn9QM@Q_@A)7$Kv?{8RqTaV*PRvbapW>{`<7r7abUntAZqkd98op;e%a^H~o87eS-t50uedZd5&q&+h zjLk4cY$*(pZZ>VtUXmoJENK7w&dm+-U$*sU^D}~n<%}U~9hh!%bskaQw^1@jPbk-A zxAniJ?v^@}-wgFKLm<-!)Kyyk3&6?U?}ePwHO;^no)D7#BC z^WkL%O5AryO$u7=65qTPi`sy+BRv@_oln-@9gMr@ho| zSKx<_DXySF6ce-QRw+q)CL{_gce(6SGb(-~=&*7+co4-9k}3p{R=@~kd(3=ptPyH% z{J=y0ja;k&qdA0^DZS8bbhtZv8hhwWl*2;`_~6wON{V`Q zCD>T_W%OUwO>aX_^iNx_F;^|b8Jl5@*wP*-EkQ7!WQw2ZqV4jZ14R#AU)GiSx9nUU z_@G9!+O#sMMZcpa=_KzxsGGgdv|x9XKez)#Xau+L`C-+X$3LI={FVRtY|0ex?C?EH zF3lWLPrb}xWnL#%`ir6=?aokK%{o$(HHyWJGRVPE6L0DhvS0js;iqIRTZRf zgM9fCi^Wp-;hlV%w_%5O@-%N{V}x91%QDGAZ28Y^%Vz(7y((nsCr6ve#e$&%|AtXY zDG`MppNF`7NdUg7nx-k`$>X12TuLM#&bRoz_nPRX3p3U?^WjJ-C22@0WmPKIjQwnf zXF2HZY&dPHccK2oj0Miv3}eKWra)-~f`exA)O3H8ww6tZo6M$PD`;kJ;R3&553%|Q!#1L%~ig)RXiAH%vv~_4nRRkbmO+nUJj(5fdOSzLgx`l z?$(&r&)ut+_Wj>1!@1!929)E&kxGoRJfw7R?b)tu1IrTz$KQ)H>I>I$zHXLRbH-*E zBeoO+aR`Xq6qM7pzs>fIK~>rB*EhZApDx-m!HLDt(!hAz@}kFAn$5TQd(|zgcv0bH zD3s5`4nj; z_La*Sn_-ODk{c-bK=75kvuX>B?p;~*^UI6v?;StZNnbqY#A0b=WZ-(r#-W6zW2>ja zkK-3Dm#`f<+ddmS?nc6?FalLQx@*{HJzb~DmlYKr``KykIsuuQ_< z8Jl5@*wPpz)qu#}!x9>s#M0Z>A6>uSZl0!<)$ux2Cl+%vOXE+m%Kl!_H*cRckMiEa zyU+DPOF`_tmP#cNebSSLzxT^kMY&(L%-p6V{I58?FSyWJ@id~pJ>>oxK8cm zmeR^=^4720{L&elVT{;P9w;S2@blAdaqJG|7meS{5*1|W7n-+Gad#m@!aTqvqs0ZsUm$| z+h3WvJB)rWK^gkPUa{5p{1lFrT`yU)ddB{1s$0(odw=i_F>%Ib7$dfX2T4jG@^VSX ztQe*KcR%9%i;};;J+f-CV>RgLPD{hr+)tbZ4*pe@EN$pazO3gm|H6j<;EK%j;@nl*?9KHUg3*25;0 zmPA4iSL8`L1wCAmcjZYbPy{eA@E>0WJ@S==tK^PkMt3hh5afQ6clPvDH*I@nDv&6FL)ao@YwNR zLftZ%y-qBqW`+jR$re$!o-h3+C2Z)t+o9TVid14RxZeexRAA1Mfp4o7XrB9zag$Z1 z?X$KEHy3UD99AcswKZcjg@8hs0b2?YXx8Jl5@*wPZ%y#mOX3sB|f=k z-|TB&A|HdtgYh?S81((&+x79B8=~<`zwq1YJM)=MetoaIbkzP%wRJ7s>!a5F1Jb-9 zy<8z7)$CuFr*)>SZjREQ?H*0Znlruk?(!gztsF z=gtb*YQI~s7^%5T;-*P~_OFQJAN&q#dG5Nx-8a8lFM8i>hkKWnY@4qB6P&Rb#)vKDfs+!LIQvwz_0vD?*9kHz3u5)wr#(-76Y9ilX=-ueH{*Ao z!(|o~w{IOw4|mw5e!Q*#Jh=evxARr=A;^$ zq$#{i;(RXWqj6B?xUYQjHhV^AY=$vnOIF}?0w(+g`7gez+;;h2#}>KMcFHUEH1`NN zv6z_|TC#jT`*E*}#WOum_vp1RSAVr=`mh8%R0unFya%)v57LX`A@1DqCZCqoiQWGX*Zc~%LsuM}u^GmQExmyg5SS>|;gUaCa{KaE&-;4Qmfm_2 z$*}W+6SKLcS;@K($M^T%mrmrIdg=A0gN}#NyEh_t-Fbxa;9YmV4o7&`U7&9Vyz9=P zXNBmxm)?eV-T5xghjrcg_b|b`?!5ckrfqm|g$fqyEL9ur*HCpJ!0t~v9(!e8$T^B##^vEsEm-z`R&3Pnn1{q7vl%>e>! zGXKAKZJqDdoTjzq(6P|jd@FL?d=ENfGmH^iiUcPyFj4t#o1aD0~#lpnc>{dKe`RyMSVri?pr1&Q+XEpkCofEv;&l1vg7nrDUzLM|cqQx9@9~r(1 zyBe(dHK{-tbUzQ`yeleq%mpS|!FC@Y26TpF1KR&j$o&nW8`W2Ot!!!ht}sD-O<)Le zg9m%6m>4V6KmVKI-3RCQem9yHc+Dm6(Zg#?oUs|kh%Nnq69kwLx^p_CT0z3_zLDJK?76BDDBwf?i;wP%0xaK2UMX3c(=ZMR=6xDJD!62Z6NBYcaKz+^M{ z7AO8EmGBMzyt{=F8~oK;)rEwY>i=F=U&388FX6e+pAYM_L05Q>rXn&r?*fwppj(`H z^lv$GcZ7a8vY*@PaeD5um*qL^{;N^Wk;R^hCNEyWE3T*4pL#ROsj&X1#Zu!tdj7@E z*bHODmfpY#2u#%317@P zpzdirDZR&ad;OW2{5uXLTl;aAy%E4s6is~rub?I`ZqL6wWB=zxIuqx-y~KBPq5iyE z?oH0v3}eKW+`#DvOq?#YTsPC>+mFTWL6YY_9A5O#Lu|DZi>bMhQAK08IA642+3H!} zPu1sg%#SYJ&j{&!K@t(~`%mzTy9K5ngkRjv+gAT|H3PF}y!MBr`_(J;*gjdmxyGK1 zl3E63#U(KPHuU0d-n=a6$}WD_qtKn){7UJtW$IY2yA*&=Y*BmU2c^i_KDG6;*xLgS z*GPBfuM$4@MIs?8k8o<4A(q`Q-mAZ(Z?bH!xm$|Er$ZY`k5o8gGmH^ix&kK@F!As6 zfm8cuhX)0;EVl@2Iqq%#MoPws#l*tWT*`>g*YCy3`jhO(!!BJ<7gJ&EJP%GS&@1Qo zkN2=KnM1Bb5SaNMe&rm4vQhb!-X?+14!OH`#L5IrDmXszVN>vEY5|2eVsu$x7AJK6 z0slB5N@{uF)5g8A)zsHh)oI5;AC4Z+-p{xyD5SDwmdn3MJA!`QJmBDNzTV}qVR>!% z-)FO&u^GmQEnR^e4#BovkF?H~ zi1FO@Q|%{g>sLVLA0RWE0&`^HN8$7SIB?Ep|INC!59i(1FHzXKQs-8f<%L5iDFkor zBQVDtdK5n2@*S|F@V7ESkHY6??t*Tt+$rB-zMt`=XowJu7BTymhCSg=6!yb1f}jt{|5u0`u%~ zl_!El-&p4AvkPB6_bH+*GJG{VD--G!JfpP_gTTB<(#sQbd5tYAG+cAp_HZh!f9?Nw z*WTVn9JLQpYMD3X6tnoM;6-df70OO6f>RD1TF|5Y%Nd(tjM&l@D4js?2e&yJR$87u zd+3?+n#;Tkw!S}faIO=JiMhGyThCVS9p{%XkZJXNpTX~OJS}X(KJYxa5#)3koL9Xs z$VHr2?iO%CPNGd;GyCSjM;Dsq@6MMHKiicvXv>)e?XXimGp<3~Edqme7^dFgRZVH) zV&#k3OPQ8y>{<0e`0E=SDQCescq@0_lou@SW)n8*7Pg9>$Q73^_;EJ6RnZxnVT{<) z7$ntzNGr{C3*r{9D+zrqy~TFjI{jo8h6#}R2C~DJpC^co$pW&HhOh6J$=-zu+@bD8 ztgT_;VX8{g4srewK}iP#UV;cLTFwXZ7y|=hVHSPcuVj@V%hsD1&OWf#Y}%1seN%cG zpKfbDr9e0xEV`C4_jH-Kwd?6Q<&2B2=6-TW+THoh8Jl5@*isB6pg^Q{^j7Cd(>p5wFRKYIL7QSaOo~Gne$9Mp)0| zU_G7RVfp$(U*(1()2R_NzM>oqu~ZE{8HH4?EV^b?eDH*bHuH(gH_QHcnmfM#8_+7~ zjLk4cY$*?vk|0>UtwFo&Z*HAK$j;>Z|x3?ixy^ zkHB(Cn)jZ`Dt%6b#%k4Dac<`g4!r*$CMT>&;P)2f(g%BLSswCBaR1_(C948#CbhIn zybRd&y=?bVXKaQsVoO($lma4UxBJRfhCTf;?M!;eZtYu@d2c?PY@HOi zW>)KS4TYzl&dgaIwx!1x+MEYNWHv@fRmFdM3LBFJbU4QGGK8ntF1wsa2R{} zS=h7eEd))M1s?D^Y2;vY2xWl;_Jp&txBEih^To>!?Vcx;c7AU08JDH{Q45{18ODe$ ziGh*~1ZyV*Y$|a*dsZR$nTmg_?>dj3Y1+t>l1v-!!zU%Fx1RXd+H;i)g~YcXnU`>N zDZ{3leVKO-&?z~sPJ>NK;+=jPqRGkS;rp6@Iy?5M+wW>iEw~?L{HSmP;c{s89l74i zt}@rZztj9Cohz+>hHLUEyLxAAhB0DGc#xz7BIWO%%U0E$H8bn)_s+v21*&3&8b6&_ zOf4-eIpiR?BZqoDDf*l`_E!+21u<1nUv(+8wu}qa|U+9NAU#KZe70hY3wd> zy~m0^VhlIuitg0e61om0wG5^)ngQxN39LO2>vdy0O#u58w*B`#qI&NZHHBDMX=J=E z7Fzu$R3ArbS;qzMJFUK>8j*i8jM&l@D4js?^oxgP zZmRc*nLtMO_`dFDV={%LDAr(M_=&+hxf9r!%pnII@$J<4y70@7C0|q* zX7aJBKJeaSa89tE8GDKnSpOGxn!u&U%n)bOdDL$xrKlz1(n_}u-p%;ae?Doo>9mc` zpK@Dqq^J!sNGa;vt|^L!XG-q8H<^0V=l1!vGtF&P6m=Za20IW*!$Tc|8`x7_p@vNQwZFM|eE~810$^IfX@z zZ<^z0Ja?_Z2`3hF0~3p|sJTv6mGXI6oLiYsHQ!p?%y91xxcOrW>0|L{>_tp@Z`%T& z^5*d=7Owhc;^nI8tfZ3>JMUz6>z|tsm!Om(@aE58s;mUIoulK>F9!F}~&IzxqHXV)M-e$Tj_Gwa8_RB{nUey$=O6nUT_1tMKpWC zF3Yo3b85ZRMVnPMwBGHWW8#d>Fh*?23X)JjLjv6CT?ETO%gny!!m-k=UvkvAa6+F1+1l zqSz7kGXOc^>_(jbh>~z5O)?5C0xlgtX>;?xlydFFtJ$%x&e#lN#FoTBNd}60)7U0G z`fr$~RsMF?QrB(e+9lm6?U9;eD=zUX=L_<&Q&>Ecg9AD4_hw@+G~&Lhs3^~Ud-8-H`@F37?cHj7A3b-* zW*8&3R05561_lOakts^=3)Q;flzB>{6IafWb-NouV$r}o&;2Qvc1IHXvXx&I&z=-f zb>E({z4!)M$z#6@aYe&ONgkPYpLu$?nYRh3N*8{NJzi{iZs!B!13Ev4pH<>BP;!A@d}w?tSc?w$SPMlO=rbr!B*gDh@6{YL+VNJ6HMc zeZ9YUvqHoQnZ1{``1@EnV>65qTlztyiXTeyKY4WA61@xN257d|F1f4sHxzW(k(v2o zo03E~`BHX=Y4Xn(+vj+;l~C@3l-whXyiK%XP&KKKL(ibTfSLpI_9ZEN#lX zb)qk1Q>a6dZc8AB-{fvx$xgR;P9An3xSYkYWtx57Jl(d*?&LPwz?Ro48i={I* z!x*t8D@0<^is}}YJ}fuwR6fV{Uz2vV?7zWs7}TM$G!41eyKi>Q1IsfEocneyOkDKO zM(quFNtH1qweU>@9U%f4@E17#z(ni%f~VC#4y-#CT(~=Sh4fQqnU$2K5P{>rU~|)0 z?nV(9_~r@e#R)knWMbHNFTPOea*@xW6@UI#v;COQjB=CC2~F%NWc_@nnfIE1r0p~3 zt&t5~Uwa|Uv$fs`gr*&;PgKIL5gA1YTbG?zoDVaz+fk%#OF94!+EeOMM-DnH}HMCd2_D93B^# zk4pP;Gccw;t3I<&=Af{ak;!?wr>8Rp+>n3}U^9WED)pG3mBuoijGW z7_p^1NHBuPi;K<}ubC8cVEtrK?JG|t)#4THG{kkUusTpD~~FaOQr(;EszB$xKjeCtzoHRtkOrzc^odV?#42%KveiYY|# z-y31a#;@z1+B{M~O!N3tZ?x9OyvNlyZqGn|ay<+4qWt3~gl{-%6t|ZCikn&}cWMd|?r6@^Cn= zomyqNLGwq%!Hws$E`=4hoQPYV;3rKupYM4tO5vyTd<-u3O@HX+nSHp0v@`1005nx<)Y+81?x7Yj7S?GxW+?A0_ci7H9C_Hy<{NoQ<^F=9)5ptJ3Y4_PVBbLkHolQD$N{Lv47TY`Xs9qhIQ{uN7MwQNz3Y#hQb_NN52~)#RcGjJ2?B`OMf!BLEMHh|WjGX~@6ap0S5bKW$q*#2=T=#nr?BY9_`@(S*%imArFBJCCqdsChsI0YUFHi0Z$ z5V)RecA4u}*BNf!i|j_zK50Hw-OFKhX*5-Uf)(keV=NtTf$Qz~hiHB(mFV$>EburH zp)v0ci`D-4jUFh=S+1|bo+^Yrz02%!cx`(g{uOqbm^61^dnUItHp3XPr5}*PAy`z| zHe>e1b?CE8B(%9y5q#$ zmo0F!8F84*v;Ch=?^>f?CcM8b_LqO%l~0|_IR`2zg>HVpo{CofI$-C#<7oQ}W&2}Q-&?lE#`~l> zV>65qTY7_}AP~8pRbTIU&XpI7Ot^cP%JbG*&szT(l!`3Ox*s`+Ut1>fMbq=mp^FAh zDjoW6w&3{$qR*HXxP5Z>-fHhOp7PJ}G9JhEy5_&xdaWq}x%3f0w1*e-iqRyBm zYfn?Y#--h_4o`aTCttCcfsqqW2K{l8+#yu9wTz;W6_r#S)La-L7biQ#{bz}jQ6HYIfk5yMoS+ON}qeuh|*_c-=EI{ z``;-FHs0Ip9&XlqMRoQ$mAX0wwo5y<&wH-Q_8fCb9YI>=8pvDW(9Ji%meFT#X%V%E3^*$x1b$3muXkM`9 zC9dIRfd}r$!^?{lWg_IP`sTHAym5aKx<3DL3rxvWk%MTKvJtivcAHX{tI7A0~ zx;e7$=uCLFz2Dq3TlyS(@1fARn>bR-gE{cQo;w;03ho+u@^>b)uwI@UaCUk6{<}Wi z&e#lN#Fnl==>&pfj)(_IPd|{g(?(IE>E=W6JT2y#PAn$IM#iD)2Tz$jeZ!`9ghyq~ z!#iykgqH@R^ua0Eks|P@bWWYL&-LUre=?U8&0d#r?ZT6mL%4RNJnDz`!39QB6a&)b zy4d$PP28lr#eMSiXS>foy20|<(|wvswG@sN_2?Z^iprg5ArY!S`OMr^+~KV^qTZeC zVO`~n%`ir6X%CW`K&15p@pj=)3{mKfg^>OeF$d;x@A|;T2)W-y zU}}wI=e5-Q^xK^w2P)UQwuB$yIydtfO5yY5IP}0gfzhPGAVBapt)}&AJT(;p zYOL}f55A3c2*Qz6o=PGmmFB)%Q!bm#tg#d}IALwO=eF(Rb~a~hhB0DGRG>rx!9F}o zxz5Y(l8`NW^5*}q*K9Y}rmS&dF}AQUU>80&CroqJtCrxRe}|lNpED*pOo23bAcHpo zDtq7qIReivsPvF|Y-OCnv0QD=YY8Z6XlOT@ zpYuQma`<%QV5d(bj?trKqxn&-XoT-x9g&k(N-Zm_wH33Xiz^AIq35x>@mCHQS8NTI z-*_XjG(-OB;p7+j&e#lN#FpA1=?6sG3)S>2XPKZZasEkPsNnZyt2f4aIWXnJ~SCaF^Td)ntt-)Gqc`|PI} zb?|@w?=cush``GL=!_>tTeJr*h3sW|?w2rYC2y*#b>E-N)r%XhoHinyLSEM2acXl? z-BEnQTHtT-FR85y)&zRqb;f2GBet{zN*fSdZhb&+f%XKWhHIR=vpUR8*YB+t0iAMh zZftz=5`+AH>4)#LQY^0X|6IZo^7{|CK@8h=@;U;(?S#Lo2EOe?pzyiQ_sRO@iZ3V2 z90~OBd-66}xs^E@CAAFpI_Y&0blZtQlq_u9$zWIv>f;k^zBcf6@&?ukd-#4_bzo=V z`Hv&Dyj}~hlU~-J>{Y(Nv}cKMCjS?s&qu$onK5;TIAb%65nH-~q!bW2(=d14QiCP( zbvAd`EeMl}ymUwTgA=oviP4k|8^oC}@Nbmmy!hnqpS|(UAD4Q7ixb%N_}ez*>G3^kN;R~fQ{uYUdQGe7*~--oDkOaq@l-pH5f2|j^-uB$j1?pCvZ&~*?u&>K&h_e9~C&rLvTHG7#*_bRK zY=QU7*_bRLEnnihVW89WvYJ7-Zwla0v;(o_*}-pj^h3`s5Que9OkEDC(Q z`dwIImB9OVeHnYUZlBTfv!!{@GPXgRaz4I?p0g+*qXgS5i+?NAz@;49t$do5pCs4# z@U618Ib-6WDOH1V9@;0w{zsIQ^D-yk!UoNE2V!N<+V`_8TzihBHAYJD6M4Z{)YUmbC0vb?CRp-J0Lcr7AsSa4y67 z!cV1TIO4jV(=5EM+}Y3U=cgqh^6#*e2p4ifqv5o}7fmimm#ER3eLW90Nmt( z_Mim5RUr4EwkE5-loD~A)fZz{J>lmTMXfZm4TBit*N{sCx zAG{J{dGZNfiSeA<<@F)VcS7S?S;zIX6Z;y82TmeqlCZ5af}?wtQsgDs)h`3rhYw*cQq=r!Fu)9*m9=_YF{FMn(O%jhF3n2ZFT zvIzW=`dNNCdKHdj^EVsbIsa|)s&w^-3$uED9=>I`?$bVoiwkqzeVnlw#)vI}L6QuJ zR(Ik6Q7L9Bv7bg~DGh@@Yip%_XPx(k4-XA_ixjOoPfS}=8l<7Zn2KD={-)}0{KM@lC#!+*@2@V`X2|K&g93oqG_A0&8$tRqm{_hQEmq^lhQMoxSwoS;n@ldkmzQ;Mv*bHODmi9nt z34*iV`ad(Ta9W}+xkr6&j#*)Wknmq877KGDldmgfB~0Fmoqnj}zwE|j7e=;wd``#< zMFknBt!Hkzzwk&fZxZX3q{mS&4Oy=(3>{4spnyfXjt9&28G?)(WI?JJ82Eo2h3(}< zzAx?;`$^yY!xBxQ2c))5x^=}zVDhJEf~i7~@$#uQLGIo^sm4i<@2zh7;?{Ozt)iGS zHp3XPr5}isK;(DVq7)(38I|D`D=n68N#c9em0kcUXADg}ldm;3Ufq87W5xH3do4U) z|HbSU0uKTjL1vl+nb)u}nLzgC@k_R_F_}Szbp%qL`SRE*)rI!xwr2D?yj>hR$w@E# zG;(U8?;xNc^D*e2J3iYRu>OAoj)-Tj)tAw&GuzUP`ltq;pbo-CFFa zLXb@y)>aW@y!>(tzb*F(>j}@VYx!^+RkIp*G_7&QW*8&3^aDu|Ao7;cov(LR&epgX zudrwD8sn>lfAZ$3=Y`)E2$Zh>Y}*pnocZD! zayl3-9gr7n3bKEIo(n;6ihy^k?{P`Gm z>#GRcJBQO9ltpD0H%q07X#OJG;#nKF67o|}Ho z*bHODmU zy&eIo4B-x7YPobS{HsEiV*B%*)0Z2vTTN4BvO`|_Ac)kiL8`+9zSn(zaBJP1&r?;r zw{dPg!+&}2vWxGXu^GmQEnR`q2?Xb-*nIMs{ic;)m?`hp_iZ{(&YQfzX#(1=;l*+3 zHUGDwjmGQ!!-b}H3w6%gv_ac5eb$;Jxxt?%1cffZ+BJBu?Ha%|v8O4t_n*dI!^vBo zX@B$8iE0VkeuZ!eBFud|W>b9M_C37(E#HlmgSA&wu-MIV#%35Jw$uYj4ZF; z*9nR|DQ`+r71G;yQ1({KkKmuNejLwdpc^d@oEGX4<#%35JwzLFF z8xXvHoneM#`=1s6*lk!UG+U3?a4W5KVllQfH1sSq<$G8hZuB-TS4Y)qv-2AF|ApY0 zAJ~E^>rnVyGoOqke6CqgoDDwL%d>wB?GjTt75jSND^CC~7I zTO`m{s-Uz7u2!n#_MGLuGWOz|*4jMXvuC-*sl$z&$f*UfLWLgvVnOL7qFSj#phXgN z_+352`We!z4A(4VTw?zu+}~ms;nX5M_i**IRIxuUVambQe@!G+q8N8@4Zee7Dfgp?mpMQWt=NL|Mu8+O<#xDqFs&h z0pQdE+Z}>*DT$zL8GLsLpN!<@J1S3Ho`k$`{t?hq`oT^_=W*OVyIQLrxw}M@YV@Z*&;ocSEr%;$g3Ob ze5wD7TNoEEeYSGPbZ2aaF=9(spmYMkJond>AJYhvu9)#?|5F9kX}mX@8c@;%(pAJ< zX5Zmyf;TVlZ_mUk)$YSO%sT?U7`^w~Ju9i}E^?X}>?Mex{1RxI;CDR=-7&w13$f%;wDu`?$+ zV>65qTk3(N2N1a>X4grFm}lzulIOeFyUHCjEetmWkDnPqjt1f@X=7tDfz19g_snEt zGJ(wRa39QOV={%z1hW^MU}Lg?obb&1C4%>X`K!-=o=@e=TX|CX(KVssM;xdtX@^N0 zRZwvUY`3b}Dd>Um0<;|0KX2lA`Y+Qg#hi4HL+gz4{!GtMYr&CLl(^w-RQdZ$`*sLd zKNVA)%=F7UDRfKg-*}%D&e#lN#FnZ+sRV*sU#aiw_$(*sRz1gZ28-oA>yjsyPAry| z2IfVU&B3NOUG3A#H*~TzEVw%<{qGHM?*_UalDF$T;!>mK^I_{DnWuZhFEtWWezM{9 zK3TgLbEhT69N8GUw*4iy-a(Wl1jJ4V2`c}Cu7~8?$^>oH@-ufq_Yv`b>w)eg;@$7sf4k4}b+eoKZxOpUt}VqZE;tg7iVIT0(P#b` z-z^#Zh0FGeg4Ob0zOj8()y~)qW5kxkAc+Pijb+V*7ixZ2f zsfGCsokyG3Y?|7=e#X8vRX>HE=c%Xf0Vf65qTWW)(9}qe3u=3j17sAigvI@48 z-FB_xJk;%nJn76&!C62oQ&RWH9WKk?^woFQqSxQpY&55tDF!AYryE4AC8#wUI_Zq< zETGY{hk-#LPz!n%8Gq}_JTCs*)AAG~u4c7N(VZIb)ad);a2)AI>lael^DHwUsPDV0 z&Arp%2VGXzh`)Wdb*nQr!x*upFi?ttV59z5+2ZfwUj%6J%iVXC(&|`cYv9CUZfaq| zsxY-sf$Lh%s=JPJLMFuqvpoqYf^?*y3*U4uKHD4q<&ml$^PQMY zEDb|5mkaE8ZIX6`^GJI%>*a3>)A+VRDk^9XYr#i0CL>6~5twYo#$*gxHOK#?l8wm( zqDD|3>G(sn)@@hXi<(>_6W%Ir-`XwTBvj$~Y)Fmg4W{0>puQBe$l=ky^~;U>^^5v{ z4e67w{N`@zVM~yE^qFuX($8%=uNQT1hv9@(y!zP}t;}y^eo49JjLk4cY{?Cjd?47Q zMqtWk)2>{>X$Kta{zMf2xbk)(IITc?;|zkO@ZLDX9~O9ToMWpzyf@C>*ah#6bMmu% zV3?%l(Q&0V!ba~H*9NuoC6^o@A{RKrW#mTC&<)lbr^?w;*w(Y4q?I#&_imiM>iKkw z+MXrLM5=|)T)c@gQ-Hm|F`TK&q_ym~nheX)jY1oEPwk!dF)DqnGd9B*v85_VIsuWB znQM|c-v3$L7ZJJ7%(iJq`PF_qCl(V!bMy4Ghk{b8j-B8>;T@VK{y}SwmBlM?rwV%U zALqK4Y)od5nP~yD4Qxyn5H{b^RQSbzg2qK$aUpx`nY>DFHf5YV|I7Zy(`jqVQBn@P zQ#D)~HiE`I^ccrUf2LOMTN5ece7eg|zE*8p+@d-a9Hor$Wq8BJaOU?^Rn{V}Q}0h1 z>%?wU^j}!+mSgOU%`ir6X$+KRAo#%4-9L(#rr&T}%RR57Ern-hTI>wuBN*5nSlO72 zpgTLLb_ByZpHp6%J8ooM-FL!rq2i%JzSe`9D9MRti!%jH*T6=1;72f!J_$u^rA7CG zNL1a_=hTd&U!wN<^m=*RUo(I5;ZVZK$xKOko7NJ&)%9^LNm~{BkMPc%aMzI08Jl5@ z*b*KjDS^oeKK=rYk*AbJa-(uG_w4Sv7G3ScVrpS*q4M~_`nmo$?kqdIAeS-ZQp?ZY zt=GWSnIWWEgM9A1p!sij(?=jU4Bqq+Kt1`HF*NbAdxH1ojyWHg9-b}W`l0wI7daJ; zwx5Y_KMPujLYqDUJa@8xdNO*wn{cvhU31OPz9fOQM&C{$ry`3Cc>5WtP%=~c&v^Q1 z)9w>*`xf2}d%4=dg1?I0!5N!jjM&l}IQ@W$N~JKV)}94Rt{wHXWL?_4a5uleJMaPs zQ^yQ&G&O!V}Hksw*efM154$-FNSGWvOouayl3~y>3A(N9cqUwkrb> zBYt$MoKDz2`tV}%n;$6*mztZtN%7u^_t}ag9at5>D9EP{ z5DA|<@13z3#)vJ&fRg~2*#2;r`SMQx<+g1r9JVMIzq9t+zs!ln+|b05OXrTG`6j{0 zqn-wLWq5R6{t{t&4^AP_16>4dJmCkr@Y(M3J9&8Kw94#L%_WIpH}ov7iy3P&A*Yam zDk%hQlA#+C@h_3VKaEYD@jPOC+9)N( zEUdFTfIYSJ_POb_RDQl>bohnv%tudmUq7ha<&4cRMr`Q{oKV1oHyh*Tg(Yf{Epv+F z^E-~a?aU|uEvPayHg8|<=+<$=lqvqh{i&bt-Z;uva!3og8O--N2+<7Y04=V9bd&gb zg4mc$AT<&Hud{4SCXm4!{$@2cCJRVyCFn4djS)H{9z2_k$r3Va&TO_^`pB1NyD2aE zdApwVGc?zzA8=fBl|Bhg&|x#I8NB2q^lnnY;girlyohX?lwl*Q8`=9qL;i1l@0$;2 zkc%Zp`2EL%D8-V*>1Pwt4YYkHXRn*t`}ZA(-$$pZ&e#lN#Fiw%X$(y4nw0y~W~)i3 zWXyw<(krKX6!#ixJF!?A8yLMbo%HNx!~vZ-532OUn(bXSDoQki`{URqIh~nsO>%yG zu(svL4Do|u2X1Pt?BsL*c}w6sa>^N0O&(_%Jd>P*tjW{6H=Oy=#WjqtBNhGECO!`O zW1;yGN6K+dMr!hO^y*)BdTXFzEZ-XHC%2*Fl+u|pXKaQsVoPJ-L<1%k%qglaJCyh4 zO8Ppj>9?~4Rrs`Oomh+v4UB#Z{#!O{r`o-XtC-iuuAKa(BvD{ z|8LxwR%0e$@#N+UL6(&bkDnl?7D}2wg05lE#T3{MWgX__4C4*w^aE>m&RcS9oAs2J z@7~R`seFT+T3jc>D>RhUvY%(e{EzwyCfQqFMSO`l-oZF&gOoEi!x*upD{w*q6Y>0d zSEVAA4xW=-!&x=Q@7>qJWqU!pYt79J#CBhPV{$St!tF;DT2%^8uY|6l55NakQ0%hdkggPia{_0IFyQu{v}2)bvv` ze_rRCaZ2I0>cV=$slxLOo4si6wXJ2REVVdU&NI)vCZMD6%o&?ujM&l-I6;7k{RN-) zZV#++T^}tuwYlB7mgAZJVJ8-I10%}~e&TaC*xG)VYjRO3T)E(tz_Kh?2MpxjZ?(!!)KIO2cJ7Y795nGZ3r!g=g zxWPrjwmBLPAT<@F`^3(o2)`kR#bPPqh8)e?up4rCnzzDs?Q@;2 z?6YgxE)@Fph|PQVj)%J@=ml|$6c3-2BIu_FUA#s2;lPsa^KDNb3Nx7Kl-|Cy(`vuL zx;MLV6iI&dNGaur!ftJ2flV579K}R}GovLc(ho~JV>65qTbcqV5-^c6`;LVehdlem z#}e${C(C^`zRbA9iN(Uy*tpYimBccukK)rF8nHKb96dZyxnU7#Sr;Ruu_Lf#JsTrr zeLAPdCN?Hx$dm&=7ZV$kDWvl*7!bk6WDZGj0_|Vfm@FVGF9iG!GQ=;BJFT>6?x$tf zUB1d&AIr19j&fc&JzCF#0Y%V~XBhR;`$X%vG)C~R>J9(Br1)H)wDtFzsmSRm;5@wb zjFO(F$3LEBy!N|>VX1+fR^7yhSr?_=Ib$=75nIXwCnYekM?cL~N=2|JuG;kYvP(yQ zW;Lx-1DytKVR3%4<^dLc*R5GOErM}cbo52!G6{J>sbJ6wc$tL#`gK8#@UySh zhDc9!-=(Cv%r#AE@1tpVlVy?1q#>S$f(}8;BuW;Pk~IMBv|>WpY*p{u(itT>pQI*= zUV5yAd@i(LurT&CWFX3w$S?8gXz0RElTN#RI zQflR&e4Fo$j~08b&N(L*LrWvW-C7fm_4OykOpF(q*s}Vwf}vmLR`5s<3Hu;I-sA^( zcFL|<iyDBeo<4PBUQQcG0hY zjBDEMPhYoMx8BlF=CTybYLmdM6~Vg6O-B%E%-TM~+oSx%YBpR|4jr)^B2 zpxG3u|I*Ib3}eKW!oW!eOyt^pTfe+yerKF3!^O*gq=b{IuJbstm>C+HzS=e`E1vn_ zioL%pE>%v*{N!BG3faB~U17n8V{xfqWGsAz1=`|L%`YmO&9oS7Z|8r%vh}TUt=SdH z!qHR&iU%@!_mSn$6&5`Dw?c$Eyfhsv9u;oe@hmW8Rh5ZUBFeHa?4?iSsdaTvoE)Fp zKXX`Ucf?Wl(Z2X^%a1r?GmH^idILEeg6&(c^ZA;cd=;{F(i9!%+G6Jo@n?|-llhqo z;WvEo?iPmM@Ws`(*yyM3^LA%nE8YKY(>;$yi+UY<@c}taP*NiaMlXgACS%)~H_U6K zUrg)o-9Gpw?L&)wz>eItJKYnXyu(qlMBjtgNRg+02h1p3w0N6h=2YEx^A%n5r(KYI z=#0%UMr^4Ek{&=L&!!JM{Jqb%i5fDO`h?WP>D*}k?8IVeVPGtELdWVu8>4q|WuTpe z$kTbds@wM}gcj!xZ!@DLv`LB6S$~V9Yfqir zE^ycEAt24gRfQ=Fae!f0qNBXCMfKj@$dOp z)x>|jx&NXkw(3lIZXx>?Ipqw$#*biv6?C;S)f+#^)s~0lElqR6TS93!`X#R zdpyqFTd;&p%ZbIz#KO3GOQN;GN)z?PHYcoa+fTXWtWrJ!ydVtAl0m_wD5W3AcINvF zPt{tsK`F3s|I>EfKlhPS$PlW;l1ea^3=UwoO0$25ZA~V}bjgjpXJ$`mxXHy3bs9$s zNm>lA#1a~vvwtM~T^Dn5c^Ut|OIC9{c0IX~<&4cRMr>&blr|tZF``aMdU{+-%GS2$ z#jhRw)+pwjMIO099!=&9?1qor@ZlOwekgTeiF@nINR68;A|bKtLaXlFT{VnSN=glM zQc6c(c_UYSWzOxWBxRA4-{dRX zlJ%Xj8ODe$O+iu#h-9kUvC=*^_T60H=_?}}*)Qa*|K0AyVq|J!=zk=}kHyw(s!yQB zk~7Vg>D)ZFJ;==+!L()Y2`&Lr7lYw!?l@%LJyE>;)>~%xtu;|*Pw(yLyWD}C&}i7) zNjm_Y;2M_A9hJKdHMiz|S==jLsTCHz@)z@I7nGwy)8Y4@3Zf)5?<*l^PX`uU=38#^ z*kxu|rv67=XJ>4NF=9)Spd<#t;?wVcD(PE#P|oP_y_T@zojKB-znoYs49rX`9r-rT z+ieiJev_Tw`X%`js{D$sf}11ak}o@4n@I*$}-}s6!+(BX4)nriJWo< zRb`f`iEl9&w#sbail_q@^v(wy;La{z9B{O@W6|4(B0>$wMHEuX$waJwPiQRvI+=Ul z#AVy~kNqfHp?1JRoO_d*Gd9B*v86FcssWLHb9`R$i(2mPs?mHHecdmi`O2)HPAtYo zhQ_}ZRGqjW*?jjj|955KLYBuozy4kVS98$Kp@P|-@Xet_9@S*0ejs#*j(G9`HBG?> z&PHl$niN8YWh%-}hHeg}(=G~kp+AawS+{zZuVW9rHoNFe&hdFDN4+7XqU>!*72UGw z=dbv^cd2e#EcEwGq0!C1hr^tmu^GmQExm!#4+INm1oJDeRac92`}^UY;uMo3PxC%H zv6vef8Ef6RxM;Gu)by1KOhz((d+StZSg!+*0+~WqH}kE$&c z?KhTo*L^liRdN1CWkH_Cgc6hNjgyd53%1%yFn1+0#7P3SIxJAueiv2<3vuWufhC2* zySCCcx#-u@a!&ogzt{;~ng6H!F};X#%1-VRc;_4?wHR7#Tl*=afAisl6_Gp4pPp9D zG5GC_%`ir6=?W4BAab)sm?7t<{nNHc=SS~gnc!4@;NCSS7DF>5%kzdmlwWGNXIGkL zvo5svQgasc+yO}~kXd%Y{Jm^UW{`#M0@Dw|uXo}9Ry2zv;I35vQ=2ohTVDCxnYehZ zq4Z|t)G|mregW*8&3bOlN$5bS@I^~bumQ}fw+e4bYSF<2%nT~q1A zVrXP!V&3~@q3l~fKI3Fjj>ORZyzmvmLEyE6CeYMU_*zXQWAk(6U$cH(j*_0$Udp02 z>5dh0su(uy7An^`f<>&*O9chW>|vJ*BA=FXNSGyvZ|t}o$^Y*l@}0MW zNU5So177142$`(0nai2bUGLa%JxlPHTJADO-ZW=yhB0DGKadmwB0EB=9}06sp684^ z9N)<$75wVgtV2%BW@aWPS8}GDQUWRQWSMn+k3~_&9YL|*47z4Z z+;eX+aXDi%j1gN>0woOyR(E69`hB)7}ML|;FhOHr_*x*fFz{X?@S(&MG*F(?b8f~dCFkriG4rTA>$FvaU z&#Twnc`f$v7T;&a&F?KIJwQ%GWqt6L3Q8h+XmI2(bB1sM%W}S&?E+U*d7o73I%6}8 z5nFPDBp?u3tjgBc!2a(Z&)-hY2d5mQpS4HDI5C@B8oHP91x5%T>`W-=uX=ZV@$#rw zdu%}6YDP$_mSMXr8H{rjDdki|CU$mX0h!m z=`sgSu9f!WKi6&eOuh=a?7^Ofs=11%R$lxV*YF{m%hF7Y?VE+=vxl|L*bHODmf9fc z2Song^WkOw^Q&&Bs^s=fKK+ ztd4^hK7uum;e`)>`%-w}!65q zTM`2$83>-M9xf;R(vl(V8EdT8jUB~n=RIu!tvNO_IpY}jWw(|Mk8<@P?Y7gA*B{?F z!;PG9kZLW#dKq}aL94YiET(+iTN$^qc4H&&)4#=zx47@Mp(Grtv~~pR&0q;l$v@YiNth4eO>%b&UJ{HvfS$ zHp3XPB{4{%0gm^1PZ_pmE=n|grBS=*cb|5_s9Q|g^kG!(yZoHXnmya$i1I2=Q96S z!SMQ>#aSj3khpzkMZ(TX#D!XOwyyEp8<+_ZZD4oxUqIIMPA$DWr7pQTN6I!Grr1 zukr7j(D5Se?NiCWGo7&+#)vJ&K+*t+bd{)1_PaSdK=lJFLv;e*-vfmfhp}&%0@p93 zZJ6@0SU1s@=c&V+Dj&7tEBDUK`YetzlTD?b6aG4=buq0rOby(^y>;tNz8J1jT(pnp z+BrXqbB%p#U$-Hrnl=V_9fXo<7KOVz*@&OG(*ASbQOz4ATQ>f;Np{9&7$dgy1xhav ze2>Xsc}1n#mkWt^&2ogbKCgUd{LP8Q*x1tKY)ix**Q~JTbLNNCJe1`Zn*Y4d0n~V5 zf-cMJ(JqT!}blwEgDMCz@Z|yEFD|nf`odTFT*{dsLq*qm(!FXuZ%i z65qTN;Bn7(_}v{-*B!^g17( zltlH30<8uy_J6mXSj^4LEN}E09*WNP(`gTKWbF!-6VKLmQ$%UK#0A4!FSyQy6zmd) zw_f<4?e|#zasrq7{pd~XQwzB}BmUVW`-YFEB2YAtk&3!>p{*AIo;&YMDoo$i_7I{d@5}Gr#xBonk3mk%uFku^GmQExmyp4#Cof zYgRL>d_8@M?@dX{W1o-zc@E1X*IKUMVcUEK&WORc`SKRj!MFJ`|Eqy-^W~e`gxKcG z;jujXiD%%0|I37!+-_{Tc>lWUipolqR6~b0uV7CkwAMl#FfioXIvrXTM|eWEyF9MZ z4U&@C+1;ql@d`((=|QZ2sCAC-->JC3Zjaz$-zn=f+>4HRy^_*&#%35Jw)6!_F(5L+ zvAJl9Ks&djbqp(W?u6#O4`ZJ=v6z?{89i+h{K?L=R_Rfre&HDo)gw%PZ)bs9!-kMi zV8OnAHYRh(q=JA9M?sS9kMlSG%v_bB>-|VgXZ6XiQyEcG2;SOBux}+%YaR&nt%pnP zgj}wC4{}ucD`X=qewx2gWW$je$0jP@L{1@nH{j(8N(z}C(LQ_jl#uHsGxp86{bcH4 zJJ%(Z&e#lN#FmyoX#;{^|K4U6=zVUfv~SFxD`9Htn;8DJg8J45=G%3nN+Oe;x6kDJ zaE58S-`-u@RaQ}LDd>caICj3=xK|>(_*{0wg2umn)0o0U*1KA4p;JPea2mE0bT}ro z{F;wk|D3b-ZFt9PYO#EKNy-05R>%o$q9gW%cB(V@8}Hi5?=(%Ho{D62DmU5qtkfBs zVT{<4BqWi6NRwAD>*s6;E6)70_2KuXuU(Heb7z7Y&?aWV2lvGv_i>-x^>V+p4fEH} zInJ!okY*5MqDpYG6nyT1kFg0p_W+&)h0c4Tp4U~uwlt;DEB?jW3D2(j9Vngix7I}z zB@sFv6|8z#y{RoRoyUkf-^S57_lWcQ1XFbH6MGEf>XDS&6_E-BCtM5V7=-3^-jzt z<^~@h_w4#T{kQ8jB_00tf&R6-Ga_Gtt25Z@imCC4)fGoWayGwDS)p&d&C^#_;#hh8 zJA>K0s7DKsUY$*?fUd4UEaAgioel3&W`8DQ=f28>TZPxx6n{B&=)9e)*d*jqX6kZy zDT9(g*4H^3*!p%0vu*A^y*V!Guxf%pp))qa7_lWKNa6sItCRxxj~W`b-3+RmC@m7x zy<=IHHl!?poNvQc>j6JeiKx>{4kvS{i>*{!)w$$XI%9%NeGroy%JMz@13Fk6K7%Qx zOmBehfkB*JLc?x3a>Hk5<#efgaqjMZR%aNT7WV&F{TStioKmJ=#GX<-WZzfrVwh5T z<;7%!_umfRW!)bh;f&2NMr>&cltv)9X<^Ck%kR0YHch&^^60Fy5_-Y1>Y&*u6O+F8 zY%d!YxJ^}h^k(;@)mPrDb!^oGFZP5TpFMLG{Dyh-25wII14$o%>0i%wHW`? zx+k%}HsmsgPiya%$r&!Uf=ZmR8ODe$T|rU`h&-UOe0vmMdyn|WGg{uy!?>5qALj+_ z+qE>;UGm4~tn)fIL+@90{$~CHwGMymK^=1@BgmAJ;OrZ0OvaGqHv;P)voV=KI#_&P zce62>LXI_I4Hjl&GKVZM=gFPG#$*nezG9h@`tm$4^N#}wEn=n27mPwLrtldAYNMnm zL{nz=C+HF`fd`4O#pZL&p&c*5(WVRo%5+r1o9gqW?f-=qbtoUbA9UMG!?{ryM~a#g zh}4vsw?z0xd-2A1{oL`w!Z$tdaRnUw?~KhbMr>&hl$Ib^v-JDAqj9nIoc%A3+UOf} zEZzF&iW7^8v56(C)5_~T8}@O0+B7Xhb=8!X&CMN!;PMB0+Ogm~EnEjwEUkN+c)Gdi z*5p$RvEhdm?zz0!@|M4StBGn<_~S@X_&qtDLR3}eKWt{^D|L^`E#rLTJV<@}mnhwVPR z52Amp7wiL-KSqXbo2Jc5p1NU*y#b4=w|w}zc^kG0Ls~qL-V^ewQNaZfh~5*9Juww@b?Z^2a%QAEi2DGmH^ia)Trw5czmw zKyq7T*n?56?BH@a9wOkHc7v24oO6i)(okK za0xDXlz(`U!a`(Xp+d< zC`sA-(@SI7ukN{rav3@HRJ7Fp-@NT&)~|Jo_8yer{^YlJ*^x=}Wu37Z#)vJwfzl5I zA6Pl>+os>)`IE92L~E~F@_EbC(=$OQ5Exo`WbKu8&)dE0?J~=1tBvUaQd=sfqO^XN zYrtDS0`Hf@kLMC}wRynau_eRI`P3s9wOh+(UJ?^7OnZ%zS|}-VmODXPKSYn}44;aN z<&a3&gOe}i7gnq>;(=+%?#7)q zc+RgQtF0Iu<&4cRMr>&blr|t(VT(=939U5cMZf$0g?BXcY-Efw0;dBb$P^~q_d+%% zbI7^YJZkq_9>4dAPcP0}J%^1UJKJ?)8OMfTl#+syUiFaaCkd{ufG)NXWc>nNY{N7C z4s@}Nz}oZB>*ocslVl*ljBWcRO0T*sd(DfsZC}^i>@s$H!_v1sJJ2%-M><%&9Nte_ zIe+&yiz46KQhP+4vX2RKh8y1bbf&=>n_-ODQVhg#Aad9CfMZr-jQS5BGS+%bE} ztN)&Rr<{6`W$-Oc`t8FFC<%>rRnpp7nA4fVr%GC}>DZ5mB(vM$JS7JAPi49I?f3}8Lda^oWGmH^ik_06&2o|MYj2&Jf5RD@VT{<)8z}uiaCf)!xya4= zf2*g=H$Se^f3f_xTpCKvMx9HE_&jovFC{w4#u705$CI@6EtlRKn%;gT^j;U`d~8A5 zC8sSVu$pba*9=mr35A@TcsEM@HQJM~E2yZ_Py9A#s$|!*bvTmKmRCs0>4|s2{Irl; zsuShQj~0}4ZFji6`Jgj4!x*t8JV;Ukk((wY>}WS>p1nMG*PV?|^-ua-zHAFR3)#eY zJNu45_nF;gH|W|g-K$j+@|5rEbL51^?!byT9PkT2;`XaertsUZ1h*YVG@%Z?hTne0 z|27AZ#K0KlE%O2y4_KswKG~v><){Lq*J5C%5KKPJ?F(8WiY}@Wa6PiHle(2&< zLFpvuoT|XLNwAGLi-_63wZZ0oUXDLtOe?EJ8 zr9R<=wmrCF-3r&hsY@@(-kzu)vTUpK^dBt0oUs|kh%HG%0t!T)aLIq$;lLi;_?hzq z+d&`R$RCZToLJ0^4GgVg4_(#Iyt3SQv6t~a#|VYTJ62eN5704(%$Ex8)OqfcAW?VG zQon3g$F2^xkBuENr%s`?iD=i8ADpRTryH~fN5=8|$f;tw>(BguMH2&a;<&i~2n#Sw zz4F$EaH`mu`FwpvOhzWlL)p2vK6Y`XnHFC;5cJ=0D zW~)7W#<=vG+;%4>b0hDYJ@+=WJo&JBz5VkId3o!j)A#;D?&0%RFM{{*1$R67+t0S2 zk^TKo65q@BY6gctMi{>zfgLZw-BHjUK1JJUkmnyVg_?PeBt2s_$h__|hM)OG+2ToUs|k zh%MoP5)uSoN)HR))@<4paZ55)Nb`4P?h@6{PAul;MwTJ&Zi|jqIEwl{k-r!DfX6L1 z*xHO*3ws3jZw$H^uCUQFDDJ@YN1H-d$DS5CSKg13q7d!p{ijJ?*n_`QKfK$|LEjrB zE4fG8yq3MR+;-;Ottf_DqW6uJ^1y|`BrCa zhB0DGdyv!wBKJ&^Tz_`D=J9w9r!8T*zpb|j7QRDnya+5=AIJFTJ#$W<6pQn<+y={< zxu@?u_<<7lBVtq#Q8@`7Vum(eDBPu&8o;n-?`PhfUQIhMWgT`~`FG!QW#rQ2kQ%&l zLW%qQb1%!*NuDpgdtt8rgqw}vmSuHAZHRnykb`*i)ML%KvwYaagJap7W3_o|&G$BgH59d~`} zzRZ5!9IB<3Ba-;0H3!icG7VCT+#HWxOs-isD`Zc;(PB!8bL6rzLQXA5La?Wn<~!dt zzx|xQsD0myw%miK_U&rD?BR^fFh*?Y3X)Plq?-3;bzA0h-?j7imPzb+ZZfm;*Aypa z3j?#Y|4tq^6+Y_nH{auMS*_xU>)u;BKwHY8r?~NdD}o=S#H(%uKM#kG%O8G_lHf62 z?VuLV@N|*o!JW4wrhS||H)!s*YLs+Cl^RCym>cvw96tMBuv6TIcMYTGS$w^_TeUt$ z?LdB@2xriHtKTR$m?5Q`V?9VUO!$w}QA_POe|(FWbY%Clo2rUW)x({!8ODe$g@IBG z1UIoxx5zR$I{)R$TXVF_QvNq~)QEx05>vg9QY(|5_D)s z{aoh>6Q0^@M%^hN0%_tzD)cmBf!9TXkU$W`e_lS`(`{%lYWF=TJ9$prJJV&1rwvz{ zB(E@=awiZ+S#n|lQkqz;cVff2Ch?-JXQyq*YdaDUcX4HqGd9B*v85hJP=H9Q%PHL{ zBJ=9w?$}TGy^be;hAra^Cl+H9BNN_R{kx|c-F@ol^22PBxBN_b4gJ@UsRT%B5j<51 zU)x8-_Bz4!FBz74STt;zR$06zb^YhNXSYl~W9WdAh)zw0%|}ttbftR1GWZjb#DANs zCfV^`hv$?nK65(qB!7{67mh@9>M2qpQuAfwtqW)n@8b(OvFfz$+vSgiKR9DEj1gOM z10^2_zQH4tyZ`8)X4ja1TpJIax?uE-`7mfRu%Vf=B}Z*ru`!uLb~*5inyBgPPHN|0BmN_4hx^tu-oJJAZ5N@W7D^hs z!=?Fh<_2`Fg&_L}=voV`htMLA#5DGYZMkuc^PTa>y?H%?^=rAWUEhG5TFxTwe@00y zoKsi)`xMHmp?vYD*tyri@jM$81D&xM#)vIlK~f5cJXxOa|7+7d;~Q|fks zvXMvRkk{Pssp=in{Tr|GMa}Z%{E`=Gb+k3b|;DltM&PlN#P~t*H=H=wG{oW%*+zF00)#ppI-_3MlF*Y}` zw35sH`)5mo?!oO{1!>_k=kNzMwSZHOA+$wuHGuF{@$FUi3jV@wd|nan7y0s2TAY%Cp4EJl`=mQj|L z4PV!7@R!rB+}D`x6TmQ`vJz4!K~@U$eKbJKBVO;Ad~c`sjct1bPBI;{_!it%E}PMS zdZ6QQE?M9yMDY3|SgVCvDTGHMxBN#Id$PhoHRk9U|9skKH}w%tA=fW@&YfJa=VnE@ zRe9xBr_7)F9S?q=bjD^FBet{zNgW_ExcOYXa*9x=tlQhTt4C(4gl${C*@?y2!qQ^X zrpDWA=7sGN7S-Q%T78ml<7CS?l)lc*Rk->(#R@r3xtARYs1nr_u#`K0tL%r{1(fn+ zw6DV;c=HJ9eVsOs|2uwZ^~YX3;Nm9vu6v4em-`;%)N&KC{~xIZbN%9khKOBeexW7j zo3@4S-Pz1=EUYfX8Jl5@*wPg!oj|awjo-IpW_7Q=#<8!ecxsuxGq?H~==353!wR>1 zA**s1#Jg|W`$J-#-X8aZYUZGN2s&2FfPCov?Hlm1T7J|+@6%j%`bKY!K9_bt;JU<- z_3YR5-dUg|9O@J^w?9G0YLTw{8TbYaEsL2G|BgJ1&Rv#z>Cc|HSzL){b}BvCML6Ny zv3PkzuVJGW8&jam#_99o{{*a*H(__iW*8&3BnC+|AhIoKLHV!p!*T9+pBCumz57tU zB|6TD#niyUDB<(twY;+D)_hFkzmYDgas8b5^d{tm41)Ir5v%ENT(wL3h6L`(MW61y z`?{w0Ln&wHE`8Nb)+9BQghsm(>Yg@qA%h^|e6<1EkU(HEiJTIuo0so!yvU8-g|2l+ zByCFjQjJbqASbkY3pp5}Jzb;{>W+nJUC5O)<)tm9CQU2M^Nd;db$fhw#%35Jwj>Ek zVh}t%FS)U0D`SqBHJUu^G*X(njxt(w#dhl%LzAJz3m`Vx?gs!(`-1JO;r?LBSXKaQs zVoPq21Oy@*6`B&3?q3+Iv|?f8k3^m`5BK!DIHZlBLGw)1x2Zj~wI;5C*9)7Y5I zAV(bWyRO!foU+l-&O}ga&az9l-~ZuSa8+0xB^?Zz5=8LHPa#MU@GGSYLs)`*70_eV z1P$F_H!dRvY-riuvDMpf)xv**Q_K1)rm8s+N2Z@kh(|6#u&0Bk8fUouqgEunMhB0DGF%WNq$j!#>o1Uoj7p^zGv#8UGJ^OOIMv4=QrHPrvg#F^0 zc||?D_jb7py1jpXTz>w~`N-?(I6l;{!4JyPbb%j~#qZ}1KPXEed?WmzEWziD@Po1h z@~0}^V$<8Lw0M6&ozUTJHvO)WleU~dNm1~UMew;av`#|Ybx7dU8vN5t1J$shPs#E} z*2lyxob}Se=RIrhuzp=%mU-L~IYm9M!d9|8)wr*AK{_z_z^{VYzx;1XtgC8C_W0tA z%`ir6X%Cc^Ah>VVR{j1pZ+}ZA`h~hI^=tX^Us;~U?PP}O*Ja+ZMm&BoWnnSDj7cqT zTcvm1oWFERPA`K8rkzZm z37*HI`Y0)6fT}RT*Lz6Zmo&(#u-&ZJW*p<0zn*K`tf#ZO*IvpMyNPnKH}(|r`n5#S zll!aA{e1k|pswG@AX8EFwo8#SHp3XPr6o|>fMDTuS0oVl3342O;CwkND<10OR z`OSyZ{zR!uYY04!Y0XlA$N0-I`Pe|p(;6P$*OAp5rkvpw0EOd#n=@clbBCKJf)1NXsfHYQWZ zI01XX2{tARNZR845|R1HRPlf~gM=}Iw{pMFFYD8LMdqWVqT#ZB;sXb)$!y#M?K%nk zRfEn|2~x0r0>|w5EZeOG{TJ^lY`?hR-WkgWj-FvIfeyHazw*nVG z(5vJHzvRN#d=hh=^Mk54p8uYFdtG!x-|jeHx@nj2qAiYcD2eDx`+yAjQK_}_cEIYe zo452jnJtg4nXq!|t>lCsvu#Zrt`bf}Uv55l-YpdzJ;_O@ZsqlfC0`!)wrq2B#%35J zw&Vs%J`nt4bLx)=-bwX5-|jF5*m6jVy}hu&iN)N=z|c7~b*;M;N4&)`g(LTaHiz|y z?QDe1gF@;pfo1>Mn9Lw&YH^u;XJfK}mP+3?-JkI7Oj_jHA9>TvlO(U3sQuV;YT=Md zE#J<-mYHK4-Wj;m5-RaB>3L}EO5eQ2kFujKZx#L)>`FMbd}q&kn{+Y%@Vpltv#WM$ z@Uqx_;#TB$#%35JwsZwaDIoGd+4&=_CwA$Vzdr8Oc;}|~;nyL&PAo=-mKL=FckN1~ zxg#FzUEng)sA!JClMC~}MGmaR^Wy=$#l!H21>WM}*eVZi@o+bG!CO3>{49CN5xJ{a zH7k!QZp{6;M7~VZBlg#@OhrF_!CE}@86?!;WLWJo(RR7sqc#caR`sP8d*`C8Gsj+W z{q()*q;lP4{;IiB{Zq^;z30B?XWV+#8Jl5@*wPy){Xp>9dvW~xOGL_7bnkxjev9Ne zH_2jtCl(8HGvkgvPNlzRcDy|=rSPuy&f{LU>2>(D;#m*4UT@W{=Vz=R zvCRxEWcsrrd%+Rwm%}{e{C0r0l?7=zynJ#^RV4EZO(&Kc`=*}^{gBK$$uov<`SZKo z+U&~P+a`C+YFD28wIbO@PCtoJ#~GVpjM&l`B-Mb(r*TiUbzi3)n5}*7ru3tkxAi8+ z9YG!pq~r)19^FE0N6-jvJM7OWos{&`OzQ6q*_+Y}no}gx7ov_W)2{LJHvu{ri0ud( zq8mTNR%eKUh(5_ldAsA;Uc(6m;+|Ezg!=e2UM|V~NjN$Ez2+k2+Eo2jE_b%Ujm7Ie zbWOMs&$Zean_-OD5*{caLGUY=pP#v$cvn4-IazJG=5d_4^>Z%J5j5r|WeJu(PT#ip zUf8)-=y-UC@T15Qb8vNL2<^cCUk|^Vm6)651vlySii^LnV{Gt07JccFwNvwLV=jfC zD238!2cEzIY)BpW|0fX#ux+Z}$;!TcrRjr!6Git_qAp)Js+)v86$vrOz&r4NuVug8 z(|G8$aPS3Dzpu+TcDHv&JZW{tW*8&3^ae>mAabpQV&5K3J)cRjmzQqf75*2~(rn_y zVrgk)`SobX-%lnL;{Q};T-HTjY5wpfei191p#4N&xjxtQYzDlB;-JSbm z8PGzZx*oZVe#uAZ> zqDw0+OVwwdn0rHe*K*H2l^Ih5PpRQZAuNdVkN;ldpTXKBVe*RiRIb(cTSeR3RA)emve1QU)B z+k@XtwFzlyF?YUM^Cc(bG8mrD`M1Iun_-ODk{Bq-K=7W~fv^3FF1$Xm(DO-20e^Eo z<1|wz7E?oGi_{al7-pBhihe8Ax8m1Qg_+kR%hrI0fuN@i2yyIWV={wGQwX4*HgM%& zz^_0yE~any53v0Gp!N3M^v}ysQp=z$W`sB{W1KcH$ch<#xl*T}{WCB9P}C`kdbc6y za@I2?9I1tq57y!lVtepmVW`W-)l1dWyu8Z&rv5zfZOwrh&e#lN#FnlgDFsAcc0ZG> zvNh8Gmd2e=mQgP&qN~moLR!a=p+V$pHdz$D!ly_D6zpJAr2H$E!lp1`}kYcBgKB_o#}Ty2Ztr3Y8sG5A>}41%ThD}PQ%R!C&lczM)un*F5{#TWBX zPZ%DQX+nrs5L$W&%1(d|BJ(M$!5S%4@yLNl~=91PetDLbJ#)vKTK+*$n}IGvD9NIO@b=XlQO&{#p5S$&c`h+J5cp1&kKV%il055nQg2Fo-O~uZlc~ytKM@ zvZI@LL2-}sE!GO-O9$`yyP=dU!=%L`#BUE9M5fQ!O`6Y^qcw^fcsAaYX`Ul{_Bt)Lal zB=dj7b^otC`u;m;i>HN2+043@dHpx;Rxv&(kPVa5G5y3c8l;9J1tA>A4__Z2?d?2b`QZM{rfcg;zB@6S7#knGd-KA!hT=zNR{P>5L+avRhI3aS7fS*? zMew;Tp8pB(xh)~#z3{m$KJk8dvBX{~!OC4{A|x#u_Ah;=nHy&ogbsov|6lh%LE+k`Dw=n#0J`<-M41?KMwYY53^Fwem&z z++m+z$9{Xzuej@f2GaFWC>a2Bk=L+ zZH6uSY?r&2tT-F6kX5XY$8S3O`N5iUgv4Z^=i!syETVhLIep07BkOH-EN4tK*WE|X zt1XwVK)w-LNGut9%9;F7!gg|Ab@sw;$J&}%Gj)1IpSwC^GmH^i8iS-75NYcb8IvO-+8sw(;%7-;YfmR9RQKtM^TfOafJCjF1E(Bw@n_ z-CHP7bBvA27&1k{pzqJdWC}@Jd`4HHv22L_RvP}naI;zxMt;rWbP2W7zX#Oyj_+1mO1I2T?Thk6YM^Jf8#Qj zm#kTN(#N8OWWGVCxrByeLMuC^wazW)=Q2~Orj*>hXKP&KQhRvK??`#8 zeEE@#Bi+a^f%o5Jb8=kQMVue7^Q+EGf zO_F(T$fpeoj5i{>wiG$Bm|B=xw7Yd4$iDt`iOsQ}E0qQ71E+gtyW#4<2`SbR(}A1% z;xTL3>4sDNOvfTrz2Dv7YU5%-spbYz2acj3esYvk^ycv#?ij?9^l`9nwD!T~X?bP}<@$s=-WmjixhB0DGZ=m!8!MDBIY)DQjQ_bZB*pFC~#SAwCU{)VRxyfU6R$B;fBK~ zr6?bU&TRzajeBIjiQrr4O zmOxhP`UNtdoUs|kh%HS)QVEFc5M#Z@yW4_MLGtra(S(f*n@aCjI2~=WXJJ?{()|<%8Jk z&bX{~o`e1k72kK(Gj?B^nDkL+|AdL$C@BiwWfM|khmJsEJAY-g<-@=rhx28QD{^*Rpwr5n(WypRQoAPKz|V%*Z%!+&e#lN#Fl(O4u{}bPNF$% zp%qPLXC}=)GIjD?>1Tq$0lut6a`dva=A@B=1 zDeHHY$C{Vin8rUWs}WMr=tElE^?L2xZ5u%rngoxRXYT8H)^qL4;J>zmSxH7q4-|NnQ{zkSiUNY&p9vk9jO zogb&>2s^CVEc$DI=Jc<}FCRJ*tn%N(8Jl5@*isKDH9)Xn!%e5l3#T`|xNrVg`yZdz zql%qr;Dx2ekmC&m{_?UhnL<{7@gEK8h+I{Eg7MoPftIUQ*|lLk!46urDCvOYUXhUA zMK-8Y@a{Dxed#e7y`q6@>+)Sb8U1wmvKz{Br-C99;-=NN8)+h^1APW;ZC#xo+MAA6 zx^bAvsXFW|{VXQYnRro7!Wo-kjM!2PB;Y}0s8rzw{Tqk>i(EQik)6V{@%8l?naCqA ze8Q%%kr)1ObNI*$&zB_F$P1rGu70VSPjW)T=FD|A)1NMWS@_86k@iSQ9YO{-VIwc_ zOIZc6-FrvQ;gd(juTNipU}jhEmN{Ryd%j`0`*ofNa_TUY!=5^LJC-RX9sZ)a?^O9T zZI;pknc~$aoUs|kh%Fs~(gg(Xx#DnsOMc{WyC(jU1@kt_`%%q;fZxv83}eKWVjz(LB5&+faN77$K5cD$NRq3aUd+bUOTyrE z0BwA*f47G>KKQo0c=(bnSmDFFg}+|P^n4WZY6<`H`4&n#AbDV4$lMRs_!#61vuHZ7 z&vL`|@BPc-)xB?}6cp~S;^EcO;72YGkkWy9Eqq|#IM*i5HFT}>p+D-Hsb-~X!&ThA z{nT*AW*8&36az{D5ZpaafP*>V>t2gHIv#%mbo^JGv|8`PVrpbyKJm(;4vC%77x#Vk zS>C5pkSrZPtqPn%3?VZ=tXmw|m@FVAg^*ncNBWO`d9}Y8Du^%|GRg%`ir6X$cZgATo#5L3jU`neP{>X+BX3D=gOu)v*RSy4uAMR+)p!4VJ7Ax!!;3r=D`Z`P7>XtR*wIpf`ry~=Mb@5Qxh8XI zxkUZ_Cn|eT${cvzBV;`ZIuwgIc62mFF);9*pDqWALIwswiyDBet{$aR`XqRCBKT zH(T|OpiSM+5_9IKRNr2e=)_`bYG`tGNBt$Xj3ak{zrXRyRfKW3=7T9ektc}QSrp;t z19Ap-!#BV1Y2Joyei5=g1)Ct^I$K%cSMT@fAL}#IOy`6bx&d>RUwQ9?l7@zKy(MJ( z1Uf+^h-Eh>P3x`HwDzYUo20W z_v*xkH{9xh7p1G5u^GmQEwzDC4+O7Ylyf1@ao;Klp(oy#{$2R-+aylViN(Ug((K~z z{;>P|4=$Oz(bFndL0|-m)LdM)(2EFrYe*!mw&7tTN@$w z0VPEtdPWW!&{By?6GX$iXOzikVQJ)N>Jw`E_|B()eop?zjwnO4*i)24yI$dp`L(Ca zW##9;;hqxnyi6nPK(I45!x*upJxFQ-kq^Hlf6dl1V!qIKb;&%z<)vp|b_F;wo12-s zPFhfI`gq!fh0zz)E|xCZsC-dp4ss7%(EBL-HW9uKM???Y3A9`tGKs{YXN5Rvp!7By zlLchlm+#_y*uf}#9=U8xmXP)o@BX$l1H*$`WBtxayDI+pUs3Tc@!`9(DCvx5C6|y> zCA0@F*b@m|>nFfw0vq;io(($#_w9UWdrB}<6Sfwa$PJzYSaR(SU1R)JT=v%WrnBP5 zUru22hzWAWQTsW)hnHLq?FKe}o9Zeztm1p0bE)pP$qSqL)B2pT8ODe$MS@Zo1jppg zXNo9(lXlrb_V?|In;$seTxN4(F|sf*Ecx@wa6#sj(bBVu`k zkjn{J?I)-aE^Q%^;D0)KZ$|I6#BHp}hd*msoJL7QL%Rj#@(5b{VOt(S(>A%`>^Tnt z<$7jG2WU(yUBck^$?Y@BdUjW1cnb<84Slniqr~yYEY4cO;7XFq!sQc}Gu(E@W*8&3 z)CNgEAo51w#FfQM9!-fl^+8yu#?`h=mVbd0i?Nx3S;islG!ehEJ#9~n`qG+QXaDi; zy#yIdhD<<;vhzM$kZ^`jra;Yiv)>+CTKq;8Thy_)@tY#wy7eq~6caS&1d9~a&Lo`B ze53{Bqg-CpyyxPID!m)q$Y}WgXp+4%Hp3XPB}q^cgJAQ(OYWWqmOE4KUUF@n>?gYF zd+=T-784^QCXbT$ap>RTee6o<>$8ji}Mnc>{vzt<{H=VHDJMXhuoor)G0*+MS zX9#aW`$+Q}E!t3$lv4F;wwApb|DOf?zqczpV>65qTl#@G2}Dk*t~{gtRri%vS+np8 z`RA5J95P1-#5WUNgN#<>T z`*YgN#tTlHR03}5Px1*^vk|iD@v4^MfxUxN!^#*U>N6&%`irOEa?iA zP9V5H_xdO9Xg8hWPTARS#6i{Z9;> zTFf8|aD;*^;I|QjM;px{bEE=mx5_PU*>>t#$eG)AY_qPLwye>bXrhUdT1Lwj2BDxJ z=xxLT*-0{x$RJp@=+0SdxhZSfs#^kQ%FPzvsu1k=%EOUbf_mX)OF;ay+ZGiTlTSXM znCl_@zxAkE%JS6h&e#lN#FnlgjsubU?0c9mxQ1%ZYB=3~#qast`{uc^KV`DOdjO*~T?`30z6gh$qsyrK}O}m)7 z=<`qcC%g@7=JakZG*duML_#4A(1ZVls6CWOL9=BD6gj+0>Uv7%>mQ%DuI<=c^*u4Z zwW&sg6H&+|QHdM-l-T07>h?^NUwZtn*^Be%oSm^5#)vJsfszjd`$z{l%=xy@V%m8z z`-Rm;Pi|@2>wz!AGBY%Kzoqw4Yq(NF?T*WW;s29gru1LKk#NGf;iXT=rRvkKPZmV-#AcrR zz|-MzZjs*IV+zjL3}eKW#2`TnBLBrdS#Q+%hP^Ok#)qKgraWo~0}nW{7@C+G?RolY zdiL8tTXUJuEh+dq#eM%;#WyJJ-H0b&KIG}LJ1B?As?Pp&ojc^WKzqh^lvF|FXx~U1 zv=NH<2W{`-m@k#OV6gXMpSk>5tCN~d%JEb4HN9par;12L_@E6+s@TYud^jLx{jG=# zng8xSpCkCLWv#C>Hp3XPr5{jwfMC;?QxCE)msz*Nc(--s&#&%{o9!1mF_{~49N2jH z;L`VQ3==BMt}HlsD?F~v4!N@}6!nV+6BBGlAKd-x-rZz7=aW#tQuTVf)VvEQ$&7Y| zPqYxUvpv`+Cdev$Y+fCHyz@mp2k(Jdp;^uQzE7F);t`Hy7TtkV`264P;k-pJI|}4;^*x9KmE@eKbE|?CJt>*EJnsg7RLlr zxi5zE8I>jqtX|V?vAC$L!4ajQ9GeJlC=1Md&&C98C^IM<%_~$4Y*yWQ{n10_%1yQG z35(`^et?`>M%y?H3_`Khu!eH;c4$LckZ}XFP~!h_6t;*1zMoD=BVtC%5v^RsnJuNW z9gUxLhZ?ZXw(=&NT4J{?&C!`sBOqQj{ndxR>yG|OD6+RycE)BHBerw}N+%G!Ty0m| zi@8o2{CrEI{akyWZP~gWqTH62tfGHCM;g?|VS*lqEEL}l zKMt91`Fz+E1oL!n_;JXBA#b!i{Wv2iwC?QVRubAECrY>>!6TFbLM0L0iNEdp%$+Vj|DwADk0b1lvA6d*gqs zV!pZAbwa`O)w=92KCW7Vauj8fEWGW5l3HRvzueLEK`B68$oL^w{?5{@BC7^xY=$vn zOIMKK29d7=SmpE{^e?{sMbP`gz6UznnO<-^u~-@!8$A}-^`$|%e4#&YX-(eOc|W)4 z8rXr>`9M$Z5^((vKWXWV82sce-hw*#$z9C_6-CfKXbOOic# zmFe;B1?q(pU0!5fHA6{HL^g6LDSd=e1P1l$3$hwH^5Wj5Z6{yO()y?LOF<=S$s6bA zC~FUq(o;$T?SRU`p5R((gI?u46V_Q>k&V9(Zga+F7$dfn2TDm0JT3U>-Uph= z3i;NZVe_>QIR0h?HF8W1EX=d2pDk|=efsF_Sq+UH=~@$<3Y%1st1V(q@lSJmR zRL*WC@j~y7PJ8n9h)QMgJF%FU8yMVOpL~1H-H#4Z%_825otuld8_C}WCmd7Axk$J! zRujsoXJfK}s!33AD%ikdFk?q$q@8Bw^0nV9rcdbmi(KRkzmy}CF_XlL)yPUYdo6j@ zeg{SRZF_xczrxm+76;Fi6%kH384s*QHnyBf({rA%;kqHqc3r-!1(Iye*bHODmc~G7 z27)Je^Yt6LexJVX`lz; zwkv$*DmK`zaG@;FT@a84k3h<^E`9?`~bDxf0AtayvZ4xVT{<)6(psA$S&#G)g>FXZrG(OrJgWM-)~-D>jPRI zXlfW@;_&L^i}XWJv>(ipox7poZv*>N@DQLSbh;|%x$CL!rv3}l6LJeaT~787OR;Q0P!^AAf8&ZC9agi}SX3hT4Q#Ve=m z=KjoJd?xb$4~``XY?qv|8ODe${eaQ~1UoLbcMeiwk5)`8kGS>e@3n|CO@U4<7KUa9 zov*i^n)s(^$tkI4iW{?%e0OXykBemoQ!5g``Dr-*b${&dlo$s(nPw95L-+dmVU3t#f3}eKWt{^D|L>|^k zUl5lq(_N+Q!8+&8RfZ}rP6j7tb5rBp5j--*KC>$`uV3ZL{U>fJ+N*sVoLHbeY{7Y; z^NS%pY~J0%@E*2Mq4oqx?doi&cB@&kpD(y9h!nnhXcFqpcNFx9gbH1tJ#75rF~c&k zFn4lwrzu^W7_n4!QTEz}_Y9LY?&C--h4n~@h3i{k(bsiXS@>8EwS8*HT3meSy_YjK z!x*t8D^N0l;0H4CecqS8{9o#0)S1$GF0(#LTNQL9sD-J7)g2oX!HGwTEa!+ZaC~%@ z;68Z~+^~fXFqFX9QcNR&_;hbvOZ>w#~5ifA@;;l2K$O)%-2fU?%l5pg+_VO*=H!a;$UUBwZ zrif|G28$OuV>65qTM~mL8W4GQ=aP;uGq%Zn)NGz5px5SInW&ZN#A0G%Z0INHXn!E@ zuE~Ok zi8troNI(KrkoAisgvB%cjueDNR_oJ8Uia294j1gNpf;bpN&d|THT~K{S$KtL2QJ?%J0vs>t zJ#%6i z#2dI*rztG=I); z+NQu|DYSK(?KRfs{GVMhgwsUbrRJD8`8O7?<`jfBt_&@Wc&gj~d51GL!x*up9#Cq4 z;Dxtt$#2^+pHJugvq}ez;%Ie;jhRj?mga^g{;x$v{!R1y@%*d4_uZwpWSV_MB_JgW zWMo(HOD-FeF=VTzfI0&klPP53un^KBVxflBNQ;P1Rlcj+HPvu0+i#$DgX3l}CN6($H8ODe$xj_;Th}=Kp+B6x%i?2F$I-YXn@TW+%{5=9bf5`~4 z4wzr-EgO?1B&qO=C)LVn%Jr~|%~M>p?E&MtpXFz_=+7EW2cUpNoKcN``benh1Ga@$ zA$RlFEa(4`@FpblL(t-m{cWAwQSP0`UcofW|FAo2^|bxaRO_@G5n|RaW#!m<&N*W< zj1gOk0XZCk*UG+$s9JbYm-m!m*OPVXa~`MPl5%1(v@|gis(WA&d{}s|U+%BWe5a4u zn-?7ZjNBe(cVLCD|D@7pOQDt@bMJ{;*1lZ5=BdT2&;Oqm=D**5#DY!cL9L0dB>NhjH!0!zERO6S<-j5@#v~Pj8dRsew?yy+! zTRz5jMnER_vvb@H->=>(amHpCBeqlp@fe6S()j&GfLDK- zww(`in65Ul;nwC`vK(hPPDjq_YXMhVhR~KwXD=I*DRiM#wnyS>1x~Xk6L&SX*xXE7 z@%G)v_PcXNQwS)Cv5n#gbuNdl55~5U4y9idxXqQHYww}*%#DR58%6u#9wqNth$Dq` zUPDSD&nz~0`;`S>ZBY30=%P~vhxWB&zRuVTW5kx0Kn{ms6(!fNlU7VC`|mKH>l}OI ztCi2+x;e2J8(5g9F1X!sEVanQU<20=3xjU2(wIm~lyc_B19&+j)V&^F&fqy|;_u7W zN&E$W7CJ06>y((a{G3!^8cOe4h<1%&`qoL^C!ysGwR=)H>Li`cTfzU%JvR+cab`)= z>pM9^?;px?J*37DQYz|^an~u7R(ew1V#x8%Hi2)2&~4k;E6&&qW5kx;ASnn$p5GF; z@l{7(;EP=f>l!ZDZ@>SAVzH@5sn*v(;OYR*|4ENlTkN7*bU}bNN@`dXS#*OKEE^Yq= zzpX1oPB%!U$pmhENBoiAr5@g;$^91R&J>e~o%!ltWL^uo{8QS$c|GBDGa)O#x67fz zeUgcWe&#vFhdx2)3)CJsV>65qTMC1u84#&=`diMW+oc~K`93_ZXfAgw_NKE4xaKj0 zjO(&Qs)PtChU z`fi;}s~)XKPAh_=vjYr*SngfGw(&q{k~4H%SAgeE?x)_Bwni(lq$&08$wVc#O5P8Y1q}l!#gKqsTf$h^> zIZr38_{k1V6VL-g1aGc_?}Oy5Y=!TGM~#yS3l5(Q*P5 zsGPouu-WQq&Cq?2g6tn){TwWtvr);iov|6lh%NPi91g)NT2?Kx>}5Q+ASIw>yI@n& zl;Z`fKnD>Un@6?Z7jn?j&%e+4dL}fv08_3E`(vI^Knlb(0l)ql*Pj_o+ zt3;g6$!O=Bo4$P8FiJx+Hp1qMu-tY^>~Wq#no68>@E^}hv^5`>MGZnTXt6Sg|Hzrq=tVT{;P8zlXJ$l5}&M|S_dYwE0x z%V)NoHBFsEsmF=Q!uV>Uz+cs?YLm`HvAApJH=ma}m6r)FZ=m}Fgl64_?+-w`HO_po z`qH)gf;dv=SU0Ucm?xRbsyYcdt7nKMa!Yb2Mhez0$V!;KhBEi zQCfQUh$~$t7;!tya@d4pc*B3Qx*ztTl$F8ia*XBKH$8_M0&{JHsS%Fp8ytY5& zYIMeC7$df{1W6qrve>ayao(p>KUn)ds85wp>;HK9&ROJALl9|K5%1yeY_Pi~1yY{v z-+1ElHulg<>JxnZ)MEH|2j28Lj+`dw+?$!N2`e?Iv#V&}YMA0;k9q$BwfB_He)l`x zgOha=N0~cvnwX!0t%jK!u;kYK_%F+2)m|@oq`qTjXh8D%?T?(X8ODe$^?*_X1i#Zg z_It*5v+s?`%O<6tP%tT*s;UKUi@@e~kj7jY`4$l~<~o_#9gS%2H z5=%7~i+=rfp-}1c6=!UQF=9(qkaPkf=RLSz)0I;HC2s2KUk5bahXwBAI_ku1VqvVy z(JjtY@cD1awx9`ndk!1Qh0G5ICn7^ggO;@0S%em6KD+1Yve>zIm$l5aoosKm&YZd1 z?hbMiqW1J4od;+aH^CaTRGA(mVSv`VxapCA_5XFVH-3C@kk_R=Q8*pt&M2hfX7OeC z0PVsF-KS(+rc`W}+F$t5_0o*e>CpRfrf6Or#1*l^}tVUs5u5dwLxg< z8u+OVd`4H{r#A3i1MOFW4ASwRe$LDLsqbxa-`-0bRqn>vZJvIbb<0NN^hB2;Y3VW8 zQeE0LY3N-fnQY_k6%cmav8G32hRCzY*Efj0;>A%UA*H8f%ID9YJGg5~?6&3U+tgy- zx!;QuvT||8W*8&3lm|&mAhONcA;H(&Ry-<^?}GoFf;q>pRZ2Utn3)@zY9_tV=UG;) zeriL)R5#P5hpr#xyaP&4@Tq{=HxPG_t$)nMWCB?|#rJhL8jz#Mbv z{g>Fz0l~I_VZ@YB8t$j01G(0oI#GCR=7n65rwoqeJUCL+ic)w9wM=>Hk%nr8shKs> zbIp8pG=n`P^65qTiSy}3y2gIdUR&R1yv`ZZR^*xpW9f!IeuytXj8tag^@qE zTMTnm_~Sqw!D$t7zn1@N*@9fl38?IW-$5p{$`5e|nfi3t9b|%haj;uhxcCFqxfiTk zuzjD6n~tBc&Hfali3~)(ayNKY zbo8uoV9j!V-a!Yl{8h1}l@R$#l)mB35 ze%Cv2ZV_nx`sL!~S+9Cq_USjS)lH#Obv6`J$a+!OECiM-5l~iJ9eT;ADz#heYi^%p z72B%Y2kt%p_!377S?_|BLeAP|Kl!L4uwo zwf?q1!rrsy|7-r2dcIxpepQhZi?OMpMR)SlW!+DGTir5m)SKqG2+q1CRSnr|37Nwd z+9*rJX^hh*om|89^Xwbh_#L`or;mzDU%wIk64%@^HzyFy)J7{<(oPd3ArQXdK zo9(pBf62P-J02W}{fn}c2C1jE5pnreaAoD%{U4or1Z4;Z0iyI6T26G)BX_DVAl7SbHXhSfp}+ZhB0DG zd7zX8!954E!`m#U@!ga-6p)wK)x`fQl+}sF(!$96^tI}{e>X-ymEiB1kh9aMjrqjd z|Db{hdi1@})@AUc?*;2+;78vJR;0s^zUMIuT`IybtI?+5URJo%R-GyDlb-!prH!0$ zs53$>wDkaVZ3WUnpV)Te4xbU~^Gnxl;442kj!gnve`+`$1q>TgV$_vbqWn(gjt}fqx|K11Q!i+cH ze?65oJ~masGfF(}mLF}}}(h3&Z{u9<^AFZkwP}(@riuVQYK2$Fkn|Oxtz{9ys zdzJ{_!;wOEXu#Vzo6kx<{D0|rwd5MZsM<1_(jx9Bljr3*V>65qTUr984G0du=9iGO zYwBOc#Z}A?ewXP7hz30e6(CH|QzHbg2Cy+gMxr^-Zb6(H(U{5xJvBlwTy;{!_v-;i z0(#UsAGonDvdy1&`qCog)G?eZ9-&=~uu~(hFM^#KvC|EDY6OMb)pIZQ=A3RkR<`ZOSr~gZ;n%vt_d?nue zYL)oPXccE{hB0DGW1utx!N33KG*p=g2fh;HQ(@>n)EPf-=L%5Y$=qT!i$=G%@AW=` z;w>@)jOkZ|*(|4nQx5b1EaW4Bh4w|l4#48SJ%x?Q0+W#3x# z>~|yI`!(ML$trU86~p>Yq%X7}vaLI$5>Ano&ikXDJ9*c>zCTYjD*NW0u1?#Y!Q6F zs|UOV#T+uPz;$eYW99L}6>-`x+W$9)ne1}0-yw034LR=d&mRoG#)!~?Nzm#B>-IL{ z2V7jz3>g><*%?lh7O>2m9cIk_a0kk=Po(PRz*cx;WZzD^dq=W96kYkUs6_Q`T6jZD zXwO7;XKaQsVoN2UScl-+qkJr~%g(X1D{`wnF=~`<3)8c3Vlg){u$18p6Dg<(<(f0= z6z|08yIx4S{o9G$T;=(aglMiF>U(c+Tx11<-l6%ET5`i51dG_s50pYqA^58mp+hTR z&DGJ;fk6=Yf|TY@<`zAbIoSXiZE^{jPr}Pu|kAXMVhHnx+qqdIhO$IV$Mzz-&Qyh;%@&_{U8P+i#qa zNx1jV8Jl5@*wPp%%|LM8t01v+V)L(+nx}6R=6iqN^{I%w6N|Z-g@Il8?9<-4g1Vho zol0~A*`;Uy{K)`LIoKK`$6n!Rknpa`SUTy#k^7&wq&?5ss22LhYvy6H63%fJ+BZms zQo=dwsP>@xyzQOK-C3)9WOlLlJ!G^XoN$hNv2AU!K75h2Ha^U-jq&;XHBx1l%AK(p z#)vJ6K@ts!+;=R{TRB}r_m0V_%fWB2XMVhYMc9eO$kf7k`>`|YT2(FNl=nSd?X^YU zQswKLc;rcKo%V=2-JLsi<~lYvc74NFGRSG@WFLGS4yo`t?q#FK z)Sr81-I}7l&U&EdGxs0y)62~*{24` zMGSA;9U|t7!kX9ld|G>k6wR`0cEKs~L z=X3Gv^9L-?5c%5P)Td@^M`iJa`@gbMh=?Nr!Z zq4jqERA+34F=9(spmYMkJ+`lp_V3%RKBr8^H}l{({fUp>7lJRduzdO8-l1pR=J&Zh z+~b~j_k4L_HTwyqLV|9yMml0s==>J=R&2q>Q217C{+BH9t=K{}f!>u3Jc$eaxtw2> zXlzQIYvFce{aut)G+O2$-N`P5zps7%9CRx-f9pztupKMcDT&^>9C#qQO!w6N$fkA) z9I5DnB2t;tua?~XGjm;d(NP7X`6|CH1inwW?u^YaMr`Q~l7c|w_SZQXbC`?7*{7%d z-Ckq8#xC%*j}w!rq3jM@mpkk&S$E&fe#LkB^kv~Vwol*^2YU3T(8XWyqc;U*%iu?E z^2tbwY@fd3L(=6l`m9zwug}feIIGho6(y|<@)Aerk`VOhO+IBc=+T=3nLf~?H-!eS z#3{UJaL!Ep)a}`S=6YDT7%@K!@?}O&E0=uXB@Rkj+0s1qe;40Ez4o6G^Vu?G`x|(t z2RdUjj1gO^0;LiNp0QWK*6>&A`|BH@|21OmDBt%mM#YK6#MH#>Z2SkS^!3}G-Ow%9 zO1mc)ap3`@EQ#wGuBhQ!&v0bd$v~MP|45PF)(jh_>YL74`nwD{JrO;MLrItFiUU#W z8H9#Xm&!f+=dyg+r##!Z)JhV(87H(nCdCKbP%jK4)W-sr{wm7X&I%40j5xFHJbfXS_s0@)U8I}#~ zPrKjWJ1FmQ!DMaYjJy<#Oc0P1_KN&}xk-XHKqW(2< z3YpjJ^}KFgw9|(>AC)I@pB6gtG63Z`d88C_n-?jCga*#>^V|7`QS;l$U6l)UlXcG7 zCOKm>j1gN}0;LTI{?XrNRG-*)K$SN$yKl|5tGl}%Ee20Un?`rPYWex=)Kz_rPiihJ zTmF1=SRF>hz>LtHXYk2r!H_q)T+`<5Ev?n+*SWsRHs6XP{(SR2vWk|w3{)MM8S)8d zSBcpMzj%L>qf_=dmmi(~t)pqpS{x0PyKYDcXM;zINTa1_Wp<~A`ZU4Pk1uPxvz@US z#)vJ6K@ts!bWe%;U9GqELed(W;;pr}uJ5rbb#!7ev@kWxaJt6H9p#h!+QY_@yXMd; zwFd$A;BFFZVCKF&d|(Fc(zn&G?@wQ~wM5%!Zzg|*miwHaXCL4?zZd^nI&7)sz9np6 zChRD5wI$N_H@wTfhkR;js=K^zb)wM1fVuBuPkgG>eipwh7)NTkUxJicUTpkwy}I(U z+iT^xjBgSPAZ;ZV-b33g9r`nO7?%~9FH<{F>Hh@2)KcEG#NC~0DT6jxz%>y=442Q-rU z7t3w16tB{B#%35Jw$uX&6c8!$V#4tkr$1!L@Lv_{lHPQqsBGC%Cl(`PLxYID9~qrk zdcJ&MvryOe%hdDef{a`<@PoqD_8!zvQF&4GQXNvgj2}lRh$N|-IrF+{gv^p zx;^yg8eXN(C-*pGGmH^iS^}jF2%e<)x<=z~$EW_gx)T`|@o7YDE!yD3Vq$4*F*T-V z#q-+^e?5e@cZWIz>S?UEafNh(AmxeRqPg&UO@y8{!|yfWJ8Q|tWCmHg%_Hdrzt^Np zY1N0XS=$3QDzgd6^l}}qoL*FSQtm8Pi+Izv^EQix z+U=dO8ODe$xj`ZbM4DK=c$Bjs~uOfwLs5y6$-LIob4Le4L{pe=#49vX-m$pto)W+Tcc&(y<_8l zeek+Ga@j)kV9aptCB2Dt1fVCRLGtN`;xVx$ihtUlc6kYpzWi&wAT&C-}4F_o6++YCAGXO#+6$B_sm_|uyUi~5vdKU zKY6V``cP_)=4fgG1vn4l-r9G)q^FjiA9L2^PJQVra$dQpG45b17j z_fXTl%xObfe#5D4OJXxl8HqWun3x%xtWciC9NqG|_j_IJmSwyDJKS3>Yzpp6!Om(V z;vO!cPv?>E;i{V}@|ERrpt|B;|2f`oSOV9EXR9KoqG3}*eR?Sh3S0&TL1TRPaABP; zAg9d9f3~ zweeREXKaQsVoPrjFM>$#`BQ#s<^OtD{n6EUUHTkZ%e>v&omfmwOiY?Z7Edm)a&x+) z9W8L5$Mo%`PswYL%N$(y7YKb7-EwlehxPQ@pu6?Ie&-#I$uHe%YKWX#C~EzF)rXcj z1nw^wj;&wLa6a##itTy=Ui-3--~Lu3u=V0h!l~tJmfD;svmZyU#9z3kc~sWt!PHa2 z8ylUm8ODe$U4haG1T#L-dYRoeGem;bar#2T6W(6!K3knw%uLM;_KU3G3Y{#*cK!dG zH#}EfNbfCbT#lyjhvcd;aQ+-aW$S;Dwx?=u-N8kA?QV1=vhry(wx>R?@rl5qQ2${KTfeFH4g+ zgaqHn`D$l=iNukfzVCvUK3}tpirf4jwe5Lkb!qjvpJm_GH5q4LcE)BHBes+WNlPGd z->rqy*?*Xw*LviAuhzGt>ufsPE%3OoDP%zm%Y$ibOlFXS6&V=3mDJ^<-B|4^>$Z5c zORw4P>b;i95jhHT9S)=^O%OPBBa{PO(&pM=xF z&qF2?r{9v?)#$Qp!k05a3l864nDN@$8Jl5@*isBA1wgRf+#_pvPh8!#OVxjR>)OCQ z3989c!0EsUGP29|y^xK`98w;zWtLBUS>!hDs>AxCgd?B!xa|1gc#1I&IUS6Q@<8bK zZ0H#bRBMean`|RLuSoOCpTB!vEoXIp%;U8ZS33B83SJ)kJS4r`#xJ`4*^aD=Zx`&} zOuxHI>|U8OHp3XPr5H#W0Fh$*xNNS~Bvdj8xIUG!h~G0)q`%FH#nRZ=!m~a3Mdkzn zfAi|Y(Z9s5oqfc#_zHNdv@s-w2>o6B@^|Tid1c4EmN|AWIO!U?Vr{DxJ94TRiai~n zzk3IMN$%`#DLI~AY=Mk1Q8U!mw-$EKRYuuS^!EY0r-PCzcFAR(_ImK?$onU+RGJYOCQC><@YVzB?!@U=Zm{n85?7^toeO@M9zU zt&jWD(}R1j%DqURDtg)(n_-ODQY0jefyjAJqZP=CdIA|!73`s&3Wn7(xOJWA=lR| zK5dPhTIgFU2{Tzk+pdE6Z^Xbm{xT>^rO7*$#houtl(Mw5R7m_&SX9-(y9=q!BFt0< zE0s`FOT>vYOi!#O&VAEJ-FtO+nmp6l=ZenQ3}eKWu0ZJof>%v=SfF_6P0e}z%cmY# z$W51 z>J$O9`iwUr@#X%JRsWr_8ODe$T|rU`h;+OBbnb(ytTovR6^Emi9L!?A$omGx6K1Q0Z)6i( z@@VRlIl=YJE~me7^zg^w1TyGgxOx@&kCC+V_>kPp7-jf2T@O0#|2jhB0DGSDp|d&hg4SF1HjaOqQKXKaQsVoPF>L<1rdd6qY13E0Ir z+5W5Fy6UB(?OnCopgk!@CaTv?EGTh1%<<~bb(aQ7Q^r+NCKaHB!-W4lB4Pe2_?{G@ zG`B@B`2(z{>PcTyvQSyO%h5dedABQa!XdWA5$2x)+mnJ=n@6+u&JZYZtRjtto?O_j zVd$V?tW>Z6XV01ZyMz-C|E+AE%%9asTi%K}JbRKKbL;Yh-)mKzu^GmQEs24W39jf!c+#9C?zH8dPkPry{qSSt8Zp zt!6><-|$wmKyVnm)hyTrs>2|+7zhh)-h6zO<0a4KDV48p1b*mrcUsrsiE_g>oqOs- zy6+_{coy1f7T~#aV6_bM?b5&JEpjH@y5~A;M}>#t1>{sDqyX=GAr(LTx8m<)U)aKz zU-+l*ob~eEpMtN+)`~l0GmH^idV{1O5LtQtaCN}D+hTF^q!03#|2(ke=WQk@784^& zgZQ}&o8MpFR~3D8ZQ3t!g%m!9-ucL*%EH1wJ-o8|Pdxls9QdVJ^3vJ4FH4_Qpv+|t z#Y#z7L>M-zjMylNckYn}ZQqj@l?~T!UlN@;>E>qkM6nx_cD}uiBUOl)!7C;HTlT&$ zbN@}fpL>C&T>n8@?6cojZyj{TW*8&3^aDx{5UkMpJX~~(io$Bs`wN|R`t}}<_p@_i zF*md@43^Azq-gcy?E}VS&f5{jkCrcdR|Tn*Ajh&Iof9rB#*gEi@EMQR&EpGk``5rb zzoNtY{=dE7|67ifI!Rbeld9*0qx8YQ^h(?)Irj1GoZ0(MpPv2lKw-5kKjCyEmN!9$ z_t#3R4aRM;Rkhlt-=iy<7?qr{8ODe$g+bB`i1f3*lpNH(_SZATncLRH@2lDJLiUXl zi=nBRr9G44pOqVetxC59%n`d8E!MMzZ4sbJVdwNiB3;r6)Wn>mFf=MCh7MLG}+apr~MA5Q_LG3t{n{pDqVs zq0~LkYK#w0GJSp4?o#>YXSU*IE50YmA*U9JIqxvopSPP$ znI+<`73hr3Fh*?Y3gQqDsWHtVRqfV|tUTU`a*H!hKFGIiJ`UOwXKd*8Hd?LBLHpy& zn~&oIKRPk4SQNJfX~afYs+7=*89XC4asmAciof*4g$sAzi&?u{am&t^Ymw6vU1}|< zeyWbx42oJy$LaK2fhmT|4t3=$6nLu2X?N1z8%KJQdIPVu#PVLZ?roZw|5mfm;Fg$9 zHc!HWT15+IY=$vnOL?G_1i{bOeF{Ee9Uzykls-lGfBZfvqv>kMQ=aS&tZYn1kUewk z_pRBOOpL%9g=FrqF_}PC(lFb~vN4%J>N5UAui2O^AggV7bPHh@19G3zhfjG5wftx| zk^H`|>hFo>`@q@8G*rh)7Pd*6Fexvu9*0vez;3#n9W8npkthK&TaZw)c-WZ$fMjHH#yL5NWn)A&Wn_-OD(h@jvfC;Nh z>S3OJ4`%QGqq$7|Ns^w-N(Ft;0%1dwsJKg7KYXfBaT)Wh;n>0cQmc{Y4Y;{u3Mq29 zowu}wx$dGo^4^}6!<;c0^u9s_iPJ3XN2FgEs#I; zz|zv?jxVPLi-o0bXqhj-bKUYN4@!!HH=u=;>qy=0P4YIEVbp-u7kMRT$`PpjE+c5w zo^6Ykw45+BMNU!5ci|0ar1D3xd(-=xxMZ$1pSZ91JS%K6niYKW^*m>6hB0DGd*H+b zCWI#z{<_}tyObm8;>?qblPCAQXPD^3Vr*n?x?@e$2ER{*8I}t&4vFaaA5arc-i%yB z39D{{FB%ox?ZoWPZeT55_UFh=m&~+W9<^=v?{JU26e6s80a`-|9%6>xq{8W&C(lS|6@-fns!Q`ed{FB@3ijWzBFh5(|IRO z?Q+Iu7$df{1aUBk)VU+Gd7*awijCpI!gmfa{7RZ9@zjaM)Y!zp(#v`lqr-8(i)^!v zWW7I~ku@lgh71xz8py)xH%L5G;&d8EVMk$voS}0-*KJidom-DWQDz#1)jvTGl^D*& z3=I-d-4BL%{>}bBO^o_e)~VhrxjiX;2XZl^;etI8^|)$xNi6vEWcRV)D6xcI^;7pe zlAN&_#)vJsfszjdFP@NgP9edso?Cb6ZKD$$?g2}W-E?BHurMUWt_U+d3)^3;7+=W}h|xt_hCOOFjr%$DxS ze&i6MvZq`m_EHOjk3jsImLtfiMF_`EU11&XWowqa;QEwS*HE`}rOJWj9n=0@s)OqC2OjiFvCdrxu+B*vb~IqD{8X z%Gx*?tx_3pJTZ$s5n(JDbi)~&VT{<)6)2rRa6`ZA9;2pt8#ghOx@-TgP4df)WN~6K zH!wC|b<@{r+O(J1-1TMGRF!?}&(`kh;7?0b6;Z zcaDAb#AykJJJkgQ43_6VdHTQk;-RO`*bHODmX<(i1A^DB>T1`W`!cJhzg|G(Z=Sbc z>&NR(%;rW0Ze~)}Olq(1EnLdxp8n~~hSu+AY{3(krjSt>&UG)@n9LxfGXiEC*qAIJ zY+<95Y)lpqHG;-PP3zBa`^Kn+X38EvvV7J3)m>+gbs{I6;Wv38Z1hMB61GC+r=e4q zG#Ja9B$t>xpTBsz(2sYE&IGSIRTj5B8b`u0)`XAc>76@rq0ZQt^V&?y8~cB6e4st~ z=7mI2XKaQsVoPEWkAcYZJu%xIuXqK!?bKP3di{)I#>agE$mv7yw;DWs2woP0rw^fw zdPMqAe)1y0N%{1S8*}z0zV6fi)%P%RCjUz0^fCOZ9$`}^X!@Y(Y(Sg9j+P(%Z>Qgk z>1WnVo{=jiI@^|T`Y`p(mA@)qy5`N#(ua4>Op-Bvw7Zwx*cqE)jM!2VC}lwKL^j>B z1LwD@U#h6TT^d|@GB^F%IwuwjOA~{geF4&2qd8QY%A)tr7wEQj4S9DRT=hT?@Dw&z zLO#Ir-mlJw>q~?eUOIiusHJMd@@Up8y_BU8VRIYk0iJ`iaYCmQ^3YRxk^<9Z#ndAl z710~^&p3KgL7H$1G0$G+KZQmAr)k@zSKAJhojzY;Z3wJI^K6#gUB}?cv4RAUzgfu|}`}*0K%pqGP*`MxI@H=bNUSufAA@=l8-sZ+^ zi`VmhAg2TTO%P#A7Z#AE3=Be8&fpvwT^bxskb6&72J76pVZJ4xIod-oxOV z>-&P&O@j~5VEvKn#A0S?X8ydXSGfJbng5|0`(nGwoacY+z1<7$(m?N25_lZ}zf(!r z+6R88l0f0}M_1oWO>+FBxNF^xSzA&(V*Ohm@gt{}!QSo=woZd>9AK${9`AsE(E^>? z9owsJY(7@F!#}!p<@aAJ+9g=_mYu_qTC5T4zs<8#DrNjEgb$hXSERJCPv%*6r#Cgo z8Jl5@*wPg!oj|a~va&m8Z1(=-+WK@;osWXo*1kJ)omfl_jSW8NJ(|d*^5PG7%GzRu zHMjU%_t-uGw@9GtzXd;;z%PpwwylEQM=P+KAHM#Zd!BpZT#jmkn7nynJ*Q5TT?&(u zWLt`IA1$%PjIb?y{kPslSamZZMow@PGt7!d`c(gOJ=vZ*XQA<$YXw*LaoZy&9NSy) zVg@DQyg7OB+Mk}Qc?9?WIr~;Yf%o^hrT;P|ceXfV zGmH^i5`zRShzv}*YBB3-Z2K(J3nzX#?JG$V`ke@_g`fj#JPC8)YZExtQ{V$@{DxT@ zDi7AZHCS`-?DGqqiUnr9Co-M22-QNuj&EQCYukUq+AIUKl4a1=Lhc5$USziG20wH6 zjh?e?nxmx`Gs@;!q{75W9p3wO5RMP_@F|bF{h+O7=6A-If2|I?O{j9lW*8&3)B{Ql z5WFI{jcML2r`;<5T|Zc?ar$GVVQ)jN6$tF2$IH*ImN{G!I7wzBubWO4fBn}_ub7b2 z4N@iK!ho>?0nyeSt%MjDP?qpUm|OLK-K3?+^H5i0XUUuki|(I{KrTyM;^CDLO1kNl zt1imV6_F0@O%%GJ!oP02y8TpVY=$vnOJR^S10r+nUQ6j5IX&TZ`)UEEx7j-wH?Ml= z#B641w2XK9_j&xeQ+eLD8Ps#IoEF?X3FTA}0X8W%CKJebtgxE}{CseJ;~7g0AH5g9 zu>}n-%k{E&pJvV49gTHp3XPB`Z)ef#9XvI5Z<- ze}x2}R@^cDY|ZMjTNmDdIz|>|eXH)K%ygGee6ltrAi~oBOk@0MBgkR|$m&~m7DYBD zV+flQbUwH-q)W}Gd7F(9vT{z?BbAL2vTj#sab}zQe#tFCXRme7Jn(oK^P~Mw4nMv) zeA1AxN4*FnNQK}#ljzi4YL~MtyZ`&L*2Dj7lMLtGUGXnKdM}PN%=C(^@r}6xqNu^=&vLn)Bm4Z$Vo^*We+?F39a&DV}d0i_37{=BvcFXt#fby$->W&_Y}2vA%R_{}wVdMDZPGX-jpz>3GC! zfuH*E_*BA4$Xj?_-r8$kn^Yablup{(I&$*tJ$l#I8Jl5@*b*Bk@j$S5!uc$=4_tev zsKm!^d|R;Z{{&SLCl+%PL*w!#amxi1jEnkD?Dpi`Z?esBYMdsxWenYc)N?1$Shdmb9wsD<;<4?E=`#5gm7x{b)3VyL`0ZjE_e7= zwU~9+-rvuQp8DPyn_-OD(iORW-@- zYeV#mSD9h|CVXanu)_NEGf+312|A;QYsN^}Uy2Prqp193gUe6Dr5|F;ZUiRvGiSCQ z=}}JT80IO*--N^&BVlq<&dOCk1EYPGp7-lJt>P-y@Pl1DxR`Lt@vruK?`?HLE#KvB z9&>2z&&%xb_Iwgjv_!9?Sh&lIXF@x$`eL@f)N+(}nnI_KqsBYSvv{f&Jdzo(*rMSv4I;RJ4hcdC%uIR4eP z_Bu;4jia?#w2!VidP{cyj$3B~ov|6lh%Jdhq5wqZ&ziM6P2#B~;{%<rMZG%a^XvJ1=Jbf_q_>)q`~id<37O)zwhlqRh^B#!oN@3RLyyud|Uo(`+8Vi zs0byg1ouLh<_f_t=n}@eAZjp;Yx6__ZuP{xO@3?TxSg>X#)vIZff5M>uX3!_nG|v0h$RqioGF_|fvuFX|$8XX5~-8oTfZyE=nZe|X-1o?;r9!I+x^y{lq-lO|MCi-nl>g9!rHD?Q^D4NF`&6nccS+Uv~n_-OD(h?|b zK=6epSGG-U+>y2I@OIbv%3D{5-k9+Qv@F-iViyPNrTwZ4V=nEQ?%uFY|FkRDPVjMN zOooub7lz60Y>beR8vcNp@B=`EqXgI(A*<+w<(!bB&=PIvLy zeL2%(mbYs9C+1VlJD8R@V>65qTMC1u84!7E&cf(5){E?J?YnIJ?d;BtfA+C<^vlbBlTS`#Tjh++Fh*=i43uObc=F>=qZfy2m#fugvD+@V$$3j~ z$y+BDLqk&&&ia$rmtGQ0KWO-sO(dy!b0W*p2jD6Rx~xh#t`T`z)ukzV{||lN-IIQE zlff&lF0VN2TL(~52>vQ5ZZ>p^Qh2mVLY->T4qlORqS#|&#MUd30&enuzD(bS(kqHP z1+S8jik6ra{nhO)e`^*>>t(90J#gwkf?rZ^moqlQ7_p@#Na_HQ>d_lZ`J#;KcPe%M zQEh#?=2+)GJ6!32D^Fu#X10zF`@`9Hq+t)p@osd*K^>~E)$(WSS zpw1AJ5oDfGkcS7cjsDU{_%?bW)wl3%^t?^H@NM+MNvjdt=oy#AFOxo;>7f+jce2%B z($-f8T=nZ7p_DA}?vQZOQRpN#)=uT3ILSc-p^?38Kzenx0NOQ;ax z6qT&P=)0atr0~wVC(VyNelw~%NW5G8)ES#$jM&m1BsGD^g%=GAT(tXw)lO?HzZUk> z?PaRGJ?IEl1GC${3`VJ3>tY}7iC88cpKTr?AlCtIv=~7;&%!Bx*_ezVcP|NvF|jcj zL;Bt9ue8~iEFl|61U_Ev)iC=#G0Ql6f$zDj_B9Oi@?+L9qNE)BbrN06BH>hVeo&w= zFbGlko(oELFXC8($GD~_F46Jh%IA7Uq4yTN;_0rHLB4%QI5iGiS(L1DygDv!!W6HU z7jE^2EIHu5s_cfuL}zS@7w>!yxcE)BHBet{zaR`X~EOvZf+q|M>uclnBF#fz{%`(1qqE0N9 zW)_AnQOmDrbS^FbQz5K4BkG~qzYCE!sC8PIaAqWq)5>n=ru?ukXLiUx?iiGId#;Po zVKxDjghsncEVCGTTG_DdK)p-LyT|fbL{wz?G0*R>Up=bb?{*8h62qR*GGB@;vYEDb z-m}QPmsgd}pB{Jo$Ry8$&e#lN#FivMNeqIolm+l8T||pygA_gjqCxOW2^bRJNNnB}J+G%q=vK?qn;#dSyP|at7@VUq!r6zQ zmlEJ#a5aFVF$aXFO!e4&J6C)8*_k=w;#CH7#h>Fy6WM>^qcNE;^Qztyu%Dj3IArSF zq*MF02Yiq_nC6VlFh*>t2a+B@q~KX+o^#dfQ>1>eERadLmF!{PwE@&1hRzNMELjhm z9T2QYhtCf1b1}g$o)u{S3ZESSv!NHy3iuuDOwGGAIUIC8#UOgtf-Ps{)RcT7G+87@Hp-o)5AAs%`4&Y2abI+G?HxW>OZ_!B{U zy~N_oPnB*BKT@2r8ODe$T|oi>L~1Y_?K9lAQ#SO5Vp_oFS5w#IsJ(Myu{1O?%WTNm zbEeW#eXs6R#Royj(@IKrPlU8aAe~~qmDk~WOoU4i=U)ou_Dkr7C|V^=)qA{WX@~m7 z%4J(BW4;qgEy5+R^Dl)5yj~f!sb%q_HZJuC+scd0?@!@!xsvoIVds40)Kb!oJ+<&} zIQ=ko$&%)IHyx6`98*cGR*SmjjLk4cZ0QP=P9V5j;nw5x=2yK-I0C->Dw<%y$8uZC ziN)O9%tUemUp@C(KPiVo?^`@hiGJn|SrThMz4`?^l zOnms*@2A8Nm_4L=d$p_%dRigXuDE9U@#Dv#-F`ZM_r0k*sgN?WL3oA|jucY17OB0O z(J}4a8u!~P86!#`Z0Y4N%`uE+bjD^FBet{zj$$xT7VEO|-nG*FZ?<_6v+qVe5ciRO z<-}rUYGNXq@??@s$yvQsbsIAON^*Kxlz51NQwVGlsGU$t&VKUvv)ES#$jM&l=IB|f9##y?bpJw&5T#F2uZKrcC zH=*RkInX8OCPr^>??}Dy*gjCxK;+RULvZnxp!7|L`6vaoDrEcVR^5o{ChvJNt8X+O++VMLD1Wdm^e9 z$=km9YWnZH*Al*~zjrWM?N{&mm(v-WVT{<48#w)d3GpVbgMTwNsXA;~o}>K zT=O;Mu8UMcRkvR_A9lUp@%E;NA3mZa8!UtUNbQ#)UG@mqvccB2z|Yd9T5H#8jmsjF zc3J|dcdT=vv@V=H^AMN0NDitgjhzQ`a{dw11@YeFGXlixdIGmH^i z0t2TQFp#fnRvqCf9$(5h@t1Xorls35fa|Z#$*baniQ^AVPmp@jLxx_N^k{j+$wT} z=l(X`Ych*hYVV1!^Sm=0(~xkz4Rr63;G>(cJpr^#L;KTI3@37L5<5^_Kh0dWRpa~a zX-ARMP<=o4G^Fu=;+ykZWR|5}+jw_lrN{2qYyNC-#%35Jw$uhrK49XKO&q^rTKn50 z;lclyR>rM6XR@Fe+%JOeFk1%v(YTlcc8Er`i1;JL=yq0nk8+0Xp?~?0Ireolc{^h>j1gPv z0VfAAq2-q4q7xhGR~kP5%mIUrYHQiQXPsCq4a|);?%H|aZB5io$u~`kld9Ntw~I{* zLTU9j*T7r7LWlay^fsC+OZ~5yAu`QM?Cz18e~Ts0p_CeU8!W=j(_pP$(ibQU?*>a= zYq~U>MQLk@fAyTRjGfJUOR`J|r;z5O{a@#Nyr$s+>xQB$hQDr^{dUG?7$df{ z1Wp`aV#zNHkHvCEPh3RYYsCFVqsyB#<1Y%g>%72rrRC7EZ;M8(Rcq@ zQpl5tg7*a3U{@XqaCpG4JQ8l52fy-2i191p%A;mA_?1UOl`mnFh`hnG;a46pOuxRV zltXLEY)vHr@qWFx1-=VUMcKYbNoX`{;t03yfK4J&F!WDs_loY-6aT)=t!C_#R%<`= z5pq*IQd|7@Vij^iYtw^QPe?^k^U)<&H}zDuFG;+bB);(6zq$z?vDUwxu^GmQElGmY z7?{}gDR>iqr?C6-A3~Z22D8;~%UPH@u^1W~8C-2#rx(2b)cifEH#C+sd;i*E5!(%F z8pDdi4tB(uLiI9iOqP(g4|rb55>kipn1y=33AX;N;diRPBKYXSc{`_X{4Ma1`Uyw4 zLlJtWkicFK*qK7ZJK^~M*ZX+OVAl75%E*m;zEh_?j$3seIpK7qV^27_4{CDV4_LUR zd7kU|`mgWV)iR!y&e#lN#FoUsX$DN#CB7@t+nbdt-unFUMsKOpUcUQFomfl^P0VJy z{gB=FJ+4B3?VWE1&p($u7x=3KZt+0prG>j35cAU055niAg#x&K2|Ye}R5u+uZy@w@GIZX6Unw1Wz3c$)KXP{0E#a8eTPJdB z`pM^4TuvEF?p#SYwRBCjJ{;7$SJ>U~h}c|{cOGV|{0(n)Ib$=75nH+fCloMIH0efa zcHnXCl6fJ&XR%qmY|?tU#finj+}t?X-Rq&h&dVM34-(ehcz?$z@a3d_aEr$j(ti@} z$zx+OgDk#dVDPTq@o$E}2D3@7x)+6Ky}cx4(eD*8G*gIhPsd63I`~ku#q-VR2*6aJy?~8j)k56QLA$>Qo)i^!d^9)L~wq4TOEK#=Wf9sAj$%o{>A9TiM7$df{ z1Wp`af<@=-v1|N$T5cZPV41aH**)_o;%QFI78XXK%Y_c+TfXF}j&+pSZY>nA@qkGI zoIs#k7=qCoU+gx8gObIjmd0iDHfskIwOgIhO!U(^I zMi|>Mhm>@huv9XGtO)U45>S!#mz(jXY2BTw8Nf2Cj3fxzQ2Uw@VD&@ zr-O`jWESL!zu&Rn8Jl5@*pd=BZGee)$6AsWyQ#0)@p|gT@{3dSkA`>@fLg4?Z&YNP zeNkiA&CT;w?PtrspSdAm~U^V80R zjD&l|PmaIFQG866fDgJ%_{9)5`{ldG;j2Cw&pG1|cWvhKW7~P1u^GmQEggXq2AEi- ze`-}h%)VdWO!g_<{#t&~{!?=&XrYUtx&EqE#bF27oPBfG-n^fZIxXU8=EzTHetR0$+EYEQ_j>NwaC?S)f1y1g}=Nmq}rIV-%NcjKJNf4Gp72eAc<@N{kHMphwnKWMchbl(zs zp%t-r0uy`4A(hrJ(6V5;H*LrB-bZVWzFocW=8uN=*5=4hAy;ftw3YpshW zS_cId9*eHF6THfMqimVO24`%BF=9(d;FJL-WH!o&6mq539uoQ)an>wMeS5skG|;I( z#^wzl)y?N`+p}km?)+^3eSA^6Jhi3Zo-pjPyqR9`%kl)?gRU!rY$g)c@jh*BXW4gI zYVqURw-xHQ&DGEUT0IRpwP0IoOZ1%L%oJE^8P4M-*juqH+|=LO-0}>4xq$1=r{~E( zCN4Tvj+|O%&WE>RQBn(=3b)qLH7@gWP3IXe*yjIX!@bhW&e#lN#FnnW2?b0Xd$)?! z^3{@a#`kwV+4An;`2(lFJ$GU@wJ_lbEDF4L=3mmgRm@ck`<`xFXJYk%1_Qgovn!AX zcDKFIvGd=Pnf*CIh>f|iwR&09PFXsov)L1e$G|T3be7(wEx0d!nyAoj`+9>NS1Sto z_n_QOGKU>|I=djprp$T%2eW0|LXU@A?RPU>I&#e!n_-ODQY1Kufr(wNx{D4UU^-V@ z$$D>9Z4U$gu^+Oa!{Uw1Wq$wLlya-&!P?i0UY(IOl>9TtkQ>}xGK8$u=n$s*-g+O!tq)H@>Zt1YWa!MY+9Z;F~qVbAR!H{md|=nl)E;2+jTa^1<3^ zvul4#@!tIRL;dDY-}X2bDU z7b6qAQ3??1w0ajXK?nGS5SIoJ*_$4s$%Ad#7t;{7w~FGs|11=i@F`f=ETTg=c`Wc) z^XA>>%6klt7qL~FT@YKFKRs{89A|8XF=9(dpo9UzhJW{++p@WJ!GX9=ZOha^gPU_j zJ~^>ini!i++qE^uw1(^WI^`P*`()jgZ!%JC1}}dxgbvv*QiLD83trLyJ9rn@+0B{a zv7F@*UCB~Q)~{LZHeYVqqFcPkX=sQyjTc$N4&KFbcC#=oo5n0}i(gHB_wmWxD}s9s zIA>ev>uf?f;{~aRS%f(Mdx6K4Nhd1a9BA30c~Sao%jc_K5AHtI>x|7XMr^4Kl72vB z#kS{H8zu|p9w|-w@v-;$1ShVbeNHSUW@csw+W+~k@a^3-{cyB>$a2f*7p?zlY0=tQ zl8W5gVOb|v@#3-8Hwl-yb_X_O_bG){Ss^Dh8n&vJ)DP#@j-veTxg7V`u`Km_a7{`i z?4`uEow3M;)snC9)(%QS`%wL{bNQe4b5}R*6UyITdAzIBCCM3^VT{<4Bq)hN@YB_? ztJ*uu+Y%?Y@@?S}+4goJLj!1AzJ*z)=!aS7In5Y$KG9n1!)@63aKWrc;650ET};Bu z&b^8VJHz95?^T^}pX$wImk0KNstrRbwJdu9osGo5i;0Gd92`hvhh@_(j($DGid?m^)q23I zHsKY2;AhGUDA>WyloxV20XtJ(XvXw4v2Cse!RvO)%{qPAPFkdV;c7ma;gg1hSBgQa zHoB*wg%;MqL8_YP_-%w&2duEVy+?n+59Bno60!aPrNqfz&A*d(X|hX}NTtSh8~$k% zZ+EmhV>65qTWSNP9td7={Pce5FW;hydcHPHv%bab+<9poxLkpa?P$ru$96y`Br;h- z#&(3hiUxk({yWRwT_9nrQpwY0D*yin)z3sp6O=TWS3AJQc1B*4*;HWRpJ|O5H;bk^ zPd^te_-4w};6;Sf#Oi9Z3*44Mi!|1>(wk%GjLk4cY^ev59zbO4<=7dE zXTR$`IMw4rrK$O{q`l92kxLI@q=qqjViCObz+Dm#zMc+-kSgx@neBsU& z;m9dvh&PPahCoXXY?qqQv|)U3n^7ds-v3!FP3I04TV7qss64w9M@m_{6h3CWy86iX zBVyBciu8wvbvi9xbZVhzVuidjHp3XPr72Jvf#8IM7ut=52fk1LyD6heCo4!%(x%Xf z#lp1PXX@1EJKJ7QjDG*^C^{sz;C`V-SS|E)dk-fjLz5$W5kx;Kn{oClP2P)%yt@y{M(fg58cn+>E`DJDCPmkwlv;$hxI?>FgJ2yFa%yS#AM~U0#dU6-jkP*l z$xHiJWc#2THjmUaMylMlG_5W6i#{q7^KePRY?CXg8^ZG4t>!snGmH^ix`Lz>5Xt`C z)8_QwirSOrYqwkre`HuKnX}1>#n{Z;FnvPP%rg$<3)SYIIgzM;EdN^1l^$?vF@;P$ z2yctVbx4Hjl*EZ#jMUb%?}yB%W2r1!(QBuox%kGPx&pv=3lJY!|%s`c4mv8;#DJo%Tk3^PAn!ShGr_0eV)Az z_|n1lz4lp$R-gCei8{ZLn?g9Zy6otLH-(7U>LQFfMp!w&-r0EBgyjytPZXpw+Rkl% z{DE+fojM6^$6{Dhh?1=?gEgVOcLJh7$WmVW3%_w52+#_O(KGXRCGd9B*v85|eI)PxN_fAudciWa4S8f%%a!asD_JX4g zX!^_0{AvnYclY*P-X5DCNixLQM0j(QGK1z#nV`$TaNTRLR{_2pOeoFmaZGX9wTbek z;65qTeGuYG%cA7{#16 zgU{?wCqA9cDpq*H>kJ>76F?>fAnx9S?()TI65T5W%q9}&}f(K$OB_3%AJ17@I7$l;rK zmUj)>228!Re2@Oxg2zT*Vht@BJJgtwcSGZ1#d_A2Zp0II&n57@3^XG&=y9(+)9=78 zHzudP5qIyMuES|G|9IEgSuH^|mo4Y)tHF^fj>*C6n#2mV_~ie4Pxbpdf3GdBxANF_}Up8-!0KWZ0B91c+VOxY9M*RCU^+Z68*{_n^g=x>Y{5I=kFR#0VToegK{X)!vo@qkNfjT9?2mUzptPpdc zrMKa8ph9aV!Opl5`o9xi6!GqF+r1<*uhJ+5)H)xSO*-o`OZ_kFQ@h$}}F`OQW$!i`iV%&a3Z61z2O3-a z+|t?gg?**!tk~k|qLb#myx0536EX)18Q>E>_nM8#7&7`T^t2g%?>66AOZX9@Jd$4U zd$-G!vRoIeiuCxaxl*+7zz_Lb#t%K~b&(U1@Of6)5uz>(unyOVt9&1F1XFiy=h+a!}=6*B03)qFRf4#QQZQY_r0P_>zS|Qw$Djr^$=aI^w1fbVT{<4 z8z}ie@S|-jU9>~z6--_^F-t7=hgF=ryO0x$v5}>*)NA!+M~~S*)MRaHa~7AKzPcrU zD)XM7)nae(JH{P*ml!J; zC?Kbz(V~d>;U3|OUeJkj{??TbN=lSdzFbdljQ3%I!D@vq&VuJqfW(uu{? z$i!^jGQRa0O?u8b54S!ti{@m^zTq_sxy~bI-H-6)GDMw6)Vd#2kMsZdxP^|kF3mGt z5OPjw-(T)m$O(;x<3pDx!0J5w>wbo2@Be~D$G7-9J$t{WUwgBpOihZKxM&@R zqZ5mCtll3j8LD$9n1Lw^IiXQ9t15i;KCE#ijM~pD)!h1PCC|%s z9=g#d-|@Rt1w6dC7$u?6u3o(Q6PD11%&aO2^`a#I+SS1qt1=Hc$=KI@>txxpMs*`{ zLc5j^uNRR@v@2|LyJsJCbX7=j&RzrpWcXad&TTlv9^fd&+QoQF0r&pJxK;+X>ouvN2gg zw~XEJ*n7}Xe`EfOO9wk=&oE$N|724iqBj^)i13XhUXVu_7=$bfU;~j@uFMps>%2P& zDa7YdCx2Gmfmy1jw-nrOiIMeFQPDlg*(`y>-nx-pA;j1j zn_-OD(h?-dK;%0{1+Mw(PkaAcG_d~4&(NEideIFuUrNG0Qx1i{ch9F*&d}IqWow0%EH`dI=pKt^V9`Vo;Rn+>+0INA4ms%_|;dB1WP<0F=V z8rEjUH)6!5)W^)fweaS0Yu=R`gYT)@UIjO-NjYZyPABp)>q|{GdneQ>++S1|(Z6YL z2;;4p22j^+M*(Vk#W7PC_9QIk_TpLjKL4W~uu`Ozs6m9f@9?j+~0_e8X1A z+}iMN_Q}GC|68`t6XwdRzj9k=;;hspXKaQsVoPt36a*rd=C8TWy~saw`r&)QS9PNQ zON4UY1r;)|v%hd$eB%}_$C-0a(-n`=0j-SUJ($_3z z-sx)d#~GVpjM&lz{Q%I_Z4Z8YKpyn9-!c5@@p!?$?hms0iQG;KY$#+eQjR|^T zrqJ^f%k1~8Fqxz)58?0jDt5?;{qCky&qK0->_h_*d#>(XKaQs zVoQ0DzypzLiREeOe0Dll(qrdOJ32Y_#go8qPAry2X2vG3rtkN)VV34Cwx1Fq81&Ts z;Ide7qZfLdEuS(E{5V_T$F@Fitv)fV*uc4$ReaH!x}266rlqLYRt=dFNBD6#^f+6@ zMTtnOnz7YKv@CIU&zKNt|Ly7Ft(xWKYQh^ud#wCcAg7SWZP-ejhbg;@O1VO}PPuaE z@M5jDNjt77$QbK6V>65qTUr984G6aUUuANl$S=}tdRfZl3y0f_iq%#kw_OB(Jb+&j z!^pP?aYc-$D;w;J7~UL1c-w`OpJm;<(no=%3)1I{7yP+>YWCY7Yr?J#$I?XjX*{&; zBJ6JhyCOzR6Iwe7US9;g1W$0M8+1;d!re8&uMRnUDcmq6Aw6PO=^6HVaqUiV!fEB{ zrXx-_cHUN!TK(`*jPGpaWs;#)FF!kDGmH^is)D2w5Ls^c%6QR%phUj+2ao6RA6#QA z&*kpKVr*h=620rhuauK=cZKX)X1=ppY5h6(R0dM*BrH`5tDS_Ocf)HZ-hw*#bP{g$owt# z+2h2?<%ui(CtK8Pd($j$%jk(CJ-uLp4>CX9v?^-z-h{t$4Qq0@|Bl}KbpL{52hKQS zGmH^i$^)e&2)>*e@W(~z@1w)J9Wzf_KJtsOtNh@^Y+`CYWdTRhc3)YCySWAvgOl&& z=Ecm6_hevXV={y^WrSbe{(I%=!Azk#L&=mq!pp5Yce%IEn~YM(j8;et!V-zlg{H(d zfrVdw;jKASD_Np)r-R77^kfoO%5LT9nYPp-cCwsn%rayvcEYs_OHa%nfrp zcb;x@SwJ||yz!Me8YZ>cMXt&%=KD8C%j-Wo7ctCo#%35Jw)6!`FA)6lsA+`lzS+iy z#lMwYoT7E+ROQFbPRy2;hNTlczHqy_aX-GXc|Xtj)=K-0?B_ihSlO7MXMnLGAC&S= z4Sv)C&Vy1)S+Wjg1<%s%TClm!<=ZCBoG1UE45NbQojvrZ17W(hgoR&z`6-_ErHOgd z-G6iD-dV-09Gmk-(H}Vpy_8~I^5~<7`P4r=O%jY1&a1DxefiwlPA6tVBZK`vyZg7q8{D*9m3Q&?BJqPW_O)6g zPef5^##8u1CL5C_WNDdD%a5sXa!issFN1q|Y&Bov|6l zh%H5eQWykBi<&>w_-#K!xm#+%>w}8E$U1VdjfT$5PE)u!;c-E#>JzM-W)~0TF z|ERSjrNj?8l-!kg9Yc&HlPWBaaT-3W+tUd1^auJ0*S1$aO8@>=xn1~(7 zxaZ16BJ0-fDK0UTyvNj#EG{|mNTSD1{xpLAcDXE`Px{pK7V)dmn5EGPaZAhj(fT zXKg+v_|0g4<5x%dZ@X9Iv3~x)2f0}KeiD0XIqS*rxlA?C<;p@nu~#YXxm=O5vd-8H zW5kxOASnez)~OsYEb-fEBNqMq)|$ED(Z5+9S~;;88C#l!Ec||EqWD?<^4ags9+Q18 zwa)I{TS(&@vTRlGR3#g1*{bl*MTljq?_R@~tqQtl!I!PBfBCmN?BD}EVwQ4ru79(II!Be!u#-E1M~YD2_k3-?*M3hzuMH`wVG z?vTBE!=#qrd1d5izE zTMpz*DRyEpw6HMxewjh}jmFe1v9ft?N)gu=Sp9p{4Q}H=k3SG$h+tzfhitYGmT-q3 zf50zl60yDS-txctYeY6&znX8oRQUYdRArRZGFtdBh%gl48dnvW>Wi&vud(Fl6TajBT^2b_2>ZN&rwQKIIq)>WplozbHGSXZO&xnXAKj7J z@=vY1_UH1MC~0DJAcsMOsSTPY1e&))_XP?vZh-C!6l(eatB{b7HekBLx%SE4zKiBU z7o>l&W`6(IHWT^M0PJZ(gz4Zm`6*tv-FdDglpeqMMJ3|h?N6qAov|6lh%NPiQUe4h z@ZH|9CZoIH0LPA1%0=PunnM+rD$?X%@VgzNq^c5O znMFiZ6(+L(M996rtMgv2?pSkd#~k5um5C?`jb>Gq2+Nk?Tvd5lnl736-Q?ONri+~t z(z=Q}FMdIu+(1fbBCJ}ls!D|Eprv85f`~%U^#g0aXgK(PQP||Cw#FHoVT{<4BqWi6 zNQ-Tks^^plK3$Y@;>p*Y*QVtj3p)=wsmIK8k#F#a_gmM@OW^u(Yq*iJXVV8w<$9bb+ z>y-QWp%>l{^VAY;uo zzg-}6IYjb^`8i*H>_A1Pl|RDPH3D5Ge3KG-M&$> z>q1|)tXNMKGt;)_GtSryW5kvuA&Cq`NGRVEQxS$fh|S7bq~4}Rp9M>=?n zsfGJJyjbEqIBV(hUxs;dx)J4tiYpZ=c1Jwtf9H(NFh*?Y3gT@Lsg`nxZRWfZ$-uhD z^Tf-ihi3&TNQ0I(TNnf^ZrCvKuixR#w@w}DoBzBn{Pc-QkWoTNYQc3Ife7yj*j*;V z9;xuVOcrNm_6g@SJ6IV-gork5wGz3$N933N@JT}=ypNz$^hmc6&?gPWE!d)KW^*qf~y_<48k%#z<-C+vJ0noQu2uRPFuXc4pGcv~BNmUpQkkj1gOE1En4a zzGODZA$~(jtnpggjshpyFEhj>lR;~P;D^x7zQM+144D*Vd&tMeWMT={$oF+O{17^! z<$u_i%pvQ@cycGOF_}XqPK5-spSgVs-Euhp)bg2e>y{WSVoN#XCyzbdhzRhIIJi9U zWzPVn8#czXrZfI9rEpmXuHW_EptJYqGtd`wX;fVe!I8MTJ4rT6*;Mh2)RJ#A%sakK4X}SGLtpXv!~|pU-wP#IT?0-YcKfj zY#@2=H}Z9~B0|$(13e-rNyTR82Fb%d@nIhn9@@nQgvs4cbV_!{W*8&3L5 zp{i|%Uv{b`%4qt>+8lAlW*8&3vPv)xgoe;b? zKMM8Azd_!q5)r!%Z6@QtlY)|ktYmenikh2k*)B8Bbox+W|9&^C(43OM2*RmFTx`+_ zF{=sZOly5B;7zAPgn=CsWjn_-OD(iJ$NfC=u5x5=G zSloISc1})bY=$vnOEHju2a)bq_~cpJ@*GpyR(pq=eX4h4y>SP$*T&M^!0hFTiZ0F6 zl*MoC;uW5+sXg^%5qNWi38XP2BK19Q$;H{RyJuy6bJ;DW+Y-2I>E1VAP*TNc>40_0 zK}1>*|CEElm%Umuv{V-uP39MW&Tj90D&qPF!l^>qRfx!{W9-YrR%Z}Q z71Jj)-2YeHG4J}Chl`wMM_&#LIm|{lRmgg6{kf~PYkBCiZRCz-6cFH}ih{L}bUvSN*^+C<^@S^G`+ZWE4sdAHVUOS}^m z7k*R^|I;0}zbd+U?!`q&kHk&`(7-^vnnDv7CC zLE+uU^XKtiUYoouMyto+)CMs-BXCQ?5VFUBIZFn9e65J0Joop1IwET$)ip1cZmCdB z_LH=k80R=L)6e6N%37w`USUQ}3b(pK~3TL#b_j22s`Kr13**|v>P9cgJ)pp_a z&!X8gYjcZS&b-Z$aIHP^*%_N*jM&l=$l(zDUc6@6twUC!@%P*rOZ3-t%hhPja$+$x zHMO*9JSdu{!=?F}$3v#FHTjd;VM$x$`5;`Y#zmAJ;m6nFy0;4Vs&T2g9*#LFs@gM~ zS%jjZ6IIwOq)-m>M+}`%yQ3?j91WWf8sw|S$r?Io`my(A&+PCuSAJP%GCuCE556>C z2|1xDUxasbk(#WE8TGGA_eLjnPM;|1$Q&y3i|@IC!c=E$hB0DGl8{6OBIVaB{s`z- zySMWq=R&K3lS%1|lsKGN%uNg}6jL6yf4Y6_q?cKD(H^!RTYfy%u!oHBL&si`P97Ce zT}8~vqo=}N-&cMA{#AaUy%baTFQ01>{3lR~tI>`R(HG5#s2)L_JX+~xJZV-b^RFY7 zYl=BvaXRniXbr=Wiqyp6W3`GI@yiOo>=0D%IU{*jjQh^?wGS?T{NRkuFh*?Y4U~Q$ z*mP#r$t6;+lP;ZVye`+PbM&nGdu2#kfy@RGv0;-T>MDFTXvTEEC;eveTWjW=-=!TP zx!m8V|Eca35`H&m{@F=uY(6_*i+eBcjLk4cY-tLTNt8{QGode{6t3)EvXCM z6$^GOJti@gJ=Z$oYr9xV@S2@jsW@ zlS_>fNw1C}mnBFkL@ODoEXnPDs9TBy>v*I@mVEkDU5|hxS@*1yOUV0Pe1evG+VrICUVn<)TJ;Y zI*7&ONVk`xErmJekbQltr)S;soVQDshu^Q)`d5u|azB+$F~)NIfQU{Qtm#9+QW$EF z+9G=36t=PTHRk>1W4V2NOGV@PdQ*3vOcp)lbK8)MBBX?-bLQLxc54Oa=qd98rnbjS zh+p5FbpMevHp3XPB}qsk1CgPrdyDoIoY}GDcDaOY#ksvcQj%KW0>=TLZlm0iH}F-Gh~84@A{Sx2N62E^I5~h-lJe~8 zd*4qeK1^A=;Je(yH$QwjS0Z2CDx!ArTZz1<>)eArXY!_pP=T0(+v?^0?$$(G|hRZ3d$uroHp7_p@>NU8ymS;bj=8bYC> z5t_1kOwZ$7q{655II)}=*+CrWqKbX=Ncg&ttMg`i#_4kCrq@A`RTH@ zNYj5>#_ScxYDGN#;nVX%Bph?IUheCMkJtAeo^a-u zzI9M`)7MqoaNP<`!9iLg<^j-zBb3VsOE|;3B`a&*6Z*btmQO^H+?Ou3j*`?zr!0_5 z9PA0leA@FEgWiS>UAyvMw4C`Cz31lQ-eXG6*bHODmc&3w27+f*?n{(oN`H9M`4+qR zv7^$@DpD6XFyfN<$ z*wcM!O0k>bxzlTOFU-P`J}kGvyVT~>vL+{J_%Iz~nc8a*<$7nfXQ$!4@6Ol^W5kw{ zAZY_c>ii4#T9(Q1LOx$%gNE8RVO`xH_dxe@TAJUp4q5eZgJsyF-0$VH`qq>dmZ;sP zR+n1Dx*vXD3+gdh=8IF0F5TL<#Q56tc}{=)w;xMqq&&$;I+6XFi>pG^N@Zn_-ODk|ZdJ zL2%of9Z&Wvc|SBhr}pkORmG zjnsnxkat&#*#3YeG_+e6CwH#NO)O5kaL#F^_^-9i!50PiQO9m*H{oC>1WRb}g8&d4 zQwHZCAqgeg#SiXYz4oWI>eikubjf4Asm!!414lx$>wuSNHuAE)l_|?l)_r{HpPe#$ zfs$R)%+>PF*bHODmLwsG3`EMRo?4NT`K)34{c}6L|1{~#inXi+-9Tk%7+C(kVE%4~ z8{67U7PMb|#NvPa^>I*Bi3!?g7ja00_t^zA`Qd$bL2)*CpPkn&fc;cxYG=n8+5?qqq8vprp zMcgE}Q{KwQZXR8f2~Ho-^ZNLz`QYdE2|n5nKd(>Va3%b_KF-$@4{w{n{6%f8y-4Gf z%e_2E5RpTbVqMjdwXnaa9T>b;}&qx$HrEs=urwPgt*QIdu4Ree;qkXKaQsVoOP&lmWqi>E1i`M2JKrUH^Vajp2N{^JoVj*pkoe;d)V@3JR(0<|dnyS-LTG_5L*i+8q z`|%zN#akIJnd-;znJH;k{?vZujLk4cY-tRVYCvRu?OWdkh9?WESD$50XgB*N?R|eY zcxQkqWF(l|c^ey(8DvO@kHeCU$r3V(%riOqy6fXpr!WGu|YuYWe#? z)9zj?Zj^of*wci&!Eu&qp~+T#BJ!b2*H27bQ?0&VnBN(jVT{;P4Hx_FH1RV_V84WpjxD<|xU3i~jmLT-c40ir||h zDOu?^@T1Ej-Wj5h;1!`y^>mT>?<7a@o(ucT>uxY+oP6RwZLR@wD)Qcqt$Ok-U0}WL z;Y@qES1RW(zMiMY%n^*;L``CYR# zn~CcQ9BIh+KfLqgSt@B2c+697cdTL0Y@rHK3C{+@JO0kt3}eKW+CZrXf>mbx(4F@) z{`UIpvk8U0%PzcW(fbKH55nAVl9XF_nTY$Vw>JX|n=77*%8O3RL2ew2_}_qctMD|A z@A^#rocqFN%=V2UE?!bAx0@K69C2m`PnARO4H5|w z`gokn*f_wicK-4U`TD1vp1wR2m^qp%K*35$XImslC*!81?#|%fW^dnDbF)?y7_qV4 zG)7JpLH^iNMObvZ;*F~ZCUS(dT&kG2;-UI0#U^KLhB0DGKOl!gaL`@X)BJa)X#I8Y zkqf`3wa&kM{yflBxrx!8FB{lHgt@ODG~oYn)&8_d()O%5;La3*ZPp?o8nyy6Lv|%x z-*r3E)n}Fcb=KpnSW)N42YWj>#EGigtf{tOk4dap;^Eh->*?WBRQ^qOpKNT>bd+#v z38~%GV72Nk*YAU&claVcwfs)d;k)|M8Jl5@*wPgwrGUtp@9SRwd3%bl@kGIc%MLGn z#ZDXOJFys>85`(bi;AoMc89n2cc{vpdmfYi-rTeor3?uRd+=O#)z@d&%#US$`uoe$ z>A~yXJ?~J;kkM3uw7r(ttx_Uk1)N9z`A)1~#@L>Aq&!9@_(|1aQQpZ2D3c}lh_+am^3 zCl+%9Q{yjDf6gV}`=1k_Q=((@uyXw#i3dNyDF-@9K+L5+B2mkB*E`P;p3KA^{v*MG zuk-%B?e97xhIh&li8=sl&60en4+;IC=&k#V@@LndUE+1A?O^2173Q~P197CBXm+HO zWBlP|Dcjpgmlpomf3U-SYST;o$$`$;3}eKW#z1KXg7>E{>w0;?!GiI^0(ZYZl{0JO zw|#bEwlFe|-eU0aq1)`HdX27Y@3_}QJP~uw1t%N=vyUP%50HzTJu9ZXjmfKvwq5=F zTWsvUL`#PY#e+8C#QdZ}kwd41W4X)VSK6ebQAW3C?Q0NkFHYpsd4nV2#5y1)oW=Uu z&P?Y%C@;wRV;$kO>CBcL-|cP|7Gu8X;)sBwf41IC*_`Rb zVq{@ydHvCz?{%+u&E@hVbbaRPWq$5`n2&r?l^~8|@x0vKVyvI3I z^Tf8hp4`@PG~VL}juaJd3_Ga`?;R{epE*PNkjzj@QLzTnclXV4yLqK)ikv&kL1B}e zC44wiRQx2Q6gAN+|Ami&kxAhLcgYZ@ms{e!ye~RqGmH^i+5@E}2);I5^JV$WpyhUb zAD>G^Z0MS_;8(X3i=m0J(Iv)7`M2$5#j^8x4oKS_dRxC^+GCUy#lr(X`%K`{NBG%i zEV{?wDM}ZsN>0*0;GCIQo%O6k@tTB(W8m zq6XD;!=UVDiG&sCT7Qdoe^vW%&%)hTcAr)kSoDj}nsACreA3vtN z0eh2Zs8DR{;j=54mu{Z3aQpYG z$SEYv2tLGzl0qD=>=tx-DC_jX`IT1lZKVY>GV@KGu^GmQEiFM(2Z&TZleQ{$TJ!$> z#s@+;%ZlC~-@2j(oDPg2^Vw`1qHIj&kUez5WhuXJt=~Sg@L=&lscjaziay;pUp2NM zr-PAEQix=5OMn88fdT(Ls3dfmY}Wfra9;cyYkRqG!a?2n_l}i*UWg+dWLP1U6jw^_ ztPOwF@OQ56Kac55ubZV7z2E4J%`ir6DF)&R5Se6mXwSlH9hZXhcWIx|O7ydN*0#-w z#oW@&T;1pftJLQI83(>QD+y?~i3;%@)dr^!=$S_%S;FvL3c{xnB$5;x1HK;L^qt3G zcEL(X`^yhXERj>lXi338$ekDl2c%RJ+mtyy@)i zg}OT40x0L?WyQct3X~LbZ!NR>%^!0-azCbr*J?fN_+%OP(ixj!jM&l=C~ZJ+ab&|= z4d?f1P2sf;YvSWF&R*=l1ey#mH&LF_e7AR3pHF-C!FQUUTpvD9slA2Vk`>7@g|}qM zIK|ggzU;5@ai&f8ReHEuFGo-R$<8zdM~cevhqh#eNj}Aw9!nnRQTLFLqFz@Q$o9Rw zsQ7-3qoQvapR;~%GV+zUB01}@rznrwttN4yCJxnQ5^b86*LT#MZCUM%%`ir6X%CW` zK;)^%rzWd^Ov})n-pEu?s>l~rdPWj?G=^_#6MQYW(2))BwcspIKEX$0g!afQExeJx z`E&T8sGU1GO0NEANoUm5M@b*>se^&<>4@aD!$xDeqM-Y?MFwk6XV#S2&jo*bD)BPz zd!*5~Zjskp#x~?S348j;J9k^s;ft<~${7E`9r-2R^^2{90^gxg!;HZn%lDS;Ptfc2Aw8Rnm!>EvLNd95gqq2Twmj?`RS! zSPs9VNq841wLn(w34Ik^;(g_~N3s3?KMy{XexI1^-nm4lhFYmbq~IV`*K!W2)KYs@ za;f zfM6d1eU69~sg0K$lnz{e^JKa4m70FgAJaZ>n{7_1>CB2PHMjWBH?eH zu^GmQEnPuU3WyA-5%A?TRi9BZS@L>u#0JNVXa`@=L04uLaa-CfWmest z`FxYLlQTBM7_lWcQ1XG`+Aj59m6?*6KR!=kiNE3VtChWVffI{`iLps*{@Sxg);_YY zK6ONAI$PMX**>vt;3CHia=u?TpPZMr`Q{l2Slq@NB>Qgio1AZyuQB{M1_ESEusH zXeSm^Gh;KM;9m?GD4lr1!ANRirb{YbY*U$(=p zbmZ~`dkU$3_+(`}E+I1kzfEP!)sXqiAa>GA)JgmzP;?vFRFK4%@Samp0TP70vD8qICy=Q$W zSKweTKN=Lf_SLIsAKZFobJPJ7#np~UM;gw4aK>gBBeoOgqw@9#W{F?<@=1L15iL>Ek7E65nFyt zI;|)FR4#sT>Uf+@C2*I}KEFxw6D(1!g*9GmH^i ziUBzsf^{BWEp`2OHzhdeR$N!y+IRT$Mu5u+c*1THBFo!&!D81(RL|=NQ(^V?NZCl&-eHIermra zu1{|Df5+KXb8ibFrQ`_}V3+5#HBQI_^~eXU@_Oxn57eU_v^wGQyk+m>Vt>Y_qzgYt z(JcH?YWl#Bks(C^WCsHS1Jcys!1r6)44?z`*bZ8y;Y1EO>0{?Sfy45Z#%@Gq5UBk2McfD%;^Xr-SHz~(BV>65qTS|h)8Uq6Z&zXO# zpL21sJ2V~ISi)bHcy_yjwiAnyk)_G)+mEB)UHRa&-O_aURdmm%`ir6 z=?alrCY)H`yZuveC!?jr+`I{WZM#&Ll{v8(8ylN$Rnhe3|NXPM>fRd(-zv2^#}4q# z^JL&)V={y+Kq2+=9FeX%HYN*5O2d75&e2~h=6fz}64q2XvPz+VY0}#S3zTyeX;>_E z&48UkmV1pG5<6N;Ghd;QnYXlieC zlV-?_S?71fOgV5Q{c(i9k!Qq4f2&kyY=$vnOEI7n0KrT6gU|Lp@m$i!s@xP7aPjh) zzAtRxbYKWc2W$$U8>AuY-GsK^fBHtn_-%Zc@5MW-g3YF|YWAsyz92pwi1fXOo%Se|n{vTM0?nx5x{zMSgoXZQ_AI_O8-|JtOv;eD^e-#@Ak zH?2>r`?ZF-&fd-VhchnRM!y4)rW7Ka#~QcQE}y0BF#J5wbXd z=bkDXBcwDCe%{T-WDGeAinpMSjmZ?c5|-mI8;-#>Qj;shEVmJO4K~pF2bT zbDlh_=w%L#BI8x2T z5Tw$>PQd#vRcphq1{eJFu&Ka9wjM&l_D7`@N-K7D?oYd?0v9nyuPm#+p z(E56=%ZbI(*vw-7y{hW6lGX9To9!!}Xhps_)#;y$+*}cvtjoq^1W8=NXPVfUOduzX z2{|Re@A~7=vtna1flm3b%z`&pa37kQEN5~#&njBWE=@?@?NBbw$yTuU$@HlLk|q2Q|~VS{E;K( zx0*9H!x*t8Nk}3Ck#pzYy{p=9z9CsP@ZCfqnU^VDe{-Bz%nU6|ZFB0sSNgZueOX&0 zaic_Q)wT$sndu#Up{WLrYJL?LU>Hbp)~gy56`T4--2>xD$wu0D19 z)1vfOA)!;+U$K4P=ZwuTMr=t8lw=_Iz0uE)HIpZb+q=xp;rx5!?$&d{@lGt3hQ`Kj z%I*@&*DK|TnBQ1xxlK6yYJl|;$VvrB9VRmUJR6fSlugXhQI}$(=Y}Nqt1q9o()0Tz z4Y6al8+C_K;WPcE2qZ{px7r0q+eq`0@>)xYuQN`I^#8dn$;L8$`U-g*h0hGc`v0ll zgp!^*Za7~h?<(+a_k#Tg-#=O`wb&V(VT{;P8^p69l8?_{{Gz(1ytqe_tTBf~TPtB^4nSGYsi^OJq(oba$e# zzX|M^1~E->NRSI&Uj*HAMBu<6;_Iyj{WcZxgr5zn|9F3;{^kvG+n|_AI2FxVcPZ(> zG3GV5-v~~bDV3WS+P(JQTo-3-hB0DGZxHW*$hes%iG9jTW>s29ykao1DO}+EKG})I z+|1M6$yC!+jJtg{Y^A&bof6u-h0vC@Fp*bDQqn-8dqR6s`FH+r`G!LAn1|Nu zh4%7((rqv!oY3Zr^Xt^DG3M|KlXB?Ut2xJvd4~1z)6UooW5kvuK}igP8#JzHub#AR zja-l8h9hNpo>MLxr#rD&np&Dg+&?m1th%2m_VP^;5v{mYW>Xm;l^d3Yzak4hurZlI zx^p5W-&fqZa`mY7)Mr8W^1?S4Z_hZWBzqDiwcs5tq-dB3TR&_e7j)Q|N(+Ant|?^u zq2O^?<-^OrSu#Sa?g{K?Q&IB8ky;kI!uw(K#rMjae5iibx#YryefcgK`_^vVF8tpa zn_-OD(iJ47fJjzH?f*S5DkiUQPyS#r>rAO#;rl(H-WHP~q?;~W^OlVfQiHMV|IEf@ z4(ZjiHYT$%LWYd^JaSnk-~ODhf9!b7AJrOGrB6O9e#fI$TEn>MBeGZyT4@QZUVv6w z!Ua5%pulBdKspnVoViZvRhk#B@tE{)O!qR1zP!9lw5`J)Idv>fhBtjsQpdUG#dEiN zPjhdweZcu|aoqG=nc^&GY=$vnOGgl=gGlvAQ6u-KY(^GRJH0gR7s#w%-@Oq$9AsX7 z;8-BXMg?EHv@LHk6~4zcTOXYQKIP6Fl5Rwn+Qgm7*!@=G(>saG0JWq2Wrge4zS)XW zX3(xFGdOFQrD3pCA+Ib23SI`}Q|^dw%5+)D&-MO##9~QF?S$;TUk|c*ebOYHDwbAi zFF1DP;y)|bbC>6>wm-a9SyeJA(HWazjM&l-#K9oaN@(k?#;3}qs}{2NT;r6fZEc!e z?8IVbX<)kP+@EPC5ovMGsYe)H7ae}upt2|#Qkp=AnqxfJn2aDrh|sZDY>be32$AJM zY)lrA%0?*7?T}<=#Z})8Q_kHe)1Dh0aCo2kAx?4z&H*qj8mJxSQcZiaWlX)Igh zEwm(9s^;9{rMYiww)Kiws1i;%%Qw}BDEU3xT-vl-=4q1NR6}KUZ{a{^Y=$vnOJblT z1HnG#j`y|0C9`Y!r0*YpVf+1HX&|c;i8KS;} z3c71e;4d#?*V@YN8#6<1Yboy&_F3g_`|^I&w4~Qg`6wxb!b zJ38QfZJJg%58Rx*_T9PtD?UVhud=T=&+i?1(#R=fCF1^TqzY&GCV#gyi<9kPXE+yF zeqAt&M%u5;~T%!STpZLJqrzbi``3AbdJ!@A7RVqNPqJzL)|to zw41c6j}O%7-bMZAkCfWF-Z>Xs6!?7F_=1S`97P;yXpIECNxOX0Kl2I7;KmU*PXE$#)vJofl?0yuh(>3#;3N}M`_gwFT>P@r8`VNK6YX;G&eNgpq8l{ z)KjyAS?+xAeDye$sugH6rjs;%QnEUHkfSvzO4HQ>(r-uJevuf1rQWCzOuS zx;S{#7bO)L?rNMh>+G)#^Ws}WMr`Q~l7c{_M9TIvFSzTRX20d1 zzh=*Wzm2!dot#+AOfAiF7aq@=E&gn=xoh+jq5Jm|=PuBxMjo#rdEwRubNEas?uA?4 zb6RFiyl6S+uu$jXj87|fzR&h}N~bDsLm+IthLVL_#11dhJE5_Q*CnYg42fR7bF%P) z{t|bK2Lelxi>nRCu_rX8pLJ`l@P6-Po&8qsY@E2I?FQLgXKaQsVoQ>sBnH6;nSESJ z9(g-EH1_{>-0fmF&*MB9&lqXKaQsVoOUP zheL3#nMviz63d;6Yqd`=2$`wdcWV}p6SI-I*^&UhiGmUp(R-7+&v+a?{r*PC?0v}H zE#A00@a`7h^7*jtme8GN@a~q#mO~Ri{}$F+dS@>8{gcudz^a1d4~<2i-3ezzE?JP$ z%~nOEhR~H|EMF92;td$Hj7;TL%($Nz^vc^An_-ODQWzx7fXF|dElq{9zMZ}mqmz18 zvRBPWyg?k)PdB%inD9|fWWsUzg&!LZ6vh5ceY%!0BvLk%TL5T4y zV#`OZW*8&3Bne7l5M1Ur zFYFCtia{Yu!p2g+6}i2;9!&?&nnQ1!6y6pMzim>u#EcDg+a&7@?)zdcsuK(>EKFX1 z$ZiTfqoTFy+ZsY?LS$z$?6%2@1+ev}fqAgPhuEI{@JAg76)^RTB0q16|TUsyEp!Ow|-q1+BJ*HcsVjyYp9j1gPvfusiz`D{Xff#mP| z4yW#l3EUCPjX3fB%m?KDI$Ny=d^L{nJ2m)4ZUPE+Y>bcvs0>k8*%%?i$t*|2OH- zM@}ibPhd|eSyslfoqwghTNJNfUSpN~@ySfR+0NJuW5kxGKxqVm{rO5H(}G<+7B6<} zuAIZoyiNA%PA3){Th&;0}%-7z*({57#xY)VWs-^cZJp4>+YqC|CS2=Yv*Y=)yVD#U><+UX`?g-r z0#Z{!W~2m>Za)?Qty(8|`?2fyYgc}zdT*@%(R41Yb?y5#ky6)DlFA`P*a=s77jcai zJ`4=Pn;4-!7 zImXW-|GjK=#%35JwnPO=BoM4Hk@d@oOVhr7D`Is}{C@f7B^kvs&>}7~;|Ygv-ig^5 z*m`2Y|Ig3a7ER%@-FXS6@S)(05|JZ5s%PtLSKWSp_C&=K<>j|a79_1*hT2RG`8o z6Mi_%m@QT#S8Ds?&00{3B7Osx$gz32HgIXy1;3GAoU}eK{rTJZv)gCKB>hG?$Pwub zKH61g$9BLra8Y|b*T9YWoc*Gsy6;VKQa4Y#gwsK-6A%1;tK&#d$3@|l*^#3g);kBO z`suqKx*yji5c4nk_t)3H&e#lN#Fp|vDG7qp?#!?Z-8u2=tQU0*Z0zSUy)P)sLxuz) z9Vx==xwuPYxJ$No#T%TDVX0UCGQqQC&LhLW)+qHCmPxH4)G5c`)jIKx)b(5>bhWm+ zIw;K)j64+RBeMU;RbJDKO{bAl$4O&&R|_R|Or9`tyXVZK5wATr`TR1u8e{3};Ofkb z#V|%}=?IcCK;#BXw|N3*jCQ`xTK8hr?v#ZQW+nNcJF_i~9@)NX++lzILBgFD^L0$G zV~rTZeZlLwU^gG1=8@8U(S7Cn>qi{3S8T9eTzs)7V$(vDR6&mh@USa0L{6*4W=gU= zu(G+(nXsWxZ->d5U;eXDPP{=%6{kIs%8a|tTNzSjYzsVR$@jfGB6{!lj<+_>*bHOD zmVQ9#0fHGLSI)cC&Dz+>#&OB(*4#Ho+8w7mF&mm0c3$t1IPK(qf!k!x&V}}ux5d6c z=!QH@Ow687k+VvOVPa708G1wo?meIP-C6 zH#weL(I~k4LdZ`yl!P<jp?haUXjyGpo;R7Mul(s&1E<0(Pt#{tlXT{0A}5^l zui(`dO2VnHcd@)7drxkDiPL+ghBfV*K3m>%#%35Jwj>5hG7zjerMSfKP~WV0Znd5J zuPtJll-Hd500MfovR3$B8Q|9Vf7nqOcsz;JR%nl zSA39L@J8jT{+~q>!YA_9XuG|cxMGl{kc)TuAf6V%cKQweMHJW?HuOm$cf_1`z5KCg zf6~6ZzKtrL-u17Z)+48oOFY<9i13o*Cj);s{W20&?L54wS@8Pg_b$%Z3}eKWmLLHI zBA-djtUDtAWPWM2*yfIH`r(r{=bZ!X(X%vP7?tg{YW?OpU0=V=KUDZrvu@$9sl{{C5$;l;D+-S69*JiTTUP9azHp5B|cS9(Lb2+xlSym#zq!9SF3dYaepGVIZAuA(Aqj5 zPbPIg@GJv#_EO{;JFeNwgC^QW#dZPK1*!+NW*-VJd9=azI7({4R^wb#r04AA&@4|B z9R9jiOgv=d+CMSYdgtm|2mjo;$f@NT;{GqB8t01M%C3J)7w%f)T9~5kqP^feW6Y-u z$DFYl#)vIlK~f5c+$4GY{eFqnhv$4zyEh>(fByAbo6?}zo8LS0MP14wyd3DU?Qa>Eq)oUMoVLwpKk+~pO}Cnh1{rvH)gNsojGyT{@0nu*Y^jz zomjQSb!X168ckki+? z^Bm^I9(QxbW*8&3lm|{qU}E0EOv%2R5woAav7S3&+KXj%_ca@wSWFF#Ob>g%v7Pp> z=V{4ePQNC_{o9_&uy=q<9O#K|B6pUvF_}Z!xLkP}cj9IKUD~hkZ)fSus0k++Ki(*v zKMf^?;H{HH?i{53ikhKWCpjm?8cnH+@~PV6pW{A9`&-P<`!|qN$ej=HHZDpEvD5sZ z-ccdO{f5&@Q|EQTUX4xn#hkGj#)vH~ffEOqm^4qktDxHStWVMRNkV3cu?ddOoK7s3 z29}n>uldC{|D1Yg?ZdZT=ecUr;-ro}Lm8*JcM^U!7xk9&E$h0GTP|CE)+cCrlA7Yf zRhJm*)#;Sb?mdQ%(+J~Vkv=pN+DAvnTN!)b%DWi!xiHAB7mk?m0_8HO`;pia+RJ;@ zF-K0H5xweY#6DehPjr3$-CSpEhB0DGlHfE3Cc@{O*~g*68kLiHM|)yMiNU@%OYeXZ znu(E_qH$yY+v3dHv&M?KhEE>UiaM`F8K`+^1RtmoFxvnhs1g2j5iw8`wQSPj$yqvE z4owifxK`Esju5B7MwI}Rl!Is#4VOynp$~MRMtIU?===gD*NBN=ZxpHR*xSl9>rt;{ zd7*hj;8*_DY{&m07g0zl=iy|eN=%|J-#Gh7sJzZf>HR@RZ486WOv=Hz3JXSssH6S>x!#fd7gh;u$@L{2x4Ps2+blyr0dw_Dk@>%SvK%y;hk zvAQTaVxrJy-iU- zB)9)mbH_oOQ^$%;Em?g*&1vW?xR6v28}t}cftq9RV@!n~yoDcQD)Mv*VisJn7IBQ} z^AiW=u0CwpqUw8C@y(C(w%jSYD_cxZ(i0s9dqke@gU*5ry)uNJY9e&440;&0@Zp=V z;Xn#5)5U)V4h;r-N;~(Zul=aptEMn7<%!q6Z@tl8D+s5jXVNSykF~zkTQFlW*YZcF z59xEO#Xg8|#%35Jwv-1>N?@WbuV$5)=GoFUJJyHThMuu(JyIm(#A0q_YH@MOq^04` z4(lzBC~S?~*YxuGBJnWrV2>H(kQ0&TU*Ko-qaE<^S^E5BUBlUN@t}I<>363DUzqP*dCYD%a%y?uiLLZ`CLOWT z?v#)43I7GwzU+Uv{%@Pc7qH41n_-OD(iJ$NfQh#Uc^GaydzAHEZ}Wv!_H9RcL(U#_ zVzw|h)O@bV8(VcWZIZ-+HigR8*?u?wEF@g`h`drFrtm4-{C9DROVzGDZ{veQH|hJG zJQiz?lAP#K_`I?neudA`kjFFSW_PdqXJywtHTSxMvgiJ@gp<>&8HTMX_APoxdN=gC zay z7CLiAp6%BktJn_}ZsIvp6uO#la(eUpg|1hwo4eJbF(p*(4+rn%hdKe{5P}0wOcL3kc&Vd>%q)$IfSZk`=^5Bb$(u88>oH*CA z>zSLmA&xZh?l-)j_2#+ml^xYWHbrv(9n@?s|1bJlw<#H!Q^9Q}L~X z(^#*c8vLn6Yk|V&>hE7JdG%r2yw@2w zlh>*Ld{`yDuo)#y4D!lG@9lE%PiyD z^!1J93_qr9!;vPwX22_(&mk{mbN1TZvJE?Xt%7$6^NUG}DV65V*bHODmU=*`0fIk# z=Qy~s&}U5m2Saq*v&UTZ-&DSVF1#~0HEG>ce>5u1bB?=N{`RQMkD^cYo`b6)==s;& z!8-8suLa+~gP(uReJ~q-o|4FS#QE2}Um{doPMmtNL^#l~W2x1L=4U!CE>k>)Wh(j( zJO5gQKB?&Z%z1LLtkQo(k6gbJzQ3(A<8|Rl9I5F0I;2!oQDxw9WzPYH&v$n{GheOf z$ikZG?TpPZMr`Q~l7c|wkCdbvS6U^H)aSQ!RIfh}Cv0%6=EAwKV z-pywwEanzFq!^(hb|}iwdpVT==G4UC*D(=@j90R?A(#4fPUndbENDsJs#R2fM$422-0FYKbv= zyZWvRD4u(l*5rMEvw%qzj&$=c4_@B(BPRpK%eUUk z%6`NV?(dAvFh*=C43cI*q<;RVLq@I%E|c%)POdjoZ&59O_sfaJ$il$nE%(QkZ#Sb@ zCARnNJ~I1(+%wbA1>kjE(3R<;O!aK=mFc^ko;&{f<+A^XHnexDN8n0?;;-EI4ouB!|3kBIvfH*G>rAxwz#Z%|Um)m#RVc?y-U z%pbh$D7@Z#QFV6N5oc_MF=9(gptJ$OF9O0AD%jv;dx_M<`Ytt)LAv8S!k$et&m8+B|9C!mP3EZn=MxNPp?4@H72j+?3KpOZFZOh!GFf3$ugbnh>G>5VAMZrITj zr_~m^Is6LpNYOd?r<*rbtHelU&+!=SsYsNS52=1yuUOd@ueH#!x#aJzjY4n2rk}hd z?~KhbMr`Q~l7c|wrd4NJ_T=X7j(p@PoORM_s))1FY9|&;3k%DWPYU{0t=~E`CORN% zpYqHlSKF;?K=l*!LPg;YcEp8>^)hTsmXL%a%J!U%$r3XBCt~vV%aZc4ghb0w%N0ou zM!9mUJr!b@s9*euvNLjke8a#Xu-AhV!V;m*+8YXHzY!G_4T_%?@y}-XZCH3P{nAaz z$d6aUb39jTAtxMmcUT35nsAoYOR+Woe(K2bAhJ0!T{v=S|LgD0*bHODmc$@I3nEX* z${2FR{t=yfqH+KGW78W{pNlIHH^i zh=gL>3Ja%j=9-mvD|~F#FekOpZvtdd2p>`sQ>eCC<%uuJt(I%4LKl z913O@hCom1di_4Dqp#ZM$xM3i$>hIc+^f1Zbp#WRC})H90oK`1EoMAYF1~r8)TJxV z&*b}0XKaQsVoPG6Bm=>kl1bYo@)@f`>-#tvj#OG$KK#%FuARsn{o_>Doyon_@R^5t z#^$R(I{M|;ZZ=&dQH7FLhDq%t${h(iO&vb^NA2DdO6??39oV36HNCfNaYby^-Hc~a zfrlsKNGsfHV6~GdXT#@@UGqyOf0^r^uG@7!F3hl_{7=3!Hp3XPr7B1|0g+Sxs482i zNHJeLV&Hb^!OksT-<)y=Eyyyon6lioW2eZ=rB-^ctm{QY67I8ZXap59Ooos)3-TGp zqP(p*&M=NJI%7ObkG(r+{k)so7y4|U#vyx*oP;CFJ0Et8DB=ubVrRPP(Cwys!qH-8 z)Q(|Y(0+9Nl9%Qp5zO_UC(r*^X`^dUwr4bjfC8Ck`W@(PRKoj< zp$9^W^52jF$uTep`SC$dM@OtVM=4tF>279T_Ijhy@vejKB)iq#7iT@Vj3b2zup^}q zJI<91%_8@{N^z`z<5#ogbD{5sUC!7HW5kx0AdUl(MbEsppA7t4_A5Sdsp7?ruF*Bs zSCFeALgBfD)oz7<{Ikr@ED7sddAxGf9AYy>W}~E)VbWv~6?_1#hJ@jl zu+nt!_uVS18;X`$qAg56vX&;1M)#zqGF}nez!O6e7gD1f%N~O;va-r558WOGMXwt z!Ai+R9-?CX`x{=fc+`4?elKp|;TBuSzc+WwROD14wuu9}nM4#NReYSkZg!4q<%ys} zkz7+h8}nQUSZ?Ty%`ir6=?CO+2o9OyeD~jvKcBOHg&ot#SL+O}>DF;#wlFYUW#^!J zCOvNIwI^EaO7D*?Y5lQhGN=&@9irj?Rs`>9^Qs%cd)mUhj_{tgs6;o1{mPzws&9GP zn&$PsO3cx!@Xnfxl5U9XJ>hQzi%Kkk^|TQec_5a14w*(U2~C`>|HKWY+*_E}uyXC~ zGr2sqcloAL9O*{l6}*WfWX!o+c>-UqfC5P4|f zFN;rKkLvcU)^g#SVYOs)redHIi=~l)ndi-|Q+FtquDN_$Vd6OkU$6YlMO(m)ALy-k z$fxX!N*yMA%KjFyh}*+s67cMnh?8te4uJ1QK`GIm3@d)_TeWa z(QcSeRIFd}lnHap4F}03A8+o+7W%GQy<8l5SAwXt9=z;9Nkbd$6EDZl;`+LCUlrTh zRi-i(YqO3zV>65qTWSNP9td__=I1AJw#uS;PSSSn|J_}#$8IeFt(Pz`*?#JTvf29^ zp1d`TFP)86+pKiY5{0B8=s>V6JE^k_nw_t#Wn|~L2i^4FIr-g!U(aLLX^)mfpok!& zvn8vDm}M}0e3(f$v8!c@K*jN9i*@NYE|?%+E{~jwWJ{1rqOVoGi>vm2w>y9Sqt)+U z?(}0FP9gbxr&X+1Uja3_&fY^c~N;^an6$T>{$oJ1S6fU+^e|E z_4U3w>Y6{gwt_|F)1liig>NK5w_%FlKS%&?D|i6QoL54OqTaIJ(x?C0i>+KB)Tx*% zTZ>$8$uEMJIVh=RgOk}2(W{I3C0w-JXD+V|72%3VbH-*EBerw}Nhu(5m*C3Xp0yKG zjM@L@i@l%uE;Xbl0@SR5jqS1Sw}IbJhWk2bg;a$gk-J~k@|SfO;XMJnB8W4v8+JvI$m+G<6E*YG8$%Y0rSe>sart}Vh1`a4l$0{0 z8^EHWl&tXaFNuI|g>~iIW*p)HsB0$Ct%jdh=dlO9%}(eavlmr%oYv14TSj_R} z_Q-=Sdct#Twy)a;DUzUVVGUtY+roh*omZD~O_~wq@T#P%?&^_>=V>oT3nfrQkkJ;_ z&_%R`OFmvMys z`93tx8Jl5@*wP!w;SgMP_gyT%yX-!XiiK=%Jh%nw!cMD$RuUT+?4Q}67~-QDv8?rE zIBRF)XZHBQm5_E1WUUs`icnFlNcc)()D@wpI8Hoq`le?6GQBQ`E2Zx0#z0R4lyozk zTg6(%&=sN7UT`BS*8lCFhGBhvgoXQZ(-IMV5uy7+a>y4xi)!tFw~A5HjsG+L;M3kE z_I&llM|Xeur}S-$+HYrUhB0DGVURQfBDX|HHP6!vc3Hy{ExF$MiG=j=7A+?hOEY7` z2=jY|jKz{AGbAJ>v+i;Jo%5i5H*z0JXx43bA4*hbBD@bJ7!a{&O_RQK!5=M`NsFgT zi#EKv8gC|yl3M6mSBdJZhW4TGA7wKH>Z-5zB|48W*qvA0f9^U*Sj2~?PNm5A(Bnug zI?o~veo202KKZNL?&jBSp6Pu0#{_Ggu^GmQEnR`q2?TGDfjUYB>x-!p&zQm%)5VYg8x67=>)Nt;Was!By{ww=>f>s0vww3&|F<7Y(;uD~xr6uA{1qkk%3 z(eA?XXda2?k_899q@TRWf;~lv8oa}E{OsVIVxV&m3pqt4o0wWEvDtI6?(Akf9X97~ z1$$ryjud6+3vbNmJS(nwsTD5~e(U*s+p;4e>OW$PGp{;hGmH^i+5@E}2%hiw>b}7X z*KI%b=iWP!;}*a*W$y%{#ks<{Lp=XX@8?C|C zX&OcqQRT-wRg<)?TzkI2>Hh9xU7EIH1;}TPAXh|4Da1Hm=#$pAy%t;BxXZNrvJ^KR zYZpHt;Ec^MMr>&b67V3>F7=1cnZ5S90tro%-hNiuJ}psgmlKPTxtV3j%EM8wY9k(- z{=43x(Ydqaaoa^{NOKo5+)KnTpQx$F+S!{lqV(PhsLi_Xac7V7lvzQyP-icRO*p1W z&|$vOgu}of5>{}n@j1_8v0~Y!pZbpRe3+iFw`RpO!bOYeiY;I5Z*<&!fApy2io6SZ z67&l_8=gC3GmH^i5(6a}2xc_Z+U@u9S5SYfO7Jgl&ZXOT8{C8>4@dz*cweQ+<);GL zeF0h+Mw+<*?_;?H#@0m!Bk^;FdU) zy^k?l5GAb)my*PCK7E((iG+Nbx_EQ9XURsBbC(mMUfN0c2op{#mY+5s6JO!BakFrV zp?=c3@~#v6gbr&tV>65qTdD%35(r**cz)m1W%FJ(7IsVO{Aj$u<3C>rv<|}5VIbEMbmxs{BkkJ-P=4MF?N7FBQ(PB}I@ z?>dqMuIv8zwAFl{d(Uzk&xLGNEY8>rW5kxmAgKmKn)TiPJMH~C-3Y&rQKDNeEG~C# zk#u4)wzM!6Qx3XsHR(KRU6PTUZ)S{J^o} z#WpV`%i;x}!#>OZ+|;)A1yXuKImfAZkhlka+lI~gNB zE=5UCbg0=x9r9u6iFTuW@S2TI<w z1iEj^(DGZ!jrn~~rp(^IN$kgh=VFumtF0S5S_cz@CVl1;6EbaXjZ|tDYGUp%<)rTB-bn zVvaL5!x*t8H&F6{;Fzc%7O$q&DIHa~UMQhu(qzlPXb3t*-@wGP_k^EK{!P{IhqxBo ztPYUaSus-^WemsV74jI);m21$E{Yeqs3_5`a?s|MY~U2lj})d5R~8b-aE4_H3ADSg zd*ij~0ll(Pvmc#)(y1c+^%mh`#?{!>>-N{zTg4VuSk9E?O14#(WX!$ijLk4cY-tIS zIzXgv**%XE^%Rr!z8ja+*57tgE0sxbVlg+iG*12!SABm)bG1)LT# z9JTdtiMz~EtC`$|b;kY7&e#lN#Fnl==>&o+n*ERI?X0_O`i43B)RD8ym1VxaoLJ1w zOihp7ZdkNGdS<|{Q){2?H4h2tyt~O9sgWbDD9H02|CVz~K@bQ~cT!PmdxIo=^ z6EkN=6B*s8uzO~WMrk3>0vo3-Uw+Gzfr*XD1k!2|VE)0zWC`hFiF$YKkLO_tyZB(E z*^EWg{@(dBZOV#EFHlm*01XC;dM|-47#4UtA9im`%ujxh=NTA;vk$?JAI5vsEdE(2 znhpjEtP^LcudA#$ynBHKt1_2;@%w4~I8uoBW%yvAtFiFGg6sV;4j&TN{@XdMe?8W(Q4 zr03uAT@hcpxAnR)`+?V{=^@Bz!uL76)IdoS$0a1=C7PZ*-PYni{jIlg-TdF051p|Y z#)vKTfKmeld)oeP{>Rbj%hEk#e$apZtG1RcADviCEiDaQdE(zrTi5db_TF}tfSJX@ z&kvs44_*Ob4C(fW`X7iq9J%X0kHM-PP7}{-2Wa#XAc>DodIvjiu&Jz9!iZk zs9coZ9cH5{rcdDpZENZoyU*Gxkk1q~8*6C29`6uUm9Xo^{&?q;JO6Mxe%g(*XC}wn;IKEbKlCp+nH61b;HCrYXptfC7>Y2x;!)R1HN-1 zkXJP9@DP10c=PW2hqAse%-c`@=Kb7^d|;<2Qn?W%53fu7|8|`CSJJbfs@CkA=4yFQ z`zMW4Ue0pHW*8&3v;=ZE1Xp@*&X8WcRm(DA%a#V6O;hAfWG!`KHa9Rm5#hL`p5ygMN5bvJ?092 zEB)N`S*Y>DKWBM^4-ro|nD>PH;V4>=5>7}&f!+PPmIw7iUN1SCw?v&~`{S)ejLz5$ zW5kxkAc+PnaFY-nuK^=$6#%4+`g9a19CoA~EN z{W9Cd2~IiCvx)>inZWlm3ENh|&MFcOGh}13fDG3O2Zk8m@ew&0)ZwnO?@Q3xE*k~0 z%3X_*6ArQcWzjHi=t2jPl}n+cD%?MaZfdA>rSH2Vr%ZqNm#@u}-4}hlcICMwWDpm+tso)`zO6ve{5Sj{Pl4bt z_(7h6UBd8#JcR`}GyT}!a^j5h=EV)mcW#)=KDTnV7V5EjM7DQFQxOA$XhaKiTY;!p ze_ob9%Lay2<(}IU_cgC~GqEu{E{U9qBCcakMP|oS7L+bKcfa>s`v*}2O(nK;{UT>< zhB0DGZ;%uOBGqrN7OJ!MmUnuMCZn*i&vOTq*C*(s;MhEFv|7 zzo0n*+_Hi8l0~C7zJ+q>Ov7!p zR31k`Ng;bL?q9W5<^KIe4i&6!E|wzqML+F8P9af0v8RyU+}LBw*S`}9E_%86v8zv9 z9h;+;Gd9B*v85$Y+JN9wn!jFcTkx=+t=xHGcX@;0l5Q<=CuR!^b78^%m7(YB7slM* zVpzud@;5_(=YDVk!PfMRxg=s%muRVy9m8MZ7Q7-)Cm{Ek8tPdOqr)i3%fn+{6WjEC zvVQGR@r(BbY%7$%2b*gy&<b9^c=iH1~0`{07~>%RfdwdR4a6 z8Jl5@*pdI|WW9P7&PAo=d7Ut6*-irTy-HGo|i@u=b#vPl zx!Epd)gPOV04EkBOJl>HwCs)rIrrtaIwqGkUs8C#B#xg2(msZa`IB~xk!W&PzPOrV zl&<~kcfY0b-<-Dk;w1CB6D17|Q0tgVZJ*>N(31c})^S6ZfQp=74DFnY(z5NdsYY4e zxBaxIx}`Z!XIDyV-u~Dx$Z06~E4=N4l7{@W_UT_72Rt(N}0|(u^5^gn%&sGHuTwB)>Bg^oA#S+*7&mI zfa`T|=bXS2P|?(L@Fk$4!9NnNT(lR9naLydqHzY3tWnmfd&|?1Q_e6P)=7NCAO~iVYt>Ub=R^Qb<6J|{BsGXoHYFf%G*SjAN;H)(VMICqL%5pv+#j=&e#lN z#FoY&sRl$Q`#xA6F-^JquYE+@H#U8STejR`PArB-7KRM7+$~!V$f?XzaQY_qYKP6< zNlT=WXPrbdIN-BR!n;1fXPtz;iWXMFKqKR*}fogr96KBa+DpGl%y8X3?zG-_=0Z5NWW+wJ*`W3My4u6% zzg3PXUE7}ce5?6#XKaQsVoO(`bOOQki+*oZ2tIY+ZL7Y_g7zmi(^q*vc49FxF)*$@ z@BKq@Le}ojt}0o#z03G?jLLBJ^Gr$?S-`KUKf|c(gpE ze}dnobncV(v5hEApF(DM(}#DrFuds_!p^)Qc|sA>Sw2S77dtJ^trqBhJ@M6TYNZy@ zLRnbT2U|CNc&C;~t0$9Zw)Fg0sylA9GxPIY*YlizaHN*P2&B}q#p=kKW9v2Usr;^4 z<9occicMzyBWG-eF=9(spmYMkO7Eu|e|8Z1_q593kaZ2!(s zke-vY@_Ojw=l?pLu^GmQEm=Vl3W!{FY4=Q52c}D}@2mF6&#g9m(^6Ipo^mjTv~-z& za3k+5u(hhvUDHH*dEfj3{s&{+FSpdW7pO{_b063uIwzFQd2r-9dC&5zfpDmUBU{=DdIg@Z|sr(EqRam4QvRO2^XyTupOW@eXKaQsVoO&L zhk(f|b==cT3;T0x{?$o{P0Ts7|Dl2ti=m~l;e9jlZErlkzOS=XTlC>tP}SOe%{FkI z1iM(d`UdjF%1xffE>6s4Zdj!B?fB>Ay`6=}IaQET$Uv>fqVrrq^(QDJls7VUZVA&F+6jVMZMB5eeb^a7TG^> z>xpyU{dwP?F7#wzVT0bcg6n2e(b`{Z@GEi6%?{4&n-lwc>oJ)hvI~NzKhjd)H$@6L z;ZUhDQzrtuZv}p{sVMw>VA>7-Ql}y!t7wVJ_puP((Wwxy!{=i892QH@*OT@TPB?W@ zH6kY_-fG(0`SGOC4#ghb|IL#+tDLbJ#)vJ6fzu3_U^AKhocq$%yE86l&+gsD#ahbn zcMa&wMU%_hl}Z^jj(Q3!m`}|8dHsB!(Apw!J!A@5G9lVv%*JE}8SmwaJI2Oj3E98I zF4cIIDW_RTd(PowI|{GfT=M?vq!Nue$cbfemNKFZKCnGY_%Asic1Du=r40X6L$>mM zOB1`wAIp^jFSI*eoNkVsSQ^@~l`?fv?4E&UruP5kRV@T{MeO~%BYrBXIAb%65nHkX zrxP#{SUAJX^NMXm!T-+W6uYXRTMAcqI#b>jM$PABmh9t3V4G%*@w%wAKCp zs8FT)_@BM=>V^fvH^lQ&p zWE$K!w~wrZ)3y=1%Rm&{NDCbrCxa~EeAMxn$!yenE~PJo<;JI}XN;mbQFa+1)i+2b zOWXIh*o%c8dBfmFsf4txs)c zi%eHKQ(ybNOm)-eYLvUQI}JHt{UMZ;V;4HbD%9I~-rugX{#K?OR>qecES#|!#)vJA zK~fEf6!kLPU%x_q&r42G=UG+pRtrA;a(7}jHnhm?=wyAm%=*sd4O19PB~u?Hl~pN0 zhUlQp+HNiq<)MxxDMoB}FztuS3;81v!%b_a9P4DSf(?89`2BU?4EwKU(^rj=Eg) zxxy44m8fo6>7}9BQ?KNjU*C>gZDCJC-K9KydtB#FIb8MNcHkYw+=m9$UV9ceV>65q zTWW(u6^Klps_^>T$17s1+nRb07jJo^$)@(!iN(~=$UNj$Y!}m=ISf`?HMT49#NK^h z9D*`NC)(?WYm9DH$N3oxZvS5Rt$y;66Dyo0Ip=z{4<>znooR?sq4i1tt8ggBep!z(mw!H|65qTl#?nEr@KH zyWnHO><_vRv@R9K-%L`~V@sG08s|4MeOx4bcDeUry?fTH-*asIpL|!B^))5yUPLEO zB4T@r$zk7!sdrrFD6_qqJo!|i?y0km4#){jgm#_qiE9S+x)%yN;S*aNq6_va2;`db z@01Nr)_xGxtb`+>O;Un)!uxm5d)36*7}uQmh{HVAks*!u(BbV`&e#lN#FivMNeqHd z)UR7x^+TET^XH@zFoA`7(?@PsCO^*(GLl<@KI@O@CClYjf%P5ZQ0K=2#; z%ZeT8O=i;;JX#fnlF(?kD`AQ#G@*%NIim*uOamojfOKkE=U%RQSQFTOrdEz){_d93 zZL)`QP9i6?Dc$gvHA+IWxK+)wW4(yKiL9_e-P^uPku|<~&e#lN#Fiu>i3~&@S}<8_ zQp1G}aZRZ!!tFOtp69*#zY~j*ftlg|Ut44yR9)sAkUH!gpv%ZR`DpbeaG%TwGQ=Y~ zErpHA2r^16n90w^WDIF?i^M!&W3q&-BIb1qDErZV@U;7EM*hNyZ_B0`Rm9vDZYdtOMC-rt8K1Anh@uJV{>n5e_R!koiisCoIap^c7{18 zi0QN6jQ6oOdC(-bFW^}Gp?&O42im<*R*loJ&puEk%Zz#S=(C^k*D|Q>0`!Ic*%m2J`P%X)Ir zS^L-7 zMwH6E_5o{g&$>bOdU8>6THKpXUzHCu+-2<4o4U$!^Gcs2Z55OwZLp`J+1iGM8!P`P zEoBswS^Ph3_Js3w6NO})u^GmQExm!#4+Nh$VtZFA?CVX%SwC%TZgA~?P|l(UI$qks zsBOZz8*?OFuRZWw@vMSLu-CNW-*xbGgdrqV2shWTF_}YBj_6z#cDHK2$98^Sey{IP zkYcmi)Oz$V1Mw+Dbgmq1cM6f?IwK~9WVLWtNc}0vGn%yZNNMAt3t~ci4+)nubA9=Z zfAOyN@VdTB>9_E&iF|v%)_d7GV>65qTUvso4iFg};c2;iR*H0~=gjlmWosuYFInRR z?x`ExJbPz>;49NT7bQ(4rn9cH*XMi#y%HDFQW2f6M&jV$oW}0l+K=yMN7qj*^JxJKz}{98E+F3^>0ZWaqZ4z})tqCWh`IDZv@bIpl z7{54jl})=r^Ua-nCqGCyV>65qTXF*>9|-O!XH}Zzl@U;=V3_kqSlv#>y!;{P+~a0HxI7)B0cj9 ztIyAks{&AOA0)Q_w6GOAr$zM1S;M=PbIg6)wv2nrc;gO#dVSH{)O$(?ZzpoXS$G;- zD`)lbdEAL0NILcnPi*H`VcpZ5Q9ozpU@J zTO!tU$NBhozb%l98KT?7^i3^`_mREgMwC8n;**)m&k}z&9DSm7rDUpr=KeK#cc&t! zmc@wkkC58L^Cz92;>6qkAaTi=X;Qyf(=L`i+WG&SGd9B*v85|eI)UJ+H33S?SlX}O zO7G+CQ`$K#>Z^W`6N{OdiG|Ak&=cHT*=g^Wc$~>hTRvInX-x-8YFT;-o>~N^AB3;Z z68ZFhWwzMbzK`1_eZSe=yn5}W*y0I2%*d%lbWm1GqD$YvQcH-FAS8GQj5gD|?Yr#9 zPT2+h$!E@lhjUa2i*PMrTK$@EYFVb98(w-taMOxn_8gVE&6|SW`)_~i?u^YaMr`Q{ z5)>eEUiX_g{@l4YRe29@D1NtLg51VW`Jjas#wPMwC9FS8=f2Yt3FLp`YJ4tBZF3)J zCpYx!CnB!u5naK+2D|!6NU@fU33~OD(DM_auJ@l_eUp6E=+uToN#|e4RBT*ROZW7& zLW&y{1Plzs-h(;>(vxwk7xN~`Ywj6KLULPQ3yI|XyxC1SJ*_CO?vm;>-(Na&zoKfi z=_EJJBNm%loUs|kh%Mzof)PYsipZ*~D6&m^$73>WWy&5upoOQ^TnZ&d(n7aX=NlO#_x45?8(4^{Wjg%_WG?C6iG zj_OEnE^=Ona>Xf9jkKy8K8m-Z+}CQ#f_;~Q7kx`?e3WcscT#wp(?(}(hB0DGJ)qP8 z!6mtjlNVQJt2(JqHF}YFW@*Lequov{W|n3qolegRA2`fSa(nWdOXGjU$`cOB6Tqnj zx^qQzO$vNg9PM6}rBhb4bZ9MLzq3E0bmrQFRh2!J%aBWu(e?`igXo$%*sM6-dsR^O zC0sYGXxu+vL2l{yig{vN_%2-EI2UF9bIne8YZoQ8oVlsu`FKwr^Oe-bjSW*5J-1u` zlhGNQVT{<)6(psA$Q$0;ohQP3xWzXMhJQ=0zH(jEXbNaF#>66vzvH$8gHc{LhYG(! z_Kl1E8~!k%OiST7o=1!x^1grK=06Q{GSuIezRG2JXK+AObIQ%qH%`w{5*j6w z3#;%JOY2CT{~S`qlGfsP<#QKJ6zgJZyFD$nvM>J1f0X4HNC|B{V*YbQd2v%yuhUjj zu|DUuZ0o;UaZj6cPtO^fVT{<4Bq)hN@S>LamIj{5UyS;az0wobP{VPS5# z=H1CfYacB02^O5p+1v9>>E^;$Mc`pS*io_@e#4KF<@9wIbe<~q=bvTcc}=PQy?R!S znU3<;kW&a<8pl`~Gol+sp-0IIAHE5@a3!xDI{h>R8Z)c*sAT_NKL1Zof&2WD$g$Asby?!11qpB7k;|cbTJ68K1|9Hq~kt)8?8Jl5@*wPXtb%03agWJ3Q z^@?xv3oW|7p3z(UnZ)cMP?y@$oO2z6?Ae@kb-S-@|MK^=72MsA@7`8IzKek==GL!%BGk0I0gKQPklC%m8=qH_iN}Z6aJl3Sm(HhV~JxX z|L$sd+0nGnUw!i`diq=cCMo~hlbIX}4PbPjk`t-?k9!-0h$rVD9&e#lN z#FoN9DF%Ys{(m`;_hK5utje~1KFX2%B(EpgJF!?An458D?z^&A{pyP^Y-fz#`?^KG zG5y;{<9@g3KCX3>8NZfEJnvYp77}`V&JH<=xe`Li35}w4$N2l*`&6LIK}Co>7Jo?f zyOTA)G^J+L9hM5Oo<9G_oDJKVgisE$K}u-*X2FL8_ZX_b*u7u#38$*t#&BSFCQC|DP#~?5zM~c&OPCSdCcd8LR zPz;?|5Lw8@1M)Hh1GdW)hE%FyH~aVMP_vP(vx}1Ii}K_-EgEZjaTHGnE+C~EujSU( zDn7;v3%6AA&6fC-=dt&RzcV(&7_p@eo5rrIu0p^y&KUiB2q* zW)>FRoAyd&tW*gN@9w*)GR>B?$y59zq*V<`IiiPF!mp1Km}~~WK1wh$7Jhw{Fk3DB z`Y6FAk9vAVW=?x^_F3HLqwe$E@-IwOTaI#tF44{E(Mpa%^w43%u}E(`9;q*$9$2~{ zIH-`@KxgT{{z5D?~#v1>X20^HErtY71>l1{Zql_7uV`*1}NnWmc=%R@tq;rd&ky%KFW#jSR`_q z&y4*yHf)Y^JXAGJbx&o-E2p}>J~xrenWGl)-aASP`I54t#d~6A%&(-@uM_NkT$X>J zzS9|-VT{<)5+rqi$cYun`-Hg!tqPsEbU)2kntWhkl%o@iv4y4K)9{<$rbX#qy8Lfi zPV1hj$!d02T|xC0>}Ye*J4UJes(G7yqkYYux0q?G zu=K<(4o}~SBSjtWg4bM!#ZpT`Di-eQU$;bQ8=ut8L#rj7Iqx}RGmH^i+5@E}2;P0f z_FMCn+HL%dA)o%Q*4sF5QOy-_zYDs_g?Dcxe3J{W*ADn57xq`$@J%iv25WuhyYZ&K zDoEcWHCx6!{IX54<95x#TH=VFOoq)eP_kf)J|&LvjNjF_MV@l#onYnV&U~}?ph^?U z^7E6c;3W=9`uNpw;Qq|3$Jc4cix|v#=Of9rY|$xaY=$vnOG%Kl0U}>;mN=hFn&-0J z^?#9dQm?tg2SZ0E785f|&??%)ue1^XZV&E!UDRp#l*}wOt(k1 zS73ARUwaRBxzj;Bx{b5_!HpT{xx=Do_aM$4UfG={UFYemCVo0QW!L(Y|I#kcEvpIc zkHX)W5j}eicJ8q68raGkc1CCl5!mYiOCcn$93E0dOXqqs>&NO7^t~6(e6eTpqU?R= zB7Y)RJ?B{AMGHy_krAAky0fIavuJ~t8>hgE2}eYNJDsr^#)vH~K~e{Z{PMFm{GOl4 zGif`9Q|{f?mG{naFNAcBAjfGDadQ}R$u8LG!lKDtp}Gq_clGaf5xz02Vcp*oK5sTz z?53;|8dNFe{5|OD!iby0MCnrrrMd)nPk12hXggIhUa;Yp&Qf3D66BO}K_7cc`Mlr5 zUgk|;dRv1?L`h4}LFShxd!4Zv#)vIVfzk*B*R1q9ddBj`>${sHt|;7mJcDB)yR{RG zsfn?9ZE4!lk_$D;9b2pRZu`n1AU7%R0VEAUY8&M4wdf@dV!GEp=D&|;Teqpl9$DM& zBq_PNLQz2yITej|uNfGK-AN~UNeR)tp81v|@x`K@ayL6u57r;PXYY947UgCZ?5XHd zsp00JN5=}Et-gG*k?C-0MA(8A;`^Mj8ODe$y+KkCh}>g8PuXwA`E|R)?_DpbOwIQA z*23e&Y;J5k#c9fInO}QLA{Phho3Oq0)>UNi2KAkwi-~cJ`H5cfBWBF++rHv|8!qkmj=$2^x-$=XK>8m+lDXZbxu}X8z&bXn9Y2%NC8Kobma)V zfpe);!u!#xmwwrNztiK=?MfvcxGnwT=#0%UMr;WWl#n3U@r%d$6Kd`k&9km@tULJn zQHR=&?@r9dCT5YQDLGl32XideyAbM@voWhEzIxxg0^~$-?IygY zLP-=3sxyWCJ6oBgJGiC>c}Z)Bz1HM%#%35Jw&Vjz5Fk>S>Gp@Nq{=5%y*JDA`x3J_ z#ik^I7iAei+B6)R57?MYAUn84btbYgnL&C;f&mfn{s&F|?f9ZK>uGoOlC+0=O{O;& zAg2jB*E=^h!6pZW;6go=dgsR?Pv`Gl>lg|jOqBIKsi07?tl5Ncnz-?{;QF%4IYZaT4;8yFd; z7vH?a!FnZO<-4sF-G38*nj{B@Ayqu0w~oOkn?xN#;gd}wuaw{w51w5ts{GP*ceYi} zS-jxm(%)M|W^DbtX&v3u)2#>4ibr(#q^DaILaQTcPxt!ee{fX$9R6o9TLTB-^mN;H zyG8)Rl(S0Q6t~3ate$@$ZzZ$y459K_7yJ9|qGBY0Qe2Tfiqur)M&I5%jmmwN=CHSDhD*<|G@1R z|E?*WI9vKP>-m8*T!s>=3!SkU#)vH?fl>wpi|n5HL(u(FL45GS>%r!m-q;CTvI4EK zF}4iRE6zQ0OfO^xlgCzO+e0NH2X>JB>Kod-iT%d^NW-KX;GgMI7no{#1B__HOJwi8XN& zee$v^#8)o~KVmbdEnnNh8Jl5@*islI&45U$`}W_SpUzO2xFdV}g;xmzo2BR9cVaO% zurx4eUOicNV{%RrC;QG@DmVUY&7ZFb>19J&HKg4GCHgS0*H7{BJfDrHLK!2y^%|9P z3#Y{|M@~Zo+B$>1?0MJ$9jOte!;W2)w$5}m7Utt63JZiXa`^2`N;CwgEFdBcJ-o@f z;rN1;%@<-Xx*oEt(zxfKtAEwn8Jl5@*isuP^+0f>?UPyWFYH!-o8#&G=)k&DCenwG zfl~?zCmS&YfYyaV&ae^9GSleNO%|R0VSe`vmDLUMu4X}Z4Ah2YT6w&Q<|iAWq!l{@ zk7L?L1I2t+RftZMN|BkIy$faMB~o7rsl0i@+O3(?#vy+48sjWg*H7NQ;XhY!r#NFX zj1gO^f}|4=IsKQC&nkz^SsYSdE`O?i99@3(k)5URHrRdXp`u&H0uyUN*wf}&Q%aPJn`ST@4{8URVPk+E>3+iAO`(RxG zO1oAKqGX|WYVptX<-Z&9(NysAouK%`jq^m++#?CsPS1>Qy$L+fa`wUJ)|#T9`7E1z zHTJ!`;f&2NMr`Q{lujTx)urY9*@GWHO;Be$ajZ3Z>eD%QIhe{ zcb&1FXH*ZYc-4GQ9n$WFoWUsYwvCO+0(vUV3m(}I8~GTHBy2oW@nZj{Sx=l!cpZsH zP9X!|ei4142Hg-hq!!_w>$QmU53sD=vn5)E_nZFgvITpXaiowJq44(0GvoC<+uf_h zJBy6Y_H0!s(&;k0{A|55Hp3XPr6ow}0FhUg+`C=$i0R0_ES0+d?K|(eiLT%1#A0q? zV)Cv+>2*Qfj5E;_c6s|tTUYH^@XZ?3@MVH7au9u`2VdkMbYug3kps(4oWqqceF$SH@SRtuHO7SUH8utg5Uo-;CVWsA+W^KAFH>r`)D zKk9bjbl&rh_h(iSPC2joC)h4mSS%)C&3#UI)y;`%)4A?{Q**{<7$dec21+v!TyC0p zYrzupZx*$8ue?l|n=9TGw#$jd)Xd!c_VJmk=8G*e|7&Wotln@-!{Tp0T)-*E5OUVJ z$nWcHjF3jKuoyoZlR2cw5q*=v#%KXHTrgbq%9Fnr%b&eJ>v`?(-z(kCmJ0VTqHNM0 z&gn+28{%hfKD9|v>rc&Po;cO( zJhup^n>WY9Z#3|JX*CI%a;h+J!(^*M>9)Bp&e#lN#FoM!P6v_O+1dVXU@AyHY{T&V zoE;03;@yJXPRvFY7Eu%2?l5q6)VJAX6|(tQ_L!e}3_Z*Unm*nwz_mB`SkJ7iSk(;* zu~P$g{@BO6LU)EU;pGnRc0%{&Vq3d8IyC^E8c3KcXe{rvQlxLewEBfB6@|M^9LzNh?Z(i#Tq0o@-tG(;>Ng(R5uaiNLKKrxxEEDOHf@hqJURN~W=N zZ~r;z!v@m;4YQ7WQ62C5?sgDP9Uq0RJdhTy*4*xP^VPPluIpcBPkVZ?${CwsjM&l< zBxQg|%kOJ8Sr$5aFaLksB|=trvA)WhNGBF!Gc$9JATbw4)@^?h%JYg2NLuKT{dYY>_Z~)f=-v(->W1krNsXTgjhU zp&Oh;@s9Eh(N?l?e16ZLc?O49obE`N^L(4+y+F?_90~1nHN2JlQE2M?jvNtJaelGl zIkNj3PO8dCMMpSeGmH^ik_06&2)_1zrfUWBnt5ONv)<|Muljp|`=So$ws&*0q_Y=V zo^i&>-tqJZU%feI>c93s49K%lo>s8gD8Y(!_-vHu*AVz@ltBAe_|_*d8+xXis2!`x zU)u{A{o5_XRTUYw+&SLuzMBW-E^n+mdZ}Hlea(Z-M#-ncW;dfwL60F3xp)`W>mq%D z@IbB2y0$In1xNI$|8=eFjf{HMbkC9B|1#MMIX!(n4X@Tv(o-MD$EJwI@7+F53w1o4 zx*^+rUX8gkHp3XPr94Pl0+EeAel|&`nHt{B@lrfzF==00$ie@hz2K&X^>U9aAD4># z=Gfj<78!o6NA1JGsmK)`!{l~Y+nGOLCZg^9eF?1XEOPnjiCrAkmc~at_f+ofG?;UA z=Qc*Upb=9JecuPG@G`ieZD--5zoBhs3U5!)T%^~X#ABtAw5oWw%S9H3U03YOaip6c z%t+KMN1!qkxhB0DGVW1QP!Cy)rFF5SxutCD$)L)^8 zkDhiHtSWJ0u`o6=$-j}r@xa^nV4SST`~L~s-x()QfsFpa&RzR?hmFY`vW7x*f`4b4Qg;3JRf=jcyBAu=~1fJb)^P+w7-W9wpyKo#3RJa)s z>{T1(@j~kk%M&3kl#}k+N(vAs-4k_qjeg(vsugBW@}Crzj3E?y(ujz} zd)TfN#D++0s~`rxe?-fghAD=XEiOM^@|l9U#N++R+^bbKyI@ZqVhpq4HO;@8HcOuQ zuVyaW%AK&-Ca^t&lE4S%|`mr_~E5UP* zrjV7I48iN+=a6&79fO}k&MwuMbNo!5|o<77_&MSCruT}`ZesH~c(ssqX+X73& zqYgV`GmH^iN&=+}2)?$`mG?kv=(RV$zKiJvrGH_3c6XK&i=mOR(H*Ud-9@^W_@kCf z-hS5N`=mhS79)5sfC;2D5o23XE)>*wMflQ*3A~fce`Q`ZZewBog`6rzOAYL2MT@Z= zl7$4nFt(!>uWj@07q0pGmVNaR(b{(cw!E_G_m<8@P8DqM``?gC4KbGUpAKo6%q?4^ zCc^C%DXZpj_j{DrZD(wTF=9(U5GR315A#{FKWd+rw0t|{alzwI^sECM5W!C-@Fs{D$39pSL=^Q(oyV*XE3c)#RG589 z|3=fEHEVJX7s)F0sG8-1M2(P5bb2XKaQsVoPG6Bm==Om;E`@ck01& zjikMXhI<4!k2+3Ca$>QxFf|st8+7ecjNgenL5Aw_u8USVuasU6NjQ+{Xrv)EF|O}8 zhSc6~75%n&b*0<_iIbDI2-!sH+4JY2q#MMU;dr;)55=ad7`Gr%LuzCVlB{=d;oJ6B z%KP%?vW`zjHx#dsVcCKs-EfD&nyz9j=VuvwbXJ+aOLO!cfYkp1CTZo)0h;5||zsg38KSK%qTpm>d*#6u zufp{FOqhD=ky8af{Qhe(q(XzYbk3<;6Ftn=^a$sxDV-9Ud0^uDyAzzT8ODe${XiTH zBH4a9FWIupI!Vv$@masG@#o*Lb5D0-F)}eR*}YnQv-|>$YrAirO@0^YR3}#E(T-f% z2-m!Y&EJR#g04b=u5Dp(ht1z`m&k;ze_6_ zc4_NnU;OysjLk4cY$*(sVjx(&+4Q-9fSi!~R)>#QD|*&^uM%tr%@$)ja7^Tg52*)^ zHO%Nr>YpifW`iWNWXSd3sxK{^vQW|uypbX%JO|H#W221}1_n_LUFazcqIx%;TD}P~ zIeBKsnzt*S7O6aUn)0yu299(i{2Sg#;Vs>MK{ZH!m2q#K`O0}6bMns4mV12A8Jl5@ z*islI&49@AgwQ&MmhOf6YPUXk-OV>65qTPgv?It1^VRJ%#**K*E#@@$h-cc>kGoqxQ; ziN)B+!ZLSS-c_xyul<*b98a_MKh-BacWOU)-w^cj0pWA6;qx~_Pn+SF5AdC}WMeWj z1sl&J>BYuq4rYppUs$gwzGIu{^w>$0UU~E?X0=zD++B~Hh{VKSLFaEoa{OTh2$re7 z(L}_+fOLb!wQag@&vkuIo_#h;=VRZNqesQgJDr_@oQNcBuqUFM)}CHBo~-z(uyJ$E zq_SCSSkA>6J7Y795nFNtM=O|kW4mlKZ)0l2!KGdk_a(fg3+bT)mK$n+BZi-HiAGBh?tZp8VV{ z5UDuEi(3-C%X%lp?enega|(O1Ww-l%XKaQsVoOU9$AL)p^RlsF-x7N5+{CPZ)!Y2q z@S~?3v{lH^*kH%G3ES`4RX)>QHUC)CnwdVO;_pC>7R-}=#AM77OWcS%=_jno@{TNX zb>B>ux>vm>E&6Y#n4LsUPlzc&+BI3kWCEc}+_0VQO}izNG#yuY!EyTPn;o+>dYC?} zDu~!nwb|H34M%#CSqE>jNX12QyG&z0{C~B9{>Iqp9P*(Vi+v)Uu^GmQE#-ky5(IDg zdN1-{<)SauD`et(rlma!&fK&W(h-8p7z?c3O2lw&*KwY|xh)6z1v1Y^eK&n0e)`B& z4&>xPbcH0>KIDdLY1*pU%>TXIru~=dM|FAYWnOnb|1Zv*fSf$!&cZ7sl;qLN)5pg1 z`-FYI$CI8{EtlnsqpnLkV>65qTS9^)4G?)z=L&~V>pJe}=Esv%+59bbJ$8QX#A0l2 zX707}ArsSt`O~NFop7IRQ@6$KI!|8i>y&l>=$v7P4#A0Y^W|6|y z#qye&_txv{P6v#;M~EoFnPuKZ=JP1 z6Le5c9HU2LM@;D*v~t3K8qmOx>XOjdDV@Q%#r)AG!;Wtv`f4|tGXow!wIQ6Il)d>9 z^0;QZH{X8U%$P4f#e2@&IfYHm*bHODmhvEJ2}GJaoTS-XIMKA>`XYrb{8_K7Oa7h) zo!Vh$Sts|=&TNH&S@@L;nhig#PB_lAe+RC%plc?@R8`oR%pikyc-BlBzjSPrJ)F~R zDy+xxW9QO0SN8VD4)2mkOw|s$W|F2Q(X&JMie_#so}j)b-OS1?VBdSArq{?RN3|7O zNu=z3c6#rf)kYe7A9Jib{Ho-EMZfNar_R_6W5kxmKxqboxfy~2S4_Qry->noSw}$8 z;rWmGG@Mw>%q>h6kE?InnY!%PxA($vcO&iyYS#o%e#}R0h&lzK~G*>{ZuW zVRLi!Bx}y}nTumM6>J}E>?fRt)K9819a<{hc7e}er}4J?tP$on*LcM{V>65qTWW)( z9}u~q@bmczylqXaJI?sjWi9WBS!3qx#B6C`SmN;VT8ghx-P`B810!OcZn-Mj7^Cc3 zyLXa}$q2FtMpT4{jmZR35Q!)|!mq;?V*JX+WCEFj64_u5-?b)u^*(IZn(*=O@Lg+S znu~S?-%ip^@^BY?w#4LFPrm(PjcN<}lvQGyyJ5T5NM8~`L92;QWmVL57yfz2XTNbj zTavVon@97*;sTViO3M&iS*3n*t&#b|K#!AidT$$?IGZTGosWxM%^90vjM!2nD1|}r zoyG{&7jp7G?V)=&%;PA{+4t^T3#oM(i}sQVuk;^lPaR3A$hr38O~b`Uuz5vY<&t-K&yik9n6$+;BU9Tn_2L*Z+$l^}*CnS}HD>Xf}J3-?H!} z@~^G^!F=7$dfn1W6kpvh~g3+x+^GOAiXPMt<^KskQVFLp5motbzFgdEI-p z_e;v|^got;SLfxjuKRwYt^b#bFgFg6@kc$3}+10)<0FvJg|hU zgrny|V&{Fp3Kse#9G_jiJYkK`n;ZA&9#t3g_;Gi~lp5rOqt}JKV6oNCc%yY)$wGkn zoSLn`H};#FyS<&U8ODe$iGh*~1owp*75skuRLAMf1)YG~>t=lLSfB31Vr*(@%xnMr!gW1?m_ahE5rld@fugicC;yT&QoDBF?B3zyGReku z?U~_|hQthNp^YHK^#o${NkiA=1@*NPyIpz;vsvVPAD`Z|yL3Hr8ZtPCJq^{L>G}BJ zRG01kRT-iU@f<6<9)ADhjLk4cY^e>Ben4d1dbXFx7Mh)2FS=-%@8b!E*MmE*gDxjE zG-chs;s3{5-*w6|w2DM5=SSQyldeJ@01`7=4&O{5F#RBW07&H1e_IR257PU~IW{r> zJ-t!;T4IjX+(eE)yp#LPLT1H6N*u^0 zN94;a#7wRdbD4$lCD#hs>TrOctGqT;`0XBI4(`#7y2pmr;m>6`Y@R zc#DLb%D0KkmUgDrgHfRw}MW#+xOCy$lym{FFhUWj%&&~wAvU_Au?u^YaMr`Q~ zlzt$1!kR=0#@$|Kt3tC`cl7RB{*EvCu@j4_rLpnu+<6ACoGV^CZxB7}k-7S#R{Gj5 zlrqO$8dsUKBs8awdzXC80jspxtG>;=^Wn%1#vzbe%uNSjnS+vA9;}|cc<;O7S3SH- zU#lBFU38DPV+Y~XVqWln%_58WOS4LS|CDB=D;rEsOxBs{jLk4cZ0QP;Qb1%)^WJ+# zf4uZu6vAK^t#6{GW-3=E{N7ZV6gWL9#CJJy_vKZEgwqIMByb)4{Kt^eJ z66V0qFXL2CVPmp{rWWh?wB9$)6Ww%wqCkAF)6>61@lgTG$M zRuh`m6b)#*bHOD zmU=*`0fH;139PPAI3E%ur&M%bJMfZkgj_VJ6=Go={>*=2#~G$y(_F0D5|>LR8lSr# z4ql683Y|h|DPv`&VK7D<1x?JmsRZ_Fnz3X$P3k zOcOM9#%35JwzLFE9U$@xOTSG&C0=6v_H4RwgyckBCl*T+17k5O3oqaK+ju^G zl{Wcf={0SF?0xWYW3UC}f;>F%8>22zb0os>;a9~Ss1L6n)qOUQyu*?96xdp;5 z7Qk{1F+FAg25|KD+Vx{W0;ih8m;CLV%aLpH>{Ud_H{{gf)&n2CMXI4(;?{6W*OV33 zt4rEDH2;sjDxUG@ubeYB!x*upD^NOt;LkU9l_;BWw_iMdOxbA4yqZ5kY;T-cEKDp7 z{mar1$xdPr-nhK$@+rCf>}y+M(!r_4lt3@YBh^=Ynwwl|=c~)hj5@A|=r!Cyj#^Pyaf%mdcf;At0zKLKaD|vWLhE6Av zetOif>?AMQ9F-?;YhYg^7-zxjFRFY$`6}{F0?5h3>n2k2sO>Fbc4cX6K5_O$b9$|s z>|gJBUe4GIW5kw_KnVka`7Ah;yNkQlAGFd+`kbrfdGE->iB8NGCKhq&k3Hu<*ZFjy zZ5Q|SYvE?qzB`-1Wr-Q2KP2X}iH*q&(l!xdYhYutfUGSS3DGFr@vC^dvf(q{xl7&) z%bG_o&$3^NoLCTjqrusd74ta_oe83(B};>LO3ohHKR+ij#1$OdEFREO6=h+qgM57e zj>O{2W_~E;_v!f4jFDOPdVMRVs7y#!FL%af7$df11xY9%vTe<8p@nC8thbRMeaJynCU!Antf8@9)x*i!VD3G?niuv8YwKc9W zd(yeQLasyeZWktH8trvt#L?>TXMz_LzHD2RugUdk$$2mR=eI<)&}Z55i3)R^u^GmQ zEtP;`9fHqSUf-VbEajh_@Khn?utRKb{EiocW&w>&6J4EIJq3;Z-&vf0^44Zw_4MjB ziy$QhWF?$fz-{>Px1yD+;K$#J>|H24@nPUfnP?6}BfXCcZMRq&3*FX5PA#J)1p|Xv zz*p$;wH ztL?TkHp3XPr7K8E0g+tyHDhCrsb$Umr|;Emv~lJxmTWiBrU7Hi?cG-kZ?S#Lxwu`2 zujTkjvs>pPJi&9u&jVp#5M)Z-8dXmkyx-Y#)W%`#k%z^MwzHafV)l(PVbH-*EBewJgNslw>ze?3Z6BsbBWy z_H^H0YBYgiwLEf}6S@T6FGfi%?3HKd-tvrej*dT7_MM|b<@B{_Ue4GIW5kxOASnez z+MnM!?|{IS6}!y*oyDf4-jrE9>y{IY*s4EfBY=^;j_t;z+E8N zzLM}-g8NEXw3i6f1kH2_VcN6qf0RY`R}Wp0%Vu|xiy znoeuG8F=n-(1OrA$O$L>F7|{Yb57cnr!r*K4zsDHT}HMNA$DBS)=vY|$cM(I3>+^QxlrvnKIfx2M zEb;<0<xN62nDQ_nGdg zWy4J7%9*(tvLR0*6v{kQn7-71u_l~aVq7n`B^S3&wrRg7AuJ(~Qk;5(F@eJ7s$_ zN|RVD&K!D}4B}`9ti!pZ-Eh=y_?~)A@qaZ_p0C<{`0?B89Osg!&i#QS4aIfByWuge zQg%CAc4fRe_4D2FtxjL=ZPGMe{@odyVT{;P8zlXJ$S9?`&dV-;Z#d7e>>69t>;2ug z6jecc_bm+hcJ#$4X->6lGMx7yTWf9F<$4Y1?M0AI6A=TwVhKqatF{StKlnNE$D)14 zS-PRDJDKLAuK6c6;Uv_I4)ns0F%$EZx4$hAgdNwejhyWggHF1EbvTUF(G=&Ditji%|yRT$C5&md1lVo6(}J#vwUKF|ga z?M{{v^SjTm&}@lPbVPNG%xRu~=?f+QEXdl3BNZicAf=+?{PS8eVz->NAZJ)1fgzFsP6;_SDEJL!@p;}-VA zuFlvDW5kyBKxqkrB|itd@d&eeJj;6ZL@iN*jcJ_*3uwKSk*S|h;6asBPkwC(exb8I zNM>?&n@1Us^kbR(AT z3q8)224jP3mTcwT*e|+puFUfPEzi4ib~4yX6HYhjlQgYQ+`fPRgVUx*dO|jf!x*N7 zT)pFr%`ir6DGZWkK%|uUvnAK~cl|i5=ril{|2cQk4{V0LG z-UK$>J5!#bU#SRAH_*#ZM5m>|FFz5?t`+kC zlypF2Df5vWyE|o|It+T+9t8&)iDfTkYxB0RUHEzT`X0|3hmCi4aUEEKW5uu-?MkBT z{Ujb}gjiEfNexERlBi=N$9*P;Ka(GB*jL?h#Waw4PlF2K^pqo0DDlDSkA_au$q!)$ zuOo#G>aEq+Ib$=75nIZGq$LnJLoU*i)6^tyqtM;wh0{Lg${oG%+lj@@!puVGR(x1v z_2$2`QZAmI9{4cwjK@8cwKrn9UlHf<;oQof7qBtu$*tG=wwdmh{wi-5#eKL!@MJZt z6Bc>=&@LI`+LS@MkdHp&&I#*deg!Ys61MT1^|D{pZaxPao*5!1oV-x@xHD2glq2JE zvFx(T#yIV_6-SxwiP`j@Ouo9p8Jl5@*pe71$w08CPTlUNRC&qrk5eKJb6LMLKEZJv zwD!hyQ_SxY>r?YCJd^!)A+kWp`NJveVC1uC#0vD_XVD0+uS1+gGp`+f77cq&3*syq z9UJ&rGy<9~Y>beOn(&8A_*pbUEk9m5x=fsP=aBaq&CVTK%5x3&iZtU|UQFczO02*g zdKQh?a4et_%~SezZ!^0mEVquO<&j*{vZEoh38%Ayy)N+~A3vUOo8sXC{v6hX=054H_2+r>A1xS!v!|4R|Ih2uz$< z;M;LKeuH7^-uOkqP2LJDbFB%jpdDgaZ!8U1w%R;T2)cwWue>gbs z<|`tnmcicK7As{KoXu_RvuD#c@y>U?vu4dMk>VqQ0sj(Nok)tAVdJ7Y795nEb<1Qdwenzw=bAnT8% zT$i3@^!3j@QofVT0JQzZ(sbTC^OCa`E6+V(eILC*q2%)B_ol|k^^>O+8zW?PL$D&9 zjma1~<6ddT#$*cF6eH076<$Aq+0gn))Q)w_nXCSn?`)r8yK!aMh5dIP3B1_75;;8) zy`F=DcC}b#0IYtJPv-#z1_Og=)G26s61jL6nw~^YCPO>;Vnm+3hjoJtecIJ^;S+aQ z8FKobFtu*35PM!bal(`ktnNP>0{Sn1^^iPq>47sg z!x*upJV@Yy$TKqny~|RJOTRxjaLs>i@2zLH`SDIHrY0t4k&f^316a8~x#Ye{XI98h z-hV_O3{pQqh7`rB+u%!8MOv8POI1bPc~V7I-))jM%`oLypYmv%WopYTd6df+MpFv| zgIM(f=u%aYO}n6%FA%&>%wt_|TC<>^l>1Uf&Tsx(q#@k%%!JvHFvW0@DS<`4W!t%zcqx ze(+vqk8hy|S#?kSW3tC|27BE@R%xO$`)@=!lTp);*x!xvudcn~TDk8ea>8lQgqJ2L z38%PdW{t_R9;a^&X*VLC&){^lR{86U%`ir6Neq-^Ab3>(o207bla>kHHQUpC7?}jV zaW4R$Zf?41_w0=}z9#j}$v@rWx(*%vx#a!{aKgc|3RSF$3BHz4;BX~;Eg_5ck^uI* zLKVh7dmg4d)O%N&`*GvXPe#K$9 z6!R=xft+%hlCh_pOy#>%ZVK#Oxiwwq%^O>R#T(YjyEa) zwe%F`^cSYTRc%R$}~5AGJVR880phx*+C*{ z0vl`ikW)oVCH7R&oDyy-TVZ#N#qPrsp3gsk zIE5HNQixbb2^*6or2j0OZvL}|`}E=3ORHM_|E#(3;@Ga>_WO5;FGEIC2m^yyM<476 zfQT08(VL>zwy9iVxW@Hi|8hl^ynij%i;ADEZ9=*4sbeqp6tX&EkBlDsWG2-mv#(TK zD_jvNYo+gu%`ir6X$g`#K;+HTCCO_ftiCigGi`KL+HG8T?#O&67E>c*;~0M{%{0mH zcl~UwzkKozla)WNUkFYihR|gYUDMc@EFfiw@ZtSwr)AY%?)x}bqk2i$U#|q#&tF|# zkW8lQqHO@U9`LJZ?JM`%jpjHnaE`b_7u`}U!p;tdFpS@ z+mE!u|4!LA<-@JG31^(K8ODe$ErHSo1ZyX*T;a9i=>3^LcSYHD+z-5GwAa^(#ni&k zc+mv`<^Qji9#Js2TGearbE0vhK4iP5A!N}ETS)v7R09rRm%!cwtM^ z*>|5>6!9)G_m{^RuHCy9mN6bzkqBIkGR-K~a|yOIop#fVSf+&#!?;5<5h+F&E?K$B zBl2vZ;J0Sqnw7jw3t|Z;qF$AK`>tPX+_`m!f&A0QCp--Eccw{xb;f2GBevuQNkAZS ztxSlKEc?klvd+s&J&zs|7XCf)qZ5mXk%hTK+TJ~Wt+zwpOxReKk)V}XW)rviE-rd6RQ;ay2C*bI@297;x5#QMcyrx@M$ z=Ky(ufkCK`pA*6o{mcrRlqT|yN^GmJ25MS};0VhtXYsZdoa>Jk#k}J)Fne%D-^A@5 zj?~g01Rr7PRcQ?W-+weQRrh`HLzSxL8CTlhs(p0EW*8&3bOi}o5E(cqP|MR`bYaB!gKz$&sEspG8&fNNa^BLAV&U?6qf8&z2=9rD~jZ2Y})5L}F zHV#U15@c3Ro9yp7ZNY?SMds?j9YzbnFF9i~j1gPH10^H~c3k8Tf3je+)E?h%m!>0A z64ocnZgyg^Ff=vSWjlLq($aaC7&}YUTf_JN{PRt+4cx|o&N2!x|3J(#POkcOsfO|M z-`-}?!u(bfq>wlwcTQp1xR(1Dy7<#CWD-#|$u^1W{7&Wfu=C#?kAiG8{Q&^%R<)G!o3DMvUFoux1 zXCiKo6Pr4RjS(^$Bl<9}Gxc=cv*=qKuDeu{mNZ4FzDiwai;{+hb`xjnHrUc(_<Uryk%{J|-EGH2UHfBAW?IxDZTTyyaNTm!?8k)x5n6$O%>!-AwdkT}bczm9@ z*K7ZyL(bR?W5kx)K&c0UxfR!DUp1X8+|qez-tDX3styHnDLS#3o12)Zr7+EWZMN#B zbfe67hS8~mANHf)9(;rYUQ@yW+Sz?09htmNQ=5ZYPcZM!$bMV>65qTgro^B@ij_xcB$Oj*`3^j+!$WH23KhtorxOiN(^$(k$EFIo47& z-T2r5qW1UQI$Kthf{SLApV%xfSn~)=YkSC7eoN;Z zVD>#65qTapANF$mt$w=mksnK`_9R>!|TftG%yp*HV9XAm2kgsq6$EBe1P-DcU|{qwhr z)|@wea|%4UU;^pji_Mvt@!q}8)*-0x;+oRkzMeNu*}wN8VaiF2lA+_FUHr`144vi1 z(P(a6DY?p&>)?)O@sg`T{L1Q{Rb}xYr;0h(;KdJ0s<^yHesf30sYOQ~Zk&94`nzMZ zZckQq#%35Jw)6u@5g_uqN@C6i3f_2G)i_mknkWLgPxg#~0>Jl2H z7S6dhmqiDqZ-_5Zz@Kwpz~E z3}eKWu0ZJof^`y1^_xlr*B-pfubW`+h9{F67u|NinqtH8e|!};QA zb_Je~^T4Ua4AM0cTl5sZybkRoNDYP*=Kt*tpHBI)Y5!-a%e63KS&ougM!QT5VvGJm zm)DVS5+wh*xX+Ii&e2STDoI zWC>XpF3R?tjmZ)^_r2UVced17-S}0j4yA23@Tonw=1tlqF_a>QDr3Q7%hRD#3j%vR zpi>KC!@F7Qo_NG+Zk+kNTXFlZhO>yhJI}Yk2RY#^N38!ws-TvZq^*f%nYcsw+LABZ z43cMY$;?d-n(K_sFh*=i43cO-A$OdzGuNwEHL+8AO z`=@`sD=T;1QSa+7sW-rl*_l#V1*>=9H}Fzm>dr zGs-E)tHj{_CzOP?n6c;9Jk$H$+Z0wY#`->&PgZ=I?2OGYMr=tEl*Ay|^^~lV{{|%+ ztK$liZ)W{du@!uv>BM4aYHqCNnB}|F{_I@m(!#Iu={M9nw$#QGF&w!1Juw?s3S_wW zCeJ$?bo%SoOZQpcRkiKZ|a;8Jl5@*is%OErG~}@9$QwIM5ljZPkOR znFb0cI4_1pAx}gg-{8)~*T}|X46V#?-Qd2eLpNS*)m=k{M*+uL-Yr?YCn@moFiI)w z?4c78NH@4sXW*DnN}1q&B(c_B!g%$q)LvPO-DggfvZW%YlywuZr<4zjwo@+2Bt))V zaaR5W$KF3H3qDS8#%35JwloDwBM=-u@$+Ue{R7V<54W*NuIA(4zVqrQa8Jt!GG)b~ z`GAed1hTXbbZiNe8MHYR5Rv@id#;tlbh{PZHT!PQmPxczjmSkw6Lf7ai*3k+ZhI4h zZ=*z7e>0TY%fIs4*C}>K?D>9lLc^b3Nz**aTA~Q2i498%Il_{J{_#l43kNJ_dCe_j ze9b%68Jl5@*isK9J%Gs02!pFV7v+|SJlepjEb-#9A#+_NF{Ov#WGOaA$ZkpIl3nm= z%;c{4^N-s~&y|1bU;HucO}nJM%hdHZQBn%+8pw!t3+?KeO|=76ddy%j%+$!~S6(<} z`~K*b-nCDE-S0w9DVxq=D?K(W5qfen@7#??rkxLk5A~$!-)LreCFG3FFh*=?3Y115 zSapNXj^|8=e)HAN4d#n;+9jnUvm3M^)W|SxOUn9vigMnXZ(j5Kzo5Ee|L3EA;1OZy zEvO=?FA=w(Zdv{(@DXEQaM#mkw_1M3hx24j+V!M+Xr>UcEeD}zWC{J<3q2!CY~WHz zEdT!@mQ5OWOM9>dOg933@gAh_Ny^wm@A4Jx%79&L~IcYJK_ zTkCDT2}g?B?gSq--mv78LxSt)pzZ8mgR3*F--_;jAa`byGd9B*v86pwT7uv?=Og|u z+cot~hS^KWY)QFuKMwr;0vfYnf^L5kd1wSbN}o~l3Vi#U@TZIL?QbGc%PQU_xZU0G za?ZPGd-r>n<3I1JX)zw&=|gO%G;I4Dw;=31N9xZ(eJOidAL?8*$GGEs;)T%JJ#pJ= zBypsVok>XPBPgl$RvFXT-OYz>c;2rJ+x~6w+IDAbhB0DGNszPwB0rZ37N2)CFupad z?DLw0HqioB);UhhmWGDWds%zBHH(d9Gg1TnPAqg)mzz=sPB_qEV&1)x@L^(JuO0AV zV)j?sh~pf0TWd4vGJNF}{FmFOG`-j=^yyjNOq7E_sk4R#>u4XzjTy1sA+TX$ET=sT zvZ_kr;(i{k#N<_PPb{~06u!v0_@hWYa>Ch-*#Cr*aKitj8!bC@;PTaF5}ukzzO7Mu zwmsV!n_-ODk{Bq-K=8y}Revp6!&$bo_9gSkr=IIJ5Y|O*_KH-`U}G|dbc;lMr@%YS zBD^PH&0fyHZdkKdWcAubH$-GVKUnU|&pf~N;w#o=$JnPA51%4NY;Os)*^4;%lTJlU zX;kg~gC?5-y8VsX3d@ruxk|I5aio;JN0Ew{u!-r*duPP%)^2GNay|X`f>-xS3ukPG zF=9(okW>O9Tjz_se3_}e-OXgi3c)>j+jm}=c^$dw!kH6-si$M5B zc+*AjIU~I3!Y+E;s^;UycNLp@)gs)UO-+4qeS*af1C(?F?=Fe$p9gEYki52h1eP#T z8jdVeUpK4G=$+eTe&Fro2T3jd$mwSPUwC5}CEaY^wt;cB{S3jpzj}PV-=cnmbOr8o z#%35JwiE_RF%W#9(b;+b32kkiH`!PId#W!zueD&l6N`zdsm0%?Q88a0JoT8!ZD3|| z+wFp}+XXF9ih>>(%X3c^w(3(%#vFb=k?0ja_%N@?v3c&@E z6|PS2J?~$A8%KINze8JQ@c-YW2yMVsO5~!Fh*=C50aKZq-UPc zlhjjdE}Y|?@M+J)C42opl@>d(m>L@x760Nh`}{Lv$!F$<6t5q}pur zJ=cVtx-RxH$gCGenZZOVagb8Tk^FQ2^Y|ZbjY-{Hq;*B@{i45d4#t(v*bHODmX<(i z1A>n+DVz!kuQuPUr0n|rpw1`b#nVoJhj&dO!?+Ais%%VV(7}I&Wo%5AkQ4LRr5exO z*luV%dveW@H6j;&KkYn_*Pzykk|qXcEp*I70OEC#7ktoj6bD&5*SP8bFZXrb6FeJu z-@dsyndKgv?=0j}<5)Ai7D7oA!Kd$O=Q{Vc^wb=Yde+vaxLW&TyE8V!7_p@uNT7g7 zlg@zUyJvWE8Gigc?_$C<_tOO*lbu*Bj4UkJN;;1#-WPcW!{BrQY{D4r#@~y6qr7m7y^r1p_ zwKF!u7_p@#P}+dt3D=jby+rMXd7_a>( z%c?k2Ic>wGv`VF)3w2P^4WeW@RX2Frw}ZcAk)B<~Z={xWj9 zIfc0Y5+&X2mAQ6ZU$=Und93BPC5?-wym|O1%o&?ujM!2bB+YUP_~XGGT9Hm zU(RLP(DmmwGidLmk%i82kAD92C5vx|7MZ5}RNirY-<~*d$zlv$(0OJX8}w*{xOWo%|bP9bOh!|NWD6e3hsFW&Qf^*U8aUyhFUwl((;W&L%=W*8&3v;+xw z5b4Fws^-XMU3j&T_ob7O$fNk`83Il$mIg*f8K;V!)FI3d7ey-D&qcGSshLUXPkyyG`SEv@6oR+z5j*z@b_x+Ci^B2t zX@+Rs6VD$ksQ=eNTi;q8BC|4VMq zC_fRq?O@N!-{9d}L&)j`u?xT8cVLL}wz4ro(h9%qF*YU(NNZOtA!%Cj4Z)v*`>btp zdj7Ak6IsBy?5P@A>E@y^^t?n7iTALQ1@AEsNSg_UW4bxj5VNVxFv1 zYxVdgj&yS|5-Hu7eLDH1TK}+%jEc^Y3rsbtTn-@;&e#lN#FoM!X$D04Wbcw+S?k9A zNxx|JLI1$T@>O5{LPl>PanIL$1b)5@aaW%vyxq&e?=`uWizUNc$LihJjawf5MoB7{ zjbP`?V3|QgDq=>H3WF%}4VKeV!fL*x9ekhnvim?65qTcQFb5(xg9_|ZcrZr_@6&L8H7E^fc};qk`|aHkl0 zr82{IZ1)@K&gfKl#TUmM0->q87^@)$Tq|pBZC~0D_50qSug>{PUcSF}H zi2C1xty37dJp$qPZY|&7@objkiIO``_sibQu&#JYI89ugak%&{=ZT-MPAxw$rSI{q zM5R0Naplg~3}eKWdLZcmM9%eKowO&LJ3zo@^H$aapHu4F54~_=F*7zcu*;P*er>Q| zU#0x+d8-t5uUWfk9TT`Hrb3>s@LNq80%owmZZ#FnGP|lG zc)q}$L!U7yzi`ss|F$>l3qpovD!Secz15VAV;#uZX|klRcy-to`4zLjUuXC5czXHH z309PSut?2Yq>|#P`_tvdv zW&ZW2z2*d1Zs2`$Ws@A}f*ecpH?J3IZ+&>Y#p-%5-;FIVnIi1%$*Aepj)(SK-%5i0oaswe)^)OpaC<$0VU^ z(vP#7ml$ZEmKvj}g+c7@d(!v2>fDC(3P_kIrs6oG0BGno;TpZg)Tr z%tY?cu+Q&;ADGGa?lt_tOp$U`*nyd1adM?h+;cWC|1V!YBV=X|7yFLc`#xEt6f6&z zhg^qdP*gCB>b->ioOfBVL_hPF{Fb9FOrMnQ;z%kFLg5w6J*`RW*33F#u=#EBUE68q zS#9D+Y)+{-V>65qTcQFb5(vJKofFb#b=X$Oaqb2Gs?)8$>xe@#kTy5wU3*J<90q_@u43}eKW^dN}|L>idp$MH)v zcJePdfs#UoOpzn@WG1vNGboCjN7j+94ox91-Q@!^?%bStaM!E%*KwqfCnw-V&ZA{D zCyXDaM=otFd-A%H-Ra-`srE5Z&e#lN#FmyoX#;}2qNj*TrXScXm$TyJ3e{VGWcR(f z8hK;TauJUB%y@l;F{+Kg2%q!6yA$!l~uiw_uUL zCyc$npYNz{*_SqB&Z$7px7E(r3}eKWt{^D|M5d-_2CQ^;EPnDK@fm0E6qVE(XGict zCF7C?=`~OEwHwvUgciH+a)~;yu#St8jr3wK&J(eb-umyCt`772YhHD@&zz_?hk4SE zXB{ZT63H{rM9(k2cnRA`PvnL)q&3`we||CL)Wq}V&UxEE3d}y|6?8e&t-tglazc9< z51(H|DwdvoTmAIqin9)9J-wHui_UBpuY3Aw+F@sGhB0DGlAt68!B^SXUl`2FJ9kHv zu{nCuOy7I^-?JbmC!xd>@Y4>7IhTRBObPx7|C>P{@ChQ>yl9!O=}^W)y;nl5rd zchMLTyi;C zYLPb=>di}U7s7gHM6QYlUF%FZ){_W=Epz)k=^P(c9116H(S< zyFY9)X6Z8J;X5SyZ#!2PMZ9J7Y%1S6uVq2K2xIuAocGUQTiLMOPJrp<3w5j5(h8runEXENaVpg{UDFwxVT{<)7$ntzNY;+8 z6GS{h1y&v2JO7T_)Z?2LT#a;MHa0e|36Bpw@b+r)`3;BOtPWOV`#kp;7g7ECPi*iF zC}NI>;TuqdlUBnwponIfNgwE7TYl=o?}o{#x1_Sag#BG<)qql;A^P>73b_7ZOfTpXzoSE?Awq>gVyiJ9gXF@BI<9v(hHU8Jl5@ z*peP7DM9eFykE8Y;=y-zIov#Vzd7Mrqs`X`PAtY2CdPs4np(AoJ$&PLc76>vy1oC+ zQ`Sk4`V87@`w~vt=C{eye+b@_`rO*9qoV7vWoP`PfY^N~X=rHo{J#_q)aJJr$D_Bl zuD;MGufAu^v@XVeLD&6faHOFxhu}T`Pj!obvH!dHHS^4^Cu@ukzP+^EKIZgGXKaQs zVoPn1^aCQfW`6NLzxbiBCl+I4L-Sshi>C2e?ePhf%o-0>x#l18 zofZxmVuDPUiT=C;KOR$Lp6`hwfsb^|NB(Owf*{r z8+%_RDohdi8FWG;>0R!pMb6j^W5kxOKn{oC+o8vInxE2tqPO*yrrc+KIZv*lV@@n4 zW`<^A=d|l1b=WOTbZ*2Sh-&q$@c48e+{%XT`^R}a>~ACZzJH-T^5GlqMlX;l6V@|0 zmT+o~*pvekxUx}F&R}X3{r2I91dABrc-X<(C=$IXQfjTs@Ba0#+J!Gx{=LF1Y10X( zoZpjMjm{lq_^$a&bAPP=<9`~9QkP7c;f&2NMr>&e5=_w>A7H7iV-k zV>65qTbcr;5ePoFuWHHpxlha@Z`+@F#lR$_mO5>w6N{y}rTLHNQ#qE*+w#X!Ap39e ziyfDK2fi!=FYmH|)JS6gr#ZNWzv+_-J2`)XEbp~t&#uQT%wLI;Dn@QQ<^Klgr3YB= zTPM^@zv$e>e17_OV_U%uv*a9YV?0j$L>VOfe;M9RK}i*Q^Oo;C%aEaN+AdHe`0jG3 z0qdg|&e#lN#Fl;_DFQ_PU2)39aAmH6lxS8bTCuL3>(E%!FmkcPsz;mwohR z7mu{i*@mfMnaq%q1+sKh^w3H+CL?GHF}cddWDMDTD;OEe#$*CfBhI*njmZqM#X)e% zBh~G%S6+B%dPcnJP+H!f-Dl6PpSuVp6^+(HL@)OdXFLYITUjKmph)dY+bRF#d$Lzg zO!|1TfOBTuJ=6)ZXSjGf@^7V^1M0)In#)Q;XQFSx-Q!p zlr32tDdgp!OW#W+_Z_fU)h<=k_Ndw0)5ie0C5t_Uu*H7;e{lP?FXo)PX8Shj z@xODr&e#lN#FmyIsRKl&NN+PcS2e%Gs?oMP`^>tmf{4vYPAq2T=9b;t{>WVO-!$dp zL7s)@Plx6N9@;n)l0qPJ`-mvY_x#Vkd9lL3`RmOmI$pOL?OyjE3njh` z8EGj*oFf3*OBRt9gkIEzBZbWQsC=!{zVXuhB!`WmN8T}%J!iQ>IE8T3yExxE%6|QI zH^bxYiIE8w(X3saa?aQcW5kx0KxqSl&mO#RKknRzeN1nyMP8b{x_!LvjGPmTshNqn z%u}WRshfE2z75+lC;igdR;w8i>%n6xMvwtuTn9mmb4AR~_uDr|D{V)+?W)#}C(W)= zU)(PbTxt>LDuSIagl!q%fR`sEq!uQH$!vQK)?S=@=K5~SG||)d#41n@2ghEXaIHO< z5Vr8vy>GRqEcV$4pU%svut+`WjLk4cZ0QP;Qb44^5tYvJ>;t#BDwwBVTK1#jK+qW* zCl*5sbMv>^YVn0S5oZ=#Zmm3eQV7;%fCJYf<~931d++|jqn&ppH#+%CJUFz6 z<0JO+M4ab5tVb-)wKh5ZiR~qqn{UECHZSB}D?cf;gK?%aHp3XPr6o|>fZ*(P?Ls;a zxD%f$2inQn^2x|VrQdO4F*7nYy2{A5X#!K;qLR;whI}O}YM&-fhisc8>n>z*z7=`f z*A--Jy>BBczWFmx=l=Y+E7XHg(h%OB54GzgYL_zNe1~A8DwJ%CfwyZ(C}nhdbe366 z_%dm$aF*h)IhR@k;%=dwM}#P4kkb&qaLrz+XOgq8Op5$uFB3TRAJsBmFLT}2={OfsWli=jG-V!Gkb5lce^%F`WRx_?7v*cH9)!cNp>u!f; z8hGRuy5*mBzYSu`f7^7}mVeRRm*89e#RcBnc$~YXnwxd*mM|yTy&tM4H&!{Nk&|%5 z1=*;uN_`k59Fy--D^7ncw`lusHm(;?H+HKD9pl$;Zu8TENKzI4!K|v^hwD7u<^kEpUTJfD?a(WGtOZZuXu?w zHp3XPr6fq&0FnP)Cw)AVKchb_V%8&-MSn`oR(<^k9+b6&47rKA^9XI;peJi2X~OGS z_2a(yyz4Xi6epv^J&~0Pv1Nm}s4JcwEW@a5_;SLaW{Jngqn3PPQ+)ewe69(4Fp+TF zi)JLhaTH3ZSyFpgWkpy<)N{>49~|B}V>65qTPgv?Is|{#{BqfU&;7XilgVZJXEs

9~0WVEHmJ|k?QmDc($$YLrG3FYv+oKJHpl? zU^!i8$hUJDcUn~6&e?G{vxH@JQMA}PPu-hBIFgh2c6d8iG~@8ji``nUZXW@uWs)Y=$vnOL&l^1R~cyQHh*Bx9auX9v>Mwy;9S}sh`4~SS&0pOiz4md^`2| z`<;iY>w3=ryE&<8lcy-Skb!RO7nhtMY_NkNZ=r?KrSC=?FHPW6dlN0DIMh>xxa2C> z#{Plp{XDF`85t3|as7&t)d?1VXFl6F^8)gGAaVsGc@`;E%oJT2R(rZxF<;p8=uxqY zb zUMjEl_3XQ?^Pfao)Yt1u>CVnJSh@!#J<*}k5|=&zJo*Hy))YTysJ41AL*?-w@aP>S6!$$HSt8&OeF2%P+O=dM;Aw zBR2g3>@<17igbACBZlMBP;mtncD`zenC3z4>##MV>65qTgro^B@nqZ@{qSr`gfU4 zSF@BNLYx*);F;x3TB_l?9}cgx&{9o}cej<5k1Kug8BXSKXQ=P=uUnlrF+M*(j+d{N{wcz2X;S0<}b2HyfwkWBKeO z?TpPZMr`Q|lwKe>JMgQU*-^U6MGil{S+OIB?ZeCyWCT^9c$Gv>Q3 zXN)p9-jJnfMmQa)+a2YHp3XPr5H#W0Fl4^qjF7#)vIlK~f5cTpR3}m6i2pzT%EoG0pcZ z@^)M8uYfF_gv32D`>Q$o_aW`Co|_uZbXZ}s>i>)CuYMiAX|qu=9_92aacxGj_g9bT zq%xsVeaC9Clj%}xZ0`Mc`Oz5jeyTol!J-|EJ*fmZd9BY&@?o?%>HQ(~dV09NxoLni zHp3XPB`Q!Nf#577v#+0or|~{LBKlYK*u~RPZWsKVSPab#i~~YHAFrxyag=ziRQOIJ zGvGk4jvaV{$Ph9CAg-&!#t2#7A|{x^#$*n;ZB~@QosAK)`j)#yX2Ob)*9&iJ@bm0_ z|0Slv{eS+%BroJ5W;mxCaa}j)MWLccIVB*$jkLR(vgsiSS9jBU6B$MPbna)EUVhSX zTqA5Za=Ov&#-46^C#MU4zucp~SMziJ#(tl5FP8*XJ7Y795nBp_cmhNg?D)u2H7#qy zst1kd_@|v?*}}SB*@?x>!qoCeWW-G7G~t1bYA_WgFn0oTp>Z%LJ7`X#l~a; z8NcH_{GE--3{ohG>!(yE2+okL%)Wki()C^5k3R-G-%O|mb`mqy>nSqhvb1@IQX>NLrMH38l1q&xM3iI#3 z2C1qbWr%1*7JQYzp!sk3Du03CF!(Be!7gF=Dt~dqNq=PT_g4fxSk&?KKo3(`{BLXH zz3!u_2ow=wB$qkjhHId!{6(*A3pDu}nE&#Fw(_c~84YI6hF`e!79*!3L-_qC;wa4; zf%$XyC45`)#%Y7f+TOV-F*;A1lbx{{#)vJwfgBFOnWD#EI4_8J7B~Jx_A%pR^|e>+IN|zLS!#E|svWyloKJq=Eg@@6I2D<= z-g@0PP4v%$0Cqu(N3LvQy1$aYzjelD7$dgy21!96Qjl%o-9^_Locqpi*j@0~eNO1Y zN_i({BQqnX)Y7dbnrj6bOt_+tuG@NeozWR5NM9RrwUW4*9DE~ySX)qD9!vk7C1wdM z3|`7J)h7AeKT;EmoIvn5ZN$yYq33ss)jx)=j6xhaBu;YgX=qngD8s3yvGR zsI8vGpW<)nIfHpUasn|+!&X_DxHeBJnNU*3>C-YZV$;ILU4j-yO`Dyu8ODe$DS?s( z1WPmJKVXlab-vPa$Bq!?7r(nVNP0T4SeTj_KDMc|-{#*P_4sG&mv0*PnToie|hr-3(B0a8ODe$y+ND~A}yt~k8S?* zq@GtN=xSN=yR8?U-#-H#z+h>#&MV+o&hlmHKU7L~EZJ>dT{mB8Hqul9iPsg2TeZR` zn1sGN*NW^}E_h3%KK%!+mFMzW47t}2hP|GW5ky7 zKq(1=BO0EaF`4pa=0W|KPY>C)KkRvW;gS=Jg@J{Uc)#VO`jqBF9v^nO2(>BBTD1M@ z8F0O21lgV><|4|*WDZ%mC2n)|&EL%H;@wUMwTeWZwn|68XMGa08YP8{h=z^0&3kBx zBeFCMTH;VRrG0K%bjkw<&chs82CH`XIsM=E?fyH$Da2N8A8%IMdu@;IA205NZLiCZ zKWJ=_>x|7XMr>&bk~%=-QYmI3PHS!ru5TGE|J{58n6D?Ta$+$yF}3)+?);kKb?rwg z%a@%uW;pO7NTT`Q@hiWIa2m2tT9cP>_LbA=l!XTcPTzKU>cg|`$r5L5 zhB0DGZJ^Wx!IeH&t9DIqT&#EGCrhzMRGyyMLm4L)BXd*B*7OFC*0<@eL~k|vYUh`( zelflHCb*P=ZdyXV6kXiWdSVvC_IZUL)lEv}p0Rpxjqyb!NaG*vlp zDI{Rm)_UVj){hEA)K7g_{Df`qXT>tYDa5fwH>R~FZ{O{r3lj|2F}J+Fcl>JqM`vt? zF=9(gkRSt*<+m5)9eaIgi%YS;%3&=Y|FFF)LJ7BC7?&M@FU}J=HV?7T0k!p#yGHu^ zkwVdF^DiB(fAin(33JEB8kAH+ht{yTbL{YIy>vOm%O?j-_sMm5Z60MDa4LTK*KXFr}vId{*Kr!X>PCI+SE8>GmH^iT7skw5cz*sghhV& z&&0IWjiGJAt5>c(zvi41i;;n`ai!(AfZh%Zt$V>+H}%zL?r41OaT=ULphtL!+%QEP z;o-hjVW0V>vQS>Gsk7`VA59^kASSj)E$)6EdW454^39{7Zfnx-UOu*K zB2#bq%DlQ8Gvl@(Z@(8u8kceZhm=BO;}f;}TvF$;?V5YX>Wp^arnC!M&e#lN#Fmyo z4u{~AZw~XaEp~I1n;mvuKY!!%*XLt5gL*(l7I)uWQzKVqEdi`YC% z$v!7+OU8$MTgE@hQ}J!W@l@Ng?w>3ne&|)NPSfVL2`{`>sqf&#VrFP+elaemvaPDG z=8R)eR4WOG{kmZ8>ns=9#C_j?mNU zl%)`HA7?ywIbqugH!M@gJG~d?f(+#u?SEGtU#ENTOZ$)We{j@FNM(*s(fV}Fw~mvJ zocPft-Q+Rx$}?ucn*Gk$3}eKWmOyC(g53|?w3c4!Y@V}R_tUH^>0X;31~Gz;{4g*) zecF98!?u%;+~ZfQemM1LgpP3Le(*H6DP$c4Pr@8FCNsz+rnsLs8t zJ`m@YXLM`kkNm2qYLVJS_nlbGEKQBI|CR5qIODEv>tgo*=gbAsrkj@JfKv;hMG*m& zpZ5mJ<-DD<4_Xf0fiIkWNB|NHVx?WOS=(& z9HohgO6!fv`CZSFt3O>1c|X_LdDRnM9O)zI9a3qsxF+>u^x4D96hE;1@#6B^eb>Bq zi!(OE7_p@!NT7hoxdEm8^>r34|E^Rj%B=dmnCXmHq7#dSnW?Fm(&` zwruCoQ(RUDj(+8uyixnhqL>9u_WM)_rEHbUsDX-Xok+*^J`^vEg*K4I_BS4B<}SZk7q zzXQ@P9a1&Py31nSYjm`jo)^XLS#W-D+htRqxyWS$QksagfY&6UG7d&BEZc+4F9p8k z=8J@WuXI-w})bzb}C;_7{(pjMP8A*kkvsPxoEFeLc1$x<076QV2QS z4CnGgJl2>BYngDgM4wLPHp}}_dVMWx+M>F(O1`Y>FMc7HA4usYwgRdASbK));|ISx zwq8@?B|H^B-j)_UC+>{RFh*=C43uIZ_|v`*Evi=SXQPfzHM#zz&dauTmxmLJv89=% z+pMX|!KUerGd}&Fet~V?t#z3{`;bRo`PQ()??@LB$%o&OF07ow#$*Z^OB0U|gx{qm z_?!`bmm0h1@yq-t%6*o~yogp={{7pkydcM;O(-{DBT6Fi_-xq7YiK5{M#8ejaYQz zXSd0zE^x+X7$df{2T4sJ@`~NP5Zl}Wxh`KPd5dG&J<~s`K{h@^=X3-Zm%-pe-lda%)~4(~Q6$oNqq(B9|41R&|Md^ziHo6gIw-Bx?>awEyB@fIbZxWc zH-58++a5d3+kjlMBwoUv4xH9iR2lDHn-|}AJhNcBzWJkHq%#E#fos~+{cHtWJ!e$k`foUs|kh%NmF&j|toFJF%FUnwf-V+&@3rtvki_i{f!fv8bBuRWm&x?G)%tU+!1< zp{8PbTJS?n!weCJnx-D)O^tXK^1t)LpE3roL$6oIdY)?aKu$Qs7ANAVx1me-M_RRl zqc~w&{z+BqytM6x$KUGB%+g)B|L*&NoN&?<;l&9`!U+X!rFh*=C43cI*BxCBQbyYexp9Jo1mA%TQvz^gH{t@UD zWphgpCg)qmDg|NtkMfyFKa5E=a`-YCJe&fZxDn4Xg70P(S?~eAn^mObdr!uhHNRiJ z|G>R<_xD$xZ%U;XOYY|>i^M0}AQz7K^$=S&Z-YqB>n8oLtzBt5rwKF!u7_p@* zP&$F&-n(trJQa`WH!1E~Rh##TWv_Id7&uKphuB2lEr3t`vK$M8PyMp?yyIGxnv~4Z zHe=w8##lGTs zC2UM4kOc%H^V->%OiVzAGqC5hurZlHYAO*O8#X2j$iWK&nl5aNkX0zcA2QjPEFn8S zgj#;wI%wv1$MQI%=&j6O-STrS?0%?oASX21RaN47ebB>nkyfP8b)JW&RaLsIJ!^>k z$~vc}avM8_xQmZg>c$`!KG+jlK1*O^&K8$6+gXBw-P%r>#M4QUp8Jj&+G=2;9Wd?3dth?z^XF_}Tqgy7l+HYQ8R&L5Fa|GhSr zl~v_9avyy%qbcv?yf>v^dr-&sX*TyqNtzHZxC@&p#(N2?INmk+G))t-ANn4}O{};z z*=dFO%w2Blzdo6Ze7PBp!lzJT(LdQ|?_U&cz4zG6;PrdmO#)`GDx9$y#)vKTfRh85 zST48cedJAbi$sqtH==~tS4;om(Q#rivM{zRssAu>x!exp&VJ)!&IOv;5?r&UgGc_M zyEep&KEkh>5x(J(o+MQ#n55kkY-4?Eo~KKq|3h|^wX*|NJ&6}{!**>9@>xL~9i!mb z@AGWVxgI}g6Y%h5VEcBVJuh>SOO0YHc*h8-dMcE7D&o7iiOaKS(Tr&s$|sKN2rF>A zIb$=75nEaUCk`;tf8J~3p?x!)rYvNl^6CY-f0u1@UnIKV1=r#8 zJ%^mJ8ODe$ErAmUn2^cO{`Y?Vrpwzey?@Rr;Qq9YN!Y}R#ni~e{P01KeLkl@ram~f z;h*op#}juabNhi)hzX=-5ibX=zlStP#3ok-if`8bb?92g%f=%Y6Rte3VbuE^fYS09 zsBTZWKdcOapFudJx;^}J%p;=&17ef+_03jyxM$aYWOh4_GNil?-t8%kvFj9@u4}&O z{cJ(!+>0FVt-3#$&T+5p+sU zmEo|4EPP8CQZIU_CnptK$KXo`7np?JW7+put>+VCc<(D5$*B@?{(osqLEb*eOH=af z((k1>&i*GeSL$YZjWagG7_lWha7qFb?%VHdGL3GYxM8Y!{P+9`cQrwQO}qJl=I5UK4Sou%m0);^jZfP_~3szlS$kP*O-$ zlWUu>P0IOio8Qau75Ur?dcu0%8Jl5@*wPX>ae#?KM|?U@o@@&U)%5!4*3)wT`$Ol4 zPAuk@hNk}m*S^@op0|C0*0hwisTsT8oDlRSwI~v=JwakoG-Y0}Ak#*Tm`%oq7G`=M zez9D1;$q~4M#K50+DF5=C}R39QIpZN;H5P82aaugjuCI?y@xrp`J7z7$2ns&j1gOs1g9}D;dNVf!Up!tSH*z~rma~UDC@mGgV%}0 z)ZEbcixb~3&sE!nZp7%h&vHm#7Q0tZw6i(M-;*wHu*&(o4CP47K`=5yofdS1H|)fp$P3UDe`wkZfBDL6!|f?- z_ikvt)lRLr$ScCDtV=i*HO%wZzqn#~!w(nB;#u*JMZf!dYR0{A#%35Jw)6&0KwzS_ zb^Q}TKRL_4&M&uSdQ3C*3hfktR9lcyIo7*p;MYWp#$57AcYnLdzefz@jT8IR^W zXTBBQkYqpc)XqbDGrAuh96l`*@wSDq^LVhFB1igEqd4(p$^Y>Af`WFh^R2y4H#Z1w z++x4sFUn{?Qc7w21TRZkPIx7+d@_S!?aK0I%X_?-3ltg0B7P2v!LB{-q*c#ZFEFf#H#Jgn=8fSe^mi}WHv}4Pq^RAA{>$a>^LQXA% zy`~cHHizv&ynR*(98L_P{=jzDnV9lw?M^z2U*J( zt=j|Mm@fM99dt##xtad`S=NTTY=5QfIrp1+7I*%#IZTi}h|ts`@HzsXTEu(3;i*Ne zHyYO;wRnDgc>^6 zJkFlzeW&S0nBhaANF1r97qS1nyXZ1QL{n<~S*Zf+TK0JXQH!J=PpfpsW*8&3bOlN$ zQ2f{1)pH@I*Sbl0-}L70wYhWXNthFhp`npcD4TzsCTq&A1Tl6KrqGmK&NqHbLRvhK z6B0xOgSUCQ zixz9^s!V3^k-z!z@}y%Sh1b`KhT1t}GmH^idILEef|WNm9Qc!$_|wcgiQ_qAyW-Y$ zg0@a9MrM{~i=@hzO^a!Mz3}J0<{*x{EH}kfS&@hR#JVN!LLaYhi``)^5e_%J~;Il^j1%ZWKUYX>r{(u_3;xZci&9%hc|^#654_J znG%y8-F1|`^*T>|o9IgS$Y-9;*bHODmLwsG3`9=+Z}DQ&1;1M#pX$H-|C@33v)lg4 zkU|O4;1MlPgLlJ(R{6oZVPfiWY|w5P@4Y}+H%#2_`{D@Q{KWqBrb$ep7gvOoRupB| zcq6BjA>Is{q5?vhR<=(yB7uE%& zJd;=@*>K{u^sFNq@=u(x8ODe$O@Yz~1c#`FEK{!ev5Pm_o>$W|Mdi|=8?V4A#RyV; zA>S`S%rG#^nlQ(3Lq?a{Gx~Yo@-EI{BfX%y|=NldXwmzRj=T*Br)bm8@TXf|WPSCA(ndjc9ULtgf-;Q7406ZwjiEq++bS^7;3pOh^swnn`@d z3}|^HvW^>;hTcDeO(js}b}by8^hd{6*_(A|wz~#zQ*h!*{~45Jvj{m2&3K8eW}3E? z!6IhM^m)4auQp6wTqRl~n!$K#hBG$97_p@`Q0jr;KdL{^-kEvv)7j{NPx4!qZq%Rs zVWSg^iHV_!700>m=$8x!zq)*wd{ccXW)hX3w>TZ~eoOOPs-;TEu7FfpxpK9E5h#h5qh^bH{jRJ_oyoe6aJrf6&pp>I{N%IqRZMqJv9U`e zoL5=3QPUZlVT{;P7%0U+@C7B|AD!{vET%nwsw%&8!JeoiEoYrrOe_s7lJkQ#$~SZF z`RwE)B=S7quj|v#*T9=^Eg@45;`24ws^t$W>xO{Z1Cg6EDn{(lk}fcYT7f-|sWu!=7E_QJuuM^-e67mS*Pr?RTj^Jk55+=l$M) z@v)kRG^^yzz^TF*GQlmr&~C=m{w(GYQI}aI)6EN;v$xi|WS&Jy6+>}oZ(#(ij-l&B z6w08?pOoltf;VPs#XXqy`cJfUsgFXy4IE{~!fN=S%>2|XAGUrqte!ecqg5sP#FFZ! z^KT~QIb$=75nK8Jr3WaU^YyHxv#0}?qk`z;|Gx94uGUQi9nWoUeo5``%rnuKx(~bx z(D2KeBX)3>;eO;n8Df@&iZ2d<56Td?EVN)RkFV^y#p3ZxFFd|@BsplR2cHg|658TC z*q{sr%R;e^ArFRx_WOBo9slda%{tu2W?7s)>o+4lpczL(Tl@qmp{-w5*KpnZ`47SW z6Ar&RsiUIr`X;~`n_-ODk|Z>dF)%O$zu$OmgY*;5tgv+NwnB|}ADbkg|(24>uYbz{Bh#hem=Y?kHLw>(8$bU zRq>}2z2OlI(|n(vykA zAZ#HQ3lHpY8pdPLi3pLff-j~s=1QHoAL#yIFVB)yY0GPM=0y`uL@V+|QWP#tYExG* z>6`Y&Hl;`+XMS+HGd9B*u_ZS|B1)Qi@yUu0yXMc^^7rTdKa;ktJ@MuYa#CSkyOzYH z^43gkZOPU8%uT`vwtrI0KXGfTW-UrmS>-XBROAF;YyOB&D$Q2UL-{R&8%oqa)X4Wc zf4;FgQ+4M@%6@$084n*qF>9 zTfW7?XS71t!k;d(FL@ir(jIYdbR&w(V1>Fag*F}Y^ijN2*ryLrt79F7Wj`*5h z*iavqv-R*FCPBh%Cr`xr!kl;cb@2ygp4{=x@B6N+J2h~moHbWC7$K1(zG_zfj=zd~ z9or&5DxZFSYV!lfj=KR7&e#lN#FoYoDJS9Twl$B+CAP#UJ;|~8X}((XqQp5T7E2>T zOYwwhy8>MI*HlJ4V{6xvKBc^WMH=#IQSo(a;rBYSeb&9hnVWie%@z)4tt&aH7uMbX zJfW_8=&V{_JY`x` zz|IqUS$Vh?g|OjB9UDcEQpXb}8HO3o-|X$w9-hw6kgT}Px&MYUHp3XPr6WY@cy}~k zX6N45=WoS@KbW-UOx+Vxx$BA~JGSH#>hm_oZnTM@^K2#5y3j}>7^e8ZrBk@2~aNX>kt2(AIoKxS)_uTSO#a)M0~3W z^jHznhhmVLCbTSCKKx!FRvP^Gn7`FQ=ciW28~-o4avn!w*_sb8S~ffFb?)c9Qui?G z-kjDTzsCO#3@<-cIb$=75nHlCB$lJg4t|+zaLMbzsixlTlWM1}SX5vIT6}J4%-{OV z@mOKS4c`f;H@#VT<>Vs);k)3b36>)P#J78VsEnR$u2#AtB=LK7{AOq4>+b}d2Sp0m zo`mN}fFY1VB0M5ZwyvLeGAUN}Qqj{bx6jNgc!nc|Y@djfLb8seFh<{FEprW9czK#x zhwan1s*29o3}eKWmJlhVyQJ{TI_|IYx{XyN_=M)e5nJ@rBx3b-v`bPeLw&E1F6RTw(Ww|hArojlh6>a zk#;simpX{kyGE+-b>88$c4?pQT&6qByzL_Q=UbxOu!c0tFFi%O?15qsg9)4{Wxfqyue6*a!-?eJQ(P_rH?9*`GR#F$e7;hR;cc5r@wx zyqF`s-gaG-ebwcbnH9)I$?iMwMGPqEpwewi1jlBUDZ-P#Y~Qt3chZTh=jP7X3}eKW zVi4(IQn2NO85xb*d%{@G=J5q@J2<<#094sn7#AJ>-lo62GfUyZgb;&gIleL5U40-; z6G&&A+j$%OxJB{3Tj9qo@=T7lJH4ZPmgH5rJ^2?|-#jg?UVUetJxXf9(vB71d!GEI z3;4(PsojnpxKd-$j{ha5Ef?o#Jv4Z8oo`ak;c0@?38$8QT+fun+;%vqzv#F(N2vA3 z%>%1?@2qylW*8&3bcIMQLbvboe@{@AXL5gBwT$!C>2W@`Rs z*O^A^3;(zL)I1;r?kz*d+r;-jhL5)iUKV3xvVf!_(bRMB@iwu@ZE`0ry>I0e+3vTl z*Ujt9uT~!b+3Tx(C;u$jeDW zJBtenXN4X&>~U3{QlafKmkBvd9E!kJ_Z)C>Pzj9+FuKlN{4Q{DY-y8FTiBbu&e#lN z#FlyxX+q;#k3Y+o_OBwhZ9nUpedja0R65Ct#lq0UeA?2+MblH1W=Ce-4!*p7*?~&g z6XKxK1Ukwm%BjG{WDe;ei+WnIFy&M74&Bb!3}eKW#2|qTBJXG|PW$%RM56MruAFVhtyL;L zSEf6$m|2(@E?XAfI5#d_cU9o-Z{Juyx1Iku53;uex>!M=r-+To1kxE2KbD0!I7WCc z{NNbjJDu=@V?@0Dnvd}ZP3}0}Rj`@MXz8)|s|y4eG*ME~Fe!e-kF~%SE6``P_tdre zFE}rnT2J~|sr)U`wl=h$^@#m|w6htGONe4o=FwV*kj<7e50PPNHl=bf<` z#)vJwfzl5I=T1EJ+*VQR>$ZE7Zm%-5y>`#^j3{!IgzGA4(S2Me&YkFtbBp;C{FC=% z$D!W4b^B7;kkbU#v9}W&U{#VUtUDxjQ5d>5S484H^r|+oesOk)14Zxqb3j-^ef+Rh znE0m!hx*7$-u&+6n(F;+j^U=kQ@-2(|GQOmDvmU9;x&9^<;X-Y>k0?e@6$q-UZ2f; z;PAXU_lI*hoUs|kh%NO%0vSYBv@{7BZ*hI5;Pdp#F5TUgH%^{k=EQ7iY<}LQR(7{W z=fcI?8&dx>6hE3hmF+yZzYIM?M*P$f_^hCKOZ^kJpu=pxS`0s!+Z^7TT#zCxa7+U^ zfnXaqA-xAQ=&PPnccHU_B1^-dcjSo3D@!qefjBuU4ovHeSbS=w|87g2$D{T-{`7rK z*>1uKd{5v14WDec1=C-VM5~k_~W-;bQd{eGmH^ix&kK@FtMW3#3;_R zkE`m7HV3Ct+9v)N>Z_2`1po0K#I_;S(;8m!d@S_dn?57HCi;-@Nrm7;54IK|r-?yd z#he$0r3u7o4R}}D(rJ3<@%8ji=~LZOXRCZ>wBaSq2-Va{IoVEHW&#AQG z`DA9ziH0B7v@!85J{~*68Jl5@*isKTIe>|8$Fwuot<~JRBPrryT~^QrwyB*Vpk9xK zfpmiMtjbx+r^H;mpL}G9bJ{9=B^*-6K)N*I7uDgn^NBNm;@#o8WtqACH?f{Gv!-Xh z;Hvr6SBacL27Mhf@TJB@M{Elqp_Rb^9ZMqiv`xkUSYeZ zmNN65qTUr7q4luEG?KRCcM^h~tHcnr`)F+t3Z1fD=`(-kM z96~1Sk;=wo1g%MqY+z$DhIECw76!60SwhCug!ahaZCp?`_a*-Wu`Xeo-RGl{?Hg~W z4%YM`e%X^B>~{vlnepO-HGP~YkN)v7u50Gyth_(9ttRR}4@{pxIDK56ketBqbnb5H z_CMd1UKGat+#w}*YqK*p!x*upBuMapNZIs*e21Q!9=Ge`_^@i)LED*SQ5$h>{ow6o zho8qGx^5EuJPy*geq3ru%f7JidGBhLzIyJ}mnNDQe!PU7oM>1fUCqR|^@G?x&tR>P z43}NdO{!E|Bd_YzfA#Q_luP1s_v1)TSMS3sq{|cLPM#Z?r&J-5zy6A0wTG6yN zRSr3&+~9do}?fRx*-Hn}V#6ZKcOwdUlvG7{>B#&4V6MT|K?EM+|Bo9mC=k_hh83%X`R6~<$ zN(03HMoE5|e06xI5AmCiV3RzwJU`+2&yX2{avN%+w`QCSyZP2y;kEE84`reA@{N9vQ}#)j?{7| z9I4)USH|OdbC*j{#i>K74^HpajqmJha>iyDBerw}Nhu&Q@K(~2>j&4rFYGyE`k^%N z({78(PoT|WmX=vYmpP?%+{&}^oz1&CT9viGyX?i8TJ9Mjr%e_{l)Dphu z%gSeu8*_5xLJN|Ep4IQGvtV<^W*8&3bOlN$5Zu&X#A12w*K4aYRn@D{acQhx#lF~y z*~rlJUzWqX7|C$g4dR9;N{u%WVPd9Vpy5uqfO$NyrUGpU_s`5t>sbIv>6^5?fZ#)vIhK@tjx{5MZx znUG*~757vT+4+VocF7NxWje8#8km}0_G)}A{<}f4iA{Az#t)yrtUBKc!Knp0N{eem zPW(}KM5?=6eRXB(O@HAB%VwFLv^aK^a78qjik3%91wnzsz#ulbM&u%F9nblOe7efT zeZ}p_b8dMBMNTCgspZiFq@pF+KdSD4_%)$F2`@a7Bot4p&04n58Jl5@*wPgwC_vf-mbDj(gp{15YwIUHadF0G7$de614;o9 z{OyW>_M*#f3>IdmYi-y5)ey@Jz6(0gi4jtfh~7HJ#t7M=E-t-{jma3Y=tSg|5*w2# zWModPXc`-nIb?YO%l^-7Ocsz)Ic2_b6$7p{re{j_Wl$3`41)4&|@*m zvxD3auZrVc6FH#G>pZ#hz-O%PB^;`Ecf5dpYNm z;neW2{FAH;_Fio8mlrGKo1dBeTR0Y1rmntv5)1y;tGAG?I&CFceE3N$F)NK-V zeFx8?+!FlK4qK`6TrRO-!}3d8e{S5rwt35Zdmg1}RxYBeLM9 za|@dPhM&$Y5F7?Som;R=7=Ajp_-pZr5z=OxC%36Qn3y70a(Lr~l}y?w_r#LXq8+)Z z=(QpAPz=#)+di(HBC_HAit82oX0S$=ZMm{!i{eV;y6JTb_EhAfdFo}fq(^n;e#xa7 zr!{YWJgL>|jLk4cZ0QY>fET4>}3i}_JT{f|gdy%sLPvuFoTh7=FW5kw{ zKq&))PcrKtkO(kh>g#;ry=ZsHMJ0K&HYXNy19P+LSra64&d+53#!ETWc7e=n zaLO@+v}IWL+psYiL1qob-`BD+LJr#z-F=CT$pX^y5f^yVT|Ox_Rzb)c@7`zOH4A#i8k4I0_b| zg!BHcQQ5uYdwl1=^juWDZi{ip^L4>=~F+= zXOLh`^%dX1<&%E@>sy`bbq)6ma3rEHF7W#4rZz%ASS)byJ z%`ir6$qkZ#K;$#OLl@gti?mOVZW<_y0baxu)HfGdt zd@Ho*x{B267MuP6*6S9mNQd{j#a6$E_qw_6hr@f_;tDG8Ubpx+*#$FuT~0B|`?*IS z4rjB@JuCH^XDV`fqDy=Dn>no4P2?pa6phu;u2+TJ9&S1QeyiP@D$7Wo-~6}Crt!tu zML8j-r*Bi>?O~MkwD*tNTgRr|lXtXEP2QZm&0S-uyM{A1!x*upJWxu4;Nu2-xpC&( zOG<)YzZ79i+BHRX-a982Q$tIGx;MJ<>L&|~t&U%kT;j0cTE)b|0C1@UJ!w$*+-o-2 zNrU1)a^WWp@}0GWpEStXzYliOpxE1XYm-CfXVclPa7@^md1O)W6E$Wgl$9^yKiV-j zKjUA|KzgTYI3}X?iPKbNBqM9HbJQ1do2)BYvEXABaw7V16MG_B#2#-T({r>)_NM-) zi^YpC?`Zo~?2OGYMr_Fql7K+u+V}TmqrUq#nsc&gA334M`*lm}cPAD@3j?#gLKk0& zdl@n$J~p-XIQp#SXY23j#4NEA|FwyNC05BCrT6#rWN%|@*cddUV*j+o4>kFaODh`I ze!tF8V~G{9GYs^u{q`>9-NtUWFMh4i^n}LZXKoYhgj#VVwBJrhwcq3un-{L$b6BX< zt$$6^6qbkbUJ^0R*bHODmLx$*41zWN_ny0H=M^z?O+xg#pUv*2%{y#mx{skOv_UGkkkZrNN$+np z<-Xtkn#bz>A$^{eEvo-3}BJ_erOG=|Pl^!;UHvVgF8cMG#ISwg$`|Fdlc z0`5)OA>^U&_IX94tXa>gfAcwzQwt@fkNE#q=)4xzO>M)w^vV3t_hpH@vP&u_rFfLH5AIm~*gQY%)Nf~OhB0DGSDF>EuVNV|t zERskCi(H4qi=`ho^uO94zh!xFwx{EVTTaf{3}eKWl0Yc~f*bbM-3)t~@OJ0CZ;!7` z4tZ#9yR!(X@xpUY71nhZlQD-kUKp1hV1rGViyWH=@4EA5zJ+()g}ytxOUUNVtuS+5 zpuYXl`OTOqCSp@Rq)g6L>7F2ZA6gZ(12akC$f5NW_Hnm356?mU1|(oFK6sI{VxAnlsR>J z6g;#`LJ}N~u#E`t{uG^(P|u5V&k8PnjTWr(o}2I|SjK_LQ2<90;+TY#gz{GIpR;i5 z-g!&2URfp-3B8bOSbNDCn_-OD5*sM-K=9Iq(VL|dXL$29KeAuuclN6+1Lrny#e{!O zi*c$Z@|;%fu9F+iHfgelMEbsJR{7qne{)(7O1lOBk{o#VNP;Vy{5h?^!?1hgt$l7z zYv1E7e@`1JTzZvloyo+Gd_E>pyF~(#JS4a_YKG<?}S-|P6<(VcmA{VyjLQxgM2SEE~Nei$FIuu|_d@8sKC zXS?X3A-H=4J#Sac9C6;R;MxZGVqpoMuA|iqN7iSFz2>jA-D_)A@pr4wwxq$IS|oUu zz!nP+*6oy1|0k$VOw*EndTzb!raoIA_n#~=1Pc=hp8MiKd!6Q*O!+LezT&};;w7vr z_NT6P#%35JwsZwbClK6u%eKo#<@V*LFZ1gyrnTkA#qFqYVzx9g^XlyLWn<9#=)?B# zUbmmE!w-=MYmu5a6wFLW@a=fawLf#s5tXkYuh@1zVvJbyRDJn(l;lK*L1hWPi?HSm z9cCuz)M-k!6S?`k|4G{82L+rWti^#>PumG1CntVASf@z>sqo>sAH2rMA;!il#PrU! z_b0C|?lt)t@9B)qFh*<%50aEXWc>%rFJc>&I9?n|uDh1WC}3Cj^e&`sf~+PMbkAaA zgfwV`#rWBn%pprJMBikbRP~`Ujx%3!@En8t#dUUB1L)>b2d%1dt*ss@MTv6D$=ya7N zj`Sg%18dnz2>NKWT(0grwr6|v^Obkz*v{JJBv_E)jLk4cY$*wnHbCTb>&QO44Nq$N z%*(w)35hj^uJ)@kCS7k0v;2<>P3zruls6DZY7u{cROUQgvL&OUd|}spnR+6}>&1;QF`2NHDwn=|kRQUdJ{drvqYVqv<=`GEi+=3F(iR7j|NA)1KQ| z=kjE^-P#GJMUP`r9adUoRzKov|6lh%LoH z(g27&VG$hOHRDopo*Q%Mt9J_4&zc`(JFys=*ymacF^GJZ*!Fi%b=Ioma!aA( zba?wh60$#$`a&j0yLqk!9KUk>sTmiW<%}*dmP@dS@}Yb#82t4(D%v=gwu^&M8@X&**}FZJ@a4e&HT>jOqu)s<2BCM3}eKW z!XVxOk@X^K%PI~qN$>tRZ{ziArUoGmlT<(lKp0wlzFQZa>$JjQ^7fI}@1|{k_$EE?_mX;7P=!+B z45Bd>2?cN131}qm@27kF*8J*2#u8ECFuk3g&o!m3O^ zf&UlrE{J!TcY7YgT~lXlhB0DGV~|t>B85|2H~B~`TykYb`hu06Jd9`h zgwKJ~2hq2BioHMMdT5dPi>q7qonQ4N(WLHc%A_^s?8vDD(GwbeEm{ecrLY=_`nP(v zehn-rO8$Ozq23B-<<)Zz%aqPv2BgkGkl6yid3z2(59Qn=9 zIJ!;#^JwL3-D<1f^u@PSA4j@TJ3P#KLNrY`an2dvw&>3N)Wlh0rKqqw=4g+5GLCek zu7s3s?t5QYw=7@g+zsx|yvZ_$9`%(Tz2S__Fh*=C43cI*q|2sBymfQ7A6T8%f4N~j zkBaW0sw+;+W=5uS{xHOvJw7II{o9Nqclv+NIQ%1KA$YjO4AKCW(D=>9WDZGOVt22y zF_}ZU*5b0?j$7|!aAAo%F*T)U=Y~tYo8N@ZM!92P_;r^^uYx2rMWC0~lhEvKd1`hs ze$t99>uhsZd3BwCDz{xnn{Z;$^iN)WE$GGJRi(f8JT^DFbD#Tbqw{xXY=$vnOIDy{ z0>RsAg;XmAe0w%CIXegM_*AqwmNmkO#njx=L|Q|2X>y5A6{q=>4mR^r**?EDklSFP zi+5RfZG~F(FW!~V)=01G++oHUpY`fOLT$(w7yI=rZvv5v7D|S4CA6KOi+AxK zN<-{W?vQHg{tr{q;(V9+OS$8z#g48!s~IZHUm>R!?OJ$K7pZ8`^gk|ifhInb!{Aqr#rk!p39*DT_pO zY}lAAATyH!nl5aNkfKQVLna%OC1gZLLN_eKL?!#}wqzrB7769dc{2q%j*6q+1WB`& zv4m~`Y>x`bi)JVp#i3KNB)q_PXK~I$!42}AVQTCCaPyKC=MO(zx;Qxns*%MMSseX+&bf&Ip9 z1;-wbNA1klEDg!pYY0QYtc5HrZ`P2RZqXQwUN&Y8bbN zC5)J%x8#T?ABEnMBid92y(LHNryR72Bi>XF9T6rtGhn$sGxURYD#Hy9{Rbsh@7;Vo z40hv4Ax1{<_OO9~Sm)ax3*XMXo2cD+OOH(!&f+=blx(Rh6{qKDhr49iKtja$>>_ z-%@~fg!G(a3@5ZcPZxUSWTU&+V}53M!1Z0oDQ6fqcTC{xA85JdL}_>2ytd3X*;Qv{ z_Xw;$B~e{=(-Jx5nB>5lJ18k9v~a#_YPzK2pM!yaCi1kF&9UhJ>Ws}WMr>&el4?NY zYr%WoJ02}N%Fp7k)$D?USfu)qdM6eW6H7zwC2xe@l%3IFTid&HVbM-~mDQ0&;FJSh z^DANI3O~n2l(!Xjjt#%;G5DHav4kXbvmOthrj;zBkz2lR_-5$r;pZcYoN$OOawN>+ zp=*8-H@6M;No+(HoCZaX#J2ZyRdcJkl;)eQXTN&n1EVN!KaPZBwiKzzaei~N_RGo1 zh5>)Bf4-(NF(CC^&n{Jw?-BQqW_c+ zHi{!B9O`t(B`jt@PyIw(CQ6TX?*O)D?r2o_Zd<|eC-UcWU5!J>eF~*5z7bA17WdZA zwb)w_zBx+Q{JAoNvEci%Q~#GZV>65qTM~mL8W4Hg@9w*WUBM}b=f%t_=lrsbsbY2p zXvLMeX`lYekU4fvuNUaO4*tZqB}(7ZBZ69^ff82R&qu%MWBhV@)xOGEt-F@12vv86 z&qYpANJWv=MLeT{qeT$|1Ikh5|0G$ysV?;hpC;M4@U!|UwOj-9JvdU7wE?^+vba~5 zJ$=>X#=f@~uOxSxEMI%Hv%j&?8Jl5@*wP*-EkW>;x%>C8YTIJvRLY#l-}buY{2#fy zp!sl1V`J~l9t)#lII<_KNZQx@%H{gMd0db_7Nnbwd^U-MEhiCYldMhgG)!ymtICyL zdgS~9zU;Z`thvaENWxZ`?6XM*>9`Ml8bShGyPG$kp7&*~#`;ejeLstpG*`YvPDHk) z@P-gdBKqcKFm?O!CwXL1%os9Dy9~1q3_V%;+$SDd@(Mi~6K#L`$ zt4oR86*Uqox&ZGJ>(9ECu8;xnl!^{}in2fc&gRwL4Tomr?NWMG8@H6J z#a(=@v-2G+hB0DGd!V!g!K)X4KL2f*p!&aO>sxN_)0x;lk&6R#XoP_|BeUX;9RZuG z7XLo~k(pO)`;P7FW`T<(=+a_h4sw%lT!4I#o5k^HRvo3vgV(z4wSpFHyJVxf6URLq z5<|LjlW^PxTUrcXEK1XMHfz{Xl>?{eU#ZdP_!cizFU6;9egj9j{~(HmvK1qKm^ov|6lh%LQAQV@vr=&iw98?ZL;AB`{NOiU zn@FeP%7uaEnR$ypCQY~bBy>inwgp^V5kFEb;pUGtQoTAq;G^U$XPeh=?Q`6Fs^4DI zJ+^!pr6IS>ff}i9`G3b~vfzw4*QAfNK9!w0X@SHJ`9VMb;f2GBev8ANk3q6?)?ruqhO`Yj77?)r&vuXoV`TBiN)B$z~n#6x&=K~ zn&g*6TvaZ)yta}_r6dn!V%}piu8H}AnoWGu9r&**OyPJfBjbF~HMtGtU#lEOX$?s7cpoga1i5MxnXC(+YDK{k17pM{ikpM4uD0nTd(Z#Di5*ta-EbT23uo^gP4pf=vluE%@qH zBbtVV-b&onfn2;p-D=Fvy*8Qtfld7gEC6{PEese&&6mc!im<=NC%WG=`e+MD4Cz_>)crSKwJ#jW-+< zn&l>e=~E9~ii-TJ*&yUmomp4TErKJV1vw)nw0&B>ZY*lYW*qA2TX#4&e%IVxZjR2_ z3}eKWB*AG6OmMkLSDzO-vV&W5r|FMHe!S+{HA3KpA%>7`rA&SQ*_bRKi_91!^eu$S zpWAXtEok_}SpMy!&(fl$1;NPaVBnkB5+O2tV4pD{E=wbJk(tE6HL)MshbV{LpQ-5n zO*DJ`(Hr_dkL7g}P6r|09vX6TahiJrd@typEs<0EY<+IkS!Zm9F=9(GkbnY_hQafW zZZZ*)tuOG%jX2reJ~?y$JaE??HqvN(1Ab+Mc!MGQ$_SAbCio!+3;{C`BaKV6^Sqv*hnMETXiJJ>5g&Vu{$ky!T;O6zq?JZytHk) z?&H`?IIV=0^X^jIYs2|Vvh0YqWuW4V;0Nq>HO|-!W5kxKK&b?Rqsk;%SXrKS99yY8 zr6S;ye4qJdAtx3y17nN6di$Fe=N)(76~9&as3fm6Wadi9xumeAAQ1uZr65RG8lfHk z)^b#^pe_AIW&Zy7G_i=nxVIfL++-!3h%D$*5NuZ(VV&q8vL8>KLWb@MXNF8*Wl{9& zL<1t# zT`UTxML$^QeOU1gqpX93&byyUPAocJROr6Co<8&-Z@F`b+d*QQC+5scK@8-vFq^PLH_@>TAQxxhINGn6aB(>M7 z#N;#>sq9)|d*0+g9m;-FTf}56Qu8I6Y4InQm9G2h@BUSN!+dk@JdehUAs?Nw8ODe$ z?Saw~1iL&wp7YkM((K=)39Gg&matGQDvNVsF*P+ekqfTmn8P3OYs>w25BITIioFU; z=c92uSt91Pf@#*~N#zwO|5ax$zgzdv(Esj-C&&qnh9g5UUx#x$`9iVM?QJHh2fbB7 zw)adGRgc;{3D*#0Y&N`|9L?18yT~rT%l6D0=hW?ME1aIK=Fs2cjLk4cY)KN5$Uvl? z%CEJ`Pd@ED#N;JY%@d;aUioz*O8bb2E47ekVmUoF1?~G^@ZsRHz&0J#RI#juyWM0n z5{6}3iFbjukLc5RFRbS7d}PbjEKlZk|5J8HS^pi=U2^R(zjSGZ@?w-ZijLv}_qI$STRDVS;@FtXAeTT$Bo@4InJoPKmirbi&M)7(h58p9 zyw~_@Xr>T}#4aI7;D|4b5QeajhIi^^?>Ri(@8xz+W;m6lo3>()Cj%oJlO<#;m_+g<_u}>D78Cb) z2<4ky6-c{PS^Z>35ptrS_QEoW9y@X8?}?<1jYetC*bHODmV6*V3nG78 z#5|Z;9e$&EPvV&g*`MaETrO3QJo72~^A3FGQ+R(Qd`q&JoB8|bhcy=7(XY?yYz`5d z?(=Hrf+ZEmX=3O!J7`x>NTe=@&U})vUnesA^ZBcDdDTkv-p^d(w|L2u8?wk(d`cjt ziPT3(1;yt_kC=DaJM^6~mNeOV`ex1f@ccSwY=$vnOFf{}0KuFJR@{xeJgolqqStOa zt!m|dHL=8r#n8aq;+wqb=HE*`@ZEj%;n&gEI%RY2FJ14+z{UpaG4ZWoMJzT<-wj`E zDBf`z-eVGv4}>o^6nxGIUu?)OdVK4>q$K_b^ZbWtS2II$}y0iBRtY8@KKhl+oSF^~=Hd*bL7#yvU_Yh6%isK}k_}d#B6PeU@Jy zChn#Aepj%ad35tVXKaQsVoQ6F)C3~$E`9%E^MmJ$HeFCDNMkCIf6`R35HwR|VtUHE z!7=2-ENi#lqMsTT^pwsIzSReAoESm&8w)TlV`H*}9El*2#hV+mb<@}D`xoY~m6#Vi z>BXPNFK*r+O(CEl7W=;ewnwmf0kq5!*|ZC`M{v$&S&%9Q28k?nIS5M}`EsERlNAjd z_9UNJc~;}oh9mlLCu_J?s4aoLG!ajm%4rT6wzdvJ{9;S{^LW(pPHUEB23= zGDjjupO`Y|v369wH`mtr0d4#Tl3VRt3~vP9!I7eJJV(nM;#1U{IgfAiw*Ov#fA!tu z*pTP>wGY}pAg8FD71&dhOq1R3h6~O-PZ!LSRQ$(QAX33y&hl$Id4Zp})! z^z1L!6pG?+EKRE4)%M}{ZzmRGGgAxuW2bCHt+rN4yqc%6cDbJw%RKi#;B^&P28<>0 z8ew|}(FTljD@)feVU8_kzPY5*b;5xI;`S@mkrNKmtQ7v?y}a3@1IEZVoKIR5VLWZa zM$w(i^*0@T_Ibh2^*z#Ge)5E7suySFY8n3UwIwuxWV@pHsd;7i^WHR$;ZC5vSux(Fj_*5heDvHQk zRv}Ta3;BkthKn<=FSyUVA?k9|Ow-G5G6uhonj)tsx-_Q?u25lF#UN`=`(>Bizf{p; z`0LMiIi=H6S^k&1Kf;lo3Ju}S>AZ(oQ8zN%Y(#%AN@Zgyi#~YwlkdwoXKaQsVoQ0T zlmx-8Y1~RPwrVQHzmNVZ8m(+*C*sBd>0&{~Ul>FM*_g~A2jhzOdb2TEK$<(^kGlJo zURsTA#QTB_5Qksw`<`RSi!XQf%Ua58}Jsb|<>ppb|eo|2V(r+bF ziX%-FyCS6tCh>y-8aHC>ZgIP$r&pOS-F^Jv9A|8XF=9(Ske~pOlEnvGFGTieh~3OB z@QCN#SM^p=)``W^(#*v8e$$nimV0KuDu1#?`*zr*nLjq{0;d+}okS9)a%@aykjAn2 zgE;t|MC?+Hopkc%vh;2Ct z9k~Ws}WMr`Q{lujV{`S}Hs4!hL9=_wz4INP0% z<=$i87$+7>Q%g&>?>~R1ri#=uH|g?ysn}nj-aMHZoLbBvWs5|)54>yUuCXlg;Ms-gRY_whwW z3zd|+_5TV_Sa8JVlx3Ifi_?TtOZmc*4@r+MCK&bo*=LgeWbHA9U)zLaoUs|kh%H?~ zQVNL7_@evdE8pW}%c*zYu8OnT{7-h$9w!!aQ!_KY;`isQzPi|_HymD@d|Bxc+qK2% z;D#^sAZ3ZlD)>RlLPs{h4^rk@7zjT|S!j>^zo%JD6TAvoH6C7AyXj1gLzLH_TZ1*_ zNK{UN9;A#|k2PphPD+SuE9Xxi;e+v_?5w)6E*v`+{v(`nDsS5--;GpTvz#@tR6615 z0>MX65qTN(qU83>jQd?BFkEgZ3t?Q-PRaP_}j^Pl>I_Jo>RuG_iSnw4*V zZ@{dOvKha%RiA2_-2o5N7(=EA7*u1~m`owHl0@~E7b34_asv5^tP--^*J_(Bk`ZBB7vBZrl2i5XxlCK&b)eh%jC2>cg}&+<-cm)fBgCYWx4>V zCaV4mZ?{z5Ug{k4ZuRwzw`0CmYWn8gDw)4>x`s10!x*upB}l-7$Rn!93RJvOPL#e6 z@N_N8$$9kMJK2fZ!oo1_wso>ub;kUI6`>K;-dan%xVF}Uixy~~S}gY~d=ZwIo))Z6 zEgEJBKaWSE_S&w#O9h>hwze_HYrOV&76cfJXKY4JH^jDJBx>Ko`qWQ$LemZH27re^ z3#Qz8zPHtbwYT1#`}y_W9aV9k+x&-+OO`rQcnbz4-N>1xUJW(9u-N-^gOv5g?)yw4 z>ieCs8ODe$g@IBG1b?`8>RZv&)Z(|5$}9rPrN;{Nf7FBe)Fzh3zkMgGrR-u4PLtaq zKRf!z>nm29kQ0ss(&{~=!5E1KK6t_r7kFdlG5=frN~OsOdB#l>+(fTg%eSMPrA%~V zra=RiaD1Gh2}ktl59ooX64=h;A$j%QkgAdz*UtE}GS6ePh<4ek9onlV*|R&`CY*2@ z@)$4KU%L0#aN`=*V^61lX-sUKGi9bTHp3XPB{4{%0g=7=6AjIB*YIfeJy(4eUYo}i z^1{f8+1Sj8r95n+>a(0r2C^_#G*Z%S*_a^41Rk4N6u5mG+ zJLGM}=T15GtP#0@qG38~N`Nl4690?ul3>It(IJ)2tc6n|v+nwQlTX)p$gyv2>fZ)f3XgLWz zrH9zlFh*NP3=Cp^_siImXFZm;f5T$iA$^joL+0=In<%F3t|&NSm2 zlfE6lAm30gGDqb9`Ro(U*bHODmfRo-2t=07=#M%O9@T4RrYR+y^HVKFRPVAAvx$-A z?u{4z8^#$PI{kTX?%&%pl}gY5*ojIa+Z>xBu>iB|Kqeq56H@wcoNr8I>Ho zbz*Nao)2IADu-|i>ArtsWe(@{>)h8mr!?uUjq1MaClYhg8Jl5@*wPXt$Ur1V&YDk- z!rPzbFG*!v71egnxaP_!VyY@ei&OA>1jHAI!0!eGW)Ro(Ze zsQyW3O5l5Fyw{hr`r683&NX>QoUs|kh%MoP5)uSI{B-?*N5m%4#NEjsnE%d^TX=6H z>M>y7X2Z`)5nI{D#$*E70xVK=6`q`g7{9`klh}*%@Z`i3`53lyT=@8R_*p4pnu~Tz z3VleC)DW_J$WR$jNB};{FqqJrEaG%&22yGKP#+^Pk+s#t7N`z+AEmb_|%rq_Bs6jcXz| zTvO5h7gO^mVS#S;?4zHCPa2Y#R4`Dpsm;#I56bVG_4?}N)W=Qo;#TL(#Zl(RCLM&g zfl$)WGGmik6{bDacm3OWOeD2r=g9racE)BHBev8AN<9!PKZ8YPDX-+JcsZu(vY~_ckiQ%)8}bR zY)Mms$+x5w-FU54u`u=9+PJZNa z2zwfu%DQOQ<5Qh`*<)VL^{(}bN$LBs@cjvAY=$vnOKp(!10uI6yf1Mns`)6jkwKVm z2lMsklkIuHtz|4HScv?-zJEn9^KvispLQ?i|5>%cMD_7NP2f4|C=v z?p>3SgtS&r^wu#pM#!L{_+M!@CSwb*ff6&Gu`!uKsw1(YY49VMSoVL0uN4%_Uh18+ zMquNgVg&Pn(1kOgvKFZnfrU#7d3LO zezNJwm4X$BS>Nq&oW|T zGJ%vgA`3pSF_}RoFC^xM9NW=g8dn(nN;pI6b))3jzW+~srVU(bk(iqYElb3=C&Btk zYNw%flX%c_=vbflRukx|L5kLD&@#0wHFW-^>bIy&Ws`E|mWAaxt#Ud}I8w{pl}M>2 z&+U58J)s$!SBI*cs?iDWynSG~n=>}U7_p@*a6$nSzTpa-WlDK1KRS50+;=*1HtUDX za$+$ww=j{rnX0zr{f#Z+LM01UXPsC-bmTlUTb#mT*v1OnY%B3 z9(ao*5iOEIN<<>pK2!(plAC%VWc#N*#eaMaq}#taV>65qTXF-ZA26|PU!3s6(xZYl z2}R8P0dshxEZI4nSd7gL%`Wt9PK~#Su>7lBDc>}+ye8f6gaxF?fwW*G7Jp@9GJ`aN z#rJMyW3q%af_WxK2Y78g{UO@Fq<;sG@}aKKEikm)*NII-xMpQ#_{T?#Je&8q z@f?eG#%35JwsZxF77&>{lgnwVdQa6yIn^KATtoJ_y{yf0Vlg)~HSxETovN3#EK+Nw z&r{b*`|oyd57mRa*U;sr63dj4mz%DBbt&=3)-~6K`WY=-tgfBZd~@YHata}%JXvN7 zUHwI1x#{pOPckgleqFJ_v3Jj-_v)=DZr%}J(s>t03R#u|FHe?u`AIK$+h20@LF}IY z7T$879J$gXCOBg=j1gN}0;LTI&JRfc#~!@tbG)DNnu(IvWcchAW1U!xj0`MUmw5X2 zO0I~G{{BH$*#C@G&h6;$;1psAS#cxIVaCQ}3Z1%K;c9bhy=#qEqS$%ElBdl9UCU$T zuA`h)FpN6;qp}XDpake{#*Wv}xsi zqOF8e$cnyOZ|^RV=j6D#a{E`+JFg!&bk~%=-Bbz<_A8o|>?p{3h z-)LuL=kz(9ry-3KNXJL)OE`SkpCe)weAr)L?N->ZzXXQ{Y{*t*^;$8lFUk!(T}!yn z$6R784tbh#Qu*&NDoa+S!-j0J9e+g2?$CNmd7DtSmS3}7qx|I+=WsvYdLCub4AM~D zsvYpMWJTZmhW5W%8A0a_W}iLfw%j0OLzRiGGd9B*Z(&JOpfm!(>+&@jirE%(`I#+X z@-6VqDbFl^2D<&j&~lS}OZ&2Gxjl1YS6Xf5eWqH*Znqj~sE)+b(k0eRgb&pTeRs~9 z9_D#5L+rv#ro&HsG&4m)Erj1gPPgQO)8Y20X1 ze$u=!$j)s^{yQM>Pz{(zJ`kXEedp_Ob*Mv!4UF_WuoOvaGfNH8*%jmZR}hHvjV zHYPL3u#Di6M~oSsX6BE>U(D)`-g~0&^9zR1n?lHC&uA@0d@Uuh?x8#=niv>F!U_&E zf6SSfs;i$Se5hQJ^Tc!ZEUWp1)5>}i2ELy^=PaH*{d@WImCBnpow^e!w%Zw-VT{;P z6~uZFIeqF&KDYcGT(=j#IFDtjBr}nn6Pb4 zA8(G5!@1aLE&d0sCvUs@;Gml`Hp3XPr7DoaA^50GpjS4w)%5TQYO?DHxn1K7zPg$Ty0}wxS_*voro?7T`1VbamAi{pj+C=`7Q9B_U*H^f1pZm!fn_-OD(ikMw zfXF<>KhLx~-ZeQ&yvw((l&x6q@pGvYv$3JcK6|rw_bxEZ%~NJCS{C`gM^s~5Fu3?3 z^PGK&t;L7_34D~0$Y`qWVVbvp;_67jv`ZI}6Vb4#sg%uWcnOxoa29|X?wPCpuWaKc{O>b-A*j#CYI*&4)2y{V^U?S54>=^{pFuB znDyx*GT@W~t=L37IpG(`2)=&@zd(ljU^e^$ z840ATsyRJ2)p57Y?bA7_EzQ17sO|k{u5TLq={5dC-|}WpDy(8d9FR`S@t^P$F}4@x zF8UyP&+o-V!mYd$SGF(E+P@`*Dx!x*up zDh4=+5`I@Waev?~&+CVl`{o)wu$DZ0)rrN((9~f5e7@ZOT9J9yi8q%q%=r5(^yc5I z;JGPd$Q+c!KG28`gw4BKn2pI2GVv+?KYLTON#WGJ;t4DZxZbNp&9d$p!x9|Gwka)j+vJPa?MriVPgT8Ifjri9Z?No__&XFe8f{om>j0u1F(_$?NBW_+M@J{&$qIMPy)#DSa8zPy;d(tt#<&zweY|)(pPV zJ-gmO4%ESRDZ^pb+FpT~vsfzq`k8$LzxU@X@^%!I8KULPVR`6bT}YQQAo}cdsFhGs z$dfnqbsELXmN2&8ls;T5wtMaVT$FPMkW$EDKco~gdFK8D+P=+8Tx>%`o)l|bGu?eu z${CwsjM&l=Bz1sDwkdnfb$9&U*4B4T*EW9Ny^pI_+Cxec$ov%%TMh(&JV0ve#-#oa zdnsF2wkhiNT8B68-%XjhrX#16A>P(Ksy65qTbcr;5eSaodt!A*dQRu2GM&3C zbQ3OfB?hKAFJ^c2Ax!4k&<;f-JkQCD~) zSolsS{1!zKZ@&d^TqL)jGjg8rI{4U$(`=1SlbSk^6A|ssVWP+WIi$T$$FpFKVEUXS z*)m!4``VqyzW4|$=KA&9Uoo$XKxx(-N9_MbNksonZC!O{%Cp~E&Rs3W*`1*;neUu( z#%35Jw&Vs$Kp=95|ED6Etj9G)njtzb#KcrKSgoD`n(BmI-~e7&V+>uAg>-=fk%y_z zS@+4Rr-?^h)9@UoPWrh4!#v%bzs;LD@ttJz`$uc5*SuRG zHlv+44!Q6-`4zrr4kg{Z`J9p1VykqpW`<76%xqsh`RMgc&e#lN#FoN9DF%Y;Z0wF- z@8M00h&+GKnLnpJ=S*}tcwYjRsRyBuG+a{;OV_NG`FKrWSH_y_VMYhl?)2Nw{fbhq zP%s%z^@i^0bNHqn23IpCcz^Bl{~7H`yXp-tr)l2ad{L)(B98QNMikzRIa+Zc?fKd_ z0e3R2P87ypk^ZgD^nr7pGd9B*v85zP+5nM8JAI^IF8yzDPABN+?r%0bqZ^ASIkA|V zn;1w1Ng~xp!>(MBIL86q(IR@3Qvwv&3=Co|VUkc5W!HYJ zeIXHa>vT$X>CM|kNxzP7JDr^N1FWn(gj z?AjKW{kGw7X~XU9pC(DlUB9)4U@ygs=RDGd9B*v85hRYJlK{ z6?;~RD~ZVNI-`F6vERI}x+i2Wf=di&UBg-O8$Qj=)Ug>}*PxwYWGj9=f4xv+F4H=f zxCb-%;~8&;PDV~2gR0E9WCg2hh&;mxe;byjWya;6lot}tx+=>HPBTAT(QC4OkES|u z`nc4Ht<1QPIO%wA{zX;#|5%k&X%ztNWhB0DGNszPwBBds%8;76HSv*H! z@6unlV&s{g*~o#H{z9*e;y0cFzcNbPeXHeHXX(=^A5(AV`2DSNJ&~fiA>0Nf9gMa) z81V0gl(-TFUHXeMbaGT*!g=z+w<=5S-+RQrzq-OxA;uj?I=IpaZ*yEoeC6OhPv!2n z|0{ld3%hdV#T~|uS)R_=3}eKWVn8VXg5SQ_pzS52b3V1$)ktVjL#4>8#W&1tr zz@COpcZ$lmCQVJpktVLqMM@K5JUT&dzXZpmZ9jRqF{q9E)tL<(&e#lN#Fly>=>bF* zcl;>db9iN*D;HZ1lk7c%k0KmBPArz@M&?F)_Z2iqbUtObxpUI})vTuTHyy*lwF>lr zY6&w}_yN_TysfYUs`+J)u`yXd=6fV=lv$>S?MiQWz<9;rTsGVMvr>yH@{W_0aBfV1 zo--_g7^xr035VyqnEdwZ2i>-roO0jzvs_;*G6Gkna^o6O!ZA!Uz1AnC6vZ(^Rd4^t zcA5A8o|rgeGmH^i5(6a}2$o!^&(E{MR)1p5vAbFfM^ut^JKj67n3$QFFMPB~|9Xzw zC%f3^Z8}>wiz@|O%z%v0LQ)0m+O>%DUvDAKe--Q50pI?}eS#Nu{ww?LQ(2P7t!u>o ztW|t_S>lp9@88qEy-+VPyahl16@GKr5Zcg2ogrFsTCOcdbr+Ain3ddFbz#+q|DSgm zugmPmQTiYyqTAB{D%8DCuDfT&z`&Z*Uuz?t)E-;vjLk4cY{?ChfIwu9*NdzV=62c| zb1$(fmToaS?0hH2iN)N^$n^St)tB7s;(fkyDu)*D=QD8^_?ZYAcZ1#>CN}*6>@*O; zigd(jAa}mNPXpn)9}YhaL|j1yzQsU-Z^x}unaMH*-$G7Gx(20K^Dr}o<)AEYp-W5m zE+2G@fjIut&W2J;mqFj$pybB`TgQNnWg@z(mj2(Lk8)b)-E4SE7bQLEsah1x*9=+p zy365-w|-b-H~W@uXKaQsVoQ0Tlmx+hD)Oc-cqrrECi+HZ^8Lck|8kdDIYsLMO5N+q<)KSJwHYI1=vI_dfsM%=Qa*`#TCp)%LguC=Eb7>pEFoQJ ziTf_k<$5ptzo6&&s-WiJ!!6H3^XBQH4%bqrAi5t1UA-Va-wC#QfgU?+2d*G`wR}go zG~-H_;@^u5j;PI=uDhlCB62~5J>lG6BJw_1sJP!&@1R0UqQlQa5~=KGot&{5#)vJ6 zK@ts!tg5*2LvX!IMg4929OZ4(J?06{xDRd`LyrUD(0l+t4umc8Ec`eS@sQ)SJC^Cj zrP^^mc>K5iyw~4amE3|*lok$M(}cvsTIg{gR61H{;L?Po=HDcfoZbI7N@)x62`YY! zJ`(VWaGH3y!&d$DqbK39f*gNUow-#!5ncCI@|e$Dzjg_vg##%ykase%6R|r*;_<}W zF3pkpTl6l-e)2hOl^k(oV@TbX(NqMA2&CO9#5QpruZFH@5eX|eUi*-CvsCHcb{n_-OD(i_O(5WIO>j-9OE zyrx%<39oja3*6|Uh|GEEbSr`MtTuEhx5*X=73de;4*XnStDWRq^xL*|=H)Gd(H!80~&O_Rs} ztb(r^r*6^qVEeqiSTEuroj)PMcpww9zByT4691KiCp&x&RhkrdnBIUN7Ow5m3xE#$@JI! z7r!=DxqEF~#lH!w-d-QL)FScxC$#RtdTj52H)KgjEyXEZyNy2|F7XI^^jz>z>m2PX z?-wJdmKP@2Q%l$Hnak|e!&V3M7+qr9Gb6HSt=lzcY=$vnOIM(D0>LT1FaB^^2!`x* zv%mUM`q`SB@1`q5hHN3HH87p>XJayl?2i?1sSi?_=i{*94nO-uZ@%S$m6D#XL{Uds zMnoG#;uSA+x=&;&Y`Txa+T%p@T?c!S6?!hqZgQ)2U8z+lT)3ZbI(TJsb3whpBexvc zc$fvezlNv9ShI^d8*vmyY6}@TtZTxKua3O%F^G%hi}yz3;W0G3fGSOXIWL z_J<$L4ljSYFiqp$6RTIBzejHXmoui2)szzNqS=_tAS?OBwk*%OuEKE5;c8vyPC1q( z98&vi9W;tiQV3mJCzRAT67Nc(t7;J!CR2Ngkc9f??6IN?E;EuN&rbf?X4@ey@p@C~ zT;vq;ZV9&f=1tQ_xzd+&!p|H^ELxj$L85YHSk{|-XKaQsVoOVq)Bz%GlV5RsZYkI* z#1nAkSIA7`>>YQGpp+&^YxH@Z+$Ls?zC?KKsjJsy9;cs}z3^z)_3zX6Y(gEhC3YHd zbmX5w;zKR8G!gT=Kc`VgBBeqlpN+l4yI8sn_@7$;WvB>({lW$G*4-Cuh0}Z8N+f|Re zw2fnF1@f-?g1bqNT~GG>P0jhSb<^vJNzJ!s%Au4cgDHJ{S_xZjfbC$+0b1IIG^L1~ zKHT8DQ}&X-nfR~TwDRBa7oy|C z*!~2w?FT{y%IGoc;<1!DdelrZ#(Nty{@v1A+d8(B|m*) zz1Eh!-x-@>jM&l=C~ZJ+!}brk7d|STPUQJ`;_Mg}A6KqR1f>q>B#uP& z7WgENV7&}{5=WHnIeZdFY`Jf5!vmw@gF4^b_xFr z@@m*54&tsO_z>GLYQ$D7l6fa^L2~88{~8x;pOx;c(U>2PoIHMJ!W*$D$;0>N?x_LV zt)KpGV4T2Lp6>KpuDsnDn_-OD5)vq3K=86zPkXHQ6+E8(@bL1Czk9l7?tYW)#A0G$ zVfak{;6-(t#AXVa^22$4_ircJ87f~Ag}-j|o^Gzmk|T9X zk$qqD5GYK3$6%h{O?oqhmW4^7zp z)UCQ*PiB=fH{F?bad%CalQTBM7_p@*NJ;^bGSLE;Ui{+S7m;>CY4xF&&Ih?0BAr+) zObpBnqI)CrjSQ-t_1>Ov<=j<#Txz2r|6}m&zfb=e$UsawI!U2{@$J4 z_FOHREoJq+V0WR%`y+R}?v1c?#%35Jw)6%{KM;I@yIx&2XNun4MOW9gFP+xJ=%Tm6 ziN(;uz%=*MRLLb8?>@BE>zMu6+kbLuxK9tLvVwJ!aIVV!zYX3^l29-d5L!KT)kgI> z(SI8hc7CZkb;O$!ZT0^Gteb>oRrVkoa!LJmV}YHh;^ykhdij>q-!zw$ zxeFtu97zUocx{DL{`|cwprRY7Ats}{?2yhvp5?&;oTpeHI%6}85nCFAq#6)8M`BvB zK~?^l4{1($H;pXy*RA2(;KX8VVr;&k*x~0E)!*h1x`MmU&vR0-+5AobwDyVIJ%^Hv zAJ~}8EkKqsu!|lK;t2b4Zoih+QEztB)$Z(lJueI=p_E1N_KzeJ7ukCbM_`IFeyL++ z-)5xzlQTBxWMT>L8+xh!oWXp_lTRcc#&iUDPI_CsZ2R)zlZGT&Vqlx*vFvvy zeXj@!1Hs*^UMS4)?|mfu*_zpMPS(QBd{2-M)0AXci@j8e;^i2qsm!}E^ZQK=MG$?QKB`%u!skZIRQvb8}c1VsIB34_CeL4v+RG|26m|EtBj zrWdK4GZWvo(aH0z>hqN^<{+0PSkr+d+tx7AhItvWYhym&XP%zA!in>5YKf6EHp3XP zr5K2}L1d%irh2^@zVFO*cb^e5<8r=IniA~9Vq#)ytlacu!PV)%pa0*$QDb#fXywkO zRYKqt0$tF;diM-`L5n0u-~H|HbteAN;gC&SV7m1Cp`0lHAQhApGB^ig2B`le$*}^q zpr!UK^dbQqgE2Q&*UU-qmR^5iYq#ev;puNRr4N>1Pa%>V@cWM>*|xUyxGJ5m*cCEu zg7LHj8-w^0AKC4lu^GmQEiHl41_U!ccbVpXV7X!C683EQfR6v^)e`+qEN12wCbxJV zcI18Lt`<4Ffju+$*!GvRXM6rkx7z7&5x`&nr>5|)+qK6l1u7$dfH1xhCn{Aabpo}E=`7C*A`*z)&m6TbP) zpWBJW+|u0A{)gzlS(9tBQtesI|M%`<&~-9W1@*R}L&N;vir_=TqNkhTL&K8%D)6CU z(fekM`xac6TUYteb&C17yn^cyDj|WaC<%uum6asF9du}zqSFZxbCM)iR&+0B{tKqR ziC9d+}_Ck z&vsqlH#HBtaz$rshB0DGOQ5s?!M_<_AFbW06FcQrdge)A@x|`#$&g)(&_)Y;!3lVy zMZCcfekhno3lscMFou8`@I%2QwifqGb?p1=_vWGW7QNNy=JW5i`t)uEN?N%^m2Hbe z?iNDY8A9^>HU7?#q;Nf~(Sqg3cl`6$WK~1qCrl1~@-eSldu-Mx-Bhmlwgo9_gwu-f zr3OQ(P12il<`;XdGrxO4`_BCpug^GRGmH^is)D2w5c#EkVp!#e)DLg@`B=A~IKuqz z8)p@9NMG%sMXc%;@1WUNts3u@imH*bHODmXJUR z1A-?qYhB-cI_JAa>5CT%wdZ#=h}+jVF&P=`Y}0<8z4}a$$sSL;^jMLZ7H^g`f%`>< zkXcAv_rgkwpMr0U7AaSSZHyL+lPizWT$y~wbIqk?;TwMVYAxh@aFQ802}z1SBJN&T zyld=6V0-0sRafNgnOf6*y578zivA)#!HL@nM-q}SfwxygKW>}%Pexx*MdDMo=DjcX zZ?pXPz~JMI%`ir6i4Br`K;(SEp2MZ;4CRJwuWse-zsou`SCa;t3WrYFz`pYw^!zTw zf_}29jvx2SJ|{}Gy!^W3ZrtkDh?$nfEGV-+NX-nSh?U~4Var$}wbaX2RLOAOBJn5Z zl$=kjamHpCBeo;}ic$!kqY`_$B}6&nPunr!rhB^I_D0;k>cnDdU}Vx;`O&R}S?2QV zUnP@POpxQzI4vBGTsj~hn;-dAV&r_ct9R}phVL6c z+)B^NXggL|?2OGYMr_Fql7K*@*>$CC%N5Pa>YcxYdX`O?rdrh33OY8y+|t2HsL0Pi z@%h&^ig~Zuo-4IgAGwH}h=k9*hM&D5DW?rjM0{s0;Z+Q0|2}vX^R|7r!kyEfDtRK8 zJ@$4xoU(Cp%e7TbD2YhU6`F{K;%wmnc6b&YkWxD(y}EN#v}SDZ)_(8lYHPia6Or6> zc!vk6B$5fbyzE7MrOm?~CVO-Xk3F8=@XdwevNJZr7_lWcQ1XG`>L7;MDSx@NJfGcI zX<2GeUa8F*;>2WVwDt7!8>Kft`^MZcK6>rJuFP*GlQ%+=5M-_p`GQzU1<>jj$ngj` zFNn=>xpp!8_<8oesE=G*qn9Q~KVzANl7fbGBSli713Fho_d%7il7lmE2FV*Ont0*& zD^~8%o{y`LS5QeJr67fy@J5PE&?o8ljv-qLzFTv?`x2nVbKK-Oo0>B=!x*upHAw0K zkr&pMRA+XtaCv8UReM^_^94~KE+>FTXrZg>7|U(gn9LxlL;OJ;8y><7OrC z^M;RI&v8VG&ouo0QSjoHK$Jt*B?o1xBB`_qx~fim)*V4m5HK)cTh%gvr3(Mi3rAxo z&VBh>zj9&Ne5HeK0xRT@OBJQJ@KOaOP0Z9}zB|`(LcylpoDGM#_mwSPdf~1!Hp3XP zr5;F7fXM0AOj@efN0Z7x%IKK?J4IqZ|Y0GiV%tTH=FZF zbp<%Jm_f=F22nvaCNoG15%2Y8W3qr;^D3!w%scwPmB`)Yk5nvQb|0Jti>fqI36j9poN@Sy)TU1& z$9q0AELbwLVEPMZY=$vnOIM(D0>J@4nJ%l%^b`r*$hY*%maY2|o%I-zZ^#oX&|_mV zg7l8X^Gev5Od!Ygh|FteV={qkOJw{J$Hrs=IsF!Vn1Tf)JxMq}gWZrP{2`N#$r93B zmS}SKTBcE-kUK5+-J*|%?anPO0%6b9P?8hP+QpJ;Utl-n&18Tc|1|IeFI4MX-D+mJ zvH63NmY>|*;~qKj&O)5iQQE~yh{6XcIjLuD+aoHk9$c~ZFOSRZ4XI_*3JNbdIb$=7 z5nIB8Bqb2pW3eNeu~`4!2iMPH>CbxJa-&h^z)~ZHpGUG* z{O#R^JjySr=?ov`moR+Ux9=3k{nVYwkG;7HU*7flQRI?80t*~T%~PQNd8WL+rOi+vF~vdIGR210!KZo{>Z)^8j+#N zdW(glqh2nYz4UkCMQ3b=F=9(gptJ$O*F=6CjJ}k)YfE&K<+;D+dU;Qnt$K0ywHMAc zM-5H{y?$}&y%I{z&vPJtCQp)+gb)EaStZWAN)V(UoWzQG;AQ1lBDi@_(BEn zY!UQGc2RepuSU^Rv*)~@J$DL!l%5#t`g=dp9Z*usXfv2WQgTCG>0Qm({#X&e#lN#Fnl= z=>&qE^snw;z9Uh)tbn<(aAF7F?Ol&Ifyx;pgZ~q^Ez(exk(Pa|dSz$rj>W3t!V|zX z5p;ni@`($Q`e&EDeR-|(iF?weY=I?pIw~qkV*fLSW(twie-2$>i8yhAIvpjlQpiTr z?u_@`x$4u8EVT{XtaIh$Pnlrkn#e#5dkVR`zW2gn|A>3>rjvfE@qKOeIQV?JGd9B* zv85$Q>Hv`)cPt)g9{q3n)?UDV&GI)QÀgLX-qnt1Q=`ZrP4`N1rS61$tlE7hOu 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%0ApJUB=21~9dVNK`Xq)I9hX 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

E`%8>W7x&v-mu{TtzwX?=Rrj_@n;WvY&IL_O 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ᯇlyp zm{LA)u}i%%d%~#Sn^hrbbEK?bveOG^Y=$vnOEI7n0Ku24jS~NR=DpxaPkGXv71uTO z)_X2UI)IFKu`sP+W3q&dT8KpCl(&7~f9VfLoXY#)oI~HNvdg1)Ek#KOqvZjC^Yb;> zTw$XY$c@ds?`J0JEZCdAbe>Ivk@!>tb2CSj<<*F0g9cJMU@O_eP`G+FL*{MCKSmMa z$$M^=7PB@uV>65qTZ)0C0T4MyXr+{7@YFqZ#ipBYPVR4Cb0ks7iN(Uw%p%llQ)k!1 za~D^>K6_VPR_^x{{g&^@T@wusUwGF9dJ4 zN9@Uot9o#Y0b11{2XU^CRW5ky5z$pn#^a`piunF0bu_on%=brw{ zk+sH*9>_}w_@kG@mk=9MOD)xva1eUsNOeT;C8?kZ`HYN+`{9nsf*oEDy z4Q%iWyA>x*lWxm+rq`ivolR)&ytYAe7`pv${-!=hU!h+v2Fp{_}=RVA6Q< zYT}k<&Zl3g9*kIN5JNaQ@j4`PCOlL)E~O>B;a<$G^lQ8mDlXl0#%35JwuA>xNnqk~ zu(IUot4mww9D1Luu>8dXaj%0fK!p%&C6m$~J;X|;P6zl(CUtqlN+!nWkMNaDvRt>| zE1A@$$2(jx&tRYRZnBK%v5>Tx58QOODW673H}GOegI^N5l8M^2+ORB!j-D?&>-g;F z$#sF6?U!Q8J+r6(F+ff?{P6id6D}2<3_Z4X4vZ48_)}6J@pKO^?zLf|<+6G%Fcyzt?C ziN48?>(Lzwj#q0~C-P;unCwhMiTlw~gF&^}O&T1Y3~JRO(D_~s;cn=Bue!)LSkDQ0 z$A^vn??=w6>z8`C1Vsw^KVoRyn~L0n)(~EYt??qbX*FDI5^hodY zzb0pFhB0DGB@kzV$P-rzOrISJWJ%0O&iA(XR(0rBYXRtH4^wl$;8jmv&)?qCyk)bk zbCzB5#BJLifmaP+**Byi+D^>Ap)L8B7D=gmE6#Eb=%~&L-I{QE=dt0KiZnzQQgz=D z!BkYbQg27|9EF5$H(wjxuYa8vIsHI8a@`~P1$!!z{&_F8ZS&`t-c|p@4ofnxN^kIB zbjD^FBewJgN7tIER!jc*EGJ@a1A#(R}T#e3wmBKdX|8

Flcb*K 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�b&RjgB|I17P(6|aCWXOa~ z=`|aZIi#zs@~DoD$r7>>Q;l&k8d=Gm3&M6pL*Db2h-s{>rjKnGkjo)_R6aCvYl{^XnbSPMqI6~Fjr_3Qon zAcA^Y3w=||^DYtxTn25`BQ^iPhZ|x0xmIc2AkV=5Bn?ZH1C)RgzFe5CHgWMWbK z?Lq9>b3z5n7jmqzoN5^p;X30VIITcW^jEn#3vn0t%Xw@}me4`n)ymbqGG1yY3U^Ps zE+!b|-xYG|n_eJFm4s!$R^#P1=!yR7`oYkXeKhDWCpe@AY<+Fm7@G^0T{x?lyJpeE zh+5-FR+Paxq_pz#BL^d-I?#9=XU%SG5hK_#TjRUK#MA`7wTC~bA92QJ7$de+1xY6$ z(&gIctizV-OC7iVuQi&x@3cW$dMczv3#nmLZzi%a89{cDuq*1aF&RS!_tg^(*_ccq zYShgyvN4%KI!F>*i(Om3{(isQCrj_UZo}IndL`;xb2w4b%4oSl^bR$R*QcQ8gsFFZ z+pgzW)*~k!ksZAE|1!3zjJcDO<|3CXZ)D-+3QAg8|J1|vW~q|r>Jr_Ho90=ska@6u zt1~vk7_p@)P%4374`t`sCq;I>{BNPK|6<6E;Fc6wedLwd+|QoF?^%@I*#N(1QPueh z{GLVWH!1Ly*{r&o;74RLttx`uvxs(W=Mo`*B^qndBwtO;cZ@pd!TzoAZ=c?nH#%9&*$$x;kWMLgmpQJD}}3$ z1tbcgBoFFzmOi+`+Pu_RGdcJ>OPh)}RP&v;uxWp%^WtRw8`&KfTB~uCHb}|iLwC}- zWirC6C%WBYO_}C=`?+emp2Q+&Y=$vnOGu!E0m1J#KYN&y!ak!aqp~KIWzvVlsb@~% zNFFl&BDj*r_Guq4be`chU3u2x>wmF(>lTScqHb!WPV)GaGSZRMQ+cnEK5bn_-OD5)ve7fXJo{S=)rq zj2peSn((agxvM@$kh{%^#mvIUNcZg5=xR<^sU_#lcG_7_vW=Kz+l8x1qw%Ggm?q87 z|2*%FU$A}a^O)f2V!F4{Hl!mNrH~nI(h%RI`7#&Lq)EP{Rjl@c&G0VA&*c{;H??KX z>bZ)XioSe+H))UxnNO=al>h3dfA8RX{e+7_Tjs|7GaVaOIAb%65nFl#r5^}BpqN-| z`s6RWuj(g*NpBv$__+CY45(vmY{F-=Z!^QupIaW*edW6S?*&uU$A^8Ot+7l-kcO`E zdw(`2V@P{ke)Aa0+4rwsUbZG3FC30)k zuQO6jS~|R$Oqp|jur*CUNl}P$>Dyx_h+`2K{}Me#F!IVJq4cWS&&Ia;B{ z6Ff}A8^qRq+EruUjUz?4Xy3BzEslNnlAtOhCykK(LKn)Adq9oxW!JfF_}U->>9swOZPrp zeyDl-d*?GTX@85`C(V6iWPp-FMtf372Y74zZigKmLud_et$qH|3u2S^eAu7t*DZfn zI(SX}92_a+_cnM>>gSZ|oLY&pnUzm3m@n4UEjZE~Q&1%1jLk4cY-tISIzZ$s8M|F9 z&FWgJ+VZn=B#v&mEN=b>)Kq4I9{-`1CI&nHL%jsF6$Dak@rq7?9sj}AAUW&9*0b)l zV#+TSEyPv@96dFcuVem5NgW!0`(ej_u-HNmsZ)E(13RP+%L;E2QpcZPZmy@iZSS1# z_Bejz@ym6~+?hCWq>jH=kWz>2n!hef-g%rc{`|si8n@uN4|nZPIAb%65nDO}r3(ml zI_7K=}Mw>Yp#0#xrn5BX3sTnjtogJ*dF{E!coC_nfiAKo5HsxOOA-`Czxt98Msbwelk5^$yd%T%<@XNLuaSza&65qTl#{e7!YY>>&)?HVL0zYF8`|g&1!tX$CI_ey(s8Y)CeRnHLu>_U=cE)BHBet{zN*fSt z__6EiJoyE!0$b1Ta+nml^39*t=b)p@%*@VT4x_H|VeIDJ6d zwyIgyu(mB@vl#qnJE89Nu(mC~F8`&AzE7_niD2fms-66WsWSY%e(i3Q)G>@}9!-vH z+SNQ-{kO|&c!id+>|O0+{oh|=k$+Ysa_ZpN0IPXWQ^(W^z5jlByQptG8FX#VT|gJ#OO@zGXs_Sy58Oh^=ijxfa9P zBk+CjB-A#XPZV!|NzoSVH)(G4dACIBePV4C;Z(tO?8EZ*&zegj3OqBGd!*ejc6w23 z5$lZ2Fh*?Y2a+N{Waql@vOV_Nb6@hLeYg?#vcz{W%PH#gcsLIo?@ZU+xMGX@s}0rh z*DE&oy|}kZfsNj&Mw4g$Anfr_m}=?{3h&ssvGKBVrYiF{ME-Eg826KKHI#B#e?gs8ZEv@?C{ZI3jMl!nUBB zW~=J3b#iE0)hzmz{p8kj!M(Tp*p!}Ko_^QeM|ul#p~5eXt*YVqbN8;4knBz#Cih?4 z<7GS-_cDp^zU++6Fh*<%36eBG#mtSE# z-??|j(wisFRW(_xc0J%i8F*ctF=XmTV)0itCJP8#Q{W35lO<#&uj;<_3$9=C&u5%y zv*#V#HvO1_T~81F`$VnOqAAG74stjH!w5_*zZ;CtXZUB#t>PIn@Pem2i0?|*6Q)j+Tb}ev9y|uqT@QE`v!x*upD@bsI$Q9;OrIbG!FUg6w zjjfTp7ADJKr{ct7X<}yLn0MJoXz}^>dV}6VAsr@O?Jqt$;M4+Lv5V`@W=&zGCCBw< z?POZ(zhs@9#l9C81y?qfsiLG7Iy6`iRgb2y4QwgYeRtSWr~w*mqp<4v80uRQdA(KN z{rmfmLaWSoPh1zjo^WarE`NM&lDfvZZOlSS#e$FGCd_4IRbS|g%`ir6=?auiAUNoh zcK!cL+xHgo^Ge;BKkw=J7jg5!X##p5fSTGw_+d`+zEW(k`vBN=B$hJQd6Wv(GdCQx zD|)iMPy334_A`_;G1~EE&=d`T9_B>Cu>F&ZU1oc0VwxqU9i6~>iDB2?b36EOqzTb( zc*j?`yiC@}(4Z9<4P zi{DS9_qI+fMiz!EI z>89iGArnpUl%7S`-1kYI`nJvCfB(0zqYNtZU&o`QoMBg*Xo}athD`8om8Y;YiRsYP z2}$4O{rkRQsdW0T#S$MT1QAX-;zuve&YyOn+wJKpFP#Ma6SFOXcAEA%V>65qTN(qU z83?`|VYJ}Jo}dHAGUf_N$y`m65Wc?+xinEhIvP&RW*NLR(KwwMymfcn8}Bt-(c3Pc z4*b1%x#ZF1MWbl~6s(9ep(!~JTAGm1B`)96EPIr@NO^_Ebl0R)-|QJ9MH>jG3CWv} zV*a@EJYYy|_WIuV-120w>$FyOXKaQsVoN-)OE3ZRLXK;gg0mrO&{QL56Q%B)wcAD-D_7u<)74Z@$=~D>NzV`WMb;nmU&W zry&{H(hB*E9c_#AW?rKRCxs4YYeiJ}yCZ+z3Ez54bAprr z*P;c;sYouFgAuaCQ4^_MBO~kbYVka7j(ug>7hQJhxon!!@%FKUGd9B*v86Xq`hj5e z?ps@ng3F? z*bepMdxW3?wSJ>8goW)uG18}h$Z7?f=%|H8Rn1{u#oE_*pr$t<&sWKr6$-(3^ZHGLc7lO09IS4<0kKW+^T-y+tpGdb1SW50UwJO z6HY=(SH3@IS?;|p^N`Jcp~-i`OnmkWotx^6%`ir6i4Bx^Aehtf?7!^G(c7)2(2Rt`Mo>K`KgA?sUFCYkKOe zP4=c;E_;IW^%S)fTW>jIGmH^iih-m75Gi8av}cpU)tC)^*1!X zcRk+fld{G;4x=kZE!*$?mD1GhK`u;4Jk~{1Z7bV8d$C8$*YdphVs!tAxTECT529`; ziAe1{tS}+@SeFsqdJ(VL!Z?5W=0mlG96k3}eKW+(5|(f*ZaB$wpSy7QFVc__8qhf5gtMTE5`17ehz^ zg5$h?5Gnkhw||ME-@hl5j~`idNHOjP`%gCTssrdHAFAgfAK5CLnq=|)%gyQ+ z?d{QPPjCrv7N8UjRBmTzYD;2V@-ejA893^f8}V0;-l#h0Vz|QK^y;)p=h=0v-Vu&_ zZ5y%1=gpfgZAxo2yfsbxX4(ts)mkae*bHODmP$ae4#B-AlD{l8zPF(%_~DOl92PfN zmfh(DUG;2X{P?NJwJ&bJ`Fp23dn9jZ4+xa*`UI|DplfNt>#I#5og8A$uGG{O?cIAR z_3e|XT=`M${`r$tMGVq-tA}GM($v+5uBD~+APbIEyscoSbO@GQ?oOWcxbmM(H!Kny3PzSDhpqDEu z|6qpSSEi{S4ZE*QeVZa|piX0jw~U>ci0@+GhOU><^Xr@*rsgQyNTZ~oA>ByP)Gvh& z)X`(90?H7}t$p0K<(nNg2p`;&a3wzDm`P^IDddt!{}{ZHf|7=oh^jEM+n@M3@#B>5 zYfPK&v3eIybH-*EBev8AN<9!f`TJJ3XFkv0PBvgYd2UY@pX)q{XmF3m6jH|UuX@SG zWCmG~p!{#HyOC$x!Jyj@)#tnq`kI}%KxIeta+Gv1WNIW$!}+kmlN+C)gC~fdFWt+M zZ&S2OJ9b-S`v^>&yY{hm+@8lD_7F}7hUb*KCdb?K*2qZo#@8fmJpXS_l#%35J zwiE+N10a%r+3cxL=YR6lpMEJbPN8S#l}6VrCl+%9bCdWQk%mZtqt}ug7uoK$U83mo zZOM7$qg>RkPGn;;f()f-8ZU<*<-(?(4nN9;^h-9c{^6gfJt@ge{GnS`$Ekhy0(AFe zq9in$6*!v42VqCKz%SXN@5UPw@ckZrYfVq;o{Glp7X0} z--^ErcVe+HH#O~$-DUpo&Gro;3j4o4;xCwcp|HgcGNub%hHEAOU)g{*7kThm&-Vqh zpE_~9SrgnBz36wU#0#1Z$kDE$Ov7TyObgFkB#tJ|>Hog9 zRKlsnEVZJevXy_bp7FY`yKFp;oI3vNTJ!;DY=$vnOIMJT0wR^}dg*BiP4_VfTamI} zE#{Sj^@3bTLk3dds5Y>{4_qehI?eN2CT$j)GlRYVze7Ws$$W;MyZR_=ay2dNV8boJ zEwH`sSdOO~?N2i>Xdqu%wLH)+#Vn||l;7^krerCNroL@X&u}Ca3;6wanr5kadtS2V z?3lX$f%Hy}%c?Agd4v=ToUs|kh%Hfp5(xzJ9hmpCId_4*)Lq5L?-R<@pS3@q;KXcX zY;uml;A?%b>0)KopO0J_Z(q8?6Hy0ALy#Fq$+xTE=hkUjWwOD}t>ZgX2%mA(aN~rZ zTc;*!TzTKqs<@&O(M%1O{*s8jHAY8m&XRIj7A5{ z>@s-Q>iC^Mv~|rDnfZhhk=0fG>23OFYbR-4-*I|{$*cdjeZnUeIb$=75nFPDBp?v^ ziFaeWKyut$4C?w#>cz2@1x{}x+Xe^|}vToa&acMHdiqpHQqxK4${g*Lp^T$WoJ7GC#1<%*Js z?7qNiEvn2o4p;++-ib&v`J&aDw&uitdwc#n=ig%X`o?{Na3ZpIo0JGc6 zhD^Ig)6o*vGan4g8tz<;)k=AFkVW*?l$&z;=EpC7S?`ABr?f<6!J_zm>LAQ*6 z@6p4)Wh6*$#(t}RFZX|Jn8%&jZpD?-+i!-FCMfAdJ3HdpGBV6N(Y#B~I!UU>tu>jI zdsw)m=JpoW`QFHB!np?CiAG5iiszOuJUwaZl?x00cIuEJTxFPC(u{ZI?qP=URZ#=R6K6k0h z?A^}T3}eKWmOyC(f=!O5?UGDUnY?S?j7iGOJXNm@mM9^Y8f-?M@Qr2~*~##YW?~1g zsm&=^(IK?Y!}^__&bjq-wr#vB_z|VlprEax>0S;kH8kMo4UU+$Mn<{mw5Su|3RUga z;U)9u=zlYKhI~$sCQ_+^lqTFa=`;Q0Z$C4&(nG|;>&S!|lP9a&yE|huj1gPvfusiz zsng)4dwEg^=hZpB>Y6Lsw&X@_n+rN`(7^E7cdeUmdCl(yUD5coNb{QHe7lsX$YZ>e z9M`Ss+0DiXSw4k!T({WlXyXBk-tg=c8q*|6}7`KR7r4n5KG&Gd9B*v8577yn{$Vl@BaY9X!{0FEw%QUTCCg z{D%E9a^IJz5nFRL*u7_}0uz*CYE@Wv@y|}`mamd7JR*DdnsE-$o9#CDh` zm6?xK--qbEwOT0GY$c>S$1+Ixe*})C;^%~vRMvTH)zLFqtG761Q)_AK+L28i*L+7e5Oh;8$N8Sh3r1 z_mqNq-y^nO!9sjS%&*i$_n@Sr(J}|?R%vY2lV(sdbbw#s$kzxR+w|?n9ln{z%TBP? z?k(D|>4iCtR1^e1|5np|Q`fhiWm`7tdkIf=6XnZDRk1$8_}v+sVT{<)8z}ui@Q>FK z>-q2RytL%#yf@1f<@c0IoWASCVrgV(5)*B?EBUp9fol5QKjOLmk_;!e#(6TZu~B~Z zsb)xjPXb@%_p_;*R!%l;r&-rW$+6_yp`<5z^r=EtLQevsB=a$@`xpsTRFKYFiR3@w8=sC^wZ|`5SuUFQ#;6={&Z7nxWgzZK- zfLW7v#Z%b*A>4B!SUi=UwupNuKkJuGjdP;no(24IvU^b`v5_jd@KAV@D3q;j`Ln$* z_8SRp*tg^U){Q<}?UI=)ov|6lh%MoP5)uT<`Ma(=*}UyhzTYjSKGrJ_a~?iYbz(6y zvM{-r(fC+5g2y|&e#lN#Fnlg4grxb(?3e|mnY3?zx?Fe+}POu5T-LxccK`5P)Q|uyG6-L1VPkQvz z$VyHLvkxz-Q}=Ul3;nxsljgCu+i}lO&PI%rz@D4}9TpZh%Whb`O4)$%CFfeld)c$j zIb$=75nI9oB_s&;Df_YM$Hrt1LC&|TqRGddWCAUBBhNrFfBnqHWC=+gny#TA_}59^ zjZ9-dxas#r9yLAty{}CBP}0FbHD%&I4(b^wf=w9#XMyiCx%@@eB?J`bb93*zy!W#g zaNjOGN-xfFT7TrH;NsdD3$N%nV>65qTZ)0C0T5|ragE{04!(;g z1nf9Z>lQzg?DFnLb0A*!E;!mv* z_MKNG8E@VT_mxXEV-db_v>0_nXXvDmBw;$PY#^9I>I>%`%-m!xy{jmx<&V1i_REV7 zbKpoJNr>^kP&TD>JH3Mp2B-J6iHnMDuKxYv<%0>%*bHODmX<(i1A;HDSh)A;>xENv zU8_Q4J{`Ej?6u|w=#UsQGnoqiUmGXY{9czQ%EWlrI%b~DhZ0H}yP7G|VysVWeJhW? z$Sl3RWS{f@iAQP|qg;5eNxR1G@T+f9Oc9M;oBNqu$#Ovf3;W(3I^wnJ%ECJC1Qw~oN~r>Lsf!}q7CSn9&B8Wt-Tfj3`NTeiZQFB%g9 z*_bRL%@^4jjqR%weNVF7yPC%ov~fe>^wi{MUzea%TQnQc(M(H(HeWP{rWCi!tMfF;5L(+yhp@0(U?NI32@F84jT`8Uk8dg6cEAN*Pi z#7{j~J~Pc3n_-ODQVAs9L8NT>&hL&KTzq?!{Et8Wp1-n|=dviI+JWpgA?9!o^^V1` zxl2v8tq0HV`2OSMqDe}BnC|Uwz484{4J+#2>#Q}fxl7Uy_rSjbZ+O=__2I=E-^YE= ztpBKT()vJy#rE4_#>hz}>mRmSC*yKo#Ld>& z7%udaaKgzoKVtuP1E*EkrJh3zTX$^A+sJ? z3v(%LT_=@o){I=gh`$yuIqOzA`|7^b+SZ*V^$&JL1#v|hqSP-`E;Kar1z`2d@Gdm2 zO34>)dwSGOael>(@<)+-Ce3blLXP`kvG9rglxrqaAS#WwTZk-<|R`IA5;`GWrS~4nbPhz@$+KKebSF_a)(@ zFRYXg`^JjIf0^{isowtO1V8N|l_m;#pydJWmNgJPT!!3zSsttAlf7=LNx+QxyLi@L z}Hc&_0Dhl07{n-9IR1J@+b^P@D271)@J zAT=IA{Qpb4cHUTo>Vnw z8*a5%c}YrZ&VJ56w)c8&q%$_d7_lWWNWge>?PF$VLhcb$w3@dx65b=OQib=3RlH99jyYWf4bzntLwm#;*jDqBK9D=OhUr*q)c6E{EL}X1JYL*Oss7u)ZvT{wxvLE?+qB-S+UAVSFh*=i5|qRsc;Q>$)%Ry# z>1*BKaU|t=p>%R!@JC3kg@4Xa{M3{;rtS_{-|hSgdMa;CQp@)lGc_?yLSe4)JV zc-aY`kfbt{!i31~k7nfuXsx9#a0XUuVcUZ;Qo296v*yV7iJ##4m7M*kt~EdN8TIsbj}Nw4|NpW{)BJH5WS^rcq%EUa!_UTK2H8l$ zZ#;vI$r93u7T)zqHNw)AgLlKS%Vnkax%_3SHb0%)iIQ3dWig{!qY3RSYto~QLryW{ zx%Se>iS?E;o^_Q+_W88<9^HDC4LP;cq+ly%s?5%^?7VpRL#X}L?1d`4Hiy+O%}T9y z#%35JwsZwaDIl_UaiM|s_Rr59J9hikFdO%2vls?Cv6!11m|x6p7rr+Ce#u3xXDY3C zVt(H{y6hG5P#w-gy|Hhx*Q~SsX32f}jC07e|JU>Gf4+Ehx8S82D0kdw)`i1{>hNx{ zA1!hi7*Nji_@wWhdGpf0o=NpLV^R+-wk}C>N7-VJJrUKdtXeap(oSb~(dD8)&!eg( zY6{l;WOl}87$dgi21-5L%V`?oub9e!u4M?_tv+0X>Vwwre6nzh8)HRL$qTlZI0I5Swrs z=8V==$cMp%1SIXh_;;nvCA;md8`$gC`DUa(CtUh8Ji5M{@s_vQdFhQzzcr^kaH}nP zK6Sb?Hp3XPB{4{%0g=hhyXHnYJ$f3!e2+1e_npY&FQt3HLv_$?Y^piM_D`g1H6?VD zD+J%&cKQ0m-_OdpcQo!nfroSnk{RZ~W13C7p^M@);U~bO6dE~ee4aQ8R~F=mKjh8- zFIZwPdOMVG+&A5;S}}3T(ZxGm*ZueB6u33H&U(3_qBAzb7_p@iki#LEB{_ZjjMYu& zFX?tCcD;P=bmd0Iad6y2rvW7&%$WR6V9SsC9SygidCb>x?bcv@!FC%Z?y24CXxUDM zVcH?k>UiJrcAiXJe4C@cIS*^K^U9@1**_!4eakIut&XO9`yPIE?mp8T$j#y^e7}3i zA2%uS3}sa17WsMVyk%_6%~dXb(98M-J9A6E z_B&%Uj1gOMgCrmjdHmAjCY#TV0ta(szOLACy{IuV^gkr2K<0d8E041=L672Ao#hKZ zikpp533e2>@TZHgqqzBaIz;cK#AfO1_5M8?by@!C_qVQJJCaaR%8(vs)$C?~9>uM( zsvmZq9Gf@nF3!LG;-ElfV9;Q(m4L9+p7KaSSnA)WOF>xJ?yo{Dhs06bG=ARnOFv#X z*=_f3pD7Z%zO6k{ITJ@p=?+9HZc5JXJe--~{(EPIVQ8Jt?OT?Qia$DIGmH^inu0hO zM9Ouud!BoEFYkklSLDU8%fJ6R&N~g-fXHM7xi3UgPMeL%7&70Z+UdZ?WCE#<)a4hm zF_}WfVp(1~u`!uLRvO51-C|=hhirjWn;!pY)2wz&@gt9)m8D1NTzGW<;Gtj%lyn0x zVKjTSUu}sDH}{Nkp3cNo-8!kkK`z z%2jMkmXO4vT=tWV$r6&dRBO-POZ3QcUUvE4`-6&;e!D1UtXiUZ4JF}FrNGhbui*gs zhJiu7b_cATONaK&02Vm4hj(8-{n@DV!~Udqe>d%BWSnA+a*7yI!s$PRRN&mz+2B6q z-RnD-mVaaUzs*_PlT&k-Gd9B*u_ZA`AcM%wx6ioA7borgZyY1BtpEFl`X?p%PAn!C zM&{f)TRD_f+;lIg9@)0&`A?&FH5R8JQ$CPNOLO9E`1uPOabfU<3c^Jk9-OAZj4Jhi zIJTcLS5LOOqUW#Rg_2qZ`Dlpd#I1s$z+qsZ@4_X5J>u!pMAl1bz5QKon9u8cMsfA; zl$6^ziW#KTGV#OSiy6n~ct!5N^82QY!!MOE#ffXGov|6lh%H?~f&xU|ZrHl{)YA`@ z7J8z*t+9)4W^(*{=EP!XZed*8oXfGNqVb7T=%<}uK0SW({!vXdsF-0ggj7nZS=MZf zkc7k7EXKxU4lRBrpJZc%lsNpl{K65Fx9xRGF;?lX%XE(P@DWZqu@NQR4Cm@;@?&VT zM(u_OtXUJ80BzPFZ7(Ee4F8_|&bW#HGNof;{GWEczE4MeT*yXR^_Yjmi zpp_7t(rb7n1a1pMD}-3)TD2oPTA$?F5iqg*g~D;F^v&g z326?d{t-=+M|qg52MFFouWB%NwA_5L^&7WDBG3C=7k?X;zqxrOJ?aZ*E`7)LPZ0-C$TEe#B?I(-rf!|mz z94XtD+Si7%%^4}7&Da2M?M(a-b(fLpxC{4Fm7_lWuP!faS zurq2gKC#(a_G>0g2yQH~yRCfP)``W$$jtna_mP)n_1VIfh8uQVT7PiO;=Kodfm=JK zkcx`SXbu~b8KkD-SsuW~WC`hDY0m205xqXz)N6^x|1!(9^t$T=Wr)`TF^taGXV>Wmicc z+j_Shn$Fk^W5kxOASnezT0HvyG_B{+REEx=9;t&yp;H%4KJUb0VrpnKK{%ka);1&O zu;8{oM&A}Rbhfh@KvD~&D8jW)L37UbJIhYKI6r%a(auS)*@Lsct$dl3A~^(7%bbhU zSf@bCO04vEdzsGP{6gOQe&2a|4{L~iI`#}Xwan$go?14DyuD}I@obHeuff94F-0dL zV{%HJu^GmQEnR`q2?U?I&i`3lO>V~nIq`WN+K-ik|p0Y7nK-6f8r$|O^*mq;W z*F7sHalF%dQy^c>_=p=Ns$rQ2%O5=C#895aRjdOEyT6e6g;?fKdJnWEIiIPG_+bu{Z)@d%ZgdWdA za9CLSQ_ABm{!;f~{f^E5+wM8Vf8>3PBZVwPoc}-H?Wv={i!T0&Yv%Jt1zY^KWx7zo z^}!jNVT{<)5-4pz@V&VecUC86r%cz$V3^?jE61bg{B$Q4V?z_u*sdjoZRu)C=3C~N zKPX-kG?_yfU*4MOYi|>&Bc!J0b>U11MmT3{%=L_0b`Ay(mh^5&t;ZA zHNMK1u=CO?o3@RIci~tNrMWm7Hej5)3f8t+_yRUyJV5JO$Qa3?PnmP(f9ebQtFNE4 z&ezuS>1dk$YuDm0gj3YwUE;Gito7X!J9$X0Ok;BGoc={P&<2C9f-{IpmyrNTJ<276jlIfiLOuKqk zZFM`dsrgu4`irVed(;i^!??WBTsj$6BM~_bMM8P=zojPYx2&@9wyv#n7F>7vyh?n9 zD~{B$^ai}2w0Kt~_d4PAesUA8YWD}+S@%7H-!~)B8Jl5@*wPUwT|n?Q=Z0N!PiB3} z{5)~9#g$1H^uF+DK_)CA?OQIcd+;mwI9A?gV={%*M;go6;FlMn&TT76pT0MJZsQjr z8PR$Fc-E{md1aV~QZ+5#2%XzT%sdT(PSW6S_O7+;PWW1T|0R$6hKvKcg;&=)OzA*Q zDl3@b&0dtGa)#IW<2Tt;Zy7t5Y+0tK{5dP6`kFH~!x*t8Do8Q`k)p8y!F`$YRrVKV zFrMR;`|)SSvi-P{3X>CPmXc6XalbUtxA){#0r{BYA&>1==3IJqz8xj0th_UtRLB_x z-ozFf^Y~5dIhCD9`Iw>#BPxY66p@q4Dn0B;rS!~d-{oJluZIeq%XVy$tH1W(WtuZK z!x*t8Do`SUVD6{PMQb{E*niBP@N??Zhj*VlyIpi*F*hbI@dT{3x*A+z#jt+&iiMbC}pI1#%35Jw$uYk4G`?Oq|Nuk%`!znlh3U8zc6`knqyw<#A0S?XkLA1 zy+QVhtd$=%6T2PPrPzjE3kZNTb0O<#SS*&pccN)-NPz7`;}ks!U)|5X`&9b(Fri4c zn#tyKLbM+}vU8m-FYth@gtMUvwz}W*FmxxHM)wcsZAjEEOol+hsg`t2Pnj`&8Q&Xr zr7%^oxli+?FW@LlHXJ}oIJdfgo6c3=SylF^Bd;%HgMqnVQnxcU!x*t8F-W2Tk=0+^ z?)_^z;&IPY85KgrG7_ry9`2}j1yI}(_eg8J3ali)S1 z+1MB%Nl0_kOg1KC$S9rKj%qe0Q^?E!^Y*K3Oy-a&Z`J?7Y)lrAaT*0~o;9cQgAZB+ zF8`tZxn=F_6Uw{gqOa0BJ!x**3_S^6oo^lwC@>fpH1Tee9s=n}aE*$tR%dM1ffI8T zPC0z2MgmREOSyU&gv&e#lN z#FmyoX#;{gug?l%XSjIg#j+A_SLC4VRNNknJ%LO<{{4#4r1{00 z&gkzodRThQ@Xlr)XKaQsVoOTkC=x_CM#%35JwiE+S z0$_r(HY`i!X>^g?YlS>}kM@d%Ukf>r8X!uBYheu#@bEpf0iqJ+2XBA~HLQj=K-A8% z!5bi&A^n+|g<;OiY#P}AKeI0XAf{8m2ai)thnJSmgTg@8Jl5@*wPm`!GH<5 z6j|mMmZqUkj~||p{`A0$cOf?X##rO26*xidfW!uSPFAd|HdYcF}#)vKTfKmelGo~!{%(P{#H?7@g1l0g*8`KALSL5EySboL zJ=7^o4jv>56dRKH#D;0({;vX7$deM21zs^GDty|XPX3TW%_f`IjQc~9G-8Ki zbEJInnnu6EFMmFVD?h%qdBZy&e$Bar)5H;lvploR^(Q^Mb-qvc+>iO&?oUdvndywp zFh*>t2b3BhIQUe{p+l~l`QwUbE#z}4ba>)u#tSMkh+kzO|7O{1hZYq#yItLi7dKyL zV>v1KDfNI4O6nNSRn5_#v|DA+@akfjMYz!`b%Ek@PiC5Jky_E!k0W&)vx8SPM-*z? z+z;zA#}&r&zcr8HZI{lSYrM-Dn_-OD(h($OfJpCmcc#v~XPv@bp<({-cpEEYY7_p@oki#K(UC`;%QAtee-gIwoB4EegqTOewDl#Q>H}fmE@OdF89;C0j{iSU6 zY?OpXySD9_BG|s6-6vqfD#NFv{5tOsTg;T`@VTsuzKKTt|8gT|k1BFPJM#kGwnZv% zPSra^aaV0!xwx|_E$IFK|NkakEjWFRuuKIX5_8%7y{Yy6tb^I0ER zxje3NVlg(bFg#fP;Y{#4%}8ay2)DpW@f|o1A>O2(5{NA?S^Qe1V$$lMv5VT{<) z5+rqi$fq+7o_9D@tS39?+&UrS2buyE_ZNbWd^a`Rbt$w|xn*mMq0O-)p-*KvS_R*y zgBs1y@fl)H`p~@WlWQU4|8X`GhisGhg0?l`Yb7c&+);`a>Li@YY0&W*q?1123+M0; z>VD4NJ}0oCTuRL-=Q43O=COnzW4XaW4hVC;Yc1= zPa`FdwqpyIn_C^en{!2S0%Ka+*2iysf}F7##)vH;L6QcD)QE3?#x-xD@VX6Q$FqXp zK9}Vzod6lWgUkaloC<}nt3*C}TXW9#c?GTBuVW8-J%0H;QEJz{(677m-k_w3!P)G+ zz63TGK*`bD@GY%0Sc_nvc8D!4;x%K1zPRr-&5->MlUA-lP7~Mf!<)S*Y2wbs@SFQ( zE;yg^xqNEw_rw`jzV}HvV>65qTj~L&1_-t|P&;qi*VfZ|W>zb1m^g3T`RBNj6SIlA z*&D}AEnjZUntQM6&4g=v4Q6bsRhb4(EN0Nj#G5_Ezsyv9XOu;_w-Dq1 zD2Zi`(hbLb?Q5)NJ(%;`F3WX~kwvJoGd9B*u_Y@=LIIH*9%`;{wF?T`ZOF)e@zVky z?j>8#ffg*lj;_-P&VuhmRJCP>??hBoc?aK#sMNa|z7tVB%o)BDQRQ&fja#oP&V)-; z7%mM{;lt8vB3pC^^2J$Rk58ODe$g@IBG z1TU;vXthJUy@TA|ByHPl@_J?KL*H8gQ)hC z-28d_Q}Wt>6sro>18aa{K2wf`++y9E4Cjrt>pN8EVpClt)Dylsun3X z<XYb;qZj?u-kM*Yzu3y`t5%BsMeu+Nbdo{y(QM>NhHLj;Htld&A<%yQ zzeGY|s{b9=ozF*098e$=J<0HBE4E37m5T4zeY<^y@o)5stC#TTB&<&t?bAbH-*E zBesMGNlGBn;o)fojkA1nJ9AVo={KJ~TK`;VmlKPbxtZm@-y(->Q@Pl(zcsTvZZ8sE zSab<;Yc&45J~f~7!1tA8v|RxV@`J$}3HeMa$RGHeydLFK69|oOkM6t@XEwJ2n_k6?^C1*rd418Jl5@*wPgwrGQAuuk%g$ z4FcN}Ulq@EIHB8Su=9#J@{W3qNxMkgQGYx!<8ZsI&_v$c!)0X>N1|Ki?Lckdye@|B zsHb5Ed^k3NJr|zX+W$tdqsXm@ab9!jVxFfHBXATfuaCkz;4f$ChuL*|H?6zm>c?K4 z!Nh6)D#HGcGd9B*u_Y={B7xv7bEh&Yd@s)Z>2vnO6qb_S!u3(pomec)EiCt>i7$G! zukvX4PM>Vm$>C?Gq`gT1H-VwYkEu50!;c@+d^_)U;>KXjW76A9%qz9xWc}=9@Bf~N zQkW1s4m={N9?iEqpvRAC2zNs-!crIc25SN%-!8DMd)~)=Q=eo<{nB6aY1$dyPa%I2 zkyFUq=kTfrC57zRdL;Z?aevACLpGA`>+eOo{&R|O#%35JwzLFE9U$^x%<~^DKJ&wm zZg}ciCRID(QES%`a0LV1J0f(W4!(CpYPJDIhzm+I?^jEPRn zmd3_wLYr>RVrAy{Uuw>szgPGUYtIf<8!@3R}+k#EfTO%LeLKBPneRtSKqwRUnMGIKBr480j&;8jMcH-I$ z{nF0n*IF6sBApzUi4aaKpER~V-SBAwGi$_7L%rm*CEp_d1Wi2QjLk4cY{?3eP(bAA zCsUVZJ(yJ+Xr$R;JFRWWMw{55pt)xzBS@=MJ?=XjlM!UTh;ceU8Xqj_zc>pyeSGnNS1?G0$tMk!wi=C~TNxMjt^f3XMbVAM!>4E7cgAKI zBes+TN*NF=lxMQ?+r+RpFZ_8`BL9b~Ke>0F2b?~jU0>v5S|tBF;y9+|!uf|Eexx0J zb^nX0?dAWyFLJNi{Y6P0#MU+66ro*Tb!^A9;GZIbw@`;sU9;*}#pFfG?m}A*OQ$4B z&C!cr;>m_1d3;NU*EOFs;>un$TrYRvtmD~SaqX?t1gn|}J&mr=+0t&@_$*v!F(^miRi}~eg{8^3ahKfH4iGMEWWA}D3?Fuu`@Qq z7_lWcQ1XG`itrPL-!7TfZmnPMSfhUE&(7YP?BJwg1lgy^G4UN6lL=(~f_l_eHYO9u zVoI?y+t`>)A^T3$zB#ZlSwIfq;EsGGb#7;(bJNL{57+iDIo9CqBzqzXbz{LWDR4A@ zwZdi@;n(nK(sGey`XnO-$@&U@(X}eIQLa7-kxy#faHN%Ai1SZ>tg*0vF1vAk3$O9p z)t+f9)%I>Odv(AWn_-ODQWYeffXInoj_CF;7yj52Yv}wz=|WBeXukdPWOXhGK_Qb46R; zOa9gULu-iAo#_}nd`6V3fQgS+NW=SvU$pv(pk5`T^#7Xc>$h7Y)sI7^L#6>!_Od8 zNuOfVv{rm;&?`_HSE8o4v zSlGheeJJAmNjOdX=U(S`E$)i%1eQw%x8twZ{C_Xwv#`?{n_-ODQV%3OfJoy{YZvEg z6gtUtJ?Xrpu=K#*i$1?VcNke3e$L)MYwC?8&Y$*8*S!p7uEy3q&BaxiXfZs&QJB2* z*dzEw#v@a4TCQKj*UZ~<|8KHJNjO9nCRz;tMhg?BjkH%u%{<2<|*HmlWv$VyfM#(jdxvP^|E8K+#f`ou^GmQE#*Pd5{NW- z>BUv~Z|BQW!2=?%PrEOy-qI8UZs!_8+PSJX6WN%IAcx9nd}(H5GKP%1Xh!O>F_}Qr zsGDD8V={xZdAXc2I#y~-b9cRVZ2nv0%81W%yqnoBlQpM2TJ|t7XtCzXgQAInLA~qS zr9VEG^A^8fz3?v2d0CD>3l_yV7bBNFtOu}^JzC6DcJWRTlYeiR z=E1m@Gih;Q>zu{y(~fI27GO^+TI_FNgD_gmQ(6~R8(s_AW$9kGSzzPdld3U5Il1(+leRcy$8A0-4WwEwaUnFL(x;@bx^prRCD}HhF`^~ali?_4vO3L z34Et3?k&|bl5Cc~eRFBmPp&%l9h@i6pO_$a1tmGrtl6W*c@(-1N`uHP)q}kcg;MnV z_$9!%eQt5P#{1ih_fD>#+L<-R^vW68ssL4ro6{CXlr}F}jr?lT)l^QEtTpqr| z8Jl5@*b*KjDS^n>`bw{4q6F=u1j@fZ%gn#)eSXz_a32cGoT5PCbNDoolzzt5vl)9T z%IB~8$^h|%H^fld=qdrpxa!!9UAj1Q-vQ2B=}_bM6PET+R# zSZ8H8W#UK^JpM>U%##@&YC9Dcur+K9OqYL?k$Og8d6Y9Y!x*up9#Cq4;JD~jhWz&8 zPwn#$h}&*q_|LP8p~ygCw?S_7|+_zo4qt0N6JPIz^sCTbk?^7K;a+}Mh> zzN;!3w%t;jpnmH-N?I9h<}zrSX-PvOK$Arix+VeJaIO}g2DCcT*z9t`=FwA@>GI+- zk9)WsV}4D(6;aPhIIZwiUoZ43xi&d!%|_u>esy1Z3lt~*>2}6u7$de+1#u>bjQdfv z@>l)&59wvoTx)M+2FHffxq=Q4GBv4vseWTad3R~~HrsqgZ<*TTCuZJ+^tU06UL03j zX$gd|F+!TZ@^6-1`xC_w)|3}_g6m1pG44&1N)in z!0|2d@2f2fOq(9sFNt5+h$GzyY=)OHeAPKjmjc%IUq5($!>P|9-akV7xp+mKu^GmQ zEro$n3La z^qW&a-EG(gHt=bf#ztUch`CBnOQ;9FflcG5w3ZFC-Mgmc%Z{D?$g3x^UApv@p*HrC zNK0rLbORf;Czggwha06N;^cpO%H`M@J^3@=gx-FMS4$QtZXleZgjqG1><@9@V34mp z78ug=T8MAO|ExS`Y=$vnOMBpC048>CJAdR|)}J1Zb8kx~w>CuW;B`0%skI=JN#MzA zV+dQ;k(G_f7&3vRsUOY82wnfMO_7ZeQaWj@@P4~y(Y0Ud6()f!_s-7mF;85hmG}iE zr3~pdua?L?*yc6H$Ixjd4aa@Zi(WNJ-Xe>CnFC6j_mDT!?VecOWR9iB9)$GG{wPx0 zDutXQmQDiJLL(tN-yZH`A z$c4#R`l4ROIbvHZT9Qsu;P54H;3c@Dev3oYt4k66G3Jrdj7xQrOI&cI3dvM>i$$2# z<<#_oU51%V%eJZ=Ri1cP;BHgM6K8COF=9(U5C?u&!h z7fAgAStLiyQhtqlo7os4x4LR0iq>s2V3KU ze=j{%7D~~#1C76NOJP#64TwoTsH11zZdhdUkaN!ww|kNznevWl%vbH-*EBep~ZN+b~cauJu;H<^hWl+`NtL>NSDs`#y`=EP!XXligp zOkz*Fxsc7=to6F}YdTLTTwG}d9&Ry(G-$PCGvTK*YrLEXKb={9wK985L%+1kJA zSH_o>de`;t=c^`^TC`-FF;89?O)U&4U7-`AyTw+%zwq|W66*;0JdPtX&&))=EJ6#Z zx{=+7lv-YLA1mBH-SRKjS;s}mU;M7!(QdrvjLk4cZ0QP;Qb1(#g{OittMeXaZk_R7 zeplqi36ZxZII&n*7+AQRO_%48+wO4q`y~Z#F6*ltmJjcPs~bZ|dsRz*`oX01pEKJ2 zADwde^4m|B1e+N?7?zKw3Q(|8Qif>BZ=9S{@`m|sN67v8`)+Pu?od4Uvr8e4GDQ9g zQmXiHk`L|cQHJ7*Ia2g zJat&miN)N)#N6z_)QbE>&DQjnaU(`bJl8!SKHR#d?CPa zaIr1(B)4hEDMaxbyqSuULIT>I>wd-lc(>){Vyoz7TwM+7;4NfpmXK z>k4ZrpTBqUfy_h4J$fHDEhu}xzgWpwe--MEkfEK1lwV?Wh3S-rp4%mg%!+k4?vTt` zCit}fs)R@9e&jTyVud{oS!y1-vA3uDB6qvpjOUNiGy9g6t#-y{7$dgS21-2;T$6lW zWogFYyUR3e6xqz?mM?vrRtxS5LwAHQ`1-?lglGr`vcYzQFj|~qgYO90y{<S7&p%<(#A!?~oLG#_EX^2pExwhhB*wTaB{0(W*Q=U< zq1SG;t*YjSm{8Y4z0q&)uRd9ToQSkEe4*W;(L}_+ph^53(b40_^*!@nMLm#zFk7;N zB~8rEX9M9xq%nW>XX)wNX2?%5Jn{44|JFo}J<3Y#&e#lN#FpGZ$p?a0J`kC**~_H1 z-OFU&>kp#ct7gY*fG(Ujw%B!zVU~<AYrStK;Nbax;8Kg0)+FfcGqz2NL#oJ0n-ZJ%aoMH6JMRg!bOk?} z(>d$WDZ;5m>+FP05BDBP-}b0va!>8iMM}25XATNEV>65qTe^az6c8B@dun08gKZ1q znLpkTyAYo&^YPYQaFqldomJlqT7>{<>T0qX!bfMNcQ(LBXEn^`FS_#mm@ZeYp4q%T z|7^Az|4hiaCV-MYunevY?e4Oc&NAreEbRtYwB$GLTQ9h0>Rj8qEt3>|OxNAb74dF= zj3a&MyoGm+w9Yc0T*W3(6uc&M{VWgO2H6MU8v|mTu^GmQEhT|c1_ZZEHrBkx|3`je zi`$;#T`lL9%Y6EW-2GwMy&K;BVew*-x;#DaT;*@|xz}d(s+OfIXl2dZh>{NITB~3y zC$#jALAyUgs+{OhQq(s(b!~08siD!moY(co+kYWn@~wr`bVW)BdS7>Y?q;6W8T2Y5 zq`1-hXxE9{8mslr*bHODmSP}j07Uk7Gre-z@${W;birQc7mT)h`6Lq|4G^L`IgAT# z!sh$5l+ULIbGoNocx3Q&a#-f4jC0PPvvh7Dr<5VyQ8qX?P@Npdnab_`Clijuaqvw4 zoO^E5rW}Rs$R&oMJiL>Gl2RBG>iU2F?u#h#T zJcfT;-d~@1;USJhVQd1gM)ba(4lQbnoD?UazbNya=!z3hxA?Z7cgAKIBevuNNf03N zU6u3xD=B^rJRxa46aOy1P~|JR5P2P~<_rZkCL>5+2HdnTfiyW(ov*;x(MrEbVPi6Z zO#QLyZbGc1Esca-O(eRHi;c+=vV~Q}>(rufomBhft6nePe5vEyWciCSWoDP@lbp0n zd7%YV+;3}eKW@IVO(f~RJ=8gzR;`zw3$e{%O6MLjmYV*HAMro16S`9Y(GBzMN(_&iYK$|s<~F)7j>0*i(JH*Plwk#C~4wZ z6r1pcyBZ8#_ns*wd}m&`tu}XpGd9B*v85hJdH|6;obH>2-yJAQUuO7dyWpf_^A26r z0=H1GY<1^|x_qEq?N z<9yKP?@RUP6A$&TWOUeTcYH!3@_o-*NNL6LFjDz(^>zsVqqjE%qId0Ib?~22q43M& zT+Y}GW5kxKK&b?RZ3?D+bN<{E8h_lfSS!FRoH6IpS4gi0vPzBl^FlTzb4Wd+@a^&Y zbj2U0SCo%)raTM&d~xqW$y)bTU^&sY5le!X3PGovCl>G#GJ7i#)vJ&K+*t+ zJe0M0_l=F_Kj+-A(UIXy-g9tq%vvXAOB1seDbB6E)#BPoKi{n0J0a1=|Deh_a0O!q zX@6*%39vDlL-q=)*(_sYGKVA_E!!pB7hGH}HEWl7@+fahuKm9FccR#9l*BUH1!mB) z-Anr7`)lD>y4Fi%{ZP1ZJaf&$?8{&Nu4uwh!5}3T+aL2LE!@%;qwwbKQ{JgdluZj} z%D8WE#%35JwqylLCJ=mFLi59vYNI7D*Ctl+`lu-yioOzXVlgo_v5-&{I~g4ta1rloR~s7$7-(&*qF?qs|f5bKCQl;uzyj|I@cmj=coU~K0n&W_#HWg z44o#3mi=q!Jq;T9`=IwUXboHwL}SY86A|e~b=yoUc&?iNXzoc*l|fD+4pQ(Y2ucc3 zWG$8V*nO|}qp^EZ_r}flS-&clIb$=75nEbPCFg3bapRwbFrr9+npR0>Ezvy&}JSc~9H7oLsnOcsY*_dGc9~FCe|A+MR)aCD$ z_$QrQue%{_-S>|VJ}lf6=`;a3q0w%RN6QJ;|3R$2ADp9cWEDj-7u~$|SG7~uc+tOL z)d*poFSk-}6HaJO&94qg`SGMno}Rh6e(Ud5O!GzdDZO*XW*8&3Bne7l5X={PaM9Jy z<9spyeDuz4JaZ|bYKgxSi=nB3;m5vBlexRxmp@I)eZXdY;0ANmmFYQntMj~f-^S57_p@#NWg>0 z3`N6b29=_>{Py;HD2s31IM+w_sS}HZrG-hV@~U;OPQFfC{4nI3oJ#lVkR0hir4rp-c2 z*uFyVFVM4&HQP2r&pJjdiqw+d*!G0M(0o_k3W;wMCdf|eJIBO1Q4dFIak~uf54kL5 zc%VGx{H351RvH!o48ePy_RakH+!>o;jM&l@D4jqsOGDC&3&$#DZ|2=O%Q5@a0%fI` z(@rerX2wQ4xfAsk)utvMOS$OZ?(;m%@6-~1}Pr{&rlqYgObolZbK7YEO{J*4%`jPic5**qh9B7<|8c<$sPJG{KpGwG^9(t87O2eKwIW36ub7ZcE|W7h!x*t8Nk}3Ck>|Vqv!7fYK4Hb-mKP7- zNFFs7k!k=JJ_HUC<4R5S(=C3qQuHi`@nI5&StGSj%9QR5iw&|JHI%6}85nJj3 zr3MIAn77}=mw!_C;YDtTdtQ6a-KfXl>BM4gVr)M9>!wAkS{Cx3d~4O~aDCmkX`5R6 zNgdMD^3_B>y|P8+&n%-2yDv;{c74#l;I71%xQ!=KQqgd!!hD^{9?~PL3cFgIrFkdf ze0^%zy^PuiNB4eCb=ig^75PqsS7F`(R(BpR_+uI&&$J`uz@rKeR*%mCi=D9<#)vJw zK~fNiY_it;f8+M*$?0$JEHy4u$`U_&fFIN(HaEI)w32;sZsF6Eg&ModWgoY7tI2#jmtE%cOU-(v4Hby1bR#h$keAv`AA5VuO`^8wc=)>`QL&|&vkN<7h z+{e0M_@p5%|4!)CwHCe8(0ve($FLlsn0%&mC3x^zU_(ji0R(i=nZZ zaYW?)w4H(HUs#Lh@fLJgsZZ3t{u|t_!ZyMaxcP$XGN!fz!t$oqW_xUOPRWz?S$PRL zg$$t)p1`w%X@sYtMeSFTxAMkKIp=qJY`U~2{)2A`ataCj10Uf*Ng<6F*R76T|I5cR z_SEylV_yz0eSUA9Gd9B*v85$Q>Hv{>>$LCbDF-vY`XPAtyJTeI|E2Z5PArxNW|nHL zb~mDRBL2Cwf9bzfA5dlC=@kt+NP+U3IJJVWo~fU;KSWD-mTZEU^q=WzM=cKZnj)ts zdQ3oQ1;2-$TS)DR>;WuszB|{PoT)S?n)}G4noC;`O?s#J*dIrF3h_ZIab_01YPGRZ znq%O=Fn3*1`Vx-`_v4+h8ODe$<$+QX1P29|X(dm7aX?1!QJq**Xa$SFE6DU2w4(33?gNtNneP_^y-fx~Eyj zVfB0SQSLxPq$sU0d+5O&h?O?f>B65qTiS!9CJ@=I^tJ8StW|G{cVs(e?Kr*V zy}bMomVMhdMMU=O`dbT*<=HT1t-c#Eq`5kLJm73>=ToMiEnoTQWBJ_wL&8^H5pulEe zP>W2Egt96lq#!KK@ExCXD; zP}0qnnfo1`dl|l&_nI#%%afS?^XQ_(&e#lN#FoM!4hE5X1s`$mR+m|A603fyX!rl@ zs&+p{Cl+%{L$e6s$LDIzzU29(+?dfn;hFRIu0wN?OCm`*ZNwe-oeuDlNL_w0{EmB; zmrn3I?zN)U!;c73n;y?xmKds=_p$tb{+8W8{yj+5nUk81Jw<6norIM{gK|NR7RhZT znx?3$j(4rJUmv>qU&L~TrT05YrchQzyPvW#nL=k#V;R|)%prx9ltLsMlLh3Q z2Mw<3M~=P!N?v}iSaRvL-HbWM{d1otE~IyQ(u$Rawv{yZwm`S4XcT{j-ls+E0vTOeX5j<5$E_oXsRK0s&oj9 zE^?P?bhB@ds#oN_TJ(6OQ|`P5{r7}ZP5ioaOHC&K`?1q_w~6aYGmGZbNlME(V>65q zTlxZ}7YLRNQD3z>*=YURU0$l<2G3@lOUr%=x}w0$)O%8{rOpNWU%@(@+)~!(PCm|4 z&98zrCWt+rd4J7(6Q8Q65qTM~l=Er?V!X?84b;Of{H z**v+-ChcJ5^~npJm`yDWS5BFty4=3>kjRt|dD-@lWw~bB{s7NmKyRMb@E3&NJgt>{ zfDLx@G;i?i_ZthR@BI4v_x!GMh01T1ZHZb};*b*yCA}`K87|1$9Spdq9%K|Upf?IGXG2g+_` zPa~GwWvkoXVmtGFdb?y1aymftq9|$eQdDT9zJ+d+!+*f{AZw$<3cb)~y!6`sM({1e zjZwLr+rmF?L@qSaWZ-QSlyq=!&PkWa_sc)A_Uvx4v1Pq`@idpVGd9B*v85PD8UT?_ z4jYWWe$tsWXLZ>A(D=d$-p$n^PArBdW~TOg{#=h?+q^3xOx)$UO1PQlte0+}+J=e1 zMq91)ugDv1#biV0N909DZniXUPip4d71@@KV<|G}<2Hk|1j*nhZlf)HOAA@^SLZuI z<^50p((KSv_71##GF&Uv@ez)clM#kgg52Jtli{$5C8j8#CHn@?qU>XL5^J2X8ODe$ zje*h(1dDt>dRxu9eFM+(<7G~NZO$Go@B9y$rGhj&IKN$CgWX_4?5z~M%VwB1MF zlg;Smu<+4|e7h6KrOYs_ZD^NPvh?L45v3)+@xzyz9f^ltPxcr2aQC70D>H${4tpGF zC94T3t?0hB4_+|g6Nl%`hyP07s8xK($++l@%`ir6sS08}h?G(|ANe7|>z3`i|2ZOMk>Ucg-tE;k5@KpiDQtR$y5P2n8KkeQd2*MRyypA(A!x*up zD@ag)$S;{s-`FqZo^xUOSsodY{as(CZ)l{!5-v9J$MC(EvNIYVe#l>8AFg@*=b4~) z6BnO6cgCb60;TYw-4d?6PS_Hz;n<&@HD6F>4@MJ{}>C#Sss zS%+5kP8YUg+#c#-w7n*+aBh2*zB4w%7_lWhP(p&>JUgo$L1&n+$-65gO%;1%Y2b7H zDx{)<_LXrQMI^QjbnQK4PnAa9UD(O2nsv6U4IIl0w4dzUD=gy~z*%$j#DlQkC`qN@ z28l-z5k2-Yypzg<4XIu~^}EiiOxv=k=-a=St+QLN5l$+FT1VuLTF3r;Bvtc>yQ%rg z%tx{t3=*BO8ODe$Q9+Ukh)h`?9Ca>w-VMPcykBAp8r7H_&N+dPA~LzSV8&6N_EYi` zwKXg?xxXpSzkS6KX)KR|5n!!i=65rGUvbX;V_)oWK7e;EOMK_6(s1PTM3>%Gu`F~f zPZQe+Fy7wPpsmUB13i@8Y~}Pck|)*M?X+K4c>Tsvwl)QUN{H+={HgJU|` z>%*2FVf$Y#db7kCn_-ODQXVKJK`{U11$N6@8V<|NH|an3hosWOTT4y1J$h?(_f`$vQ%!j-w0xoZYMg;fHJQ0S4_lRM{+n)O*vxyU!hjDQn?Vf%h_+bH#&2UOJ{mdOR9bBjLk4cZ0QS>ULg3-BWsK1 zowsfuk9V)ytG-M0tDIvGqng5!%XiA0uq{|Saj}V#(B7`s{?qF= zqNJ74whi&Sfh#vd``{XzU6xH)FPKq#Tg1ihMa~_sW5staWumNFN2-gE(n=K@r{GaP z`3)W~LW}g}U-(-7nfK`6N@r|_F=9(qkaPkfIh%Oa&5c>M#o6Kf^cf{W6|27QdJDQz z$;|A+otftGk(akMEx5aHk<#bokDdL$gZtpHV-~CL!;e`MK)vMeQ`*H-+b>&v)425C zdvT*^DeJPSFHlkoe04evNB0mVOZ89a+%lI518X!YN@XU#M+7_uMz`fb3! zObBJ&C{k*vL7ab7#b&bZuTt8-DP>+wff9$_wiiA1>-BfWW*8&3bOlN$5d3XhYs@*D zSf?f2%Qf?}<2SsRz40{ozH5U$M%AyUE?RDX*|+;wO~mq)+NDhsP)^0FsYBOX5k2OMJdXG3Y*=xVeD>vg`biq0=03+Qetz%8 zQQy>g!CNU+Z0l4Lq>cw#zmXM6+L*f4(__lE@H%H~hB0DGKOl!gu;sjeu|hw2oTfYz z*(i{{^n6p9)HHB?13j`vHnxL}$pq52Rm~}eA6X-Dn3avm6f$zB&i(?vzlCZ3dKR77 z+r=j)tIqzkTYJwF$2T0`xy_K%%5drXXf-Iq_P4;VNuud$s=ce6U$FG2us$pLwfgPq z`^|xCEZdRON<$gE?}L(7ZrNGxd-Skw@1vf==O>lb@@Jk<33J9~7$de+1xY6$Qd@F& z`IdU+DUWxC?QIi0)^+#!p%f<;6LV9;4&yD8qUJB*Qu|ZK^laa`xhl^acMy|`w3_^J zrJ~<`)A?P^OT7g)eUW;w@ho5FXY+T%G8Hvt(l-@l9slTJTmHMq-g53H<)c@d&Rl;hG2dc3d;Ch}7Blvr+$CS+jLk4cY^ev59zdk2_yevb-FA$5 zosG3;1!k>v>{_%9k|rSQ!f_o4py=Gee@!fEmTrA8|I7L#yKtn5wkJqwVus~qkyh1<)2*(m zIIW*GDd}E-#4=}WhB0DGJs^ieaK{v1!`8MPRs~rz6vd7OH+}bO{sm4G&;u56-JGTH z=;-v>8WQgxNSXw%UO&6Dae|k}?z=4n(?rK!=mCpbcn?b>dWFJZFDJ-J6U`mb6Rzgw zJg+vEW1FkGeDkx2iX%AEM8^-LG{LMV_&dIk@h{WKcTwtx@7~$TEEwsG%`ir6sRxoC zK;+~Vn(dd*-ZVU05qr}9?q$|{vpu?;SWL{!jf*TVu&Gsw74Kt@zIgY9ufYQl2zjO%`IKMrSV_bwR}`J{drtG=mDrPirp-%g z)57e!M3@@DuoSx6HndaeG;CNZ9%iixl_#ut`tmm6|FQz28zlcXJaFCKyZzfWK z6KA5lJlDMGGGE7|A1#jaug2!zne2?sFh*<%50aEXWZT2bdk-lZOYcf~%CYhO+@8rz zpCm!I-5VH|E&6D~-O#x@>H4*O7Dqha{$F9b9J1UJGQX_3P@av+6tc`ktKTW6qBy>% zLDGJq&9@fWZRM^;{}ZU?RPr+a&mJ{5q?? zCU1{`^EgsSe>YMJ`5Vt7QhRaX?bTUnvurNR>Q~S{y3-k(VT{<)5-4pz@cgx#rXF=O zU$=I_46_5h9J)-OFDW^(n3@<{s+h3{x6kBS`l^X3teffb`*&;7ASb*UK~u<{7TFOn4MNo%31c*W$0oI)n9g?D&SQpgL*%-Jt=ujsX(?~Br#!7TUa&>m%HY=$vnOG}W{0V1b+ zD9Sb+w!g*wahH`zK=91?`yR_Z8CcjzS#~SCHB#kC;hwZP%RFX2{ws9M6eC(C`Dx9!#A8<9BD$Kax2| z)4Y2pcE7&APpb55w8SpwH!kZ2Yr@f*x*v8|-~JiUQ>(}rHK9+!$?r>INDjFEk(YDc zj*r|kq!zRWv*1WL)7X#_&V;_c$8%22nf-pvMD|AAh3a`T)?9MNW*8&3BnC+|Ao9{R z2hs04!@})1<-3~Bo|nVEXR@Rdi-o1Bkt#T28}4FdzVUG!She?kvZR2TUMJ4lf=7dk7f z-u2CSlhd3F#j848OoBu^cIM8|+$E8KoGNA@_J5$Hib-j~YIkkkZrkyL{awKW3r;=n z*g$7&hB0DGKcMsg!B&|Urmt>L{L?&T>%!GW#m~fT_Hu%5i8V9qnil_axAH5#<#*g9 z+LKlsOE+X(h1@q%yE+km1B#~ca(Lf}<7YDb1YnH=PVj>ixm}+iZa_H`0lNW3Yvxz@ zDqOV_8El81O7E(c{KKMg?q)(a#>TpZxUf_() zFh*=i5|YS3> zNZpI~FXMSOOPU8c9cUE{_!8SWanKIeB|Bp?j1gOk0i^&4zCZU$gZ9kN3Y~4M zdmGiyOwcOY=;Op9gW=QY5Vz~Nn}GNhU{Yn!L93R810uhdv!`MKLB z^-sqEb{y$x-d%XJW=`+N<=d*4XWZQVwCBr{V}%PDU(BgBBes+WNlPFye#Kq+ zqJ0fomO-a(Pj7x?*JO7q0zB{!ogie;a)xgpLYp8wvUP^h`e!ms_m0a?;hZHb>|shB0DGJ)qP8!3B{AXRT@Y7QWeSS>>&*;{H=EM!x|sFffEPXeD&R zuwFimd&ft>1Ray9t;OBE8~IL5>py9iR3K}Ml2jI*8t5G#L$f;iVw2CGcX8D-o8^n@ zmzax)RjtcJIim%sS%Q>Q7RyvfUQ>@d#%_ES4)mx1+9mju^GmQEm1*|35aw) zD))6=tZvfQ#S5;uJr_;5YdZHmq*($vFoXZK7yM!+PLt^s8)ou~@Q2^z;P80;@ora4 z9ODNP_8e+0`3k*Q3IAnmSogsX@8+p%|Er?oFV!Sot&jg$*R?NZZ<;>Jc?e5Y;LTH% zbnr0cjOG9Nd*Tm-Rx((n?`wHcD!<+tn_-ODQVb{sKrnajwEl!|qQ}!;oeS1&N>DuM zvN;(%dICLbj;EgicGjGF$#?i!b6Nr+u(Rd_e$1Ma=>B!<^Pn8Qe`>;$jA!h(+>)(^ zQc4W=Mg}Dn%Cf)Ev*t8dY+-}4PkEqc&0$+zK*FHgqY1Jti~W8za9dtwlG3z^ovKuS z8M#71N*&9c;1$YZnc`Uj8|?1ber90!`OW5|^5k!wCwDnxGmH^iI)bDO5UFIbAl&iL zlfd<7sxGsc>ZN~4ydes@Ny*T%u~8_b=s-8yKZSYO%M=!7YV`P~ff}u_Q!ka@`@_$g z(^@GFKWk2Nu_OGfIq>OE=FoG(gnHPR%pt4yHGWFpa$mL3Rk(2~OGx6}Xg<%aeNIYu zP*N14-dSl1J!?+$@Kfm81dW9+pyiF`2}4$pM;I8WzSD4M);m?Ni>|QfaNWQE{7zi0 z{?v=6%W{PYr>K=v9=cj32lq*@a&eQ-5kC;f!<~3{zcV(&7_p^2NECob8~bIpM?C%& z+5hdYm^AfUthioQuoH`=v7wQ%z%lvPN53kb?2Rpu$jR7bB^RE7G8(r!H&4T7-`A*$ z&UG~x#P79FFWDLPq!c+-;2$Iz!L`upcKoAp$29LJ+DuXj&QMi;8?t}Wub-b|LXcC% z>Q(Ss2&tS|Ipx~TBmq9TIaj7fXO!<kX007qG} z{u{i_vi5Pk5tcREnhKPdXs~vGd9B*v85kSdVt_x#xvU0uYWDt$DrL3 zm)hEwv3t@>Cl*sv6XO;Ai{e~$H!Gifrm^_`J;8}Si&jG}qlVoT8eIavP)lp$dH97| z;-`-MPJ86lXxKj8Pk*Y7iCg)>2Ok5a{1_Qh6d-mojMh913|bps!q(5iPgB++RP+2; z8F8l3`|pLf}|KG^(s`$MDDM}LK%=1j&|yd{H@o@yovI7q0=BwHjfKJ5AYO8VX- zl>}#OhB0DGd5HAHYG`XbVacj>$HIb^|C}+2=_nKPAyDaKXxMVPb78U7T}#D_mpWdx z#~R(dn|u^JI0xNBrnSu%zK2Zq`$YI2GPUO%@ZCQQ>8bENWSY97t$Cs=JM+&Q-F@EM zvU#qd+H0{3N03v|aB10SZA%x01hMA4|Io!Q8apSz`rYdpp#5(3cORhrZcVPmu>FR_ z-e8P8S;X}Gd5iJ!+8QmEhK-v$rzA}AUO$a+D%!TI_`#)j^DTEyyW7Kl9_@i(j4K z+PUL=uvT`eb{Y#x>KM)~oE?*4se|NE8GmcSx1A{YcjU?a&}BAq z|5PL=P5l%x&xys<(7-&Q;i91HE<&doN5ObTJ{5YpPU5#GX4bnY;` z|3NbUz4;lP@9Q=_RQ%I*^xxsO(bNJ8aHKK3U8kWf9K;wN!PFwbcBxCE;6rlXlbT8O z+YQB@T+BsT>4H=v?MAGB+O~`3#^E+o6HCwklm4$%uDbkklS%PfXKaQsVoO&bheL3K z=yQiqQ@Mp)!cmvK@+;;{nA@O>yq*QuT7QP+rSSDE(r;4W>seTJHzC%ult#kVvxx5F zVq>y|tl3rZI;HXdWWsfYu$X%R^L5VFME0`=U1O(Ha@unrww{HOd1p$7go!PD$VpC- z0VYfzV=s%k?^a08KH(rXDI$Ftj>2beCOj=lk&uyp>xw~gk%>6H)B~Pt5 z{?-|rVT{-k9waG&NM7HZ#79T2|GQ)`V~(A`j$A&w_-H2+kH-eS3fJa>iyDBevuQN*YGV`F`%(z#})t&;)X@_+-$T zz#FEQ1KO0<%v>No_0sXlL8vG7(5_uWv!X@oU@yM?&4}d-v@BXCZ0!hR$k_8{ZfNc@ zkv9nwv!~xinHxY#6$dvU6)l=)8H~Op>`}O<{^w2LozEq~FV?v@V>65qTl#^d2oTB7 zlr(3P>IQ#{cQ3VibC*w9{l6>AiN)O1)O^a#{6FVB_?t9O&5ym!;9&IrkhB3(UtH^O zC$>|FKzt z2;-3xuN$P_aZR<15z^pDKZmj{4JkbxVL(bxA7l2m>07UA64bEYIn&W++VrUW^Ul}| zW5ky7Kq(1=XW1_LTEFyG&Xq@>@2EsBd{n!&)DGMlhTi|6`O+1B|AR($GW`ArIrT4W z7oUFGAN086E^qpUa_;S~Bhu%hZbYMC&OqxZ?EVLhPbsj=LNYeME(<}NbV`Rg1G@LD zHKs5IKFp6YS(LPX^PJ3}+~n&v8*$V;NNM7jh$w$)N9G;*scy$Ycw}qjo*jHLW0x~F z!x*up9!Posk;xmy{POJ*OU@kS?(llcsdN77#U$iL3eF``9Q)vn6x2g;_4zp0pZmaa zLV~64rOAs`i{1qCqHd!<{ub6qA$h8LL?;!#*Huef%!}???c-JYsr;FZa8fy8 zziIi;w^R87drmKPu!`lY%P%Y0zRww(VT{-k6)2HFu)?*<2c5d&)osx)&+aoUbz=Xy z;w-o+Vh-s{Gq2kG=*Ndy<-0A^x_o`Dk4UXwsm^4OIg+amty2=v0XPaf%{6{+e)4?S z^Tk1C*01~1UT+skc)A`(+@G?BR~;wp&vY$LvIx7eA!5Q4r{e5;^FuOq1D&xM#)vJI zK;j)lTIN1%-nM4ilzXqQ9a`XY@>;0D)l1;2!xXZT61=>{46;;CS+9YO$r7?dl_6$t zOOdUjF~{Bd(-JWgZO)v2e~oWx=ipBhT4zKAKptmc(4um4f@*0(?pDL8N&5E8j+{%) zRF_=T$$aTtha*j#@kdG%Hx}$xs7Rgm%V~XFNATuGb|#L>^)xb<2>} zISs@R3(hS=frhdLb0ePZ?@T)O_kQA2xm|DWq26v!yWa6RC)g0naO@qcKV8(lw(@_B zUVsq0)6+#yH{Ir0i=5ET?SS`=Q4-o0>8tMzvbXJRSW?WmVXdv;iXF#oov|6lh%HHi zk{ARp-o3f*iI>;kiSuJv*)3hJUsq>(1M2O-*49ZP-Q&tAQ~_UGN8~-O2082(H)>p9 zZ!+uk=IXwjdrIRd%DtOfh;(ydB6Mw?7W^Jpibhq2ce*LId7!P<{gR`?Z|BEPZ%hJw z?bg>Lr<)5Ou&0~Ns$16nnS5=2Vv5a!fc+PHUS4RJ<&4cRMr@0(?@>R2023zH;b?M}?E$18FC9|5wAC|tDrmb>ni~U6{l!|Q_H*~cwJ%-IE(O|Z5 z!?rtX@6W9`xp48ZJ;LjXMAF{vB%E$8YrMJlRPyNNY05|bXBcIAK6vwnb$zij6Bff5 zv86CjihPj_I1KFf0Aulu(hCph$Dh+K0 zY2Gu3Z89>P4?BhM#wX|~ou>2|*opmE=B8jd>#g|PiamU$ zNy}pme5OhB+(CFVNVR1vY^DkA{-QFg-$p_cH{`Hw;-CNO<936H`pF0Al+dnw!kR&( z57i9*gtqu*#`oUrtg85I_hnPK58G`LY)B@Y(5~;lba2V*k6+57@-5ZB&ka)Wu-W7> z)ft;%jM$PSD2YL^OS<3d%cu60y}LNsPx!;6tCO^*oOfa|F|xF*NMVTKvc2GTWLC+^ zbYuHldW%jPftE)=XS-C_AA(;9EaNW%zYtjAUL*WMV6B@o-mlWgyv?V5YE7f`k>88j zFKSM$+DH9_qjhr=<{01bPBizin_j)H56GKz; zj~}>YS;DIx_SA0Y*!{72_y1K#nm`GM3DyqEvWB&T7@Ni5?I5k&7vb%oh;oIg%pq1E zemQbacvq*Pvw8E2z9}ec_l9-*`SxpQI|%<#4P>p|OFg;4{I%8XbyIi>IU0VQVc2>- zYaepDxnqE>{e1I>2cJ9Z$sLm6q*sbvvTY8%@t+IQtf5uJT?C_O!Cp z&wEpuoU;AOS+e=ur&bD2<~I4^jLk4cY^e&8PC#T+@kLQ4_mkE>D<7ZVp7%N3a%<#6 z&|r|U!SkN zjQ?A(Px+=ZHp3XPB{xv=fnY0jr4v#MtCB8S{Yuz7EqPA8&Z<-=79%qggNGO1{|e{n z393xU7xI61eWibz`84qMY-7mWgVv)eHYQWZ__O+F17YV>>k~C*GM}Wbeb>^P;b1+J zTLUG9kX+1YJ(|J>aipfRBlNm@tlP8cJETMJVrILr>WjPgFR4UCU94GCy~C)i^!i=o z6!PdWyqG~rA$F&~?ti8kxcQ?!3aOt@9FfRX-Ya9Da$b<#|KhMrMNhWTx3W?eLG@Vywr?~dkd7hV%H_sTGJveOie7hE8dy)K*F&?dqnf3+#f<{f6$)#x{yPNQ)eL zCzg-)LCI2T-$TBK#ILgbyOA$^E88OE#PZw>dt!N9VzTA1X5N!#T_FyJ?wt!VJPMVa zu^GmQEm=Vl3W)sEJ1;NdcFl^!Yn-_m-WSB?|7ASy#B6G2S?YIoFZ0)m@%MlO^OD64jjIW&3?A*|xlycsIxR?w5@MH+uOc&k`(6MiU4F zV#}P?OATyCC$7u;>F<5#$TdR;N!L%S-IdPPP0K}2ATPtQCy?wQfwbW1o^M1IwR!lj zJ!_c3zJIPWHp3XPB_&YOfZ!tE-gdUW4W^X}e>U6f4a(ePoi72pUckcmT<4EHG7lMS zC-+Pbd3o+ITaC1}1UQ92uNTm~sKv%)0cq}Py*8M0TD_-(DcCt6yKRr`te~>5eI6@O zQpkX}Yqef`!OpsaAGtaN+O@Y!Bd=b*yZT{e{!VA{*I_2HE?IAIq>$H@9E^~%UhC$M zW(Vcj*FM-EpV9tLPCh{3xc!6d&Cb{iW5kx0AgKdH3LZ)_i0fZJ`^mA4G|ttF3ft5> zRw7SeY6NE?4hIQSg->8gTZX_72T|(X%*F&g97H|L8Gbm3%HgafZxSq5(17%ZhG@FsjX7$&ZCR2@O>%ql-W5kxiKq&@-kEinn@Vs?gH6cXhEg!4Yl<6&b0^st) z6mqqmn438plNqE5qWo_z_Y+0Qy`~2i6-x@ow_D0Zb>unBMM(!#nUJK%0It^iuE8|L zbfI7N#D?|N&fgASeiSC_@Mc96i$CFX@P21r@8eq0a~B2QZttC3Hhr^T*j|AsXKaQs zVoNcQGyo!1`I(dw%0Bx?-d_LqoO8W%g5}1$#7rc~`$|zTktDP7;gxf%0-K`lW={J0 zXTg+@TzSa^cWU;ZCZL$W>H{(_EeK?gp<=Jjx)RGsH}K( zaz#qSr76ueKO$XjJ3n#8W*8&3ga=AU5PYd7Dx>K7(OS*-ju~l>R!w^KkO8!C%h1&L z^2*6ArMGgxkNB>7K8wFvlppy`os~fakcT? zhnoVazV7JD4&+pGiE`5;F&9^pqqvjJwkZACEJr`!vWZC2Kho|395}E7u%Nd(tjM!2b zD8)eVYXkRR8pV-ftI99BSz88%O>TJzxuFkwP%q~tKKMbs8gXH4OcszXv~Ur}H7T3y zy}!D7ny!5O@aob3|3&MWP?wj}u7N|98cFL%Jai4sAghr)HR2}lul=DN_Hp*PPuw@O zKOXpWig23vF)QSSlXbo93?FsYO}3M2MOhopt$yl^%`ir6sRxoCKqR|ko1*#Yjx#TK zPD#X-q)nN#)6v|C#lqCoqIO=OPxHaYXKtSt@p;zI#d}S3#(Hp#WC&>jYyB!_V={)Y zRcHCKF&RS!U)UIx*cc%#V=e!DHb%%a0Uu9CRN3zbYgf8W+4QQRHEPG7rMU?)uTkow zpV>Vt@^yyQM|gKjQf)c9Qf0~V+}9^u6sPseC^F$`oB(P_9V~w z3%bF=#K=#DiD!)r%cE`IeogXJ`Lpu(k=?f;X~+VsRr2jBHYOuT3eozrosG#DvU!1p zzlDv-1foX6jgyVZ3{n!Qi5lB3J{rrP%^MWJKT(@|a ztzE9X#w^+yn_-OD(i=D#fQeU5M>jZ}iHJS@Mc38R_jc-;w;Z03v;rw(SS*&p%Nxc$ z9`N!;Q$HG3-Y_n>2`g{3l+Q1Zy2sfTnBC6(>C^37!Z#JO?+V1Aq?DoE{{8nCR^HIN z{pY>7iz{I|7IYUH~$gsUzC&*%2@k*fz0~|$EVNDKOC4h**^Pm zxidDy7_p@(a3TQ{e4Sf3XXbvAipr?}Bp%)WGA-($I<-3GGS4RASlv1Gm%)+U3;p;5 ze=7#hXF7SraOY<}l;lLSf=8QCoeG`uLDd98E_m#=%D!T`xKA)?;cqr&_r%$0XLWuO zOitR2bIZR!Z`xqMBO~Cm!quYjq_xEhp?%KS3}eKW@W3evOz68izLb)mutU&$_QlE_ z-mjlOUCipqz{JJ`ohv}T7e`@=w9s8g1LZY)pR{*hUzW4>G}rwTGk*-ObfC>#2AeBT z6NX;TrUhT+J808^Z0b9XgIXD3&yFwu+_l|tLGC5-ON7$_^HNUUTt*(x%pbcva>N+K-k*s+t`>aAZj$lQ`ifPuZzW%T+NTO z6HM!LFz`R|Dqwi09BuXs(8Cp}zJUd~<~h|-koq~;^iD!|-{&gvc>b`1{PoT@STki6D)<=yZ#COKQyI%6}85nCDqCmJyE(75dI)tWD9yEi`Faet3!Tg$8m zbDdaBEDeliH>o8&nOFSs5BJ|yu{@d5Yusg)K^nu5UEjnk-PGp%fV6b8YMK036VIFa zeI8%$ew3WCtUOT*rT4AP#RXfs`E3Y}>J41)`{c4U^A~+e+hX}=Mrecajm*N|dV8@a zB5kf1Snpe#L)>uxtm#2b2PS2zseYMecQfbGo=JAj*bHODmfXPU2TbgXKfJBGRA*7* zgXBM}-cM!N6Eypo6N{;Vh2>4ov)!+`4DYyT=*d`yWV6|wV3-6+M35d8t`Qt<9#dG4 z3UvhMpr2}s9}9d`oZqw9*(ML3HLkPD)rorbh|{9!#RdXM1vyq$hg(6NWRLUl@T zN%f1)eR@;p;YdR~3y{*#^=nr@3J7md$nBWyc6URw#eJbq70%cUW5kx)z{v+paJ%+T zy0YfV##fa~`|8&8C;w=k!wWhE&B8F5y<)<_8#|R!+m|^rS*O!mOeH5`!?het1~vk z7_p@#aN+W{wmhPfhhb;M#foqzet zEBi(`_;4CS$RMz`!0dyeDxK%d{hdA?|K_*DJ^8>&ql+l_UW}F-3=CQ%AHk_Du+?v+ zOVcrP*>ghuY|}2hs$J|B@NWT*R3QLA|5uyukZr@%Z7y>Z&R6WZ5OB+mUUXa-YOT>i^#YKn~?Uo(SO?HWN!1WxS(Y)mGQv0L?`lWa_8 zkmif#$15BM8QV=AY@*cor}~sVI=gvWS+U5#l@!`S8=-fh4Ed5mp;Np2;k_5uDuqg!x*up9&mC1 z6VJGvL|2`ZJh&)TTYhVEn5O)KSDTzzEX<6}oo?xtZh3HHvp3@g(XHqF<>zSgStF0z z;X0f~TjVHwF%9y4*2Eo7Gpne3+tlWs_h;mKTGqJy+WjE$#5RA%~W8K-}|{m=Q|PT9@kmQE}dh9*W6+Y}oQNfk<( z&OhR6^eXRb*(sHa;6@8{^`5r49(?tlR^aCSnvMUSNk8a~Z{m^u{o3K%(hc(+hGq)U z7WaUz-qXn62R$G{Yv5AIUY};)B|nbG^syYWI@@&S#A6NvR;21lTf7{53Q>FH_KM-9 zsP2Z><{ufQT05pQekpgxW*8&3v;N`~`E9 zHAC_P9Gk40o}RQnR(F{F)cyp3`?Nzq65qTapB) zF);CLPHyeiD}g&y>Sm=M$lA|2^IqXLCl)h9OQT7}a&wPwy}9jH>Hay#1Z&^1u+88C zx1XUavb1Hd!&hW6X%xa&WNGC@Uy!f)r=BU(yVBSAqKR$NqQCqv*Px`9LEfyp+D$7Z>hLHOrpGv2mjK5u9X5!?ngj~)jq+w4v z&6aTq%l`}MEXfS_=TZz_SYp5OhBG$97_p@>aH0Vd7q!&F)<(_S>&>IjdwJ8@6AL?) z9y+lYnVMSaxfm;)ToRbD_Q1y$Wg`XIr03buFnxlOXpjb zY*JX-wKRA5q#r#sCPXJ|jUfA`xS&BO`FX-Elv|1EN- zO8Vcd7s>Yi&R(e>B&AkeC=vKu_;_8ZGd9B*v86U}@&OYOQyO+mNN1|8!Q(EUtN4%H?;eW;b%0pzkQ3 zwn{T}L`O6JBXsPSlFe`fH9Md!u+>wXrBRMAM(n1uqg?re&Cj+hIe~mQh&EE1P}v8c z9gzN~^hU*Q{Y0JD&L`Kezb5&?`ZiNSqBAzb7_p@uaB=_>GmJi*-4S9ND=w2adFg`Y z`4v&OmO8PRn;07jzrVI(+S<9>8Ld@>`6sS1=-Pi{Iay)EBj?H zTt_Z7)E>ZV9+VXFMc$BieynQe)a%tksVq^iC)Nt7J7Y795nEaUCk`+n_+Qy=bIZnw z6HIMmS%QSsw|nH}fzEq1Gwai1*)n6&!C6PG5{A6b<- zk?B)!PM&u$Wg>E_(D;TuRa|tdXDtk~e4~=h_(A62f7|D}E1o-JGmH^i`T;o{f;2WJIlTH6$347$6?*^`A%phyQ zHIeQ=*49F~|M>9rZHxOn);v0O^}-_U-JX|o5?+RlrWR0uBT|dD7UuoO1XGL1)MH$i zCx2Ys*2#D2icP7HgTWHyOD?pv;rAbFqm&_D1{YFJeDzz^EOJv@Xilo|ul%H~&e#lN z#Fnl=4u{~`V)Y6)LN{NwU(sGAes4i%_tOavomfl^OilEx@;7kao4?iX_;baH_Y0Rq zRGvu#EzDzt79l!+VRtSuSRY_xGKTbqRHFRYm`ovakesU$*_g~Bb5d$&+1QvYAhXw+ zA^pC4PA7*PsntEuqqO>qV^L+j_SXd{>4^@bF50@V`;UjwsLKQ^o!ZCiSLn8SqzGs_ z-~27HZ{dC9(g%Bb(k<}{Vqz9JdeZNUstIpG>Dy5Emu9`r*bHODmhvEJ2}BmUF4d8~ z`A}0>ghls|&}>Q9FY%?*Du!I$1tT;d|(l~F(AqRceHX+po_Zy1q=1jcytY(Ao>sY1r>e6vYWegGbx@j9C${5xE!SFIhEBI=IbL16>^@u;USYb(BW&&CM)_HVWQmN!k;7scq4r>2WF(#qE&O!9ewYw2e2yddOX` zp<4$uzc50#4rpFq0xehQ(f=W5y;VQ!^1+y} zTe#{P)vJQYbTh~lsRs6o^ zK>TX{o0A#3);bruN3V67e#RM_VT{;P4=6Q2 zaMYis-A4r`RD7LcQT481Uy@sNrjrwkiG{JzwdHp?Os;#Faqg=Z2)Xpe*wXJr7`W7c z9$%+1e+~TjI&Jf_vnx7fm>(`OE1F|i^us*y_x%mhD5t@U)*ggb&uN=KhaF#+r4QZl zsx7cJNM_^i_C|3}j$*H${);4+{C~ci8Al4S5QC4anSR+MrenW6?@+Bnu;)F?e3hpw zC2Mq@u^GmQEiFM(2Z+4!*Gq)&nUsnwd+&)?4SZ|6`6-_00d3CTc6Jx3Y7tGd9B*v86pwT7uyHf95@C%iU}1UAOH@s5 zva%4T*`v5xl$0|-v(7YZ!PrETICn@^3+9qi>U^!V_Q>XrkJ>qfat%ARmaaoiIW~*n zV|7SnkyXY$J->U`?nz8rA@Q=>wyY?AamPA2XKaQsVoPI?R0AU0?aaMOrv)uIJUiZV zd9zQtmoYzReYc5;8E3AX;@!`#jV9?T3r*Ed>^dHMNFTXv!*D7Te)AH)@eFv|M%%7B z->akh@P$S{O{l&fc_coqFrq8eRjo3dV)1p)Z}W8ODe$U4haG1S?q7?k?dH zP`SgoHT_}Ljvd#+-lRA&8(W%(-|PInxu3^2{q+%!nUk&`pT#<1DLAoUSIN4vJNn_=^^##Nu!WwxEUB$szhAmf5!!3y9V?pV@I# z|H$I4vp4Tj%({Y{SRDRhPb?=JOP|Px{u1S@QvR1{CO7G@xZg5oY=$vnOIDDC0wSHc zuD-E!sdwGZx`p3n$6>4TtRFVust2|T6Y0vo<5KWdn5b9&wbwl2 z!&$m)LwFIt*qieLD__{J4%wF9zhK%|XKaQsVoOJ$bOFH;iwdrvoV-CKzF^}g-<-tP zugtlXz-Ks{eYu*NI=8n@H{+AIgpF{o%E~n#6d~Ot$hpm`Zv)ww%pn8$+Ad$DFUqJd zsh{B!w|-txvbHDB?kFDAb-E)Wg=o9-Nk9Tt{oM!X4cMAoi(%7<#tti>aZZ$&$Y--KNTWuM^1K=OW2;qiB6p{0>NM zgMS)P+gC%oJLIk ztZBgY?Y8K$@6SE>1C9rKFFl0Pkaf?-R@=DRvSoeY^#4c}EpZsseAOIiwUE_23a z7$dfH1#ujRTs<>s+Mc|)j;TD}Z+RE|dsFp3Q^bkI*v!bRv?$_tLq|qs%IED$vt~?? z*7!cL37lG>6GAu}vYsvnEnDResrP7Z=CC*+ba2iGxwuQkD7DX^?DlAT#=#o0^k|!q zlUfdS_FC<6&cECwar4w({qqmkNT04ou6;abVoxp4E7bmMGoLCY`J=!ysoLy!Zzt~& zXKaQsVoO(`bOOOLMk#uo9`@4{jxp)gG^L3A+SEH0+%|zOsU_xw4#CM%|6?@rLniH1 zO}nCe-Lm}P3-=cr7NMk%;aB%~7s0y4@YV?p>Yj}rAq)b#_r6+4@AXcOl{0p&F?vfl zeR%Jzsyo@GRaUk6PtBF}f-VLJg7>TzcgAKIBes+TNgE(CCobo#TgVObce}dk6vXC9 z8Q#pk8-dmGmAhAHy36eA<+$HwqrZf9(UF=9(spmYMkUfUx=dZK=q zG`(18+_`0z?9E-p4Nfd(=0=8It1diObQhg`s#vVH_2_J~%%6Ad!3(gVcVub%gEmS- z7O2R6pUB2!0%_x_J?CI!GKFlQW=KzkAMdTHD>`+b?qkmUBuRG5+O0+GY|fi@#~c}s zsYu)Z7W6n(I;En&yLNt0J>Bov`{m(5%ZD||AC_-HK9UzlDhkl`dh1cszT?XQ7l)F7 znyN$FZiuaAb;f2GBewJgNkJe|YsbASMSSe$Od9v6UCuc#DAIPN8dN7iZ$}Y3vyF|( z9J2HY&z-_OVtFTZm+y07wKBc#vQkC(K=Z>a>L(BFAU2FUg|(?N#!qY^L-*wI(1@ex z^rWQJ_BG8RlC#DCZ;Y>tCtM{3`B(~Y+fo z<+4aJzt?*q?u^YaMra=!ec8)VP!x*upDv-k=ct3B$#-ya;{)B={@O+Q+IpV}@VrqF` zB(rJSj*UzzqQ`rag}m>F+Xx;3)mco2khY8F32`{;q;jF9GycEmz9CJRVi zrXXjkx$SyTY}C~&``FG#3wcCLn0xmNj8fe-b5bCW#6g=AIjxjUiOc1W9b3sT<_XTcmHI| z?X-${b2Vh-l^@zsH=#qhq~8>Pqx{en-um!UX4MLb_N;jMz}T$Ef3BUxkq)9c;N?do zLt;d!$+o_#EV-1u`|f_}SR!uikl>8XFh*=C29yFI_;cnK!K1IIu2$8P+Ig?wd;6~< z_7>2*p}|6quWa)d9WTmxT$CXGFZB|qH^)8X6BjgRD6laZK?(}(n1^gkCXlj(VR?S7X}JwN|hsVUQSUBEIA za9hU+ve`&Gv6qd>2r@6pIGvx3$rw^@Nu=*)W3q&lTN>IuQxspkICuZRnRySrQu=O( z3#{orzHmq7!j;n!oUs|kh%JeMk_-fgyqf*;!Y20o#i0>7B4?O) zcwMw9aAGkuFf>`zs+0U<&j0d;h>*1mjHYvPH=kYuZUz}bmT&UE_F`i)hg476$;Wsu z{<~FOFPwEGGR@gVAlEbWea$N3Q;2r*0~Uybv>5)un!}H#K%2vw&W`L**~EpgA)J=& zoDebm+oiG1Q4XmTqBvpi?S1byX?ILmrkKoSFKU>Sj51D~!jCgFMIxq zja4<8+*kfw`{azxFh*=?2@K|z)B{&Kp6J`LwJ*DCG);g46>0lx>I>56tuQ5O`0TF$szEIqwxO|8(O9Th(;Y@V7J?Ese= z#*oyao&JZ7$rMt8NVDkP>`r~N*kElyfYEh^B<&5$ZoWE>TCWf}7m4UZYiEc-OO1i= zL=Rwtg#Eh7jZTl#|Ao&M23qac&Pk9^6~?=MNM<7 zCkg!6n^ltnZjnG&*lB0Uu`xp0x9TO|;VbO41VY#tA%lDZKW6EQJ#n(t;^2`>buE6a z|3C6Yy53~ul7)5yyaV4E($2DguCUXley2M{eDRJM^S%YAud>$va;o0(|d80Jak>Fw*8Zns}&XIy-?z}R;!lWFh~l(_(;N+@RqQc`i+`!HuF z@BiSvAH_cRHr$MTZ4&9@jLk4cY>5hzOhDxQ*#e2D51dc?a7SfH*sO(O4%24ELXrxk zm{7f$2%ihk_|goY3t*jvmf139hW z-}5>`8nHw+ShVvRp>qN1UEkQ4G%i0~YWh#@{UpXM%gy*zSTye-7b|&J;0+d(v~sIX zK{2vkWb2wA$JyuE%NBi_G&k89n_-ODQWYqbK(H0tpScS!WV`P2+o${cK%UVNo+}fb zSPU)AjZE#c%vC%s zl-9vs=&{WB&l96*g;b!RGe7Cj((YY$E0+A3x;d1adk4yf0Hl;t$cI$Qc<=O`e$!}P z)6I}?vtz|m`c6Fyf8mVHFh*=?43cUgs4VCR4}&iY5#H7m?IjjRT*I3vc=Cbe3CoxNNRYJaRf9eS~c|H)yqsoG&dOaGq=OfF>$jND*zBUOKP%rw`Pw<4G0C_#|YL9rN%3`@Cc<<~nc z&+Tq+`uBHDWBhs{XKaQsVoNa)CxOW9dEb2ZRqS4=7Jp^o8yh9#7g4JFAhivotxDRd zl$z%beir?E)K8%4ZRniz2lt8(OSpgXM7iT?h}ShG@1bL{T8L9AN#8<5PF>S&@ZO)7 zRl8zS+ytjalWrSp|2@c8bZVD6!0Q^6l=33V@nMnoqU6?7AJ4x|5^i4D(Y?bNn_-OD z(iA9-K=5==|H>_^ji;4P?~`cWU7ElCTW}2c6gdk>7g(-4Q?Q%&<)*SR_P5t<^eDaj~1sY$MJiWv}zyAA1S>3ELgg7+Ce{SDm9J#3NF%CM1CscL6-#%35Jwp0a5 zB@p~`)1#Z5>4(~vY+_H1)}HsHuj%VI$iOP3MnPVbtr9a2c~N$E(8K;eeX6Ndr?`wB zFX(w8WPbG0kV+HPj?mU7wnf=U!)EkO6V>;ZPx0IOV3Ti{&Y8^;XD0O;?206uCaP=h zyM9=FO13>VbSihur*(-BCv~UuIAb%65nJkkqz4eW;>7u=uDtJNsUP>syVgIy7{ELC zwG)elsig%o>-|ejE>E|uc(?V6;+q{7GF65PJsH^8V5e+o1ZS}^K`;E(t__8svLS65 z0zYL#sdqCQ6ZDh~;h&4(7yhao&PrP3wZ$gaRCI>L(jG_igj1fEKHfl1QHUBzyEY$s z%7#|QUS^P^85p#z=Rl`#G`}fAr*G6f55opxlW#(&Z#1vALZ@%kYj?n=Z%AHUK;Qlg zg*6h7S#zM~-R_-}<+h5)NrY%_I_QRS+7nWZRC^9yBURVTe_HfrrNSM9hYoXZw)L0h z7~QYf?2OGYMr>&h5-lJyqU7A+?*7b8$GzSgeCgk(wfk#86X=F31IttUt|qxnPs&uB zoV8%tS9$ZE=f~WTm$49Y!OgTP@yp+bH$!X9r4FI zlT6VNOZ`FUG8Qc?H(XI^o^arry^nvo?3wra*mcfx7m6>pdv9ObvCtK{=xQ*BH+xYM zTFQa7|X>K1Nz}Lm1x~&rBgy z_-Ho?j21rYVTUT?SVG6g71t2a+B@WL${m+5G?0?rfGa{iQfdcUS4(+zKZaV?zUT z(M9w5&0ODDMVzb=`}e!j%!Iio3N-8n-8Z7yp9J4GqExwxjmZ*{a1?I7W@EC1Odo2u zsQjL&ck0Pjr_GGh4eDxsZ~uJVJL3=a6OML^-AJpoj5FCew2KSTS9Q2fpZPqHIjK?+Q!^h*a+hS#E@5m>W z>`j)KRsC4%mc>1ulvEGo6hgyMmLXW(Xt$L^$K$YVoktnb|CN^IX|%ZbW9)^TYi?fJ zhKpQ1O_5Vb+cJ1{gOWnF{Bx9TI}m8O`CxjN;B~o>(`p?K&e#lN#FmyIsRKk_ni!X@ zF}G#MMd|h54HIfsEDh8;=EP!VYGG652q|=a+1ybK2FL-0Lo5$#>wdI5Zhvnj6 zJ+16Zj~=?0aY~`21N;ryu8YugK*oZ%;a#$59`drD`I&Rml8?O4t$QTm@)%Z6M@|Rb z4A@GRjvq!3*2F5vFqv@wNNe1>U2ymHs-H^E*bHODmSP}j07MoTKg`c;e|g(9gf$?% zLQ*-aHslXD9Y9Y!RWe-5#$*Xu@TQtm94;if?DMWk30tGwZGN9NO>VeWe|j_>fC3WR zA~$R`jCRjW=!_3a4HLH0tFyDk;GD*Ji`HY38pEIH_eCer53VI?t zum2a5ifUw7dm+IYn_-ODQVhu95WFulw7~Vn&G?+?W7@BZX6tz$<*IRFF*GzWol|m9 zbbiR^^SkfY>z>p&tu}qu=JlW&2DW#Vv^yTO`yRs2U)K!jfBc56e!9Z5)>}q7rxc8u z{%#PzdO5|PRi1SXh2W$Nj@8$aKLHi!vhvm^8^0OvQwkSKkj&OSF zk5IBQn&!4KF3Kd5MK zsAw{6ojKhQT&_Up9J#ulvN4%J$`~T&9643%L|Tn2<5wyNUU(||a-QiSYo}qER;G5+ zch2#j(~)DGrp=Pi7U?_J3Qi9n|0D)P~wQ?VB)#{Y`v9czg0; zXKaQsVoOz^R06?XOCH}^o{_fC!`Es4oN4tY+%j`w!Q}_^SUFV>OZfT7s;GBAOgCFm zeCGGGi90h`g!6aR=^X5?TQ>yK#PqGu6>bFDC5ZBa-f1E+B0!);In^g zttEzXwLJDTG5y2xfHl9K>3m%8CSEY1)8?~6g5WU@XKaQsVoN=c^Z+75-W+f-36VBV zOAP#|a^Hz}3%B?>aDNB3!VPIeO(1Eu1oC%0f44>?!Lr!hTTXNW2TD2^?e{Wh z!`Cfo&pe4SqK2ct03^zcc-V<+aLS->GV< zC$r0*PiA=-u`u|SmoqlQ7_p@oPzr!x?+j0&)hwlV6gFI0m3;c@X8o;^fyn7VbD=zZ zWL5Hxnruc=V6=Q@{(mDG!7Ii0tJwwp4Uy9Uwi#p6CvAqy*t_=Zi_mnSMQGB-``o;Q z%?B3+9OBiEFImwtcZ3+mm%RvLhBQiiQGAbtGwDC3=;>%T$* zzRDgkjN7(U+;so4GURlFw4Q11OO-z)ZhzzXZMNzSas-D z?cMWV$~^vFp9nho*wRu*U`PMoSdOFymG=iU4qP`{U6=6^+(L!+e394AYA+CkpJSk@ z9}PRlfN{Z1SkG7U+`;*t=3bvQ!kANMs+Y~HeF+KJWwzbAN`x^flX z_F3hO%`ir6sST2TKxE3Kz2eX3O22;>weSNVAd_WR?G(1PDYS*_{gX7XfFyavDAH8b;sWO))mv9=JYqOPGU+4R5*rQ${?kXMf2db(>x2Evq>sTeV82f z*n9}c=X|Ux^~}b^8Jl5@*wPXxZ9s6UMO-M`j3@pDFPEwc?fx6E=1E4P6N|BtnPI@j zW%Jb1zG?^AE|^io_^O*@K92&Vl!0s==+9vdTc zGl$yN2Q#^SU+h!p*zv~ce@6E4XEN`!LXnFZ?IjaoTL&*pgjQ8r@GIc82m2Jyz!ftl zRYo6oEa6<2Sr(9WV#mB!!JfA?kQ338$M9kXB@wyA-QC)@YCiY9O@B3C9l9iO`_3+N zXKaQsVoPq21Oy__#@uxN>9w%6Wwx-*ujtKt8y+3~?8IVeVQD7%*7)9^W!Z6?i`!I6 zmh!yZ^*#0-BoRRdP>2|$)n2v-R#nMfTVl6N>!3BaO`NvsqwB6;Yq;<6^0XkQp&{Pf zS#}LtRcX_^+x%xqbmozjOrKU{oSuI@ba8w`N#7U3X=u6nANEf1No!9Zwzms^wU(u_ zcDc*qE@y0pF=9(?pwt7wellH*6LxS{_yl^MkYS46V93k61G$-uYe6pO=2&7D-r|1%e9hBc-*tr-7;>r0+*^YHp3XPr7%dE0g+vAw#nH!QjdZpc8d;Z>jc0DcWG%OnfGSBJEZZSpYr-Rk$AsH>dms~W~ zV7|g(#M67MSWx!5fipJ47_p@oPzr$He3Qiw9#BIpBa+s%{nbScH_)+f1_rZP zUL_r#b9|>m-Hqox^0V?78ER3soNBLifDgn7B<*-PgYlWxjj+q>#U?7e%Sd0Jaw)wR zIfab2QW%g2!*oPHW+cT86M@9n;eoI=)i!dodw zCB^FWt!r*w*M7P4-Vc#T#w@KB?*kMR);eP|j1gN}f}{=*X=KlSZ;@U09!5tiPLqr^ z>D33npF(bnkk)Nh+~fXr^Mo@yNXRf zQX=LY&iL<^A$WI><$Q+oOvlXD#IHt9DeE_5Pbs#nU3UZpf5h$9{6G8AM9r6v{r4|$ z#%35JwloDwBM`imJ6>2`B|y=z(Pu_-?!1ayyJtUhVlg*2GM}71BgLg%FhDjes($wW zila*c{vAU}LmPYGM@SMLdQsfteogNz-}Yw{<8wkT=ue7ZdEq*v3U#B<&`v`emkm@J zVq@Pht$CYHO~keL%}<0I4A=uJIg!)Q#_!nEP$c822P}0pK5I4C1@Oc!oA)|6X_7NG z!x*upHc0vbldjHc%{(u1nEF&@FN<)y2vnMQKvD{%`z)aw2Jb#={s7fLkbxI5j(za% zvqs%rSoc}()yebA-Ok#)vI_fukNwcpl+@ z<;QsSwylhPipZie)_G<1aiCNKn^z*W!z`HFkGzA`s9}cXU#+r7=@DxU-IQ;(hD@Ka z4<+5ePvFtsVK~}hCVoD0_E~w2G_@;TFLVz4bCjFYQ~m$gb{y$u#{_tXd0T{CMjgY1 z9zJXKBYPJv2-yB>n~S-WGd9B*v86C@k^vLHBza3;JzKz`ou}aTI_SE~d=K*}pmald zX(PNv_giT?$AdK|jNeQMiII34YjNwn(`uAdLytOYS0-$=?eHmW{4)~`9>qsXvFLt$ zvTMhmxD)$qWC*94UB@OzN>8qgz8x|Di{OXE{QaE8d$uP!V>65qTlxYg7%;(nR>Q~t z%6SW^3zoN6pE`QG_RnPo@Jc7>m3ItU&TLF(kfDAx>D}JPp3zg!(^%K2L4$+r8f$D4&;IVd>J!I38R z+=7=RyNzlgb$NJ4$lWU%wGF@G=)t>K-Gd9B*v85hxasU%A|Ibvr^SJSp@AjE> zl_~QXq_hv(JF!?87#V)q7xz=#$@P>s>&^O*U+3(OOn=V_PAynAFKh4HjJ$cdwDy&8 zgUzdppBAs+3Mol!TqAqi9Hj)omRk0mh3*F<_T&WGt%Dh~sb%-pg<3s3E^TjnrfXHI zYh&ML`Pu+SYT1vt|6|v&-9{xLO){PDxNh&Piaoc7H_hDpi8D6C7_p@*a6$nSlFda^ z&zCK3IxMwsDt~X}w*JOWdr-XtYpfd!o#g}$-PI=bMT)eINp zb2X@RJq*j+iOAQ(2)G%m#jm(i{hWU)-ZXx&>Qc1$4IIhoa6eLVx-j!i>V}^8B4RgrpT(svIR5^-+goRB zhB0DGc;J)-CO%v{=G>wBdGn#z|10}$`e>%t*oA;jN?R zBXt~Iiap;@r=@t!kBw3c*jWxnmO@^fKz8%G%=-9VPW;JW4RcpLI9cO1Tt zr*aAB&Aua0cXDDgcjmbq1(e;b+QjycjxT_o3q{6xro*v+w9aYs;V1mFB_cj`3KqWG zy!+6%T}^}&&hckc&hpRV*5;Sf{;tuPUi{-@l=XBcXKaQsVoPG+Gy^6cnaMjRywgp( z{P?oRzPCnq4Y$OqBiB+?I{gW9j}T;}SnWi{WO0op_xKpDKV8~e_gO@{@NKv%$|f`# z&Q+e=53QwWc>2@8%^uucKGQGt>y-O{Y1W%mw*5{Y6;E{ajj}L=!B%CvO@Cxks zGxdn>^EWNFWpW!_U2|<|!znvoo>*sWhB0DGV&F6bCX$_2@82upx@ATEq})@p7F{V< z_`VK2?F8MusP$wHeD|ViPBHw%RIMg|HrQqJTAx8X=%J@{T-Tr6DamZ)@sQbIO|A7` zse95o@^`vX(hBXSDCt_rXrFV3?OwEr76XSSgSKPc+93Em1-oMa_45&;vsI^k;mEkqJ z#m?9aW5kxKAWjF7PhQGYFFN2?tH9D(<~sYJme}PL6TwTTpliT2x4eYk%*w#<=@`S_ z-><|@e`6Erk*g{@^fhia)3lM74zw>6Q#&2xl}10}FnxOSc=I&2_kQ_i`@cJ*%s*aO zggqVXcetwj>D`J=^DJF$V{w==53|UnrNt;a8IjV*r9(({N`#okCZ`D( zH!i8_ue^HH`JHG*mVz@j!x*upBuLr-kp`j(uOEq6W<;kvu@EkPpIRdOaW?4mI8y_` z3rezTuUU_Z)X%zWx0C6N?CA-T$R!BME|M#=KR7>-OMUBn`jO@Rz6(;0bql0soF9QH z&blr|u^MMUcTX<@tOU(>Ho=u@f4O?h4N%!$R++}yap z(d~;{hzt8<-YqLLa;Gx?x-KpRE?c0N!!yU@Gkz^7vX&V{Krue4v|d|?Q7Se-DWLfZ^Il!O%NJXJ&py>{U)CAO*E{LbzL!& zF*Dz^9A(w+by;}TgOYHVm#^>px90hQ)6JI;`n~T@Xz|z(>5R=VMr=t8l4wBWl?UJB zSo5X#I(A*1{raMe)6Cx@r;)qOTFkQWyT7%r>%;H+@3?JN;ozXaXhw*Qw(1`)^bK+jjvy3-?ws9@WnS(SOg}Lz!+HKYzj-xPQ z?|7>K6u`dz;Ilc;AXMGWmm=CGxS+pe(le1`fusS^GjOu3%F_wQ<)Fh@dmxs}U5_Wy*_#O;Q4 z%Pewto=dsVu-?wq?pjjly6z1k&e#lN#Fly>=>bF@TK(c=Z*E7tP8#3tvLm(xjoxYy;BhAvCG^xwT@4h5t(OO%(* zCb3x}v~8kuTK~=Fs_EOe`8vc-&r8hnqEm8u*o)aLA-xJBy||%Ia#|oTW0hd}-LDe- zveOy9?e~yZ)J8e_6nnGe5p!?Gx+3e-?J_4C8R{K&2J5;O?w{n0%`ir62@jNzAo#5E z_543sr>^8L*HsmM+%b9A&#hOTSj;U<&A&~|_1J&>zLwPrx7mW_p`MqlkIn=S*BU|! z8STe+;FqqdJ3NG6x~l#aap@|<`D5@)SC!^3+Rm5W5jlVPv5An zU>}B|PAB{EH|V9S+5%g*1aZy$F`2n$^X)zI_t{g_jk%OjRxTi=q9>m4PWB^ad$Ex7 zA79V=Z^xS4@#$<6=b6|*FK29qF=9(^kQ4+W-_H1&?s96IGt;qWcl3(|eSamNTI0lG zW@&0}GiyWn*~r9ytB)@C7r7I}mJ|Q?CU_Xe5Hg6b^6@4clR0G8Q2UwEvZDWP;dVad z&zQgW&R#tG#Ir5I^2C=j+RtpDM{R49J_$X%%Nc=rYqQ>+{^{k(Uim`u=+%iYp1;h( zQEefmkZ0M#)1tQUJqyzOd!N@(N3v$8Olw1iGd9B*v85$Y+JNBt0NJ^6P`Bdmi_;+wR%PTb5#NiFmp)_oBN?HFmse}wLs)_Uy)J?K=M zcEh^VFHfHT+S)IM zzS7lVk4DIsBO7X+u^GmQEnPuU3WzN7<}6`+x+XBV_EMFq#q#-KzWU})EGCv_#uBHC zH*pnCvvKh_{~@M(->RaS%U^@b6X=oc+OLY>N49I5pJfsI*wIFF$;} zbEEHQ3IPQ%(Zjm0dSFMkBiA_j2eiLBX(Vji z4sB7U=k};SKlU_M3C9NA)NJx>OZ&X>0-X}tn{}`Ta)>=_cgavJim)d%|Med?%#ii} zeo#B?BD45QUJ0AiyKp45w<<^p?UQ2Y$9nNK7fhyAi==dT@vO2v{>~YjVT{<4BqWi6 z$oI{P?>1N*VB43jw|l=uqDWoA#W*JxV+#X|!)u-hbYER%uEb>8c8cq0qyEpz7vQ4E z5ZWVu_m_>y0@Ae6dTr3Z{f1RXZ<*H;W_i{4=qGZlyc21$3LIPGm&g>N{a$=P?*6ebT88x zn_-OD(h?|bKrpvSY~9{1HLglAeb0_0yl_0(+n?aXVq#!o?i}JZRn*SUzwGkz2Om?v zUOC+0+m76YQoWf7??P#OX@+;9SZ5)+P}(2m;aw;$r;M+;xn}QXs-JT?$G3B{L9E&- z)&P_{f{9&LH#*(Kz@Yun6554Q@A{Uw_65qTY7_}AQ1UOh@tnE$NEp!oN8CIIRqs4 zb2>bCVlgu^F;}yf_`BJIYuD*5yUdrczdO9vfC17#HiIq;|D4LkWDad0Yn^9fGKX}n zwB5x{OnqAa(ezj1sd=jX4{ru9ef`%r5~Wreot$LQ{#*|m1zd~wz!>Dz@?~DZ3#Til zTc>G7@|HVo=Zmzx)_|N^KJUVwS~3)Ob|mgFcyPG8K_KvO=A{b0ThE-a8ODe$U4haG z1gEgOTm5)Y`|XkFBn5$sM{c(#e826)Vq$Dzp~rqF>1*9Q@wNK;pWIHY{q#;hfE&5_ zgS^^T`|D)*w57JlQF!x*h`V0VR{P%iUHem7?S)T4w)~0t|1H)v&SFcaQ$qW?7TWxw z$7)~v3-Jidf|HZbHoUjL@ab;lNlES-ou{l`aozKAh(%6l-;}W@v{#dUe*BlZXT>YV z5V6cuE|GUYco6O32{=&R< zIm(4@s(}?Y1%%VY5A*GQbs8ak-}CHuv>mUp+xy$S>$niMV!gG~F;TXg=Bs?XzqBxd?6IXl!=rdK22UN2Er+a}wX@v(q1a>z2N=#gBoR z1A4rIHukdQSN_)L0RkUoOX_#}adP(F(T!EXPnqMCsGh4QP8d>GmI-3?LUdq8!dmuoS!;3rEAeH-&Oa|$o)Ah zjGQR`v|y`Xe&v6-yoyDuT!dRcnknPGu8-}qz(hM|Y=$vnOFp3F0Ku=`n|+ktJnz8l z>B1}w>mx6nSjBo0(no?EMn%k7&dMbct9yHaqma+>}JBBxeYH!^xBYC58;^t4q znJ7u+Uo7-6DlNQcIg`;v8s14II%w@H&M3{UC1*A@smQ(kcquzT5;>{-TaP`d*zmgS zs4=VU&pKUtDez;@0gaN4YR=dUW5kxIAjt$o?iSp|t`zUxrnvj}7cP@$i=W#?D>$)O zTACQm+s0-zXVa8@BJ^u6lXSM$%N~k;CtXH@F_<3{N+Ukf_eUtNd79yn~ z9fr@?)6kvWcR1(hyi1s0`*NYG_WXi(Kj(%xV>65qTWSNP9ths_p7-z-whoo+ht-SC z%t~YracLKVs~U4iXPU8I$4kKDwt!Xn=D!z;f7knkO)av0u8$J;h<59UXn*K1ouSUs z8Kx=0FCWyb*_C_e^n1I!-j6H%r(Gi$_c~1P4bHPM33cvxwqfCtxPPk8m)l!^o#u?q zFh*>t1QPEcvbK9KTaeVL>(#a03GX-UItw#*L{_w3w8iIjrOvaD~3!}v;HYQ8R6o3xfokIOaFCO2Pp!Zg1U+oQ; zVD-t(?8{&+O?244LAM@h)2tUvwbDd8;)2(y!}&Y={(BISVV=qmRQx3ar z*pV9nR?oM$t~nBtzVH0=#Qa#7IA?5zF=9(&kW>RAvxDmNYU8-HlxOPnatZx-x!%@l zBe*nyu3OODn+0FDz)(^IU$?-X`r(mW*uu~#m8GI{{B0_qZTL9v-g49{Yv|fS)!`I_ zu3OMH-UwT_(DfQN6_mIPmL@#oV5Nz}A?V^=ZMBU;puk{Y(8%8>3}Fpm>*Ch(EOWaP zw{(AAnsKz*w&eDUh_lFp_&S_{u+{}?n&5uWETSPY=_$j%xhI4~92^chS1>wbGmH^i z>VbG0M6$a)ugUQ$%5dShQ-8RxyLV-RekpiL&=}IXV0m^>*mbSf^gl}3Kyo_J;nrdUIfQ{h)7g<7!qQ4y2;J(g*|MDzBBqU{r!tJv z!FrGT%e$T|PZo4e?w--LdFAJAOl`9*lTB8xR{95~ z9SZt!P(ikxUmn;zEj{q;(yaNNBw9{jWOgwn7UJK2|bI zu)Xqdft11G&3mr(#C&zeW*8&3Bne7l5FF$t-PKc5T7G!SmobNnF5L$W(!vJ&LR4WVH)}rdW@Cb$+^jV(4SsU7wjtu= zW*z?7Y)lrA=CD@qRjo^DKU{4Z-(6M~ydS7J>3;M?Q9F94CmsH+cvia%(e!ksdXq+H z=7SBhT@|aZZC-i%T>ZWP9O+3w2;LlKw{7{PwA5@??(6v%FDy3F>DYQ}!Wvs=Y=$vn zOL>sA1R^ExBr;kBeLJ)gUjV+y=IsmnRVu`o|n=LloSQ;bn6JQ4)CD=kZL9u zTsVK)z%}QY$ksDg`A&8QU%7A%`Hoo~q^b}pMG2+!`N^x}PJP6&UG(x6{iCMq_T0Gq{CB+06engQOAF0Bt?f^z=dWhX7n|X6 z>G&e`I*%LR_A_+zo3`wA__4j(4lCiu_Uee(zOhz&-z>RxIe)UPE)fAM5X) zIeJ2f_oQcuTI2g5{+kY7;NG|)WZ{dBSQdP#KVnhBmmhl5avA+}c>y;33*U!?NBAvA50n znjQanNvRK8pwQMO8rOG);7B-Pr{MLLPztZz`i}K?xvt)*t38qNeCe{ESF~O_V>65q zTM`2$83^{Y@ml=QlBHH_WCq#fruKd}`~+}iX+!T5uM!*+3^nAo#UAv~ z=Rf=EPw*j>@&ijNMMvs9^aODFE=?FxtrRt`y+3d*EKAD$7Wn1>BB>DwkS-L$%G)f#L?x|dN=*T>V4%Q6wx?}Dw zpRAJ~y!MrbmB)+S;18BrVR9Kq+{?1T>ketITZi6jKGay&al(~h_U>2Ld4d?+nw_y3 z#)vJIK;j)l+O%${b>cj*OXfRy<;!_d^TACE=s-WNGseVE9f1$@YfW9&(%5EM zw9(1wc>FzwC0izj8LbfG9IWX>NA5m!PbhN48K1!^2ihnl;^1W+h5zOUx1=-2 z`AldoZf|-amo2@t{8}wa!XdI!(NUCyHcE*;c$wrquS2R*$*kekQ<%ZM5cx z>pFd0cc-pNdA=%}@v;+(k%5tg!NulPv+Yw-S!KfYO}?C7`E^aj0dNz<7_#6^!(Wh% z$pXUGN+m6oQN%!nzHlyOvCN#Wv%BNu7#{jF@eOrLhX;9Ig_|m9#8w9 z^q_ho_wIl@&$`Y;pv3)XNx^{aP!}E5G+9U><5(G6Wfu6xHdFOd2FIb!J2w=0tfx%f zK{)PJJO9iPIi1??5M@=uE0`|sQKy<|DdCLGFh*>t1mYwRX)%Aj&ywZuJ?b;}Et&po zcL}?|=Ov(FR|B(7qqczb-s^hH4m|41IJ9G%a*=cZxQc-u2c)B(1V0W)TY(jR91!!> zF8Fak>KoVYo4d37v~a1LSVKhMhQq)5LQg-aLrFQqt~0BnUIRN02!2p94LY-$Km6_| zcwRTSp}*KLYJcDy-8%i%suic!&0|Z7bxO^gysprR#oWNysJ4B>`sV@n>Qjp=6n=e) zzrU&X&x-gYw}EhK(flY8^6c|lUs=OD z?V0NeC+WzP-h3ABjLk4cZ0QP;Qb1((%Uw&_{yvYmkUv+7p_ZlC6m`)Ews1-}zmNBa~TlPP3lv-*Mn_?^JooF8Dz zuvG;ncpm<$yx<#K&6B!^j{HYlvbWT|6hTfzI@(X5%doZap1F)|taU^;RIb^UZ#;Hr zx7T*Jqia(leq_A#7o3kH5$Tx08!DO~lS+5SY=3V3a;b}0eVw09!Z%l=C}(VjF=9(@ zpyUI=PDd;y;y1)~Y@S`%vZXXmcX{33dG(5hUqP<1_aA&2wsyQH8zZE(tG#Rw8zW@QMMsa{>ee6SlgmGtMJOKN+sx$m zyyNYB)Mb}Lx**cg(}XR`dVE0q+zG;INUusp z!?3wAE_g?-n1?t2`<=2Xab|+f*bHODmf9fc2Shrrxa79*cc`&OrPRmShu!yIzh7nU z#A0b|V4S^CesKWn`4!2kBJGuapF+(p@7#=BZ84k*g)h?OH=Y5nwsZ`Fw|B8Mt=m>q zE}wniyx{wGw$pC=QEzx1l#Lu6gIs8}MeMX7V#J%5hThg!&4uJ`KB&e#lN#Fnl==>&ogDHgsw zbNJQ5FIJK_vR^PhFp=?`>BM4aZe(EiAmEVL%+4c+dId5w#Aj9d*X7zGrxqQfMqH^y zCT!{Bxc86r^u+Ay93s1p%#%%=gIqsp56;wLG<&e8mg=XeiI;ABminBYapSyJhN?I8v^^lIqdivHwfr=%K-|xmmeBSJ5S!t`8+p{?g`Jgc! z>}kc6NqbM}`7g6Y&N?mVEDP$M@WddqSHu~cVT{;P6)2TJaMlve_4h;rQVmZwEEn7P zz?b9iV>$4=4|LE)^xE7fEAF0*{jmDw^vOFlwx#=Q5Z&K-XEg3X!H54OT^+OA_y=A7 zb0>f4dTh0@>~f8VO?D!0h4%kQ!sUe7zgCWSXLigno-R>(QmJ)%ch&RL?%dAU3}eKW zNW;LTgK9yw34-hEGZ(dzWd2@Exvw#&ff1ePuj-?7<5ba^;;&pEeci&^jAxw?_I zpC4GQ=XHxgPAWPU*GIcNyH3N7TbX@P1`-oU7yV-2CB*sjwe-oLrE4P`3~g5L*L4V# zx~+gCsaR^lyF6z9e#U#wj7nhDVv}w(Wc+#Ur{3PYH_q4$W5kxIAdUl(@pW$#->t1< zVq;via%<4m{HmNw)16q1Oe~B$z7?_V48GsNcBy~)B}pa=)&rEtfsS@OQ8C>42r5SK8u8MAq>8 z?{v)mb$*}M<-y+kpjZF?Ry+2)tjBl!obQayFh*?24U~K!_|?z$3F+4NOhc_+<5(%KQWwxjRb> zf`y6-x!)>&T7;Zd5VwUOR?T8tk3!$6Lt+Q&5dCASw@a|pO**#jh@&zXw0E;?jBXE* z`6y!=x1LiWO{|-Pa9XjQwO~`)$x8o;?am4k%T5+;P;e9Vv2ey_7$de+1xY6$GBN9D zsO!GSaKZAKGWTyWJrjuCa1}i44_%X>a2~YW5wad1&*sC&R$pFmFG|Zjlr_tDwq8NX zh$?a{Qz4jZlFL1_Y7$dfn1WFkY-0`M4etzHcNvVdxll*=h+;ejO;!5Q7A*1pK zzByI9U@d%eD%zSAYrE^e!@ox9d0S-i|2h>KX}8J+WyC~hFx54VlVRy&@Na8&eCK#V zR+&9TUW0Y=^Q^$ScU5g(IMRpXEqH^)e%BVe(xNNpQjK4n6%t#0^3>)h-5z|-*bHOD zmXaW814M?-U$xP>X;-<^kByAt$4==paXSp{kcdj_BG1IB=P{@qGATz}@!5N!jjM!2bD8)eV zP1EF*%a;tdOcUz;@^Qk2*m@_&L?;$gQv-uczl!ALwbMNqE!SN?7hJBdzG!*^B^wuY zTwfD$ta8+(V|TA{Ju~VkjIOMIHo-@0$(u*W6&MW*C^uH<#zkTm?CT7r0%}HRx#Gn_lv##vsF_PbD6%bDgmn#)vIR zLJ}E>lrY+KVb!hcHr>ZlPl@L&I(uq)bBPm+k(q(z&TGM4f3<&bSnLTnak9GknM@~6%M*~5F=F5F{uJN5=SwIDTz5yg^69>(%)x-^G} zQn949mGxtE`?X*mZs~8ClHwPPAFCP>PAwiQgR@OlR=uD3RpI3}!TF2ky?tmRv(g!x zVT{<)6)2rR@b45?-h9DH@|?>TPF*nf%N7N5lcUtC&SV}1oYv-NDfTyaRF@5n^kkb| zw_GLQGmdoQ)dZ`~M$-)gwjn;0Zj@ASXnloZ^smcD{-w>U$UNltcENVS>Bj5fyHx@Y zlk08YdYzOypdKE!lW~jOMrUk>F=9($kTe4#D>!ztgf0Ir_s+98;8T9hqkre7syVS3 zn;V$>U7R%W<;Kflm0U|>S(0CTU7yWx9o&F6gfxCsHQuo?LT0Tsj!UsInL`R6HJfE@ zjL>F~&#sxLeEM&neK_$B%d45$qAGLVczkmoDd|SX=L*IpYecV;A=LfWkoxK(#cyGK zt8=w}Y*pCnW{Yww!s*6WvhjHSp$lK%$RFapB(tH5kMT=l$`og8hB0DGVW1QP!83o) zo@H{O<&2re-bB4bg){qRzHJ#De;(+mFNoV}5S!+QR9nWIE4RBr zu`X}LAthbYsuyi}6W>PRNG<;E@V1Pvq~f=Z)o*l6)-L%g@#*1#)7;0BUu<*6W*8&3 zbOlK%Aac4(um8~iCSjGEn{&P1f4j`)bk7I02G7#)9oyd&nX-+$Q$Lm+wzrygU!J>; z9l6o06R1G&4q?(S>)RtKv?%D5-RgzL|J-hRw)b@jryoO3Xh_Wi{brp1!$WaGbYOWCjRXLVNSdz_m6`Vs^3!OO_Al}HIKaKr!8*+Cv#tHtN% zMO|55cQ!mU!Is$>n_-ODk|ZdJL2&t+5a+z|jFp!kWtJ|HF>;A~n#v0H81t*iL=Lh$5|Q=+KHkPY_L4#Ay7ZJDS0+87>dGqq=j!tb-JUG1Y% z8UFjc)}bfJg-`Gi_-Y4~G*PfvzjCQ$)YmgUH8TTj820n8`?JCsn_-ODQV%3OfXGGD zx?ZTRRBB1BexP~d`StC)CJ4RAiK!cK_5%UHEq+(+-1SRIY?>hpxuMHrqhca>aPwwO>Js z=DA|Jm-RlroZKrR#nneR4TW(CcS@JUmGpWzXgs>?5=o}lN#IpODDCl)hvO9Q?CQ`ReN;aYv<(l@5{w(rioWN>5#ry=NC z8e;a<>x4gquchI?u0PS(?44_pgle1Q-GgsGO632$-4KV8iiS%`6#g5!mWEEN^fvqD zOb!;&POLDF{jOaW_ux_UgnHyu6yb-hBnsoWa&KmLYTE@9O$)b6#)n#>e?&}YcgAKI zBewJgNkJg;_nrG2cxHaSnHn0J_VjT19dC7CC%VzS-T7}z z)wcE|@UeJ?kVWJ=QR-|=rjXezfutP_U+mVGWuDw7Q21-p`LGRALEV46M^gwWh}9}1 zpm$dzZmrRYa)d6U(AKyNU2&t`a}#<20OF1#?LUdBx@-<5s@sIRqPYs0(mUg?Epul; zP9aeR*i(r5lE~JyYd5(k{@!lowP@o){&|z4ov|6lh%GIF91g*gc+8G`{+qJl_0lO( zv;EILKAkix57g;~ULdLZ@h}^cIb^?qR$@CFlO?35t;V>RjmZ+S7*F`3fvKYDlr@IA zu95sA2M@k!d;gf7#hLoaLnp?Qs;4IEAQo;C+ms2XMgc-X^4LE^Z)fMa2TQhB@_aQv zdq9{=!T|Yx2%VUI?8)QkLar0%55L^Q&VM|(i~sY9;Ea-)&e#lN#FmgCNdrW(bKJkh zVZMA4w_f-GhPp(#ZPQYhII&n78JNGdH?*Iu8Dd==vEmu`%!}6_o?h`1-0+3=x{=RX z)rreMK5KR3*`4!uB~SZna^A6Q?}fEjo_0&3?yjavbwhM&iED!Py78a2Is{USlh?P^ zlO|itNp?;PWLLf=>GbtzAaY?6w-8f?}{kdSD(#Phst!%bFhgM$G?Q+Iu7$dfH z1xhCnT$wj}e$g%~w`IrLUin44FG%!x!{@|eX>Mt-e51j3y{X%m>c4w``?ON^eW$W) zZ%{GA1l^X;RObgjD@u#u3GA#W?Q47CXGQ5GOzSwq@c&uaXQrgxHB&c4rKtV?fA2Io z#f(nE2I#hYY=^Usz=ZR;NnLDVQlElU@6;b`LD4p${+kaYC!7St`9DZKrZA2V{pQX6 zJNNpg$Zc7z7n!oz_RcmfXKaQsVoPF>L<1r{9Ts)Jx}%cpF23lIQ7dn_rHf3T6N{;_ zq4}nuUpx0RZkU_!=}(=X=Y+@A-AkV%w{|%uzJsqE=ZLxiUpX#zW*dCvxR$RbytS*7 zbpGF(o7!qGR|N*{Zner;+G92IQe!)EDjF_>emY4np{-r5$!)NWw?{KzL&VfSIQ~*h zn!)eu0dI@lqc3i)Ud`0=pqU#-DoVD25Bi012wgvAU9jnd1#6RSk>bWzYG(wL{hYBG z#)vJwfzl5I2j_2_?2zQbZmF-vMlAq_KzC=ze^c}d#C5kkWB=Q>oFiGlZN-7dgcD0@=C)$n&qj$` z#KRmD|CK9PPU@^nX?DhD7$df11xY9%viHf`tBY@3nY?&OK;4IYf05wH%xjPf7E-sQ zFmVJN{hkrUt3Y1D9IQrjI z^<3`0h%@$ASEWBJzRu~FXaG(thLB-9ZNhgMsqRRI4cjU1ao_Ke_l|M@5$(!z4O@j) zCRH$B{r(=MR3WkjJV+ZdnR&2bJ9_t*L|;m@#hl8?UhNY;k5P;5n$Fi=L26>Y zvIXa}8$4CWt0GiF?;!4BtPN#jGJ*7=RepHD7x^jmZiX-N6U^<0FY;44oaMckbyeQEic)a%pn7HI=L5wbq(hknp?*|%SybK zxz*{JQ#hAAathHN5haUG?kfpUure^HMJ7OR%A#zuI}#)vH~K|BE>n>Rk+?Ko|+ z#65}o2g5R053q;lpG0oM@-7X5w_&wkxWL=6I)0z7DD8QCC(nCFc)s(Im;y;%d*f!5 zwN!L2HS#|}+pyGL0Y5wn7L&^KDfm~<|L6$5u14axh45K->mH_RB8G0gyGmNua@dz zS+W!*9{KROMW7!qM~AW$%2xK-u+`^zU%yL zLH5_gAC6HjfY* z{!@n^?;&z4e0k(-=QX?51ZF&WXUMku#QT4mKc}Lk3B;xYIxK4;x_4aS13j=o8}F%9 zI*8sey?Zx=ueFaN6aAFjUgj&PbNY3F)+_N}vD^P~-iqDtw>W8sZJ*ON_PXxnhS`R>98*BYdstXL`kTLp+o&}pi-GCv zoQGdtpJHZ82DNaZm)LNptcP7<1Kz9xy~IW($`5{tjZRqt8pja?7AZ*%BrB3*bJleq`9OdjOB6I^q)uHX{N@N>3aOk z*hn}%m0eGdaAkTH_T{=eBFPGd9B*v86mnS^|-kjd`cJN*`>Rchbtv z!}YvBcdW0k6SJ{_iTh)@!-o%sO}}!i;m6PPOeVGGw@k@TPC6AE;CCVkZ_%~vI+Ok3 z?c-|)j_5hx>+!5#h=b)#aDLPifeD=HhMh&2+Fmw*sH8c zHI9Ef*6BrBczpIx_*R`2d4!?!?KNj?hB0DGc%Xy?!9O+qf7@n8Z}#D~WwH~`uGUCN zgRHuPR#~{NjTOpyF2mjDy2#8s;{{j4qP*6{oYp0Yy~t@|kT!;^{==#)BCn05dt=zR zLgU2Q3o~jqJs5RBNk~35q)Uc-y?isp%`3rpc@k)R1(> zW*8&3)B{NmAacs4={uG*_v*fQ67}KD#wU9o{Oywgca)(kT4Wvtz*n?rvhe#piCl1@ zvT|GZ3Fn`Ni{5Mq*~GdRIUUeruvTZtlnpwy!q62h1UHx{onk-!SfOCz4%xG{Q7`mW zIGkh438#Zvr|fH=8rSMhmpH(d#IE)3kHJz~@deJ<3}eKWVn8VXf`7@UM@MgFy7j>Q zq~Lr5tz~om);=d@fj8UJrEE+lkiE5}FYw-^+M|=d;1K&XZ|j7=n_s@T{i_Do_FHPV zgzKfbAU+?K$;l-!isOXrFS)A*0*CM1TVdg%AB{3Hhg8)d6)W``#+`cHAaI;X!%U+d)KhS==6YxOTg>42_tG_z3fcIkV} zpmZ9u+FsQh+xBK(P|I@ngkw6g_4+UJ z-k}sYLuO=7r?Ca|hGE2*KfU|U6^{G53hi&aJE-bZx>C{k+LV|_naBlB<7RmO86|~$ z5L?aismiU?qkitr2W0^Zn$Mlz>5R=VMr>&blr|vv$X!l;?*q%@J9MWCcRqKjxF2Hk z2y|b$rD-0Mj>F9R+6Sij`j#ILN=&@O(C!cJSwq)I=`{Di$L!G7NTpQ@FLt%yxKW?v zJLR=5d+Qff8@B;WEzQfIV|Jvkks4&FMg5`n+J0{dqm&6d&%_mNXkcwAe2<)3njd0M zEiX4KNbX6>OMNhDaZT@AuD27E&Yp3`W*8&3bOlK%AadHZC6jM1y07+4A^1y_S;0Hg z;x^F2ZbJ*RrPGtn+3cBPr}k1u)4TAi~ksojDIux|S7`$!{de?y3k`M5^1~gRJ;dc#avu}gnHNemx)AoZ;YuT-9FS?6Y zW=u?dt}Pf?Vl%wchfezo=#nSWS0<2@XTLl&FNshT^nvacE)BHBes+TNgE(i!eOFk`W+sP&)(swUxW@O3JzgyH<9$O^vhj1$DDy_8pq5V&P z%Zyoq-f||^AJ#OT<_>bkW*8&3^ae^l5bWW-_>SO|^5}Ic7oYkuwLR9<^1kcDVr*z) z;C+7i-`$*&91EI1Nx#1SE+~du`ZYKe5m@=6)8hv_J|1=DOJL>AJ+j$3^VjZT+^H|i zdOx@0E$Vfz^lb%GyIs?h0bBV(?^f_W76GYwYU;~k%FbgcJW#e8#GO5W^91n|4H9wFTE?I<_ms% zB|pTsE`FN%GmFXQsHl{2FyS;Yk!^YH;RpO)lIDKzxvFZ{M;~ok$Cm1h%`ir6sRxoC zK%^wM3(M|~ICr&+R`d2-uIs7h%~f(@F)}nWPi&OfcQi-T=3z?e;pw^$=Pv$M6%Cp% zVlskUIxa3b0kOc&@;!Wk9Z{#~O}fv2^M%Ph1Ko+O$#!oRt`M7Il7E{8M~a&C6S}}o zhsa}xMs$k$x~`7HM?>qa^NgeuBClKc`=^^W5Kd8(BgFVzT0KKrSnGL$mnK&pOK5Zv zO?1X)7$df{2TDs2y#Db1xhDAv2cvI_xW#b4dZ@>{OV5ef%-G_ta#}I>9nNnI2dvx` zwoFieJ!z)~sCHt4_OR49KZp0Qbfy}@dstfOU*SD0*{zYLPYxTrUY4L8Y3O<1`lyev zY0bQR-;k|2G?GA8PKmC?ff<8t++Eb!x*t8F-W2TkzZ=R%KzXy%HrdC z^-9{xt!FnGyk>V|F|#l+vvS(=!2R{%Yd-l=yBW(jD_>mgkqat{$Xf}aGd&A=>bk3i zH6pv0kD32R?q=TG>jQE$u53h3Pe{{Kv@3|Fx4@>ZhfiON%_dA|;?|~?jJ*C;cHM35 zc}Ej?a1=yH>1q1IJ@J>P@Gjf^^RINhZ7=tBi=D9<#)vKDfl?9#Ta?t^y}c>z zV3f+Yf(wUCj~l+yc?3!|unG*<3UPr@&~*oplhE+25dV_(^0n}M!zVp68a^o9TlMgn zajFb*xVh<^JF52@iYamN%DJs zJF!?87@Kaq9}~#FZ?>^?%MP6?7rjmi3$+K}K00)*C&^nRXMggjy4~P0`xK9k=uLe| zN!?p5JHn?8%TzRn2R70}pV~~x#>aPJ)O+Tdu4uvSlfK;O>C2jgBNfewM@mJ1Svqn* z8(;S??Mu74p-E-?&A;1=oUs|kh%LQ=(hme%onhYEe_+Drc@B!ovnu0$88a;mbz(L* zG)X&I#3S>`WWCkYtf;s>4#MY)ZXW>^OPH0J&O8e?CIZX)&?>W2M{IX?9XX# z$ac0nx2qIlk&_c$DzkZk!>=;S3sec3c5mr})60)|)UK&Lu z`+~J}@F(wG*6mCmE6!S8WMy6EjLk4cYzYsNlt3gOYnW4iLbK3Hqd#BXx74IXThY2O5n6?5J^Kya}_? zIpyPjWrixNz6to6rd)hDRekw-XKaQsVoO(`bOOOY=kh$ZfBgD=t?{#2$M$432S1D` zrlg{he_ zo3*|#>-OK4JPONbasS}1QLBR$nYsMP6zVHZ&+l+*4CZIulCxk{hE=F z3UZmTQ~+LPprnJf!5$2JRX5jacuN13XnFT)#horAXKaQsVoNcQfCrK1h3gNW&yh$M zW7s3e@4e2ZNAiJ$6N{Opx!Dx9e7m{{ZSwVh*EVm6yWqjie3=Pc! za$J@6zRhe*mXM`bEMN5Xjs>QC_J~~i`lsjGl}e32BC73Mky8t{QbT7sGqi>wb{p*= z=p@m*)HwK9(ym@E;mm) zdhPzYcCJs(*bHODmX;u?14O<*?6FX22HQjL(>fp0CT%&Xadtzj6X-xQi|M>`zwrgu z2LvCsU*GktZFwi7U=z4?VhAZiaNPx`v)U5ZU2rP(oB|Us|C}0m@`zY~WmCE83}*4s zR0N6!Z1F8ePdF8=UdC495yg0CQ9$lY z>AX3!xI_=K; z_{(wDqg&_n6gX!@hTaaEZvwu())LZg(OFyXJ+J592eHM0%t==gtdF+vS_EbPMotw} zuYK0egw0yIVL8MhpUCalq|ap2yY~6~m0$ACud{m^Wd&Ic*LF|c_i^DT9I0aM9(e7u zdReaiq-{}-PjtH~3o0}9ZzS5?+qcabn_-OD(hnp>fXLM!{`PLLi#shjYj)G5d2_eV zo-oZBbW@Y5g?32N@=s?MTW%Xd6_K z5}MTifTUoN35ieI6rWCVady1+YB!%VHp3XPB}q^cgW!N0Hy9^ZpK;JMHF?s-Wn;E= zimn~#fN?|1QlBgSn>GZj2+#Ju?Q`SBtqTiQGa?P+X@{u7cIRq7@P-fLY0XQ6@6OdW zOoZ>w)#0BFpOezr_|K%{;Cs<4C#_dBh~&Rsuc60d&WN(gn1%%xB0X)A7=Gy~`p;Ss z>j$fUty78n;8M%XH*&^i7$dfn z2T4mHQYV!+<7?$Q4*#!jAO8AsK8Y_x*3^l`)X>=Yy;B5R{W9Uby4_!%-uw9__~o9e zd8DN$oh^R2(o;ypL1y6s)~>m^@4^__Q;y74xT8j=iV%^Wwqy*y^i(+|Shrxt^k|bM zv&!2-pYVyCvdh4cp0*rCN>5uhEz6ZzrnsWt=XA{eeO0!_2TI;LV>65qTgn5aBnY0I zp%wkvp!UNrvtA+50O1%L|4+9;d!{T+=LMRHaW@NHWLA}X@xbDcnW1-f4su0^>-H5~ zoAY$G&4XWADD!L*tRiF+e+;h(WoI;=Jgl>A{|DJx-nYIomX^EUEm?oc13975us64D z2dp9-I`a?sdvnO`aEZ*)pzzi2j?C|yl=(k){%0N6C7TH+wC#FZ4)3W`|E;h4Y^T}k z3D57JpYlj@i8D6C7_lWuNFoD~xxZ76&z%@%b--1@B5z&vZjORhTPGGvGZVA3JEk+O zsWY|-+5D-%R=L}m&$xFpxE*c+Im}#VC;P@dbEMdo1^hbg*?B5MYQY;Dk-IvhsR9(N z1bSyX6`^O^Yd+cvJ=0zXIaNqazPD9kopJGluWoT`*2QZUEau`QoGNy@T*~r}+rCmZ z(rHq)#WMGq)93Xr{Oyd*Fh*?Y2jp-Ft~z6*FX>~zuRpiI`uyWr!YAH5lyYJ*Gqp6F zKWXBw>oNJ#cI_pP)x!Taa<1E7OUz;~o!zp?i@hEQrE={NoxJGm8SM@66J1VEoOTxF zHYd6?gy>sw?KY>!VlTO$p&kaB2eKpoUVgH*p|`3!sB|HYl(V}IUUBVok^gXmExhsN z42NG85q~WnYZe5pOmoI&7$dec21zv_a`*IE#x1k1>o1Gm=^=V|(u3ZWpFV=N(->HE z_WiK&Ik%)_{v!r~n!RGn{ihxINrQ?@XKy%i#dY~|=6OZ$s1Ns4Bg_v;ZnOCm#AHaP zB5H5pP_DQL6;Y)|1?@A$*){fi?5kk;^11coJQiF7NJt57@AIV|FFWTXO|w0=yQIL# zut2=%BmFmEEZ;#Mw|Zh*gASE z+}?HAqLn4?;qRglhbqW0B&6cfn6!(H$r!TOneP~AO&FxVuf8CFjmZqc*4cl6jS+IF zl8!Z#WqnJVV1(O>m7c#iIqrOWle4d<3po+#?7sz_PuGDj38VTjz;G=R=5@LOO1KK(-6@k)6RO?9Orvy3ZBz|9zdYBaR>YW0>zm=?kgkCzDUgA{Jq>| zas6ul$hx;K2Zv@l&^g2kJ%B*#V6QMJC>R*DdHi8puMp#o^r^Kb{P$nYF^N~BTff=J zi>bW2V9N%S!`hJMNDrAHrGv$nH*(%Ie7Ps!R7&ZA8Cz2xCimMpV>65qTZ(~r8$_m7 z^jXYrGGD)!e~XdlE{h5Ed(x~RGog?o1Nk&0KG9tG0e(U`&l_gX)PAyW!{!Sgo8Rn? z`PX%<z~D3QsElQK75jp&M~WjDps^Pmi14%U@iD|2}_GSJC&_n!HJA0l2ed2$_UXy_v{H@IG#(b4QL?E%$g~cQJ=C{>GpEIe!;< zBBu@-4!sO~3-&|`?6MVCKInPW`0wLJngS)%f}JKlBPb)|gs=Y>#e?hhEdwS5Ou9fg zb(~l^Q7Qi&)7)78zKuO{i45MGlJ<($Ib$=75nDO}r3(m7d>Iy6`_;Rw!M?7KPv=Y9 zQ=xhfCl*r+1C#g*7iD{UKPJU3Ft9dLG`^;s(8K|5mKZ`x5|xiP*_h0sE!9&^%S_z< z+U+vA=#n1Qr8FmI@yoZo0mP>eom22L?G+`VmpW-@h(VWb5!iA!yi>^f;)b&QI{ng) zzcyd#OI-QxQNSdW#lc9;5~T9u)ajA}zRLOeS=&GMTnad#IbCkXiYNZg*bHODmX;u? z14OQzyN$L0On zTz~QhN_rxF`7p^#0d>yogUu=opQV5i+W)>@T9G~FYg+18ms91vEeY@DA(uF3rQu5f zQPR_rzxxa1nk_zE_j2T5I(&}dMxMb&XKaQsVoQ0Tlmx*!3tukDsBEw9aprtC$NPBk z?`=;qoLG#Fj4g!EFDS5`p6y$(jak}Y_hR{3t~Kw#Z5rqf7@c!pNV+6U{+a06`%@f> z?uFfnEX*>@nv%G~B>^q-lFm+W2{ zo0Pu%B#u;cJ`vukId%F|?SGXR)%}u1!Ko#TH*U-dU7_ITjLk4cZ0QY>fAd^k3s0GhAj?B#RQ|9r89@e5_zD!*n2aHvDDhKA*qAIK%QCd4 zE<3d;}$_%POm5WxeO$viQeOMXv&3hC2V`AT0?+HKa z7#Ciy(2Ky4J}x#Qr4RLFc7ab1E_-rhJ@EW+E+A~{!^k{mY=$vnOG%)V0l~Z0P08iD z`^#{D%DURq&h~$}xc}=R)lEp}n``U*h1X5E&NoNf2=)EPx_{e_Zw@`YX3y4{(axJM z{y6W5oNDm5hN;xnxf}(no9Mf%mzJ$zk$HE;l*XPC%RiiMkQ$3g@&vQbF4ou06Pu zwe!t#X_@zvoKR8=eOoeDR}GhqP}PPx5A2`6%?+wx?F@|;nfh}r$6e&qa`h>^C4*GP zT;3k#dF?@3P^%YTAWOY;R@<~!4xVAo*bHODmaahQ1cHyw6x{a2uk&E-lKnCd6W4|P ze!*`KZm&R>8f!nk!^UI;>1C@sJY-`shSW#uUjyMwjTKG`urZlI<^h!EFS=N~WbGk# zt=Y`i6wYrDetA_>+xZW2S{bd67#Os6orW%0*PeY5x?o*v{blH6w)U$Y*ktzgebA-G z+5%gj)H(G`P|-2UpX)Kl&gB*#k0k1Op-5@vh9JB?y1cz|hl=*Od^LwUX5(TP?^182 z!|LJA*bHODmZ~7>1Vpa7>L0wmHrX^``yzLf8Y8_Uk}A7EC5y3zsoI zitaa<>v}hODr9^Hk}7m=z9QmICV^;W5kxkKuHFIuT7i(GX3_XK(l{q|CCQt*dyq6SsQuAno4Vqg|^>^ z&seK?ojN69Y|qb^wzaz6F@Ny_5uX2+p7qGdiH7CS9c9>zHL;V8gS=g=a~-K1DlOD6 zD1IO4e&|#Izt|0t|2_}*hv7(0cV;4$LqX?PbiZ%BmF9ls$NJBP%3GqZ_K7)TGmH^i z!h<9w5Lt8P_RH0uHFsq9uV!%n@b`(W`@Of|Q9bB}Oz@c`hz*&SN{{xXEnm!LeB(o> z;e5fdDI)gPiFuzBmpfxKj1gOkfdo8=+`T}(t#Q`hm+m`u z94+XY{wkIEiY9W~1vD!FYrANCX@<95SZ5*HE=*q<;B6N!rwr>^?ax{w6<5AKVLfY| zI`6(2EU74)xXGx3Mr>Nqc~AvwyZlM?+O~9;!;|6}SLU`io`1K9J!7-}A>_33;4JpE zvLbC(Ot3Y1D9c<;WgCI2TaQeSEPe8~>K^R-@` z-bZLq1+g}QPKAU_D5!XyDtj?y{=Zi)r$6Kte0sil&g^&DaVSL(4XdC>%Z76m6#lpU z6z_xGS04x8`1B)V%dDQ3sVGMvAtk5BGDua>$rHNgv$7Ar=&3uDqqtZ2(I!!rqt4h2 zW5ky5AV~>CE@Ji*Eo;c{FSVxS!s+u)R}QM_$6` zUaknJDGWPe_Q_ZH5wlu}?eHUJ)fgAUkC+v{Xuy#b&9MB%r!4jK+89l~gB8cG1_&Xy zU8qzJJ>`cTC)%snaCLChQs={gIw91@K^==ZHoV8;H_W>2D1KmYjks0X-pcTG&6T%F}5@`>3OPfxn$3d;K{#rKA1e-Dr26h;sstNZVV|-be`))94T5q zg>g!5QlO>=>#EAt3hSQsBd3a?Se)oQ_kb>&qVG%qN{jY);>QMYjx`5e_;8JASF;i;Oci!x*upA4rM-k$qlYb`-C= zcl6|bra9YG{i;uPKe!1hG+;9Uiu-zqnF(NbDE?`Aq2yX3|FwXPUm{jpdfQ|V+Vt_# zg{YZ;L6JVVFJ=0v$jjVy_iYmIUB`L{G!p%&QRH-ksBLs!r{Fv03V#o2m~4!|>V$ zCEd*Wza}+Hm}9x_%|8cDXbRdZw}nPIV>65qTMC1u84#IgQvZ>&oTa_iN6g{p?+*+P zcd8_jdq`4ca-@##zWC92-NQ%YxMAa8)*Ve*+F{5ncmI+c?dHWuz4yw+LIwl_6@ibw@xdp41T4lN(*l6aA z%`ir6sS1=zAo#?BPzl!d$cdIezJwI&o=NPvSiUakuinxwEF0JvB@?yu9bca*0|2m3cFltqn&`Awy?oQRn?5 z=;Chm8=qjU6vR#3*p9-d<;-GVr?X}U6T_>Q+nsB^Y!NBGcF%k-;S};g@CcXa+93H) zyhnxY?tPbJF1}s#$*XuudC@AYLl-o+O=S^dCT1iS9W-?+|qe(A%L6?2CAgc`S=QYc%t@uap>WR zIzy?X`2T0c*9#Rw4v**YShRXcPJLT{WG;?$@CkAL?+3w^3SOP*&X=EDTB+%C!y_Vp zd3DhdXKaQsVoNcg6ac|%=NuE?r222x#=j3@cmr*J$bC%w&4g1T`x5o z4w~|pt>W!kHn*z+oI;=@vpSzYAs>~;?6$6kN284E-{}K0=X=z?Wz^2ZG2ugWyWYl$*`l z?_$Zby@%PIu^GmQEiFM(2Z)@tjNPr_OzOS0V$p{+u9k}EFUaWyrvofUoH4To{o{Sj zlpOhJS;qZ86WE`GGW)(+sf1iojMf+^N1S~VfzBA~5L%h7vrwb=lF=TwykhAa5~^z_ z@0c2fa&#v4bnwl2qjBor3G)26``OC(dTdCw*}RA=*cqE)jM!2PCO7j=_ z{=I+u!2Gi42Tek+D>iJ)n0lmAac_5mpd+e z+u>P1^Qr7^&WyKhKkR2Zv6vYd7{_hf=(;*Kss7adNRF4AbH8&;Uh^I_ZUP%@{gnhC zY?bjBfe*GS+-qcGvV?2_(7HK8u+C@6l*s2@1uG}`Z_c!hxg37;Byz%`PVuAjs|GgM zinzN8vFx8JOX29!U?slzsoVMD7W4Pe>h71ip#j!tXw;J~sSE18$KnqsP4MZE} z8NJxJE^YJt83+FJZ(ZSfL9QQVu=UUE_s;`&v>a(xZF1o{@*qbgd7cixGIFXIlEulN zt*~wkVlx>XmR;*07bj0MBsso1zFPY&?n!Iv@oeTC9&VJg@sKK|KR4jT$*)6pN}h55 zdspAntSNky%C`BBdAps7Gd9B*v85kKiU5%}C&#tyEwj0@W1qxZ3g(IAo*l`p;{~eJM+IOA% zmr~t)=cOEZFC?V#xY}3bY^F0d!x*t8Nl+4lV6HWKXYO0wx8XVSVo{^VCZ}xS_GnPO zWoF{@SIuyWydLv6@5haI)qchje~*RKReKa=0u}E#V>65qTWW)N z7DQeye&P4~Smm-GM)h4Q-v6sq+_8-Z)WRWjCmixIK{|bte!f33UyY;u!8bi$rcYbj z8#T`U@Ig)=G_1@9sEpBNj-$~rK`513AeY6g1P*CSA+~O&kj9JVMc0(fu%{1Q=B2PQ zMwhYG;L4Jx7khpuyePlyky*5U>fb53rq0+5W5kw{Kq&))`!sLvpQWPacA8^)iSl=! zf1b}j>x0q~-hP9!2*qUL%#3~)?Yrue%KrEN>}AvHwl_jf73{aLr;4rW=O$^~ zlx65qTlxW|2MBigyDP5db?+r7mAg5sH5{eOV{A_%7aB;{ zVDrCZffpJIsMlccJXNq*eu}O4Op)Y+KP&H9RX>=x0lCniPMxC5xfxn$=pfE?9^Q3| z(z(gAqTgh5`ETA+AbhRnsPKdZGjSvj&Ywti%IVpEo~s6(6!HAM>-5k11I~R(tq+{B z8ODe$AwiM`h@9b(fAmU|iqu+xi6-$^vO0b$gjRuz21`hLle4ll(UnPShsEx{Y7O?n ztCEb~KDpS0a-KJ}D-2!kOEh1fHYkdQOGd&66~huLR%~BBfv<9!?Z>N`$XB52a({&v z4JdK1)cGMnFZ;@lJ4VZ|njM&G)pSfo!x@`ljM!2MDApl3Ecu9HQ^Ms2|0Da4+h!|V zkO{Y4=EP!RYH0G=r@BTo`ZtFyo-EYE&Ms^y;y8~qLB*_UEUY4)8Jkcx$FdQ zt7F6@qS#57?Wb;HR&?gAvE=cpUM<#nO!Jj5{1%#oefawHx3WCFc0deErpeR^6 zue@@V{@&kx{LE&xd(4db7aF-&Ag2idKkR8@h2hVGTw22FD@B$~x_Eb$Bjb%GMrUk> zF=9(Ske~pOMUO)7Hpm=zEx9nI;*r47#}+~i>%mik&_yIl;(qW&Bsz^*dL@OuH+R0) z*mCtrY3HG0y`Y3RrlFY*bcNKRi%14VI65qTZ#dt00=(til?dYR_v~0MyIDf(tlo4 z^>L}C6N|B-ff?)X>W7sp``-kW3BBC3T6K+kxchJ9MUJ{6`tU`L+LrGTiySYg!WTI* zSRa5da^yQ}318%>GwD80Q`z-Ptgk}W&f7fuY;@&qzUyu%3)c`sWV#}r&_#|q9(mB4 z)^vzG+-aa@c?NKZjHOgrf@MmPleYdO*V;_Qlz!C)W z1Gzlao%L*i(>ZJ|>wWBfjof6B&<%q(S#-r3;Y}7Xj(zYZi$>jDSd&HW)yYY-avMwd zg}CqXbxg{ezfMqap90ERE4pH{p-q<2M8v?LL;N`Fhn9eaZ^FetuJ`5mrSj%e$2K8` zWWvRg*xP6GHrwZ)O?@D~O#M=5N~V0oUd}bn*bHODmfS$e2ZCc$|9=aN4mn~p;rqji zt{Y#Bk9T}Vp86r?HVB2F7{s+m*l&YCJ5<~5=yO{yp)_A5<;`3_1$W6cJob!3spV*v zoOC6Q!KQv_HuF4yWzw(9N3skm`!_y2>n9-<{am`+aIF^M`~LKP3ciSv zh@|zQWfFCU>8R6&Erxn?? z*wf0(Q!9Bz6rVi1)5=nBurV^lqJ8mxXKaQsVoOyJXM)IPRqhLF&SghJEIHr!ru{46<%EME9oayo2xc19lYar(p=@@`Y&g;RT`?|$ZE zvIix745A82SH2ClgRH~{+WpqP8wu-vV_CaDfEAK#sbosP%D8D$)u+Cz=sL4;Q9`UZ z;q)PY_EXd8L#b9@vseCinWWR|ruW_|agsAO!x*upBv8tL;H9%&v)_i)ylPMDZR)?% z@QJbXggj^|l!+Nb+1I*_R#$HP`&2baMaVWhY~!;wlx~;eGI+O(jJ;*aIgTIlTbP=9d{M}H9wXsoDRgnw-rH^* z75iHkf=7Cwn*el`f3Pt@k7p6+a@FVla=A%i|BOXJt7iAc{t(ntH2j8~KuDiP(p3?J zZUWFz4q^wnm4RUdP9rT&y{u?=h&wGkzol#conu-jzD(f3kw8=&;L}L*XDu&JH-0Le zpTDH!5vyYEipGSEYgwGJ8ODe$DM5l8M80h(xgYav^MnT<1sT>WNUW;upKgxad?Dr* zYgJoj_!4h5QRAKLTNblqYklwc4|UP&GoAQua=IRJTA^L{oAmzDV6UEZ)g+ z3E2t`G8!?lt*hU}wJf^R(E7Vwn{ZlD%X$Cy^qjlbazxK3ES&$_+kEk-jov$)u^GmQ zEmeV12?U>wnCbZS+LMwCioZx=QaNt1~vk z7_p@)P%437k(x8BwOew-zgY;kO?+kPFfnwm1-LAMUKXPEx&U@r2t)D%HYRf;us*HZ z7ugsg9c!(K@&M=dUo&5rO3g4z<@?ff(ds`h`!bZ0WEiIoU7d;0%R+Q=UqLSmQHxBF z1P2oX869Qh)M03nn^M=3Z_1d`!rD4b;rorn+g~E54xMY*Q^&3Q*Q}LRYq$KHC~f2S z$>I4IbG0ST*bHODmX07!2ayMNL~&l;_CrlJ7|;o6nQ!Ga+RRWKp*E#vb^hY+b$e@I~1=J$|r7*{VB|VT-aA_qdlFYUbLT z`)5wvLz@{d>Yneoepb|Y_@p6Sy_2v-*+mMlgZtHMpo?y4nufksUY_u5dZ+v&m$&um zMXDhmN^~-j(~!Ot_B3?I(n#WtZOYnRy|d2nA3pr8^X!Em&e#lN#FpAXsRx4lr1({) z%HC}WEKr@P5k2{l)%n7sphKLD4Blrq2N-RaoOylqi>c4{z1(PU=f_-d8p3k@gRa46 zHYO9uA{ntW+t`>)4Z+51`D(H;SwL1t$UhT(p|ib^d-viQC(e4Gu??0|-y^p$1UVHA zm;RBiAulu)(P`nx`3*ZeH!zUC92x14k+{On~=~G65qTY3XWF_;KR7O#-IQ+8!R@$v;(v)m15EiiILo^qnnskq3y zjRbhZv@HPWs7oDD2mX$)?WO3}eKW@W3ev zOjLE8nmPOMkIjBZTO6irdN++@>#s!6RnrEBpBvUmS}&LRXSVj??^_klHSgxU(*+kw z&@c8MbgtS=7aZD1l2zGSl;t)S;_$`~N(#x*yxnzQ z^GLhO8`tN$2O9RTud09SjLk4cY-tIcIKYHeT=bqjb}sH)u3M^puq-~H={@xf==2v$ zqbd1rg8L86GjTuPTQY|+`{QZ*yJFxJVgzZ-C>gG0W3q%aa&#>}EL(Yd)yy*W|K2u2 zyLX@O_FJ2N&}B4*fWnyAE|#tp7i=yPxeR&8DHg=0vO{UXhAF=#oBjr|RO!_smmyY` z*i%UGYu03~=cajOeg)PooAh^{d&nc_jLk4cY-tJPa0oW4_F;S7w;}Mg-~*Oh7X(h9 zyY}<36N{Odfn~PbyYuSioz51 z<p;C+3Mu!99AH>F!VcvuZSCsW=HQZuqH%YcE)BHBeo<431kp?b-Sl`iD(Sgfvtzd*CXQ)d=^%m*`}~$=s@%+7NbR-o1SjtyEN}7a^yV zAzlgDdDFZHj-!Y<{@(PwO6l8quM0(TB6mL#7ShJ*Itaj!vnZ6&2%(oRRamHpCBeqlpNhct({DaNxt#dDEONR@E&wEg5TOIYZ z4bm)ujJ;@XdCA6P4mrY*;Z*2WS8)-!-^W_KAKU+(TJf$=zHTMz5|{xR`K40BmB=zf z*J&ZyBfmJxjJG_ES+cwKN)<1Da7*x=z>2o;yUoby!07_EGQ;77#`}unwF#4#U&vS5 z9dp9T{OH6v($3fnW5kwXKq&x%gZ=%4e@A6ntgxD$>p0uR{rcm_Tbx*oEDSAER%_X; zOKH3IQP=PX&vkE}M=piI;QdNwkPVNzE-TrX%pna|ZLRZcOy-aVt+u<^vuJY<&MT)r z?{t54S6^sq`plSAO_Wk&G_^43x*W!{pbkfBd9ia#zKxOc+?>Dbex(Mu^Zb)FG)GP? zF8{En7W=)`rgM)x6)9Q#Jng$2@9rD&chj7)8ODe$T|rU`h-}i(Y^XkXyzAYT=^MWt z-5S4h>FYI~3~X$$BezvT@4%NuY1f9rccTb|&W7(s;mLG@??w^K?Pr4>xvg?IYg6m5 z^O>ffre*o6XU)DN%vka0t}1f6L9}6Y-L6BIMd>VOhAxZJvYrE57A4jKz3U9?s+W=1 zhINcwe}7rEGK+>@_3hwO(nW7B9CO8yZrsh_ZCHmB4;L3NkLJ*n|MA$okM-cL-`tT? zmpWrJj1gN31Em-UUYC)4V(lx%<4QcK_O6V}?uF=k_o1{*DxFDfnf&FE&2ZcLvp|q* z_J!b|s*3vQ^ByCol|i-Yg_4$uCqI2#CZ5ld|4o%%^=bp-Npps@lE##bw%df$if58j zd!_$AxbP~<8Jl5@*iscFoq)&>!U9+9f6QYK^!(kJbaSP??@?Px zCl*T!BLg0(6$=hM`cSfOo|e~?QXid3uR&sTf<8qv;+UQP20|G-lM+k z=&7MWN?u!@nM z`lp;x5nQ7|r;l{~kHfd2X#Lp^zh+NowI%$DV6=6dA0OI3=$O(Ho$7JVDe=py!VmEo zA5l`#aOrE)qek<82%SFC*z6)3I^~^{diB-b1K!cM@^AC+Qe<>ME`PA6q5u=`R%xTj zB{DB{TG$tS-M+)qfbV;&Gd9B*v86Xq`hj5AH7>IaPAX60UtqzRTJ>UGy8gb4pn8iD za_|F*SJrDiFlA%1fb`6Tx9D!wWZCfb@FQ89qpBNY#Dk?Bv`ReaooaN0c!|2QUU#s! zgOF3rGFkRtGiBGa)jln#T4io|ul}D}D&bTUl+~2ux3?sZ@4w%~_ubzTI{wb+m?qWNQdGd`91)vWziaz^{Z`x&c2Q`e?OCo7Ze`Rc;X-sLFHs6O#g zao%Qk$hu%dNN-#>#F>bTrLSoGE1G;nRr#g7NYr29SdPmf`yEjd4w20r-H=#lXG@1F zdr+`7cZO7@l@Kg=;+J{)o!<}rmP_^j?U>TSDTkbJLKb7Iw1Tn(W^Q89d_0MF*I&)+ zZQF&F%ooX*Ib$=75nB=iB^d~Q9r+_O=Ge1>@XQ-&Rcr_3%dC{oI81Mxk@jk*b3dIvY}>)*&YxD)rLC zrj4|jrlMFub!Jnogyf4cm6c7~f)%}0F5pNwVRzuY^q{P!YJWFjmZ-fVhv z=0jwzGd9B*u_ZA`q5+W=!CGdkUZj`^IVt$&9O{{rS8u<}iN)B$z_jC%&5fXoS$8eG z8l74!Jy$ROKgSR}T8!oD3f+jUSAVCx%51r7$;MxI=)1=22UFtKy+uwT^yr%pojOT3 z;yiRiEw-yGbdl?%l6#!}qPY_z_dJt3Al$oNz}-3FJmC})@h^VwQI_K_vhVp9y-nr1 zzwfVdhT}tLY=$vnOG}`%0m07_6w5y4UO4)@NdDfX)HkgK-`bu#u^1Yen*W#Ctgh!IFl3feH|jckov_X^MffbGHjgQ6ov@aFK5U&ZA5X`-?#%0l zOh0fX_Q!a?>EwOBdH$bU$Z2S3momChAEC39bYGI!^2xe``DrSz$-GZZx03RwuMRr& zA4eLBc7m5O5&yUXZP{DyEi<3VlrsN)`Pr{#bIVnou^GmQEww??4~XO_FfQ8tq>=BV zxM)m4p+$Iev%4)Mr9k!>ATPYrmd=CsoRBXl7eU&!qHEeAvBWfanzW4dj%9}r+_#Ts zfA_R~9&%bin$gBPax>bLVPMdWm4^15wErY3%P*d!lw@YHc>ecrGt=bU_}pnl$Y~`u z58jkPNh=PIy?+QTJkr%-taxw%L$yiqmTOm>u^GmQEmeV12?QTi(_i*`USV9V&acn6 zl7Fqa8oO{MXm-lnc-`%mLmRzr$Gu3O9&DPbySFwt-5F9NK{l?i?B31BWC5AW)QxwS zl{;#xBYKh}?(fdU2Ns0h#eEeo2RZCq zx9xvO{pOz$n~<-;(Z!xZ;wLn*wN{j?yi8iU<=x_dhMdmQ2hIu3*bHODmX;u?14Mc> z9rLpOy=c)*{ivD(h7D`C&)*W@#A0l0WWGKqFJ(>3?)Jqq|3xMhOnIuN5MYRWV5@Fo zX2i1JH+E#iGo4EgxKbi|X!T0N3^C+#gW7eBZela^z*c&!nHs=4=9Kx#Pg|no%lLGX z0$vDj+4Xo^9Lln9q*Rf(3|_~?Pl%u1;_-5K+E&*i+<&IA{Ib96aB+e&Hp3XPr5{jw zfZ+50KkG5gT&&R2KOyt!tybf8ca1iJIy$g%UF3s5aP6Fxz45I(C+FsiE#^l(4u5!S zetf~~1NrBjkkiM&w_}k?jpTahxULS#2Y={NWkimIQlnzeUekq|;X({kd=*kcmf0s* z=Ip>xuOOw5*ZXv`*lkFuK0G8RS&82;j13Bc5Q^O zdQf!kxUc;~L3ruLjX%#GJ9A2!$?A2&sRZQIGFqB2FzBZ4gsytfo_!J8>(N>dKSt

5RyjM&l@D4js?;fyy+7Uh}zws-k4C&OY>%0_)bJ<#|qY}Etu8JytL z6HOp1VbqB`gHt=AUb}wJ^u>FpCf}L4bM>aZXW!`~ryHbFCjBgQ-jO-ldgb-J6It}^8I?{Ic9aALMFHo4(7|{IJTft3nfvEu+drFEIEv=)1jTDnZ%=+ zRxC5&QLHmI!x*t8A5e0D;ASb+huZsno0~prv&3HE^Xa{tIm?N~*ucy%{e`XO<${07 zM;4`NZMqYFqDZ^H2Ha>dg>;P7mV97iGJ|w)G*sEym@FV{ZT4+!OcoF|x;au>4J?vx zu21pl+@vbsU_0Ue9Cc}wdt--RaiW`JLiUnf5*jUMmcQ7`z1H8fW!m4?Eqv=1@p^te zK{(~)RL5U_zpY5xFyMQ$8e{U5fAS{2ep8*X8ODe$jX_ckh_o=i!7jGs{W68nKWpc+ zPWZZ_CHtKdii@;ZL^{OhrKqZ6ot!kl2#%?n{;GKQoTl_)

J@By1UP7!s#jRv_~G>)Bj&@2UpFQckHqH0yd#v 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ǎ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�XJayhEQK-I*u}}OApyFqcBR} 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 z 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

RW3RRx@z9opwoLr)9%*E4E*jVS0%J{+Qdu%zG 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 z

hYTDP0gO3;bL*u=shSM^ZXBTQVH@T4tfK`5GX-jszjWyk~?^i{SSN7 z{h<9~N3HWv_KrMR3NJxWQjTG+fewG;{I|=*KC#W0D3qC#)2Hl=%`ir6X$+KRAXw4u z=323d3Q-bikN?T>ocpsR>e*RPM;JN`=OVz&#t2yy!5AO`ABNM|tOXy2bGW@6e&mz# zO&j=Kzy_zYZ+Yk5%RkGyNVoXH=hFvS6U0+)qYkXlV@By&9dsDZRX-ax3`hEjh4^Qb z=skEVS*;kI{dw&gzZse)c_*hNEe}>JLoRQyr1L2)PX5AE4Wx3|UFEv%FKR9y*wtYe=SMb+JFU~>F zKpkUnBYOH0_aSz^A4ufd0$RGcjN_VnT@gG zV^jWg=lmsZduKjvPt9F#`#J9SYUJ5SDot*?zPbj#qLG7vOM0?SmF+8*polw1o|)$= z6wiGw%ZZZEXjc@y`T(1a9F9ei3*XXNC5h);BR@T}Wnj%xYIpOyLO7wlPTRd<-@|XA z6*~{VUA)zpHD9%Q|GzS4Y=$vnOOlX81|sd|y=Dk`8dSV+{?;FrubYZ5PYrtL#A0b| zY8X9j@msTNGgp82=f6~YlXd^R)0~z_Rh#QudkU(y@QkgG3%DOg=eut>ANg@r`TXxP zs9RR(k)Ga04!^2xQ&Lcreyc#)9@z(5>TiEx5c4Q4CY+w$ZrgpyewkBz<;MNmZtpW* zKC9N~e5B`$%`ir6DG!vAAov4+$=Z9G@m(?<=|Usai8F!Wn5@i@X2M7WAd?UYSG8q zyh@%3pj1=D_Om`7hi;|Cc7liN$V(m%#cf#Ff{#x-I`xIT`5PZgdz0@dXF`4A#hyIo z_2(D!9V>4xIM^6f&isjw#kbGe8Jl5@*b)*bVL))zyGt+l-Hi+GJ2dDlt=+WLAyI#W z6SIYxrDsUl`4g^F+Vs5;09sCw^*U!&3zj2-v zs3}ssbMK1k;*#?BQcGvCpd^;jI*7sb^MBZt0Y^5&j+lcV`GMm=2lFdx5=wQ3`{zY? z6#v}+hShpvS`>0wf<3W(vARCZ;g{*&f&zKb#Cdnz)_dNqX8rGs%`ir6$qJHCK;*lq zV>=G-J8}P4C1d%|p0Kp`e={nbSd7gLj4y9Uw@~_P!1q&VbFj=4lsbbSFj^L zz6m4G9Gw#W+9f0XOgC~ahup1@WCQzc|0+;Y$Y^oGfd5hn*KfMmW{zf_yPohsUG7}i zy(!b!)_A?Rzw?#Iatmd9gfY=$vnOG}`% z0l}C4Jiqemxslz%o&Mr=T#ifhAKc{xT}*CnnDMb??dt`l%m3f^$UFXDbf4XpL{soQ zv>~Jog1i^T^@k}jdtvkz32s?YUGRRvp+%|fn|Xe}yc%zgl8Qz<=}1?o5!eg!!yh{T z=rF}9W$)WRUGKl2H7b8J^Q-6e?g#Vw9^ptuKNi6|>0hiKZmYe>z2W8_hKVyyUzU0r zF!kP|=g!y+W5kx;ASnn$TJD^=iN(j&UiQiD8GD` zU70aE_Dr&xx*=Fy16^eocj4O@f$UqVn)Cm0Gpf%b8}b7d(2*ANd~`80aoqHEqtk7X^=zQ^>C)@Nxzv zg=h<~mcKT1asRD!c21!xN7%KfcbU%E3}eKWmOyC(g10eb9`NZ}rWSr^RcY9qX;Odh z%{=GCVq#)y8WO*>JNKhg+@f7Sqd#SH+HAVZ{T5QrKvIR1{46#mV+h-Z+l-CL7&-v> zXD%Bf^w?#)2W*UxR*tL992WjP0mZi(SiC<>RXp7J)X?a-+Dnu)G_*^ZKigqf2h(FH z5V@4OYjEJ`^z95u2S5DyT=w&*g37e>;W*OJUk;>Frs8zrK9>OBKf)a8muv6ETkN&G zb;KE)VT{;P8zlXJ$hUfbWLQnK5)Mgr#Z4=>QZC?_n(f4FY+$)W@j;~FLoMF!)s}{P zs+=yh{<65q zTfze+BnWpSb+?_ZK(h@ZUyC4CIL;>L~90D1?XE8-jx>dZVK7dPIgH$*$1 zsSxws{rsP9!PMOa(NDRtrw=#Aa(Hp`KU{vofylL0+ZUZZexhMYUY6A3^OCcju^GmQ zEhRzH28f)+axlhy&AvZpzwEXZEA&VY3$8*>)E%>=MR-#Yl=KP@uL%qrMabPe|xZA*8AY1!U~&p zNt^F0UVE6t2R_cq7_#KXjdkj5!M%ZT%W zW*hAA{Va7Yh3kRyXlelkH{#+?H}<2jQM`-$prd%sK{?QadvT1>1oE9N3VXfbS%!@7 zVyDz^qF<|3RFG2(2Ltxha?*KSZO$*TRR`;~&G)@!6`Ft8-Om}DVT{<)70BTb92Q_O zE%@tG{w3?S^RaH(xnH~Zdm6Z;Fo9Gz+?hIudJg{D>+r>6RlU=)zj|I(r}7=5k>h@} z{$Rj5vf{>h6BhUI%jsQ_8zJ1C_Y}+68J>K*SnBalM!0jP*os~panJb&ss50B9WAjl z@nG30^R3CxFTOhRY|Yhs&e#lN#Fk1R@eU#{^%+<$<<(fOB=lH&U1pguCrg7Tc>Dy* z!c2?Ey+ylx)V}yL|LGO}_xHHOuG#-Xg+^dHaO1v8;=)XV=^%LW?*CC7n|%A9<}`mh zBxpWQ_LUBfbil)clnyl4UA?ZVSW;wHce-SdHTs}Ma_)DhVwp+Qk%_$bJ;d&@4a7X1fp z{z}EWmTXo>UUTV&lsp9dk&2Ql3pFO|E1PaKm2bYg&-l5S%)-z2ov|6lh%F(35(WfI zCh%Oh@I15HW3ij;^$mOb)<3|7k@cib79VT{;P4@(+H#E|Hr~&$_O!-{|@KNuxvA zj!!`WSs5G6{tm~q;wEAP-E@j=NP`yTN6S%uW3_XWSFGOM{bWx?oV@-bz|<%dW= zQd(*E(Oq-x$4a)8{BxBu&rMdb=&7?i8)7kx5nHMPr4k6%=3l?Y#GWt5_apa$i|yaD zrf)j998|q9L6@&-bzOulUsImy24BABcy0k~`I;lAy;X_Rv;}k2zHj^W@Sh^P&?=3Z zmx?1Lb-0OTK$ox4AayLuJ$bM`S?cBcDA^#TmAr zs};lV$?m$=)nFkM;Ec^MMr`Q_k}^Q#zN?d}l^;);c|EK?y77RhhS2m`0g%)IsYQsm z3BqCG_Kb&jcIK^%SjzHV<%m+mjR3~2zZl3#9&QqC(B*5`Zh{#2iUwQZLDS^n<`#ZT z)a>@RO*b1a2YY!=cYAlm7Dw`sID?ctB#U?YJ&crEcD>-FYJ6}Q%&b3?-^FL>S#{3b1=0_b8Y3yXBa zq!iv&$`dZRoN>5*@Afp&zbz+`nPYmZZbRJXJNRCJF+pELJAy*!bJEvU_2@t zohBdG4ZE9{v-Rp6mi9M~dyCoj&P7f|!(~j}P3AJRS>j6am^xX#UfGa!Oa4A#ZQ1|8 z|68_6vEdU>!{5lMNLCHr>qSXL3qnp`=_u1od*JkFUsvo)ub25-vz)OR#)vJwfzl5I zTmCXim_NrmeV6{D_UhFg?QbtVzJOfu@Sa)-UpH;0@DO$dk%MXy{0bu1UJIR2nX92S zJ3K9dxrO*%bk4kzVR;@Uc@R0Fh19q40jZ)}cx>zqrMQraGjjEDbP%=2ILfnf4*lXsmbc>V8b&0CvZuliMQv9HkKw_n3QXKaQsVoOMn zqyZwm4(De-AXootRBbjaTicQ2(%NQ;y4rIr&c=E(9-Q{bG$= z#<(fU!OIvTyFP-eCVrl=^Mv61Co?K;-EsI)edzBmj#%35Jw&Vs%J`jAV|6JuYrXby9h0AH4`xh~<%Wzr_9*u|Iva2q1g^kG!x+tx` zP{(am_!bWLjlzQLS(h#}2;OXX_zXE644t~hO*t7lT!L+cmF{)TyBS}c8}je`w3_|+ zuG&+7rru9Sk=MJrDNlmeH7M!eOpn5+FMUB}3d?O2Sd0$bb-TZU*%_N*jM!2PBn^Pb zl+CC1zPxIe-sO8V`}RcF)!%o|<%P6jA*&E^&C*J@`&aZk9nnjlk$$H9_0_lW!P=i4 zmIRHa2~eOS&C;r76E#bVGV0F1@jKgj!^=)y*X7s#v=RBdy?jbAa@nA|411bLc=~4R z&c=qrcgh(Xejd*_pLF$@nKL%S7_p@uki#LEJL1IBR#x#DQhckK-exW-J27Y5W6&Z* zCL>5Y)coCEHYQ`pRz6XeSMXE+9hY2TV={%L8|RjlY)s~m^24ckHXD;UWcW>Uv16-d z>i;w6qc()aMI?NAEv6@CCRv1>ZV+{fn|eL$BtXQ4ckmTLqjd@c1Ii5Vy~jK!k3Qrz zR@xlsdH&6;%}j|?PU1*6>i3Z9lcZRksRhu@+`1-5QE65Gs#1Gkt16?7{n+Upm7cw;Oxa5k~_grza&uN!SOurug z!r3x!+Ow4F$mzg!fEuW7n%iM3E$nIFW8l4M`4h)95ser z$CF=9(G zpcDYXjR|_Ew8QMIZl78(Q}u=8a}U9tX5h93bf(|t;63;eOlo%bu9pd(~*`TC@Av1eRN!!9rdp~rhAKU(4H*)HcrERyaXDoVm$U}MEwO?=ABzDU=Ci8e&$~~WUOez%LMRhQ|I`;9$985oV>65qTZ)0C0T9XF+z|S` zVv5Z3>eQ1>J+t?G-lO8^#A0b=V*YB$W0o@~l24Qte|LJ=vr2mMvuQz~8U}jA4$?{2 zZo0?eN9+)J(zRV@jTOf%zc|YmK|Kd{9*SX>5)Y<#dUDf!2wmombka4+YYhikdeZ+@ zAyr#EQ&r0)q*P6?Zr*3ntW@Omq-O_jm!PC4_PRXAA5X5%jJ}n(?UGTQ=(pE_g3j0s zW5ky7Kq(1=m$}cjHe(g{RC%x{o+H!v+aI-$hrr_^1P<dfXYCVT{;P5+ry)WX;TnR zKD65(+S%9FoY>?T9kt@Q(a$`0`?sM_wh>MTMrpF^qRJR1c!X>bRC#65qTZ#dt00{oN>eVubrn@eRnS>-P3%3!P?XJbf}m;a+Ts{Vh`KYK(poR!?MUw z<@xqDNx8>t{nqs>ICjd#Ola)jLry9t6R{N;MrmH6$Nd%N{bx~s_HCE9i1&%RbB`Z& z#%35JwnPOG9aw->m<(bo=rHRV}x7|6Iw5nyB$7g5xlXZZf4EUm1p*S&tX@t;vIu`8|p>OlUCnVX48a@t=POdbX|p@^S1VT+Jw`M z*-75=Ppvx7K7Lss*{*tzbAhMd6aU}N*bHODmcl?O27*6m=A04NJUm_f7Q<}LwsM2N z3_HF!u^3w#SU5zoM;3FeU3@M031i3+W9Lfm2QQHeA7XY?xmhfN6+Y~m-^?bYvA%n{ zvZiAuqep@KmDua{F4@S5$jxF8wD1`nFJWLnoHamjCG;|lO_p*~f33*wf3^}b>Tfr+Tl(e#=?0w|d z&r5IHi5d#J9hn}yQjR^;8Jl5@*iscJl|V4ttEk(qOMYjZ{A}5_Wv@5y65eVX$a9seY5SHOkv8J+;T}FlUE{@zpwUq_&H_&^%(=E}=_r zNVRm@i_J5*vLL+RK*m_I*# z$qjo^V&B^M!>#X+!8d`D&9l4B!U8yAQe!_mV>65qTS5XQ3<$PM(-6A&KtY)mGQsUD~8m)MvrAl+)*cVAAq zA}jy!-Vd4n!?kf9#r%#+ipDdMlN0S)F>a1=u+wHKxcky=u&yK!_FJsAr|RI>HxDBH zy?@)jnswij0Y_=$cm>{yv2W$i3lN=E`p5g=rc0Tz0^$bwf1Iv6V>65qTf&1RB@n6p z{QZR^I+b~sr%Alrx@1GtY(4%BPRy1@Cap4!%be1GCOT{__POoX5H(w4nmD-1GK8cR zm+W--aX4oUs|kh%K>!5)T9)?-lHNaO>~~J@LllOrN(O;Fv7gO-xEru3dsX zr6dRbR(x6C>3;6>GY0)%+KG!FtPUAQDaG}}K&2F)(9iA9<#Rv1KCfi{PJHc?D<53v zAg2^JN9-x(_{W|d`3=*>7S+`=Po8o@puUJ*#2K4mjM&l?B$a^39X{Kx>-C14Y4r1a zecK<}pIqnv6OvLO%L|--vcWfx^6nN!Y#x1S2;V&F^z8tA^C-jWxD)xCe(Hz>KP#7W z42-ui=vmY%`4~B^P^lR_BHB4_9#YWFqYf!ajaDy%4pyls&CZyqC?l8>moV#V8{xF# zksAUe`RrH;`t?$ zc1uolVllTcGK;BW+;if&QJbO4BcY?~os=ay!)Aad3Jf6!mbhG8!p39@**ECsDVi4*zkhMYW*8&3ga=AU5S;L! zeOm2HrB^y^>mBDOJ^gv<;_{i0$_dioCGGr2t^%*Cll;G}ao!>K^0KAHe_{K{_fzV< zkyFah?lZah!Onklqxb6T>8})AdRV_yu{`&jT>Wm^ulYGSJ~&c}Km7bhH=lb64k2fj zFP7Y@=etrPHM7CAF+_5fGd9B*v85?UDglvGoTt_N_`OanegEQEp81FWZ3$u31*a6~ z$S*M~^||hc!$65q zTdD%35(rjY@sYpJ>WxkJ6r*!#&$c@=->|z2PAkyUtBE-;MeA2FyvZwa`RO`yj(hLo zrTS&Q%`N{|x6vrircVJStqkpsG<_R1!MxBWuS<#Ko6bAWGG6}hRLZOf;$o8j8O5D5 z3puR>C%_vtC~2ip*N|r;m#fJ8b#E`M7H=s2cRu`zGd9B*v85_VIsuW}KD^6~QTeRT z_s~|aA?Ovy=G(_ooLJ1wjZJ@?c8QZ&HeYJ_dnYNCmU(WQ5^5&lN=0s=mWYlM(y2RW zsmL%p#wqG$o$7@{iUI2VYP;J`ElC(nMWATFw*H?$vp6&uk%}Jtm9+Hy+i_)X!oH7d zw>G!v&X|IHF^5|yV*Ni#Dq8>a^(QwozLmirerP|IfAT5$&CH9=*bHODmfk=Phu~>* zsv6cUDymyJ?O5vjdHqrh?;CTF(+X?$TzDs&$n)|aO*AX1nU}TY@j{s+Y}xg$5(U$> zP|^y`=CJ88`is<(p+oKD7G4icD-Khv7&^0URW3>_>nNI>?8a%qDxsVtja=d&rIqkY zNVU_s3sYvy&sw3t`lq-}U18_B?TI&*Ib$=75nHN)q!SS7@Kf3N?)mzo{jxvrPv9xt zd0YN`Eodb#Y_EuZuo8T)i0kou_+Am$>(TJNBChfu;d@17XEeh1iiq9ZuGjD~{@3g& zg8NhM-gPWy$k_NMw+|)Vz-ubE$knjDB7S+yAg3`fxO|F*U4}@(xuLXMctz)~H*y)n z*y+AUnEkt&&)$wrmOH(6o?H@TiJWetxZpJvO1eqWIdf!f*8zdKo}P2X%02iMe=ncm zjLk4cY$*&9Egx5?1p6=ZQAmcQbQTzTxGI>WKqzvn5qf)5Ra9xtpk zfi+QVi`&P0CQU(+HK(Hg&FlEtEp-;9m>7a_?-s`gJy;}VoFeb6Xcj&m<&4cRMr^4B z67L{#^}8meZsWC2yjDz0wmqKfsUPgV!imMqz|7D=MMM1EVXJVC8+{wi1#CkLHI{XP zQ-vjDR@yCrYu@C|(I2P%vMZ8UX!T%0NB8WHyS!+bD%=uOpsO!wS0W6GRPmo}O|ZvO zu04SgMMn2OPF`59{YQ&%iICu)_bt2Xk;5bRxmqE2U0xPU|6Urx;*8BOMr`Q^lpY}X zlgpfw^R`sxyx;KKtUs!vcAZlQzq_03MJW94Znq?budLDsR)s(F3vsPl<*+kw z(v~f&PoShHIy7S4lB}Q`i=0I-K=1B$R#*hvFu)}P+pt(F3EMbwSRcA!5&sf~0c^zH z+ooLZr_<*Xb@-LWZ*hqomB*v^;7CtN)8UQS1ovk7$0zNj&s>?n)p(~jv}u?6nni}r z*bHODmhvEJ2~4v0r=4|HT<=^{JEd*cX=`hVVhtx2Gebl3{j1woF^PSX)rfJ7c%|>| z!Mf-AM9@+yCPTUrE8sq_g1%kDWZ-j3C9GseE@$e z)-9zAdIlKjS6B|qR_ww=P1`FmueOBW=Kr?F=Y=~$s=v$X!1brb~Uw*6I*J>c) z{`FSJ(fRMHaHNk+ex!QmeB_I2DK+=I62C57`15jhT*`r}H%zj&zVMj+726 zHm05nD=Ev{e$9IRa&c$ht3Skpov|6lh%Lo{lK_~w@m^kJvc{`gmV=>ROV2qRUFJFA zl@p7liHY%sN0QH`x*w|6V@)}`I_jv?%@hC6fJzYPHZ)?Ea=YbxXn7Uu-}&~0Q&#EW zJOBU3)y&%{la5lsP^WvG%LQG^Jz_dS9$U_KK9t$wnxOUh&%4bE?QgtJClF3JxdC(D zs$Q~+WqXu)aATBy+-bfC>m83dV>65qTM`4O88G2@@$TmhuOj}=Jejz5i`jp%@{O}{ zomh;`j7&rH*s^cGvAk?9lo=GzcQKFAcN63oZ0M{ZsSD-Y@->(FI$WN=SMK$lE}bdL z4<2x9$NFp>O+}!1aE%m^0?`aa->vPI?+hEmPf6lj;}P;{qORcT-(N~5N~>i~P5GZs zI2Gkj%ROrl%WwDX!;!nzE{{G-%xst~r|pc*Fh*?Y4dP%BSt6BCo>38eL2Q!SwI1$i z0dL&4Wr5ECGleukWYj^|2SOHDvRQp*W3q&70?-obnNYj;`f|YvN#ld!d(H?i>e%cd z%!869u=H%)3iF|Zu88q@x6!66gBx7WYgaPO3k5?t zSkH2s{B&Csc9r4r`Vf?hCx=bLrg*L>BzP%VyFx<4CURTTs=SoFJAMc6i!5qjzpj5k z;V+I4(E z?vV!7=pFa9)f$n%Hq3eXJ5E&6*sk>9gbj24;fVXvH%M_G>sxwdrGxO2#D~|8OQ$Y! z-n%TC!5N!jjM!2MDAplZUg}u?hZzl59=>fV-8OHTTUfrYw-bwzp^3?46{c0Iz6)QL zx#RVFC9{{w^?+}`L4&m9&KbLvgRTLB)K6kJw@)xK)e(5IZrU>GgZ5?bQW9@}o~e$b zPAb0-od_JQlNcDV-5!WiCw00$Oehw6d2`cri+dl!{yorW`GRu3PlX-4PC`jhHcY$L ze!lioRO^-LZ2k{AM-P^-i*&|j7$df{2T4sJ^4bFR>%UeQ+?0Qos4)Aw-3rb`hk7R# z3o~Q0ZOTucEZthPzB3@dEB9>cWBclcoyaX1mzpLvCNoG1ajO!Cw_wD6vP_H73SOGq zbjtmSR;BaYxyhMdx%5y{3zoqZw<<$u3&xd#(fjk9u(zIS?-lm*=vG-PJ2Xh zwq{J6;8C3Hja>d9rIxB3r1B>-$7%ObHNDi7ryESnxO{Zv%Tt#)V>65qTelMsv*F341)f1?OQy0O5p+;`^WoR& zX?%swoLCHF#FpA1=?6sm%9rN{FIwAB{HB%X#7F*!iJyZaKogBdCjW0=;?xSM^wqVj z5lKuv5XAo`;vJ;Kfehg~uajb9GP493!r)*j!Nz0>8Rm7X>*O}{dVOuPw(!%oheDS` znm$K9-nn=1rxv%m#n5R)Z0DXLrlkikwb;ckHe9M-a`e;WV6LSRKVGm|s-vvx$6n&p z-8-}Uo#fxRc^WNjHeT_ONT$xHVi92Zu2Ov1hxGu-?|3 zS=O+jyxy{sK|kD0V!OOd^400crA(t3yj_D-Q`Oze*EH*$(ju_L_VCG$OHZ#`Iav7X zJ7Y795nBp_cn3so&q$xurx;aklP>17w z4JxuARSXQSo2=v@ER-Qz@xRYMEbH{Wv*pTavBT~MXDj^)xzWRa%VUi3Z}1i#%35JwiE+#2#EAN&9$`kcy9jEh)kc(<);@qF-S|j!?_7(0?jiBp+H|J* zF*2kmfGlBPU_fkbb{p(RCA&&tYmZccFmeKE z&%#!xw0bTze5Y6z5V~M$n)rnaE?wehui6}R#%35Jwxk4&H3kNTx~k9@K|F$!|KC{5 zTFZT)zWI=jKe$eTj?xNytt9olu+EGbzB!X7{QUp?$DLD?L(F;fPNCd4<~Cd^l}=~q zC@m%Dg^^I0u(a*jSoe2&!||C!bWY2(_Bgr7`LB+1SXi~9pAhd` z%?lTuu^GmQEma}Xig3HQJI}l1nmfIJ)%RbUUH&Aun+IHG7((WM7{p@Pm@FViBScMb;8SO8hB0DGF^F_9$@k4p z`Re#$&7CHVmm_61?fbG|CnOy};$GkjKfH0_=H+(0^S@S;xWbLIUEQ3!uSM#gtC^;T zk`9JWe}o=&M{hZ_aY1mL^_#fPib)yI%QTlhQ|Z3{%W|d2qddhNAdn#GC5 z*vQmC?8NE)&Od^eJ_!lA{&?^Gq<88*3y^CSQco;(>#ujTGf(_={2w!ifbH+HYiTp? z6zzIHEK^bcOlYlwII)zB76|dF=yYZ3%Gs*lFHhLGGv)KGB7qOlrZUK>sQ(SN7D)HJ zK9lB(`z76F3Ae>(@wQL!l~VFQ;f&2NMr`Q~k&1pz{Qg$Iz>~9Q?MelftX;$i z8S{WFomQJ34_`Wsdu{Bhkb-GVtITIiJ+oS@()bbwU*;A=vXaNdqXWG*7Jnf_@8mJ< zkfS2^e|e*HmffO)$5;a|v`p$jP9BrEu_q74Gaqf^Y=o2#yL>&}HF;J0$v3v~&e#lN z#Fmf{$>Z6%o!aVWmK8jZTTpvU*4oS;4V31VyDk`?f+fv6{FhYFY7YUc32*mSh+M{Lc3f69EHHBb`Kc67~Dme-p3XF#LQyMopocbN}z1H*qAQDFN^~ zp6+=zvm#S}U2T{kzU*PsKG_Xi`s)sSbjD^FBevv*NJQR!h3q{mcWw?}^`q|SeMO-w zGM3Qc5Xi{8@{0RxOy-c*i|g_YQIehg0;P5Pu9j^rJN01E^76G76~w0lw`rQNEutjf z#XijE`d%zv=;(QuulBOY;wz7q&rEK9|LrP{bTBOfDIKhMl+97{`%_}5!wRE!oO7PH z8b{1=#%35JwiJU%2hIVE&oY~jl^Y5&_6zlkhjq-h@&nJtm_bH8kndub3cAk5WC5vz zY>!4(SijBE%GvW(Hp|pJcuBCf%!Mx0^(T1ChCz@fW*9twi1{(nx4C_yl*B?$g zzHP=Ok6mn&-h?f&SLS`zi6c$SK+OMk&s(E-sc+J~*Iy+V)aSXfFA-XvVKBoPn_-OD zQV$|cFr2%nC3YceZT`julP|TLoiAp4ah?;4k%^&+@+HwddjzNCPn@H|EqDF2puUI7 z2ILBcnEPSeX1T)lo;#?|_FDG!#-dG3rd?lUv;wAXEcY;OEJG<+X2ruQ82rO%qpcLw zWsraO>|FFTKA^9ozUNNsl!Hg?-L@@6PDHad!dodQi72+@_-Dn-TJ2|IuBomTh-S^u zd@<7*n_-ODk{cosmDX8Jn{YBQCal}4w8%*KN<+cixwr}z+3oqr14F_kZPQNe)V7PI ztWGROhDJvFS596Y?|5x`Wm(#N>$4>y(V4qj!Cf9x$kHSJe9%H_$e@}_;e9qH3kchS z)0>US0;0xk-n``2)$itrw`xDtIrH#_xlEz@H1p-dJmt*WAqELx(l1>nVL7Zt(*wDm zJ8zi8uPsW@eZSQDssx7)j?!e_f25Qnp}_g!f}^0)WA4e7TZ|Ny#Xrt5cE)BHBepaK z@fe7_Rp~yf&aJiGS~2b8o}IFg0p>`RM<@YCEo1aUx(}dpb58sH zy3iS$VT{<4Bsg_|3FdE_N}Kq;3UsnGIr=R+@KO2S4SCSMATx`9?ziS{PAqYlA;f!G zrS*#z-t+|=UjebalezYnY-%z5|4$oUM4gA`&4kGki}g{Ddd{&Dr?r`{+AYR^km`ojWS&# z!}!J-n_-OD(h@jvfQcrHXI!V09;LWGnO3mhzRAt5zDw1K#mv&g%=XyzH*=KMnbr43 zEj`!NcR%-0<1XaY*`(h7?zS|U4e9pxsSnil9G*ILA!pLx<$e#&O?%|paTrILv$Phr zIvc*;mZJXF@J>-XzLqz6$P|A}WiZ+CLRv5HlJKnaI8xNoJ4h)?TsJ05<=g?*UEkkk zYOi_uOFb{t!x@`ljM&m1I5B~Vcb``ObvpX%2y<3r@O)nWwQYK4f1Fq>Of1bm%)Gfy zRG6(hR`pGpL6l~`yh+$*aG3+W58Q3}R^eWcfdMX9^{S=+%9H*Yf|% zW!BJ_y{Eb#es;c+ZS9QBFh*=?37j~`nlc}%@x!`G_5W2+O3nVGpE zx24Xu`ws2zMFqmQT%G$$>q1SR52)b`-R5isy1l_1()zJyp9Q~d)AjCe_-&hRE3b#Q zFYaw>(s0>$Gw}3-l&dptCwp|D6fIOqIBqLHLbo|PzrP1P@5!}+7uK91^5Snd{1-b@ zGFL$Tgmbp?=|dNtQuYlcT82#BW=Gz?xxNND;jA*po^U>XwL3DYX%iRk>sCX-U&og@ z+%P)pjLk4cY)K59X28ToajwN~&oj!p^;SC`$)!YXsQ9HZiz*$+1INBQPBVwm-XAk~dwr z_V`&Jud9>FS8a9uhMW%8*kexz?aR*cZI|&0=r|;$5U}upt%c7iQ)g_3F=9(Gkl+T9 zsn7qu_kA=~c1envi1DWG=U%bvj)T*IAtdgRhx?f;Ma`{~z2c=VUly7UXqyq|Lh-BZm51)@%Q!+OdJeLKa(cX?!Z zw(gssv?fcaMC>u65WaBS=kY2MZLorQ3k z*fepOY|_!syMOI2p5Qj!`J(8`?Kh5GbH-*EBev87N(~S^!EXO&wF#gWxj}pXU>PmOU=FIZ1*0N-}&?J?-S-xzvrAoy?cW?$zw|vwBbqm z`8rrvL=OJsvAJcpx$S)4^|F`UZY})YXJh74wuNx=*s@{n&kwHiXLincect4#$>hq- zwr-Wcv~m(j$^e4*H|NqKZrG7TP-Je^!d9@qRfOxK(;N0 z?l^X%PP1e05jqM{3!24_?7+*$|OmrFZ&UOH9%2 z_O^w`H#-Ttbxe20W*8&3bOlN$5IlMB;ui`RdOXrp6PTxN6!aC$GJfyGVrgn*DX3?W zyyl!!@fOns*6a2N&EWQ6`vWRwVEg}^Hp;>F|GBcChVTD#+p!(C|IhBpe&&TI@?CpN z3lk3hV9UtVfLW8oDaoYjg|L3}&13E6^=z35R67Upm=DB-NQtI_yQJq<} zCoe^=zyDcds^|{F>1LhWB%cXe>i&ye4@J#|;E{{U*v!p_4`X9t~y4=GoOxkCZ%JdEss%Ysv7t5eFtj2o7| zd7as~!f_W$xHZC_p{$G_+%Z&Q7JlZbC2xOOsw44Am>RcB)| zhpd58@ik^+GKX}arQ7}g=FNYewe3fU(Y=+z@1s^lFAM%;Kbl%V0giO5&t6AqkO%_< z38Sym&e^lgy*|my-}^<#m5k%%-?{9UBbPFJYp|ylzfX*dQ$N2qJQKWVvM~GY-K(rj z(w(sx#)vIlL7WL9?dI&9G@D~j{m~BZtDNaZzHTcPJAemIOdux{Fuy2dW3q&-mvjA9 zJ%=H`XS(c;s*Ejj1k-=NT2a2Q%4jg81GoL5u*1$Dm_T>=4A@{QIq6{5_XX@n_MOqp z5%^jrp5OIj|MSnH$mw8z3-)yIsDy{b?!}{bpFAb+t>WRl`Z>xq-Wi)=jM!2PC^DnR^Vh{WEb4R<^Le;QZ_f<(Q=qm8bgbRsDCjUHNRQY>-WERAuET2t@AAmZ*fLR9@xg#NN>a*jD>c2T>eWy$J*TxV{5~)5u5r%VViw$ zoXHz?9@&oFLJWHh+E6b4LP{P77sDH|JH_^SOo;Y$n`aQwUCDEi`CP#2lsWFs*bHOD zmXIJx14RB!bhs8=9-yhCX%8qSja=r3!CcC7a;z?(0hB0DGRiIP?!9g)|wq$&r$`NgO<=;(* zFvYTShTY)f{h)WS2(U>NzjJPXHFIXr?N64sHVEf$=v2DWj}rG(ZhX2OT>&j8@XyH& z`D!GibLldM7uOE={N5bNRCK`Z*1DIwkmLU7X?Qh)68GNE;D>=Z-(gpG;tWbV)1@|oquDa++1UB0oBMJs$x>-J_EB%I^>pcTxB zNjM?x`L>}dn?eNUR$bs0Y+B>Lpidk*;hbQ>o^Z4lIBVy9-KDB?_WCiY*AE4~SXZxb z#%35Jwj>5hG7ud9ChG@t)??-9Ce_6g^%Q6AQ`aj2_f3o;rwTh9p3cT(0b$E+F<@h| zgfvFjcDzeS$*#1Nb-r&ryCB3?I^>qc(G3hJX@Y`Ahug`!u!-G)Z*Vi787M8-t?F=`bl_W#H*7_H5 z@75oed$${JEi4UYJy8?3ebYVUgm$J8UihFSw5B=!Q(`0@v7by_FyZ<-eTMlW87rKz z8ODe$NrI9X1T$66ezVSfx4Ol`MgPKNn|SNDX@3E?ZVe$x!X-N$e)OZ#>=5|TkIJ=6 zU`Ib1G~a|D{kW>s_1K41d6y3ynpGV>!|Hps_vu;J1W<~kp`B9BMTtNH&aEHs_I3Pg zj>zdIKR&0Yuh%FyaYFyL-jlNOZa0@sLYWynw;Fp&>HOK0%4hW_e#)hzKm7Ku*tbYX z$H^I+VT{<)6vVS2QuNa*gR^h8uL{xSXbjYqo>=yA3oob@!-QoohttxZxb|}7InTKI zck7fBAC@R+v#Hr{j+_3k6eWEOzbflO3;BCFi0}JU?qBmHsY8XudXnGzrrOiHd>MjK z_OBzQj|-=fs;u~FZ(n_W%4GgTOEuW|{z1m#&Sy8Au^GmQEhT|c1_X<}X1l#a_*th? z|0GfVO`G@gTZ{OBme`wHes6w%a_jDb3oBHf{+M*LRj*54@fNkJEVoNba8y|;=e*Nx z7e0*%b&R@OU18F?nWsJxC85!-AiA`V_Epxv6-3u`n5R3;0rML6f?&7PhJTloCn_-ODk|ZRNfynO86@{t)ru43T zm7MU|%Hopv=Swb5EQV$l7A{KXgr6!KOk)+VS|h-Cyi-$kN0KK4GaD0hL5r)vZul9r zjtklm3tF!7o(Q>q{a91mo#~S*{@ph_``jLe#_#vvZmN6`@mGYge1FX4pl!Ett4tCvsZ3-UlyPP|`~IlnZNS`G|Ne zyxO|eZNG+A_?%LCXKaQsVoOz!bOIvRrtms!cHo_T{|lq#+}}UKv@Wko12=I9Tu*2& z-GqES;pNY&Y-gGdwamWgm0G}WdEwOzPgj)mF__Ado9WQ&35P&gvSNCR8qW!_IqNFT zec9Ki?6ea;B!VM-++2rLmgvc^-<2lIQ_QHN8hi5?<7S1MQbEqx3}eKWl0Yc~f-uLT zjnd$5^2WBzU*+sH|2b<(uIpE=n>XIxG0de?a=N>b_D$Y_OHMD&hXqXdbB`@yMsqJO zW8QC;3!h#gC#QSr*ppMUP$Gk8>)Y8&dw*133^}|?aha=|Gd9B*u_ZiELW1C@8#+v8 zHE6fIY}_lRZc)1VRmN^UCl(`9ON-YZZbdcRk($A9>CC3J6&H^0TCuwjd8rhx&8cn= z7}%IhA4$#Da`ctGiQf16?eTxh=e*)R&$OCxaHRvcM?tW~FGDFEJlIfd|NSCg%`+{d7du+d zb0kgUJ&Ge8JZeNr2V0XIE2f30DMd)%3t)b^=T7uopBc{B3}eKWVn8VXg1Z+9U0%lS zqRJWSJN=F8+^fqQ-*iCI0c0M4okbCTV4TT=Jr|$++p}fbLib6Nf>j~Zo@lyScx3i zB>kZ9ifFnogOk`vtEtn@pqz;QYz6k@QN}#kYt4xZAI>kiTP&Lz;FcfF>+6ioFh*<% z36wA(SVwUkhvl8Mmo{79x0{q`jyDGvg(cn%IWR5ls6_M61y|I% z7a+HEkq_!|d(jAQ>B`v3!{;Mi3s%7ABb~Nig3m`v{WOLR?lSQ;!sjC$OlBVqe82MZ zkJ$MM>CHPQ8{Lxboqy{FNM(Kpgxjl)&T+Y}GW5kvuA&Cq`{#Fp^S@mF= zrO!I;QyZ>)Uzt52F$&Vfh784t5iwk+#J3fBxNhB@KrX>aB72_6H&jgXcTrT*&*eo) zE2D)H@xyhmULl6-SbBon#65!qRnJ>_r2pBHbm6ob%4W3Jw(vp;C9OzYU3b>O`{5ha zOp)E5JI{-kM`lGkV>65qTdD%35(q9Uwb#Cx%5wbU{#%}ZSCvTnb*O%av|S+U7L;a6 z!H;fo^Kz45J9&1tmU+RnrftU-ziupZ(BDKt@0jSe%W$cj-ipaUg4sDJ2X^T3H(l7F z$H?hGOe9Zu3m<>=e;jTNEJQE)U{?t&)nQe zDbCmoW5kwXAdUl(r5k^|3s^J3{`PI#=0A?j9oKRemN~JQ8=G2s8Eon6)%9Yp|tG(Z(u)pPRZ1L^x zL<67G&V|m{3}eKWmOyC(f}dB)d|SdTRHC37y25`?(zjDve@+CoZkb>M`{}RQn2aD3 zKZ+Sg*_ezWOYGRo1K|Vvt~b|m?|5!hF{}UA^IxSaYhU;-53t#^86|xTqHWD?A01!= z`&8N1Ow$dAUH5%;t1eIMPPBJa*j4i>MUi!lCE@h(vAyt5<-h5>XWp2kJxih4#?8tq zGU28(Hp3XPr6fq&0Fl%8`97?P5{*7K(df>hZnONnTd^0x>$c4yBV=|$49CvIBu36M zy2+8pKJ$=BeaUv|=eI|4+`D~FfR+suZZ>UwD}OFRI*ohX(GIT<+gPtCYfjlfIPO0; zd-nJ(yB)4vlIZmG^!>@lm3~d=KkkgpFh*>t1QhEK>?`bjph!{cobKn=TMwOu=Pvg< z@ZO2Z$Rw@n^o%)s7b&}Z{Jv{{t~QsU+3L&SG6TzcC%3OLxYj#Kwu|hUt65n*af*7A zx8aq*DM!WWHG(=&J(aH|^jPm?xcORTJEudgJcITT#+Nz5_P-;J;Yc@Mcf)%spPOfh zaJc<&ogrvtI;o~FI3_Z_zGbsBHp3XPr7%dE0g>F^H@$`SnoIaH=B3vEI=K38=b?*E zEanClmh-B3(`{w%`yCbB-&NNB@KVf~l1^}|1A01_+xIE()43!Te|A@qv($9uKApD7wVzpWV_usJyE8V!7_p@#P}+dt!ye0G_vmUEp4Rw& zGCjY=$vnOC=BogGjLnzny)3cUk`9=@-Z|H<+?kb=!L6aSYb%x$tF2g3lS@ z%Z^-@Im4G7NoEJZ$1z;mlW#b*O%=)${p~w3ccGKmpB`(!j3=XM1r*q1q?O;BpyL=0 zQ>-q!Ei$*}{H9`m*lOKvGo^&6YPr)m(#juJq_pxj++Mq2QIJyA8OGqr8;V|TY)lrAj*8aAl)&Do=Gxm~0XjPVuh#~j7fxokosE(_i0z#Gy$8J*%sC_jT8+5e zD243>qRMF~^yr*Wt$|wj>hw}yu0<1AWTY)AL($rr%M1KJP;UvX^) z+2x~>EDmpox=x$~zeK^c<6F@S<*I82myR*Lz57)|tNz5#i^2&g>0{UpgS!3y3u}lr zz)s6?qyFH=xs(ITgjP-y;^Yxuaa^lcGd_v+D^mJ!XK;ZJZXgvO|5Su0-Fzat>8xSA z`!{1z)p=K!t&zRqjLk4cY$*wpG9b9a_rHYwkK~rpy*k~obKhx~E_|W~I%nF@VxyCe zjJNTY&8s_DuLb{P+IM-W*-~&r)DTjFxHHMZ2S{0jzw~a;GhFO^JI(A?^|e(;_&Wpm z-=g09G+Kf%xPJZ*ZH%}xnL`Ii30{u=&~#Q#RQ)ycz_`S{_cv&jzG4ZVPcVhJGo@*L zQF2+hJLciJzt@!VB2GBg9cZ}hjLk4cY-tISIzZ&yav{00KHi+!V)Kv2t-s5=-rw^m zxCAkT3~vaoZGfG&<<_tre%hApg-Y0ITgHFVt|WYlS?IT8GaI)a)0HE$t}l6)xoo7A zAMPyn;-G+JV4y+yarsV5#EI8cV&|8>>R{kWF4!kC7kNL0I}76c6GZvp&Xl&;_{XAU z#xfpjt}9GB(pbBAf*Ik z35azB=xiiNiNRbcddYC7_ut32cHL>nzFa7=s`;=&Qq(&`>|_vfDS=1_?rc4;Mf5<(9V){>vj z#t3PUy6GNgV={(J$V%*+$i`#}Sv<%I+V*D-Sqts7W<48|1!PE_H>#B5TP|P1`xDb5 z^>w(bw~7H$5ppS#zN;Kw%iWg z!e{i!b8D2HH*)92o#PO!^?{mdWaT1+w@t4us*kSi?AyGTWzur_`Oer3W5kxeAb|%W zUH51ukv@PZgOI=Ff=pG<+xS3-9mENjiG$ z?QHHd2Nu8IV#~|FLF5VVne9$2h88ASS~sILcncz${Qhv<%SmX*LgB+9^}u!MOQ(^UkwBFYHN+C^dNa@sl$)!x*upFi?tt;H1VwmG^47!&kq&X?x() zyH8c0vZf;!L&!&}AaB;;srQF3VZ?Q$3hvE1-i!~IvCdgiUVM1T@2+$DQH7G6 zXf__>E*J+bhTI3dMMQ)8j?r}g((Z%1vrc{2eXMu>!%W@%e~^d%-370}>pPU>bbj81 zOv{DeUmeb8w_H&9y0n|etj`&nVT{-k9waG&$i1tXwyL%A@O@4CZ=qFdsO))6@Uj!L znUUqE*PQXu->etb?Y?~Ye3_3%oz;c?$lY+Qu8Xj4xV!LLcsJbf+yYoP+>z71X@B7J z$KQ7+y;WO&KXmfs0RH{@ekjRi7}s9z!pC6UaPF(nW)jtEuQ{t`&ig2G>ea>x>$JXo z`0K|Jzs(c5_CiWFBHZxWi@#M@;(KJxm#E7r!Yz}YnB9t6eNpt8Gd9B*u_Z82f`Q=O zRZAD7KE2uSCND0elGP$$X2Z_MPAn!yCgxcjmm4p;u3XOEt@-Zl!Nk3X798dWryCLm zfZau(eA9d!dExu*br&{WzqRuJR9ojfP7jonGwcc+chP^)0boQIj0Ocx-Ny;1>>}L{ z7;l=={P3N)eEH!iGm%q{7<~PsJ4(t~C$(;Kz?v_yY%A)dM7dJGmWSC;2fL zf40h*{>S&abC&s`7_o@&i@y$~G~q5G2fdTq4ciTISi0qON)yjqiVh_CG8_ndI7g>J zZ$g7y>Xa|YX+k0rUJ0S3iMuYLzR?x#{c4wjJ`{);yDZmyqv?#zFh*>t2b3BhSU;Fm z^ufL@6J4FIhToXpHADVF@mt9JGbBwo$U5eKBedrdU0cMktI*_Zd8S76?h z+N0rft^D?0yLJ{wN|99Tw7w5JSD-Wf7%m=fMpAvu^GmQElojE35Z-1 zkQO7Ow0+N`fA^NY&pmLRL+M&F=n_gZ<9ADTBn4~xmo;qvFTZx-UCHUY{H{aN5M^V8CyEbz(ln7ZJ*4!hJ@u^YqY;zDR~lTWVi1T zjzlDL0x1#MTtBw4d)gMOm{0{S$*0S5SDjxr&l#IxjM$PJB&tB9S823Qv_oRrEv<5% z;4SkKKiJ8fb7Cdq=m>*BQ=s8h4|R6OlYGyv{;NMBNEC`l0a$)fk@!Ctfqm&=F<$ zKF=AOVT{<48z}ieaIuldnx7dro$KDEXswko+_AW}YK9YwrJA6>wW5F$8*!uk^F7WmHu3Mbo>-U+x6yWRk-4&kQdy^)3?8{8=uXoRV-JsQ| zx@GRor-L=+xGOU7LxRQisyp0Ar4RRCa70N?w5zjJy-6JG8&V|?&)-Yh;mFXr z(s|#Csq}f26N{OVk->^(8>=b{7uBu^nwD&=7&P_YU9VfUXa0v53KMJOGHrfe-T4eWS#ApHue)oW zU}G|aEVD3wxA)>q`&sgHcWG$lPkgsx+T`b@e?Fp~e=uZHh`Z(^AxPl3#qkM4SvB#n z-Z+-~cd_k6#J1R%tQ7KfQS5RrR(VHJq?L3cs#GpI&@b9>Q&}-nTB6EU+?`Q$vW91bHgLaec+ZZmbKt~ zhYE451%EGU(z$Z6rSg|o0Xrv^@AK8)$T`)Iks(C^WCa5Q1F;2&yY?$qh?ap`3qHt_ z$Ga7&g-3i=O!!~V<2*ml@W}+BdBuba5FG<=rnnogeq0gGbY5I`#N^8s{n)~MXKaQs zVoOMnC;*WnSHoAbW-R&AkYK7*pyzw5A<@^<2?7A{b=fepT35tri4fN#A-RMU3msMg}4uRgT!4=8G4}C zkZO>qcZ4;bO82%sy5pMeGHd5RyV_rp$SFiG2wQ_h$6(IWOmW8GM=f5Cv%*>8v%eV5 z6OMAmW*8&3v;;~U5Ue=I$EvYL<#}(1^AQitrocnGi&Stef-pW9O6npAdpEDWCJcXn zNJ(0&#I7x!w(`r75ae`&RI(Uo<5>hTTCy-OxaB*;HX)@XHEz4UB0WY^;D*xcN8PiU z%1XC?M&4!Ojy>HNbUpcgs#Add*q2qZI}fS-PjwWGX_ausW*8&36b4B%AX09D&D_gV zT0QPCXKgWNof@-9aON>5787%G!&lmy3+x|uTZaC>>aV`d$nd-7ejns2Nu~Z2e0!3q z!yQ9lHS?c|MEa-xTiuuEdtfhe!f_|EL+x%<3$2ofT{b+- zhkgYT>ZTpMo){zWttGheC|^{%Y(DY{g2)NS=rFuPZP2xgS>RT`%9|fK>Yuz`^P6xz zxRSHn8Jl5@*pe71$w2VrynlkSEf1WgZn(*)QSiu0>&hfmaPokS%^{twA^83sd~6Qw zY>ka(Yzt5Sbu1KovEb>m$%}jpY)<|}P9KA*U~xB@109=l!*aI9AZxN*k6&1>drXyW zwa{fg|3>A%CcFIp;;4|2(uc`o<#p<_Z@k?&Lv8({E_ba!<)ikyMVzr2#)vH?LDB|@ z6nUl1;+ofEy-G}otW(U!;!BnSHZ?O#ryd#P}a@`&1;es9fYFqryk`XKgi= zXHgEJbT`{W)Y#l;QNqCBhCDVG|F`qg<|dC#n?*hyUV30!Y;E$Z^*EA>IUl?zF?pQX z=&D&uB%hPG}Mct7!rGd9B*u_Y={B7tBdRe|@#YvvsLb5x#9G@w`I-iEwe zpq*^yMt2|ZIe)d5?>@mdCE@KxZq98|y30YW8tC2x*MARTdlMJ~B;b1!+%2BN_a->p zUe3k@-J76%(+0jb!QgcETJ@B=`yT1Huf1R>5Ghs&;5QZ7O7Eh_-I5WyH^Egu8@4yW z$Q*jJvs-sQtSvm0ik^Qr?_XW`bBk8d(M#(e9u&Ico}?u^GmQE#*Pd5{NvIb>wOF)~bp2YO+Te>sk?hgW2_gWcl zV`DOfPHY!9voTpf7YaX>(`2%`r^)eZblPYm1Ux(aUWfPRu6embxyNU%a;3yQ^RL^8Jjn zj_Vq>yz@d{UBy?@247ue^>!(Ib(Onq@;C9usvGfp(oQ$+7mv+QO~^LBymKfOEbg{7 z(A8CgtW8r{^qrfdr{Umz%@wZ?Ur9c*fGr03dI#h-FH&N$-F_-VGVk)n5m zI@fDft#p`bxMac+$!_G-BGDNGPc82D6X2=E_Gn~G<*myG2MSlr64|6XsVv2F<&~?R z$f;$p7cK7gtDvdHiG3MtOt!X6c_1%|UV9`Q@k*?l%*PJXn-*dc}>x|7XMr^4E9Nl2T>6tyZ0L$*irXX8EHNVySPo-STabhts zwJu zNF$XRlQeEATX8c^a8UfeyTI^D;f1t$vCh~GW5kx0AOQ~|mp$gzW3BtH5Pz>dm;2E- z=T#*KPCKy}8Jn0TY5AXhd@LoobGM$V)cH1fqwBH%k(V&Ip8g46!eBpl8~n(1i)&f% z{YtLJ+u_?L#kju1k6d?}Rs=h8-SyQqHrN%=?yg@d6KpRUnzCzjv3)Mn4!9G!;j=XA zF?EP3M=Fo}y1VhgmM~DzOB%F|nd-VD==a$babn^m2YhfVU~z3l!!bbSp@>&;xiHh<6XP9N@G z?a+-#G+n%~WzsE^!@ERpzIAwho<}@K^}Hbm58;x;>zqzq{|(QxUNf&KNW7G0)Df7p z>lueLHp3XPr6f?wfMD|*)0Lm!^y}AAwC4;cGW&fz%wU=mi=nZxLEhe#mAkq8xBu@t zIN3gTAOAAjq!q|z46f}c?mo+5WsEDzb`+I3B_pm)H?L3 zG^mz0Z^JV>1fx5V`{Y*TuPArC&78cn{ zomytQ^roZ*Z`g0jpt&3*|m+YO#-e%bfo4~r3UdZJ66 z<I6G>>V4LsR^*NtHW2 z{HC3_b^B(_LT6`ehB0DGd7zX8!A#fE)<-z6d04+WkuBmyPr{*9Y&A|S#wM1ASM)Vn z%gfImP5)W;`%|IqnW_S_i{Ory31q*LvqA?OlO?1LIml$)nYIbh2X#MMqBRK_MMoLaPy}U9H+MC;DS(AMZ))$8d ztU0~e8Jl5@*b*KnAwh6OQJg_d^_~ck_ASfWca%R-$Z=oo#A0r4X4WfOuubR6%aw0@ z4B{5QxV&|#+q)!i^BH;!qkHHY*!d5*k73LTm^8VlcXw;`b_cENF$POTr>{lnTn+1m zd!exNAMo$uCu>AdUt;YQ!A*%lXLigLT`*&sa9#KtF>~?Kf^~ z@jg;kQsQ5q`g!@{MrUk>F=9($kTe4#xpr?1lk$lCJAKtnIc+bwole;rJDgZ7%`A;h z3aCFcT3&F*grV+Y`z1};CB+gp$OROxEi3NfPv8X<>F3k9mmB?Tj9IE3&!qKx?cMKA zdVQ6{56EXhrVR7{A?`&hvf!yQeWT3QQNw>p(e=EusW_ zLgNXm+U2|S-wKBRF+VrlSbA`_?t(|o*bHODmLx$*41(p#x)h7-f*F-m_!mj;|8dwX z-eD7{mu6}7CVQplwB$BF`vUgVxD$VVbFcA-Om!MTTR~C2Y)mGQd2xp3m26CAkd5Fr zUxb%UXJT$TK4leOgjMCN;>>dst~l_Zq!!u@Lu0AV+@sQ=Ybb_%b+*jy)$7L|6JEY= z>8*eC@$=bR=3)Dgt23n36151aI=g?2FZOBeq`MaKGMo&m*EHPYcd z5ZNkm^UnE=%Xy-MKW|}{`u$2H_rn_}7E^O`^L2-(KIi%UiuLKgi|@6S?o4qwwB-i) zdJAJykVXdgnCg>DFaCJ7RrA)`g|W9g`yJB48h6mEmrk=(;T|&;Hl;amZDxJrnvHcO z)e2#4M$#|arfIJcl+ePFDq?mZrHZM)y$>qC+xk?OM>{tz;2yL2sdXEju^GmQE&YI_ z6->-LJbQP0UtR;-gW31qEnwZY)B7+JIPRerW*I7^_vQ01+Zj7Wc*f~o;VT#Tld~3E zunzSSfs(j)kDEyT)h5WR^gfs$v9oSDk{GQNHbee{;~@)ut}+~PAGZZ5?)#3L+z>ea zK1BMF;IhABCH@o5Hhp)-W*8&3R0586FtO)S(e40MO;uSH^=6M|*YArrf4&2bdrQc4 zw$MrCVkynqrmA~}3a{VJd3`~}^?pGE>S@1Jo-1-s=;Z{vjR9!}U^tGZaL(S&S-e-( zszQ!E)#GsAA8wa}7YWCG!iFjDQk$7_ndj@W-h9@-+%w|(&dD#Gu^GmQEtNom7DR?# z2k>|A$&!Yf*8be`r0SR6EvI7-N`oU5{L?j^u^GmQElGls7zCf^=3f2B zo$>c3S_DsMJ@MLBYjhJ!VTK6H9CbXEb|srN&)5B=co>k}>=1)h(7t=aKTCHI5gmz-YY zRFl2~-iJm>H8U=p4&1|j)oqrxZQA(_tCo5xIec}-W*8&3^aV;U5L^%|GNE7G@NvT4 z!$1FhbC8*BYnAH6Vr*b(A@+2WhSZDBjrWAFn0%{vpu8?$Y8xm$!49D|f43KY2(^3W zMEL$ow+9UHL#UlwR>BXVc3YYZKZIIyvE$)iu`WVi&J~)Ar|`^4(w&f4`x15d58lsq z&s+`Nf9bYuG4v2>#0hGMy)Q)1dk*h%$eHU@*8yGy%_bYtY_C`2kGmH^i+JmGf5ILnPb>04hpSfpE^SQLa^OQF4 z`$xOLGvv^{3c_A1*_ccq<1l)Ux3V#rKziBYd$+>(Dll;b!1pRR>6=w`)UTfyc0T_8 zhuHU9tWR~#p8GFxI5v*lvmZnED$r?8Q!Yl)K6-)3?3LdGuW6|-6E7>tKSMaJ65qTdD%35(xfp`D?=dRejO#rKUR=3rTfMyK+&% zlZbm0ST9S$2ZY^8ZUQAe+jRG^z^dO@X1X8Q?m98!5}$_{a&kg6fv8^e{Fk7d<&|5Sj6MH zRM^aGdvl@|pRoNS>#>EY%N`{i&|_j?NH=QS3*zKJ0nfnT_UaY%2mqH7NweEqHXixl zbU#i&|F6)$#Il)U73Y!DK|wFPQG=2W{%iPN?tQ_0`MTG-Ec-375trut33SG07$de6 z191q5+-8$i(0}`+=%>2mdiia89OZv81UWHVni?$Pw3ghne*2d#+qD9XWS51m5@zWJ zOfwVEW7p1W=nM0-mT;y%pm@FYn{d9PZ*qAIKX-Jme$z0-jeKVuxW8J;k0X;Xa zo_+HwS?5gpzqk5qmLZo&{$#zgyp_i%*z%;%<3uEJzum`-lk*(MI!f?#Gccg2!OuWZe`!odxpM|f8}Iv921Hn_EF2x*}rujh0xD~GQc z$GM*KiE@zt`yYY~oKKdQS23_YtQF>$8b)cTY$A#4If(EqY4iec0_1%UZwL zC*6W1mx%2Yxx~DI< zTBD?cA=9{Uuhzo(-7U3p?f#VuY}TDZ zP6rjQ;EfBEbg-?BwUImPLT%=Yfd02`|4lo?#r8O3GmH^iih+0=M4pp5x_H4IofqdD zPTT$WZkj&r-PKLtbYKMO#|q!+M7|C1uJelXM`vC>U{m-YkG1Vj*}sZss3*mbjC4?S z7<$c(>#hf|*~1?zr9c77Kw#q|j&$H(TQwu~w&UI#=M-n{7cB{Nl6QTAoDQl!VNVC* zBCj)?I8Mw_*(H3PKabItX z6!(j-TgAxF^-26Ot$BKai1YlHxvTy=V>65qTPlG#7(_Drd7jJuFUz3GyeV8sJbUhg zN%xYRSS$?;OuTk?`<;DfKoc{Jkbw&dCi+ywSm&}j7O?NPF`M{OVom-$ z#nA2ELXIe93_Y4F%`Q}!=%c9FO8w?a@XO2dRQ!wEPR~m_$Z|cS`1q5bZpdX!^FnxY z1trz2FlJc&r+s?uhq<>m_{M(!@jh>DuQN8o7_p@=7`(pdo_a7+D$o+AL@5c*g zY=$vnOJAV$0>K*;jGDGQTYB!@mX}-SzS8Ku>iX@86N{mdg^|qSSyq=eD;sdkcWkI$ zwYlKE+chnsYNqxLrJE9hzv#r6rCRGru)meu?QALi9woJ4tC`wQjn+(rhS}cR*Cj1j zVBN)$mRsk+x-nvdLEu~*silJzsb<dy{0tgDV;*KsT_N7@p>1+Vj@`LhQfCGtaPUW`A8Yv)&NW zX@-odyLaA$&&=4BzIo2Du^{_V;Ump6lRM`wopI^P&Bw;bDP*{;hNIntuY2bY*g!1u z;mr4P`FpoaXP5i%I<0bsfLY3$RgZrWP9a_D5dogri@sY~6gPjcYdw^lks_t?${Cws zjM&l=C~ZKnvs@U1h+RYO%7il_?_a(V`g-h}o)e3yv6;c1EgNp0S?q1SEXyuZSLd87 zk7iIht`y?l!=QYq!+Wa0o^~II3KGmoAq)ug@6LtHBtoH7jnmYvxs|-6t)y{ z`_iUc?_Qg~lgTK}vSVyjk9)QnWex_Z#z87WdOVj)6uaB&$a()r+ai9iOJ)_=ZD#uJScjUB z#@n*ZPIHla$nJeg8nPPok!iQJ%MK5!hz--G_6{(q}`R9qS4W4dZlTHa9TQ^GkFrsoe2k+NtoW|Naas z76?sd05?ORR|dOJu)uXp;rr*IPKyq1(^>K>1>{~aDuiDg0{#xaFRD`80= zN~2a{`C?Q#n<+@>UeJxdanI)*S?zjqvNn#yGNA`4vBdkjv_1N6qNU5}P`XT3 zlT)0r8ODe$S%H!X1V7>1Y{9Ik!Cx!@eqEWerXZul%e=b_{9S$@~M zzu~j|ZY!^|N33&6DSslh@}h}`U_j-m=7t_#l;lB`p0N9*ROl?f+tC%US$@Ql*WuWw zvF8dAYrmfH?plZBPis+G&8xZc%aN1Eq}A{~4NCHenw{-$r~Tn-qMF(pHHnT0$5&N1 zoUs|kh%F&Ok_L#3I@)J3WwNizGo_u*c1c1R&)B)eomfmP3@k->w>OD0tY0T|Y3i&g zztyKEaaFGaB^)N`zILsyi?Ds|?!s%?n9Pkp<}tWWX<=i8jKMi_+W%SHvnR}cL(9Jv zCYIj|-YP`CDBXpUZU%erhLU1s$~>%ecFt}~Wf|ex%wY!Ig{Tb}7)y$;{EJZU|a$OW(-xiMv zi(YTYbC+I~u!*1}}|H=W{xQnnA@ zT51(YOt`nG!RTuUj)XJQ0A83(`yR@!^+Y_LMM7qRWB8q{v}WZTy}QoX3}eKW#6U>~ zg6HWqU7oyyRY9`m_0HEk5B?f|*mM?j-KMGe{~JPL%Rlh^dU(`_(PT~N%KInNAyYok zV#fIn6C0BSq?mD^%?U4N7$&#xn8_M5*ZWob+aEP+cwfEy@@!*j6iRBLpvmGsTNzr+ zjKC(#=RNB=TLRV?ckf||`mcCGrErc-GIDB}9S3i+prn>mV_v&O{QqVgT63-2bh+Vj z5w~?c&e#lN#FnlgDFsB{v^CHAV&F388CR)P#^GZp!g+$vgS)cf<3^_drtSD?_~I34%-#wVnvCZ`I;GIOJfB&RR?{Ak&hwF@_Rt$k8-#LTL=#u=MojM$PSB$0v0u8#|Iw=S2; zeP|VKvwh9kRkux)qCt218W?)3B?iyZUKlmIyfSssiX&H>KRhvjERuz^aMeQY!EdE^ zIkuaP$rQ2_PU_AlHYPI&+g)xU{N}5LbF4j-Ib&b*$K7zw)v9jhi+pYQ<{L^PTDT2% z^VP2Ru-$)!`OqmKw~QqqX~h>`BMM$iJ~~<*2@wZ>}lf93V|mxy8RPt zANIQLP=BeJ9&5C~8Jl5@*isM3;Sj9ZqHQW}6qKkxcf-Bb0Q-4iC1MLeT_GmuY1{ny zKJe4F-M+@aPun(mtjfk@0U20vn>TNN;Nwp$70-pMHzyx_bJD4%efd6al=MNJft5kj z7jj?v6?)pXJ1qxR&Oe;7yYI!e3*0$ND%+Q{`OB=C-h?B4EVF_4h2};re1B|~@prEa zhSs5scb$%x8lKtr&Ka9wjM!2VByE65<28{7o_;;}_N66j(Vpy}&IkK1>_VRUlaT!h zpB#2+7A`&eCC&P+m4kAUf|l;qefnQ?6rZ7_gVDN!!5x1&u|gC!^@qG|Z^!%3?3o=W z%xqr#ozt@O)5136ARFX#u)+miPN1ZN6tT(tpCuR@85G@BSzd5$Q{r{;a>iyDBeoO+ zN&yi3>Av~#XC>@wj4bxNd-G4={jG_!#URZLNEsj|W6s881gS^dLM_>tj3MV6v)wz% z#$*CfBV-xI#$*QB;wf_Z>8ksV;fxbDt`c0```P{H5aF!S=YG)WpM#gs#&uPsitB2wcpJ_o|mma zUf)xA(yMIW)9VtPu^GmQEqy^!42b-;bK98CEM9oD}HNT{PI0#e|o6P z@f8FU%eooRt_-mUnYiO^mJG|pqMXTOY`@b{$Nzy`j%J|NOs+o`Cd{J+D3aO|dn?~I?tbt!NMAW9yyQK*WR=k=J zY1r%L+w*qg+?q+Ba9qafo(Ve)$9?Fep$*3{HjUD$z)^c5JK6Q1%xjJKsX`~;PkM5< zFzgnNYHFi6Qh~E>)3K!$x}5*S{1w^WrytyIGyTCkXKaQsVoPn1^aCP|v?_hwTAFwA zDLt5}ysn-5)p~{kCl(_M6XTg38+3j&eMo&fM>Es5uzA6Ak5g*k5(l<$Wzz>-3s*u; zeR}Ejk|FzxVa4uKb{ziottqdDREe{h3*W+(flDnix7hdVHEviFvCMaY>_nxwHuu++ zI8w`ISESTpC#55`az)gN*&m*)tMp%$DDKiwu1RpV{k{=5YnJkn;y@`WCU4sAa){#jS(`m<{B%(#$*8*isSzLJ}dVLzo63T z_p@7%T+c~w_vg=4UW$@Di0mJ^ZZ9Tg9;zX19-|lN-S2yLJcE)BHBesMDNg5#Xs%R{WRbT%9 zB^FUB_eB?$eJNE9bYeC&GV2hz9kYJ9zd*0PW(Du|x!a87A6-G72yowS3%^H^b^SB= zJ&F{ZtM5MFn7#SS%p;3T(>8V1?3&*CXzil&N3YWrDiZ1_KM?CGp*UdO6p^AlDDTI!q6dw!7l>+$rgGd9B*v86~*3WMM? z&&-!wocs3cpz~y@8)?@wUid2|I5AtA7@s`vtDnoJ|8n8Oyq6ZGkA;&s6}-Xa6LcU? z|CI}TAWtP(96pfeI&l(wAkTg0(i`5FmVAG(zL#3F%#4*?Rqd&ob@+(CzdlrjvfAvl{X( zoH^&Wzt*ZQ3VZ_TXF&#%g)aVrPe{6}&w}4s@A~;! z=K9ON@0pJCpEC%4aX4v;_%koFdB|yEbV&^ZgZqIZ=!B#@lR5Of1=kHK(Br^xEUEd( z@aEE?q??Z?nj4rt+Yppe@1}8(aGE%Cl;DR9PS7$dgS z14<1Lyne5jjeT5LO7rV=K{|In`#zk0{Wy3z74*UvMyq{So;?5D==&U1 zur~Cx8HS%m|(p@sd44hBW(Sv5;k|gyBAGX z@;K52?PFs*y_&$FFSVN-gCTj;yp}(;UsBg{=B9f`7hM*;&T;(qLmbKD$O)w6@kmeL zo!%s0-=#N~Tw#}C+^}d@*%xPQhB0DGNT7rP!D$aatuy(gll-&&quQ1Ck_EO>ag&g{ z(!|{UA$Rva{89!nuJ3G27LZ|Kr)foOjFA1#uCK1KF}}5?m8+ezZoZ!7zW1i}(l?u%=Qv|Cj1gPHgCr#osqx|2snQs^?*e;G7S&GF z+7Ou=Cg8+kVq$6jKaKtT+#}XPf8;B^A9HvWv{6Ao6TIlb7}73rKk)Tzu{r2?cl%2LLUDgXZ5uL7s54@lxqFDuEv+8&>9jZj`@M}I(ei1j(uFM&m zVT{<48zcdNNRy-4Q$8=hZmW|UIE^=R%licdg6`l3tp%hovG9uBv5j?cj?2_@Tz~kI zy>$wZSx;qkuZwXv2?%TkgK!aZtP(DO;+{R(Q~IfDLh)m{d_RAA{o(5 z4Y?`4@;B!c#P!NLt=nRi`Bi%V<;6J40HkzqzUlCTubV13%%7d|7vD0a*kQZj#CHYG z*bHODmSP}j07OQKyeSmxd9X2tZ_b;?ZE*&D8jrP|m@UnXK5cXQQfB%7Ol9DOSiaA< zT|~WX?nCMkNV61WwF36BGWUzoY>bei#JVv?&(>sR@TB4!)x9%g&b<67%A;SiU>Fr8 z7fZ+HB%o#1cmmx`;Uc{(MvLJlpws77r}`a2cQa z7Es=FhM&dH8Jl5@*b*Bk@j!6EiLW7>Dvq3A;Bd3)Kd)>Q$N%lApuRD5&nhtoCzyU} zX$@Sz?R~lF$K<$K7q&>;nZ5GPg{>&bgF3B@%k!XnR^1Q>Ck*dahJwZ6>2Ydr)!)ow z+k8lUo|VyBMIoCdF<7_Ff&7T)AeSd#I+RYi8VT{-k5+rGW z$h6nDSF|n=F%HW+XW1+&do5Vm@HFyJs;XHkuA$WSUx|?s4=Q?1PPj+K-MpyK$@`ig zIZcp0lsXJ+ovV9EA4(OwExq~liG+nVkEYCblBsl8xIVFuaGJRKBROZ@<;mr$-{lT4 zs!Lv1vHZ=x@0v3=5`wjB@P~Hb%(iRbKn!u*$`0RcSZxv(IvMmF=$$EfeG}Z_xKI?R$!xQrw4h>EV9; zBD8XG>z@g`>x({pl$kv&pHH@{db>R9VG~eHSs>qe%^x|X+)%<+dR+ZstaLl{>own0 zKW6JQ-iLjm=u~w z99fgwW;-=mtLXj~?{x{rXIB1~vi_QioSbM_@Z9`8R7TdwDR_+fJ_JQuTBf}5U-Cjk z^jFfG%$d6hC#PG5?LvAo*TwE|rtDD+kQ4l98XN+DgbbD`w=S z1NS>#&{KKbJ|{p=hC@0pkeqbzxMH=A)|aav|3BhMvAOKuwP)82lgPI>x%yVtD;J611=-hI#V$0;Wk zBO_D8_*C)9pJekE+z^%RvfT2Ulcml>7PRIBc7drzb~5||Q{#i7@C!^`7Jr0aU~1rN z2EV}6`6VCx0#o;UL1uysn`Se-$YJhYyjpKgW5DrUd9gTB)V&<&7G_tz<47j;JSi%qSyxUcE0SL<-+o~kQ6yd=2l6S2)xBPjb--Z9%UqcN(@w&6S z9{jGw(qk$)w3H*?uwxR`5Aq|9NqBSwHek;^M{+h>+iwlI>7ESw(-+^Ea_(AR=F)JKH1y~$bim$y zw2WaOVFk+0z?W~f>o@T3SQ~sTDIq$*G3%2(;WYGE-*8E_PQ3b-$zq41Hb%Mh7f)t$ z5qHLB7$dgS21-2;JT=rvm8)t_=^pW@%2NzaimVf@EWurAQ%F*AUMI!IWCof2Q@&lo z#$*X8Z?vWJo}D~6$?R$Dtm9eQ)d!EauiWNSB{2BYg!@wtSh-?b1Ks`MuK5Udu~-}* zY-Nf^EVP4!f3BDY_0BJ|){+{p6^Y^jnZfhsL_8JIv0p+sO+0nhGv1e|z>{O+_n}7T z3vYMJ+>=-5Ib$=75nJkkqz4c=!!VpJ@EkVh}vZC1CdCt+)MLWTt)d=D5>#X3xS% zKAy{ z0Cv0!gIFvvyFz#vpGQ=)J`T7iXJA+ux8z!#>G?*K^fCO3o7Y$9u`A@q>lvFBnIZQ_tSrRO}%ZqW`T5rcl;b@Y=$vnOG%)V z0l|x8%{N+0Nc1u6sXisYcr{NcYf=$pqz2Ny;n5DI=8=JZt4{Nm#jtU0);VA=>%<+pZIaKb^4|#)vJ&K+*t+WIQLr#^U@b^nYrL zun|x8?Wd+iIgsuV!jLk4cY-taYnn2{4wukOlI$0Uh!+(j0%C^tVDm)tI#A0q@YQ8b~qR1E5c@RPdTaz5N}_}Sa!yUA?+ z*Q7;!XXeIydRBZ7CE-wIsK))v6zHl4q$A!b7!Do+-SR(kRHyz?==ow-=p*d-vvt$a zJJ){@PB>p~)s?TlVrr$UbmZcmONBlbOpLWduod_PPF@_8W8}IlGKaU&j*#Aw7Z-geFKY#wskvE5*Oj>Yg=ccPdR7(@z zHp3QekGwSTMvpsACtJe9-F@oydu69*neduCC!8j}y|bA&V_CW3Q|;^f%-4(9xPLyW zblKY(n_-ODQV%3OfXH8_4<`x9t^Ry#|NOXRt8bq^$iBwfiOJA}tJU!DPOIAH(;+uD zg?)6}7a8R>7o1k0$4K!VFoz!_<^BV7^$a8px$^b0RexUnZkdVEA&L7Q1W5$7$de+1xh6lyojH1xzoZUPgX9U>b&QwMfW8Yw`oo+hNc!~Q|d1@ zM{O2t@9#P@C6>pbVd*K+DM%HMdr=y^;&G9;g;zZ8zdpk&9$9{;hqJbRJ#cEKgY=8J z+-vuoxPC*eMH40AAlkr`v{-)gLMtAmDg{joXU30=OSQgss~ zf*p6OXP51?pCj_>n2`8&1!Kvp0jW+b=EkN5ob}m88;+e+*&d-W%g}@I+gx7L<&gRb zGTMtg?d1L+G%N$3c6!;fZSmaQT|4R?e5?_An&`GYZRbXm)PkjbI|%Bh|Mi1?+G*8) z2@Q$xm1*`_ovyt*r&h$a=AkTiz@A$E?^=H&*5s~^@V%FR3u9XhpO>#s=gM=&W*8&3 zbOlK%Aad7-&-af`wh~s_U|Ab>d2y8J%H`4Ey+bCDG~qV+iHzJEIkknS8l>!BmI$nn z?cI3%ofb;mk5(~Qhgm!rC&LaxfDg%`R58+ZLbA3K6Kus!o`3AkRs368wju7ol)~D@rlHQrpd3;-4wzLj>PjN2ce{tAzi0< zF!w_zr;%3g(x*;YaQG>It6x7@OMJ2Hg|^yq~?Guc;aWY zg!gRNtUwJ^NY6$~sHeh`={nOaiT!(8w4D3vDy|ZrZ!TJSznh5yy?Zwsgp*!Mwa&OLbmRD>% zutV7yn_-ODQV%FKKyYPgvt!>SN%h6+E}7o?^Z(FFL&s=PGn5H>l!i`O0ue`Pl)RBk z&RTBZTDsCcg zru=EoHlw5oER9VM&Nt8^gTUHa+6{&b{>Em-$-jIOGI}Zb+%pBubg%8?Hrj;C*^56I6@Ux&T`?XKBZ9ngf%`ir6sRxuAAXvfX_|pipk7;ev_bcwtNDJ&Z zt+>#M#n{}yZ2#oF<(YkF9F=~szco0KZ>VYY`Y!UkjygMN@g$_OaXp?7pVx7{9u1$@ zah3mwnAa&k3ZK{U;9;orSb8E=_UNx?rI&brKG%A4tt%9DC>Gu@@!*ky&g+a;LJSPf zK{>D{EcS~a4m>;U*U*=&Wi0yt##@Qr1Mj#LKOv_mo=SKngeYY^xYUK-eeT@%?aL*x zd$%?yc}=wXIDNjiGd9B*v86poY66kM3gNef6F;oDb3IEyP5+LRMvr*}xCv_nnN@aE zlw)Hufi!2u9j)1zOdzN3SQ&0(V={%DtL#?X%*JE^S&iWGRPH~IrES%I?Z^BVQxs23 z61j2gkuxVs=`&1fBoDqI*cLP*FB-zXznNf-WMv+9```zQ-CN%(#pc}%6?v$(2D!WA zfs|JGmcnWz4=(j%U#CS${d)6%C&!vcWjU_0Y*EUqov|6lh%HrtQV9fKyWKKtBHNv< zE-nY`V#1#8T_1H|Be+H~f}{`kC|@=v6G)n1XkN+2WCrO1GrT+F`zt)$?Qq95=B+*Y z(l_6*96Iq<<#7pjhp}Y{5+oK>p2#b={YjjT&RVl^67jn7IotNbO__XSY z^VC>@3pmOTft^TcqRjc_>lDLc&(iBW7M#~5_f2K4I^c}WFh*>t2NF;q@`_f_Ki;1Y zz8_$H@L%V3?Pf-c| zhB0DGlAt68!Qm0YE5r28s+^uYQPXhd-&n75)`hr|la^2qeATVRwJbI!6G+pT^yKu% zbzk$U>PkPQwn){J##v&%Cs&!%DLILdzyEazBqxWm3EwW%ooG8yvoe1A%p>o-S{jZK zF1JJrcY1JL=+FEV{Hr`F?~RF#xp!)ak25yI7_lWhNKyik=g;v}p0++^zvh4ccSF;) zVsX-&QSM|_-u@ZB*~o436ZmE$*>=zrG^7n=_RR*i*~ncc=11+0x7%9eBR_9*EqbTE z*RJ42P&jf@@eucdZ8pL?kw~46_%N#C&Tl-CV#uxBs5ZM&;I8#D+x+sY$XjHQOCIq# z@G4HUkTbn*-o@^9vPO2!Zu-0{m3vw~SUF=ej1gO+0wod%)~V~0y;dH7%0y3WUq^p8 zQ%LOkolY!9mS$$(I8-X0a&Lcao@LMFu~~w{s%worxIttFIqXN~?mhU49vsu+;fEu8 zNS2;pk=FDRNm+Z9>-rP%_vN45SY|1VrWR0uBO1vblKs#VJ=_*YLk~wL*hrRCKdmdd z`1ty?de2uZYgsEf`(EN|5J{dwN-gGl-xu!v{O$=?ztmK-Gyboan=fQ@#%35JwsZw@ zI0SbK`EHyVQ?oEHZikvb?-Gqy+IH)lSS-y9%<>p~)ZQQWzwofM|JIya*J9S*+q0dL z8q7m_F}AZ&(HcbIs>_eR`@ZU9dR)Vfc})e8eL}6J$O+Azb`2uwy~DXd#BQ|sH}n4a z)_3OfGNh#kmptb4>BdomAtf{!<9p09BGWQ=m%d5Pk-y5;*jx0{$-x<$VT{<4BqWi6 z$Olu6cX}C`T{#uZ_M9R2YQDmfm%p4?%q&ff+I&u=8QHc)`zZdj%4SpQm+G=)^<-dW zV={#F(>&yO;D^e%)wsf^rJNT^!48#isgQ*qDkG`zVEe^Wsl4i6mWltFG}lr6mTBy< zy~8IBdB~|jr={q=XL5J^CuOTsM^1AY{ZHsz-g#h??BHHN>42GAaQ#8Zs&hV~$BkI$w@_er1 zHtZ?NLm>+`o=BAuY7aV;N&}dpl4Cord#`@IFM;vck*zy_EsEc?1Z9L8X^aS|R8ly} z{a-Gl{8q;9F#8RUh16r}9`5g5&hlA1u|yjs44tL6x`i`#vZDdNw|JKdpv z*NMf#+}uEGLV!?>)t@bDi%!W_?wRPAb@!1MC`B!G{42XK;9=;+dZ zl>j#u)|DT*K5IF%aXjHczO>ClSrR@zjgp@JpV50c+bC+;M>X!d0=GVfEVAg9cgAKI zBes+W2>=lJMeUeQ%(5*Bu3HS)|DNx4%{=A0(TT;#z|yQRuGf}7_V$C961v5AQcd4- z$~DbGuH|qozVJ}_1gqsxk50?~sP=UJr=^GPU*p)x{&-8rhZSt7H_;C5G^EM{t>x&x z_~MUnEw9|>1@}yT#;TrP{Y`CIT(c!|EvFibJq>+cd$~V2B5X^~lbegOp07BP`*DW5 zGd9B*v86Up>Ve=@KQ$t^1z!<7`lRJR!j~Jfl%}n3058#k-dCcxqVX z1n}-zQ%GCbtzC(Y$qX_)D8}y>xVA^jFYBrP?wd`g!*5wK78yv(4$XSRL(>Se9vQeY zKrrUSx`y+7-TmQVKV@^KPL?cfM!s9mLo*Ru8K55d|MLG`R@W?#_U4AoG&;TcyCe7R zm(JJ>W5kwXKq&x%3v>8P`6_#h-5blDZ<%@Mf0Joh>%?MgW@dQv`>HbMpOb}e?)_-+ z@1el$b4RmZfa?+H45+ZzO85+@-s7$C8Bp=PTj4XH9@E=r7P0rX1W5kx;Al?Cy>OL2n z6#hFOsXsF*&*DCw<%=JTtsE@We!=Vp2(t+-J_#mJ5@}2qa zS{(1*tP5gze*JO8TCdu5FY2AK8ODe$#eh-(1c#j4DHQfXlF!|1dC;;4sa(2WcbPje znVS8&>D;2s+^Jr8ro>5V_SSjj$38KG%M#egi+%@u44wLxGDqVoeH|g>FB{pTQOPxVcsSqAGF<8Tc~B!|(~L=S#skiIl9YAghcq&Q~@G zJTD^t^qJZlM*HpFNmKohH65q zTk3(N2M`&?5q!4z@Z|9P%UN%AukM|-rE3GT6N|B-sreMa6LOm(e*K+(;CEP~`RmN% z8$%|7M%Q4c_2OFp>0yRA*8|V`PmLn(2QH@Kn>gQgZ_GRMeq&r-cQJA)gH#Wh(Q5tY zu&jqZdHxZ;vUl!ltyPz;-erW|HvD3rgPfww5bHltQdIw`=^VNRPefNOIT*NchFwaU zOz}ErY=$vnOM9TS1i{g=xd+5wC=2v_x4O5_K5(7_lduEm{AUx(U&#h7HddRrow!!C zt1&NkRm!O_J>=~Pyr&kzw0uEBzv)wJV#@QQd=H+M&ehc9m94mP)VVd{ zx+Lnw&_otR9u_&U?Fooup7Ab4r_MnCpe>3fRb06x^`e-$!FYdS;QF)aZ<>>(2`3zj zO;`55GCK9vn45cAhcer>cNJ>)-sw4GGmH^i5`!cf5c#a^O6Vou+++0*&ClHa`Y~c- zbgdbUXS3B3uWGC@TyW&Um*%gxXEw<2aOS&if3JvA4$&?-S#?ukHha(}r`$EKmP;!h zDtG^*u|J?r_xtMRj$MS4lQm=ZDvLF2wuYZF+uw1y1T@{d6C9ZBjLk4cYzYsPkRbTZ z@2i2GZfiMSubQ`L%ba`;RdbmT(CMuPrrG;vudro#7Pca3sw_u|k?H5nKfj~&scdeM z)~8xt&$l;w-mDFcTgrIN3|}k|y5zkGB@H3Q`G;a%X7gpB`c$8FvNfOWd$+FZ&nwr4 z$tEWQYws%{ry*Ncc%KTXF0*EQ|I@YTN;*nRjO825WYrCv^d?pz77dz#%YxP|vf zn))-rFqCwID0}SX@XT40QI!qvvZrvP`)jTut*vSACr|gd>g6~+bJaV->BhcRCiw9T z%im@{LXQM?T#esXXt**w+!>o;SW_4%#XxY^R<(lEwhz;}g)62hGDbQ)esb)Z6N{y} zp~WdR_9aUeyp4!2O>TOc5l~dU;Ry$Fib8HxdpL%{cU2MDsy;b~Pgtc*S#9!y^jSuK zXB=6xY{eCn6on{>91CD6ippDiY1pbBxRQvs!GGyN+=PEn5M zv6V#jweN3Nw>IBCEN@rU?zsP`$E2VqQ{OscGmH^i+JmGf5UKdm;+3}CZ3bhv(!1PO zZc1bpcx8d>Ea;p9sk^F_c1c_j5j=S6$8p)JCZE)8!S+tm-k0n|PAkJ^oX2?uY)*mX zT~%a_^BiBlFaPfewY41f7hhG^XXQ&ZrC-O9R-EDIKYQ5Ma;+@s^LUk3tvIRTn~C`p zuirgI)10vx#)vIdfl>(sw^rnfpYcA`!*jdo>9p zuI0ghTZ42Ta4!2P3hIGD53=xZy#ha{2+sjmS-+$gx&M75beH$|wcYjtTMzr*;GurP z@o;?yJ*No&0aw`8rBi8uklqRBzV&pK6%7~UzTa7RbB>lu!qSt9$Ol|`AQduhCh$oJ z``Q~XRK65`kKx_SofMVyM&#B+*M+st*bHODmc$^521Ld^5}#tvJLUE6I~A&H|2qC# zq}I>s#A0G@X!Iw2;-wE;H!7B1ahuJgAJqEU`DzV#2-yTOTGL-f{l);Hsg;#*f){n7Ci~ zdOJhag_9v8i*Jbxa?#=u2Cs%tQi#qT&m*m3p3O_&X1-r@Tef}qq}BVJu^GmQEiHl4 z1_aC4bvLJlGYdW}a!H>5^w`XY$KujJI~Pn%Tk<$R-(J6=-py)f+VX=>o<80u_Z(b7 z8A4X$;oAP<;iV71YX^1v%kMR>=O>jHwLaxAY~RK7OO%W8B1*5y!^@Kj+h0atG1Ink zi>aV$tQ?n}%By9kf3w{Ln_-OD zk{cuefk@4ub*K0r#(Wld`!dJ5>hzRNn>ao?F&kQ1n%(taop_%6!|doqL7&+F>1eHc z^#xqYK(7$=@F_vQLa^fK@&*4+Zo0Rc^Tf;NjtkVU|M<8brIZ;F-6s#9UTR+i=ntNe(w0cV9tkXg-kvmDay4^M_Z@`b9Kwc`2*6ofuDQ?kvO#bS+ zjUVEFEWG`RVbbm!IMR*ZR9Gho%Tn>7-R-79x|y6A9rRqr`pLS~R&T*s({5G76d<1r z?SWJ~Ar&lsU*xV&D^OK6Y7KUH!+bZGBXX|6(tXa@3}eKW!XRk|L|)9An#i+s^E*C$ z1Lhy4!Iyq+a=k{a5oFQR&1{U2H95%pq0|zunmzoi_|W`Hjmn*kRq+e1-rI9$IZ8c+ z*bn7F?c@}2cF>F<(;zuraahl~M4R>e6#2rxw=Slgcj~cnB3ujwIy=@`FP`|tPr%M~ z-4}J)L*EK5xcZ#28ODe$;eiqo1g95%oPWwZT+X9a>tndRqE+8fgLO_U#+IgLGo;M= zCbaI)=-wKeVo>F__D*%}c2GYGej{c2Yxs?ng74qKZ>01H23_a{S#{xhbM1#oY?(@F z!3&==wEdd3UAy7nOJzMe6+|Sb9FJf#=pF;aUU2HnJo=7<51lKMr&iGN?5hZ9iSNQUFvFB;l0!+5f*bHODmc}5d21Is-xVUlOuPLmH zzEt~#U(@!;y?O7!>BA7Rjn`?T92+CFx5R#$jmaF6B;0mvXJdq%l4JBN`c`>Low`U& zYr$e4+Y46@ty;%WgllGMz{?eCrw)(MFzA|38l;XXy?=C6*7xsYZ;H%W^@1sA=6)YP z!l@&4_USV#s;+T~bJ}z++dSjk^;wekk4l`e8ODe$9f8sX1V_)fX-^?^_i#jD8RRi`vl3V^6 zt)Hcq?u^YaMr^4Ek{-b1;<*c%F21{U!nEz9yz-vsQx|F80;dTxNDG2RdkK8mrcB=k z__9sM*Gcy`-CmZSaQhGMrq9|giyt>eTZP6Ur-{Kn4(k!S7`ki|F%CN@s*%+Sa?YAM z*(q5OM>*qkJdEBfstHC;6S4Q;)d)(OIPgDq#w13Ijjx=%o^Z{XRy|Ms_#|g+hB0DG zJ>b*;CY;*iYf4_Nxi@pwml$W!$+^+dr^-Rq2ovkfOv*KtciH!Wam%5TJ2ptVlao9=;U;{gl!F{$e>^da82SH<- zEhe^=F=&&=!tYJ9VpLxKd-}iK>E@D;--3m_+t_`lebN6J06)laT$3`#rdr5bQK zR{o7q3b!*h!x*t8BuK!6NTbOY_Nm9cKDzjkRac00-HSuJ&n-eu9_F$eh)5nPQOlF> zDY>|9Xf?igb;n`d%lA(^kd-_VuZ<>;RkF~_99>EzW4p|II{mp$JiOOgZF%|Yo>iZ^ zP_~LB$zV?&^B(jXF1n&?oi}A^=B>VOYp%V0v&k8oVT{-k5-4FnaM!MR(U)f@l;;UJ zI=_QS)WEU3w#dFj*#!TPfbw`8n}v462> zD&+P(Q^-7@>s4JgCNoG1@kkSAW3q(I5Nr4g&SH|)by!~|e2k@W*9^9QuZx=xZbC^d zM0RRD=vtn5q!~hw)EKnYOHg-lTU)^j<&mY=euFu*LoM zeh&5JJ8tPLl(;_sCXRHFQ39XXO|k3wXv4hZIivN9uH>cfd)VxRlln59u^GmQEyY06 z0Epc5CSeLIcZF1s{)3DwN>yKWZdiR2*BStZd+zWfFmbN|aF$ryWa+pt>gjPi+j@Js zO+Hr&{-Pw6EMID@0U&muWB4SMb>Ajhy!qE8SHJlGcjj827|mm4H*h4CtocYu<(4m# z$H#=5Ya9YD#xV0`K7E+48}E$GFh*>N3Y177xXvss;Bb<|d&N&bK1@A1#pSl-Ocf^< zLkkmwD+_8*9jl!f^?uUg3EifhC&HTh;z5(Y5145F-28S&LoUeo$&W~hCme*BXj3XN_x=lqbrK4o?4x_d|&C6D{^|u zc@M9GP|{Oj*@`n;)`~5Pp5@p0t(lE?hTbh^XKaQsVoQ0Dv;-o5aqN@I1;hdV=j^B<6l{kGvD`bLY_R zCqHhkGsn;A)0Hz^8`7=0HojvESvLdPQ zUe?0NIAzDn_-OD(ibGffXJDBQSq;o7Ti#J^hzuCGw<`?LBDY3w8*RT?%`@AdlU!w?7pec!)~znk4FB~eVT#Cd>4Ap zK~5oqpj;`=8j6kN?g>jo?zFnU6q?+;R{T&~>^2pVqc~DX@l2$0#rf;GO+oIH?j5qe z)LroTE_dJEDItmxw|UgZGV;65q zTPlG#2}E9x|GQBjcsrxy)_Kj+F~=H9Tr!g&9VEz9j{Al+@SUgb`}E-FD7*VChn+C# zelZ$$jxzK8|IM3?-`!jUS?fo-Q2*=jh@OPR(y@Yk@uXj8ODe$ zO@Yz~1alc_2yaqd9~F_rI}J}Os0^bHPe^RRRybm?Vi-$ z_^2;Z?)w>~pI=kTCnBeV(e?xbgZtu#(8K>dDrZ0s|0j5xT4k{im*a&w$DLpF-_p!z zy~i(-P>7rkDv!h46Da9m#r_o;YI`(}3Hj`>N?O)z@xRtZ&Ka9wjM!2PBn^Pbjn-Uu zc1(QJc&jSq!UV_3!ny57);qCSSQwhr>jqkM-k&BIEB{(ddPV1H%h>9krB zE8@*_(52Iq6LO6amSt?Lzm_2{V-x&lG{5H`ujX={CuYgX7OF0s@lnWWg3e`0QyAtl zwqo-8y+|!udY2_x^R@1BzsyU+P6_^Eoa*$B`zQCL)z3;cDLNV(iZZNpL;h z5y$y}!KVJ&Zf9(UF=9(Skn{i|y~J3S#bv8CJTrf_nk{W zN-w-$9`w>^UqaZL-*>;NbNNNqAg7$+SDJXVv_Q{Db`L!UZOgb<9focPblvqp5)|+Z z3@$%bNM>aI4>Gzo@wEyT`QdNUo;$TlV?aYc3LhZUF zxXw)zjF~xkdlO7lnGK2L-9cqvIQF&E%IU(53h83B8;U?|2OSk|$cG7WF4T zf6BDVE|^oY?uKZ2T&CosC=SA@rPFYwy_iHxxyE*fWhyn38Nz(az86F}V>65qTe^Y- zEr^_7_@$9m<0Y@%Pxts|j-Bt9-CugpiN(~y*qqb+fac~CQ4jC`>UZ$ydT^@e*vHwV zZY%ZZ=3-+qf%MFgui3-Bt+YI0<$KWp>?ty_h}ZKYJ- z{zc1#_F&aRi+!JTlDCA$9D04EQ*?j6#tFg+t$WsL$wz-@eh!kHAiF7dv()lSJbWMJ zoUs|kh%HHik{ATXEn1jD>cwDtFI{-l%Bm z^sx5lmzmy=c3C~-5HxHZ;f&Fb*pzCjFxBT8_cu<%}K-7G9Vv};L$%7etH~{2P4$Am494iVq~~8 z)Jy-K>$w2OGi=?+2?}Z6sec`GErSQ%gAow(P6X<<;a%i>4&9?HS?RX_itzpk+l<1+ zHT&+O>^ekh2_Yq@3A|sf)Rm?3m%fU+o_&3#KF^h01%onYY=$vnOM0NB1i?(FBc`t3 zQYG6Sxnk$q`KO||=dpG=v6z|}Sa__8IAwk3b~A%o;PT^D#~yEteG6#`L6`G7uakl= z=XL*|3SZ9aG4a{$s84otj=2e@9cZ&Gk9Iq_wD7{)!Jk?@CNaR4^HOjoyaz2Ss4a#% zvv0?JvGCp(zi0PG&oBEmc;*od*ym&WC`A! zx@6&33(nHS#zbOG-uu3w77oxVeMy^(^y&zcRFJ; zj1gOkfusQtS@ z*siV?7H|rI9_qz^dkXweFOL}>cTSydt@Wwg6<@giyWH*EK5wTRsMpxjcReKqbP(fM+%vN82_D; zu43?c`O$1A|QY$3{%^*gThg-i45D5O(e2PVMX)tc^ln>(_11d_PubrP zJ}dh5?KR&Pr62x_GGl~2rOY|}epk+&*UwY^ql&iaZQI#x=eMtYg)=t87_p@(P#S?? z?VC(2#^+~jO(#qXKaQsVoNcQGyozatkdcv9^d$^lO4OZamURND^1oF z;B;UJ*=A}Tq0Yu+4p|qc6}Va5_2TEv$MusGBNi{1clvFB{)1%)k<$VGVKI*dOISdb zGB8kSN5=4JLHzueATR0#nQ~&h|9NP zcdh;;!M|^I>t0{{>ydH9XE)>?E3VV=Jr=Ej-?)pmrm0rWNyj;pTS4RMrpTMy>yGhm zdVgqGrlLj1U_DkWr{mM09Xi{M(ZPh_qm=66RkPkqer0{^){56SQqf{bq*Qcp-qo&& z2djG*Dy};5;IVc{+sAeM&e#lN#FpMb=?8*e^Bz+cne31gzw}qH)F%PHeLQN*Ky$`e zPT&%koWRCp30Yu(b^_PWEt!v*rp;#Fm9OKab5>I(S8YGV;pP1`~9h37f@5!s|?CzFz%y-Z=&TFO_dAxDE-H z?K&Q!G-6W6N;UG=nGi}Hc^^+z%=^1cZYOJ|AJZ$r6Klmzv=S~dR%YAsAGY_(>Daz@ zi>~RRW;?sdnWgugu^GmQEgeBp2ADiBU*)6K3@Ki|c=t`qUi3@ekx~Me3>J|2ex7@( z^CTlZ-hVl#9-r;|qvZd+Ig16wUX8{*DDXU1yFf>^+^_D1?$2;%GKcQZ@E{cT?pHRZ zU!Sf%#q2t3^83RJYl~!Npj=vs)Hgw@E>@?nNMFF(8?)JM&)d*Ap)I%6}8 z5nCz&IUIsNr0}xJ#H|wksJZg}<-EE}2eKM&gIk`4kY)pG_FOh5BS<=6zS_mcWDMD} zj}N$K^a<7em9EZIX@??*n2V&<=kJSw6bhrL5n}f3WX1uZ5k(F`KuiuH1=rJ$}@y&Ka9wjM&l?D2+g{ z$<}YS!Q7(Kw|=hsm$dcG>H?$A_n@Axk;%DxMm_)AJxi{C|GvLK?Um~LIIkvfU1JOx z|M1v2ZPUAUHc`)QjmMT9SS?*9cbZ}U4AvoE*KFJXTNX5Msp7mHk9PlGFS|A7zlFW+ zuCX@Ekut^6&Oj zVj?noOxAh_N_a1_Tyd9)xtzmXDeoEcn0+;W=e^4=Vl%8|m{5|+)*H~HxUd~`L-erf$Y_=z zCl$dX2e>Sj#qL)X_0bdE#q!)D{jwg8q_Ry5DXFZO{Cn}UV#yMNr>%1)s@>RBXt?2_ zGd9B*u_Y=~)Z1r~=_B3CJ*spq04oUGir@*Y2%$!wu8 zo4Zp}=hjB#xF4{sHSlE{WK72HV1`vGSgs?$wrqn2Q!B0is?*HPc%>4TFnDyCo{Bm0 z*2@w(?surcr&dtnexm%H88MY}!*mawulW>wdB$O>CJAS3hB0DGC7@V`;Cm%cWmN>O z|LS%+(>l5EN9lxK$!(x>J`GH^-R>|rT44XA+~U@i*Kw8d=lM#cAwwRJj*7?5|L`M( z`3@DrPMG$v2!fw5tu-;F?xM|tMStoei(X9FpDWmP@ub!tdz6Gj?A+`wN$3&6^jJ|! zU_@*%v_+T<%m2KIx}~>%;kKN-_ZCM?VjrR`QO2HdcEzitb44x{ZQ}Ib_P#)EheO%Y z$|vugu^GmQEr~%A4Twy$jck#TbXwd0cJT?8=dvsBO+B~_JSPWT_r~mmaGJ}kOuvvX(W3n^>8>uDK6Is}Gge{HZm*eiu85b|!uuFRp)`3!L zV4KO`7sU+L&*1hX3O0jF$w9%`_Jt4i>V}2)R^7p^$E0NK^BzfymnuABxG#>J}wa zS2rlBrMt6Rc<$}V_kwLU+E`wDlJLmYrN)pPRwQo#)Zf3J(`fQvqW(E2Wh^_Ltpnb zGyMj4XrRZI5Va`%&;&Ln3&^4oCw;S39qKQSJ@KkOzPd6u;PPt2bdH)^$cc#P>AJz* zI61TuHpP!vlupaxvmV~Q1x1=sO@BO8*18*dZvEQ$8RZa0q+$js5gq#D)gRmE#rf#P z8Jnd?zj3hLSd}s}-Wi)=jM$PJBmsfQUDM~h-`^j%cP*FSnN=lueC2lhw&1FV!1i9@ zB94zsmp2{rUe>*5>E5l^{afbO6o=JPElnJ`3N2XNv2E|AU<(u(4OV)miD|1Grtfgb zTTnee%JWN~OV9u6#C*a9%Ta-K$=yqtjeq@HcB7=!EOP3?qt}?PJ7Y795nJj3r3MH- z)O+xs#P><*Vf7gW%0_EmcePXoJFyrVn_B#umD$iW?ZoQUx=-AeYP79buJPmrxc>{C zzVkTta@E89FAF&%BO;eBP5;>!ux9!jOMT>2F>gwZSta&; z0W;qjM>FN9B1Rmk;J3xe-9KKej?>rW=6gQ8v=2G8V69h9Nicg#nW19It~w!XwdKvr0zr3Bk_T0KHy)>Tp-acyj;?^7 zAmRSp47#!3V>tG1F3)V2TIm_px#i+>Z~HH^V!yLmDk3M3)5Y-K4N_rpGUV~kmu?RB z7jBr|QQz-muzjoE9XC^FY=$vnOGuEU0V37vclBtoZ|gl?Q@!fiiCK~TA{yf0CMt9- zfYVPl_*wwo-NNws8LO9u@U;MJ*Ery70o?L6oqj)?~PUfmpsouTC}i0>P>z3u_BL6F`z<*33?h9f4&dmG_3QW+btmDDJG9q;iqA_&6{^I zV)NsbHv5;XF)3aqQ6wz2(nA(?W)J^}+Ysy_dz_yHI}K~fJlJY8Ec@svY_eE&UJs~c ze)6bRnYnRhzp`@>v(jW7Dd+r6c$4Mqe4eJaPj0^VVAR{I$FgbdX74cmqC#hEhB0DG zV~|t>B0p72MBhxfA6ePY7Q2wW((XL>1s>1|^M)4FXE;9(RdL|$42_N1KWSq!!^UM& z;4u_z$A?_p#Fk;+yv6&(iIXND`qaOb|1A+rSb$u%453Et#WVPh4}p)#(kX@P+xODv z+SMKEh1bkH_uSnjp`2;Qj3b3y{Ed`CD!=?~v$n3wST#j#<{ht7Zjp1(ayVl%j1gN} z0;LTIer_h_Ge1#3`Td5C|FV9v?sR+iLlRtq7(qr@c@}J9V={tF>(f5AT^Gr;kC^jJ^*Ksh`GdjF1sF?U;vbOqP&kN$Q!8EjQ{d%-Zym z|ChYd`Il{9?oa%_HUv32(XP1hxcUX!>~-J$1A66&2Ykl_8AG;%tGL-za`$|-d(@k% z@C4ub?~66L9iE_U=tXMwUdw_PH&>)5@xQodCnEUd=X>aC+QuM&7{bzwg_Z&xc}eo~#eqs;VbqP;m9<8{`y%b(I0h(>{Z~V{{{y+8a2t z9v@t|xIUr&g2dNF3uNDJi7L-pgh=#SW31ma)IM|`X{`=(Gu!`7dRHzvfu>{ z5eMk0{g;9lIBJPkYc%J6YLI)B;^8Ykd-ltno3wij7osF5+V!1orNRmve^zLLIEvS@QUws!=*hI62+At@unQ@9iU( zKNC*GmA$xc@VBJZyUrP#VT{-k9w;F}u>P4Q{)0E8<+`jC=hT^X?(R)x(Q#rnv^10n zO;g&>`*g1w=gJQkwpCq!!S=Ze(gBB5P98S5;71F1+}Q%ZUd2P@6YP2wUi;(l1=g!d zlV;5eUb+4M_nG&k)_mOeN25=iFEf()#a43 zezU09KWxX{OBIjkebYovLU-k`l}NX4mv8qy@b&+uRc^`*r}i?H-dZv#;=VIB!x*t8 zHc0XTk%vN`Jm8gUXnef+!Gn*>GW2(H2!3;7F)}hR4s9&4;7E%U?AkG{efxI9WLv!_ zXTWt9bYY9fz3=daEv~<+t7ixl+~wVC!0~y?sd#CXw@VsWbq7TXxi1JUWGGr0H*hJ$ zEb{8Jv%h45-z}e6qj>jf*nVd7|Hvuiz616YvS?Og$gV?ECaP9AEPu9VL+*{DvPI6= z3}eKWmOyC(g1hcb+%kKgsg3dSjk6t|CtBTDEY%Di|HpEKy;P4R@)7n2HDgN8x!0YD zNKW(GSAW|hEvFcz9Yg1q?n6mv#WUnvx{4Ob?_=f${h2HEDDwN2^^-ri=+D8CCLV^s zTe`PyuL_XXJ8Vhg%S)cWL{3gm?_y6*DWBxcXa3>ZlC;W4)BovidGY+EEzZ~sW5ky5 zAV~>CMn62gEY1J1|HK#i9HQFcKBhVcYQT*Y=xRB37Df1KIpb$lFOyzxGh=snxBK=* z?n9*q=JW4bLP8_OU^$D031<^B_2Wv?VLFMLpX^Q-LFyH`Hc?EOxBu|iRDdbw{n7b_L9 zQxE<(vi>4bE&2K3F?B<}&vQAElhZ2`?8&LN@!PHRRsZKi-9MW5bLoM-_nszRbH-*E zBesMGNlGBnd-1J=g9nY5bmv&~cNE(DYkd6U2rgD&<8?kI@bNlMeipgy{$^WOKVF;r zu*5g8>2tHL%Ek(mbTBdoSl;kTfC7(!!R>Pb^r%kKw;!WS5G>U$+O}|aYi0Z$ABoRN z_n)rr+U!a=9lWtwpXHw>^y0!)i52NBXRjZsUO8`4qcb+c7_p@oh$lcK?~CR*^ZRQP zlOJE%-W`6Wykypb`H*oG$fST;$UQbDW5_-rmt(uxm`ou}4yikz*qF>9Z1>Ybu+4)a zH%vKI6>bG?lYjli*j6m6f6B+tkGozYCl!x(qOi?_h;x78L%X9z1_Oip3Q_2d#_p?R zq3al2N+iGeMI67f`hkVS1(R8o^U_1gEY;^CCzW^U*ourdHk&*-=G<2CXZcciXNuI! z5^kp{H)lCxGmH^iq5>rn2#(+0v*yVZmpNMYY^7G63m)yxyOrw1Vrpn&pxx4SOr)Og zNZgfoA6NWfSjptKN&sA#zy?x2IKT%|9G6_VY9VA1TPHY~`<7sM%k(AIj&U24kW&Z^ zXB+X3)_Q!1f)1q6Wwe(1g-KNE#i^YF9gjm#%sO4jsO>UCdtoZ!6!M|-lIa5Jnr&XM z0+&_zrJ)b?TpPZMr>&bk~%=-gR)=3R&8(X)i?qc+$or8^*C*rrxUY@i4k}E z*98gXFF*UK94%km!N>G$=3DS(7L1TW#(noaHb!U}v-cSrlQCqg5csf1Q^+Kw$EPGV zCUeNxF4v1tHYN+mq_)7a|FZ5^i)zz?*XtKe)#bian6)L(?i_M*qQ@AF$ERxO;J?T4 z8H3UIV)dqG?Yy8V3v?YfT!`lq^_;DOBRPG#0Uv|;(8;p$^}M-aY;sR+w+S!s{L$0c zwl~xnn_-OD5*{caLGZ)3)|;Q6`_k*E@LWYiGOIp_>CsJUU4g>?$ou2ehcA59PDY&Z zd-T<|PW5z&hk876x@V1uj3EmhJRHN|SLg8kiYMkOTd!PyzXPk{|39r*@x8DyvTpl7 zPn0c-NDZ8CFJb9sw1LAw@B;SF8BFSVcORXTYxCrc@d;TtxpEy!1LwO3yn%y~Zn`&| zz0o%}w#YB}^xwQl7wK=TO;*m>3}eKW!aykog0FjV)^bd%QU7pPFPS_3LUc`0)+W%% zE_BVehwByinr~dkg-T!2d=_|FRC)jF>pK!$?lUK_Stq>N@))^Tp;C49Q;`GWYQ%A& zh{Z3%vN|%WeERV(>nq!Tt7gA4b#ZxYGQFf2xjI5h9zPNLpT7$HF6l9Fy%03_(%z$& z88adcTVMF`IAb%65nDon1Tu(h-K=A>ZP{dx?72U)j=$_$v3u47P z{M}n<`uNUUsVRqL3XJP&EmnQG{%iSXXKaQsVoOz!bOIv3{|Gs|*Xn5Tg5sT8O^-Ye z*}waH2;6rzhMXiRe9?f7$rQ58lK-#S>@)WAFK2aZ(U&t*`mJNIY$ij|TI6&g$CaY)eHSJbG)|{j*=j zAsp0bg?5oWlor9d$Qq@;;az0TN$PA&&@M9P(x31yvPTYRw+N(*tRlvG_GrIX=!EYL z3!UU%m~1~Pu=P%q54}^3C*wS57uh9Y8f=*Yb!G<#F4egH2yeTgKK1XkM4QNS{_RZq zjNMz2QjI6$Z|tc?WbV8(K}T~!c8O2ix!m77mACYXzcV(&7_p@f0e-68sKO(-8`{pDq*yvM}Bi<_XEn{l1Zu%J6!+bX43!Rva%#GxK zsmv1RVygMsFTRMUAoF3Z;)P;x!t)3iQ$lF?jC#>1={mx(cE33lK#m_ZzSn>Dh zapXia+HhrHAoe(PPYz}1bddX8^FK%J`<_iXX`gkRbIyAIs1vQr)nW)HB2SL8e~tgM zb{7gB{P%LY*wgy^~gbuAXlyAh2@NpRz#KS>US25Herrw%C!4$rRE!@#ON~-*E7n_q#0q zsV(-|%PoIReA1wYvUF*5zy$eVT2HP_*n#c<44jCk#;zjLQnHc7FX*;Bncb zlmh9!*{|($O?G2XA)Z__VB`0m9A(l8l7h9ZIER2m!#R`4=W7RE|T{v&J)!)`J=*_ccqDaTbDlyV?5MeLh7;U_$K@)WXu)w^wYSMFuWMTZB^zKZjRbWz3VFWeD6M+DSgvqv| zuSFNWh$!40>*>B;K@@3Z-&5crF(dn|E{AeAELrvF?kiu$L$i1y#MqUNASWE^R8*b< zzlX)hJ_!|7ei=jzhQUgoNK{!lwLGa5hLgbuc-Jr&SbZq;$o=m4bdz& z_*vqonV-3v-5Hx#&@^^~wCZ=C~5^?B>$;;oFr;!ty=t+1}2PL7EiHT+!K3VE` zP3g<(6S~($1sRtdcgAKIBeo<7PGexg=g?&l-Y*;lEYpLgJrCo_bLfnS0d220H!J=a zpR(XU{Gt3Kayh4hEoV_;(6 zq^qw~Jqjvo_s;lqUq5$8xKzd|@E|jmQ+VCJPhn%Sge?3NF5-A-{7`Rh$BH5U;(W=MsP z%(T>(>#w_uuy2)l(l^<0V@=%sYTh1aY=$vnOFiJ^04ADFr>wA@@`90b(lL|r>SL!D zXI98Nv6z_~m_+41ZhG!;O!$VrNm2a@qumdFmV84VAM}*VhmQ}k2!C1fTD&%+XnUNS zpYWNZH{aO^PvX-VO(CE##K8WQ)O_cunkyW#->^ko-{+awaq2TYwyjQnp zAn&{P#GXRrcBH(YJoApz%Ytny4*xZLV)VuPOa3uuY=$vnOG_Y!L$KSTR}&?Rn8of^ zFY>eRvfeVizymThWd<49VbNZ~#$*N=Czk2kz{X?&8ToU*9Q3v-v%!6~lvepNugH|A z;tTI;zi&oP6N9}8?5QwO5E2L;nnutA?K}{-6u~F7>D~n1E4G>YzVO7Bw7#GjBHRAG zyU{f5J915;a0cE4Mk+Prb}abIv3>PQR$t4MW3DYmPj||EQ@rPl%`ir6sRt4iATnmb z(zSPa)@)tC+!Z)W^V5|%Q+~yR8oEqIkhs^(xlYO2-6>x8gqKGP>lfV4=)85*OvG;0 z)E(HojQ7&BRBKI%}=_({JuGbDX?YJI&@_+y&%xqs)Rm-53ge z2~qM3>Epi}#>R3mA$g^Y&sS$`hB0DGVW1QP!Ed;i)V&olS{ky|#o(|*%+cItrE(`0 z3rh<#r46RPN|GneI#>JSc7Vl0y^G&tk0PJ>?x}M3%woy^{URFWYb5J_O>M58JY{Mj z%Iy&J7}y(}9UxDY?-*yklh6UOW1il7XKQuYKTaKu$6i?mgDO?|q#%o3+w3TmPql#+@JF zxHo~cKaEeBuB?cS86$d>4Xd)$?Ay84zN6OGahxP5WeL zY=$vnOC_LKhhXD`;;#ox>Ylysm{q*wkmRKgF~^Zt^CJ)H8ZU3aHK^NcRJP5-C;x{2 zg7!K|t{?8sD-LVYAbDuK#~9Qdiro_ul85E}n=cQ{O-s+q{kk&8Jm`YiC%dQ@BH5W^7&z_ty{l7y|(4i zTNZH9Uw<~5I`1wkJS4fTw&(noJxRYmBgefqeEpLrQnjFIDlgOOw=ywMHU8g+H(uNlHn(Q4 z-S3ReFh*>t1QhEKyhXHpiiX0u675Nw!#-M6i~opT)a=A!VPsNu-!uC&;mRd=f=Kah#*{g9C|!_)(% zs-a6WLsw-Gj$S(p_^deUu#H#0O%nOS8gT)w5e zvwnfBc=xu84hMyKe4Viw#)vKDLDCY4w7Yu5UizJc;$%fDqwQu7`2JnHSM9`NVrgW~ zrBt>=IWOQu+s)`bbKb6VWKI>l3t7AXX@C%Oyn?5G6w>huP5(FW+y4{zY$fg5_NdD9 zOu_3olubjP`X$ig6-Ems1_qDH8PL%Xg1Zm#{F8V>65qTXF*>9|*SC5G8R!)aaorkFIy! zsq>$U80Ahlu~=FfnD9OJ_56`#V0bpZ!Fm!}KAa3I?}r9YKVPk|G%;3mrzq;%- z&l0!eA(h+g)j~5eTp90goQIq`hI3u!X~Kc$&JhahvgphC(Q9mq-PqQC6nwF==cDj^ zbL9PKo=C-zi7&h^Gtw{9DNnic@|x+&DJmjQWQ}ZXnl+v~V>65qTRH-z3kW_QYoz?l zEp}5z#HnuEeT!@_t9Pn_<_t|N&MjKLtheB@&M9u*P>17_1UqG3KL@27==NyjMO2<< zYVZyfx5yUwDjDfZnl-#r&jh)fZ2MREs(Qokl{ULIngnT(aLgQ_9V%?wqdf9Kl&M>;tXVyQl!R4vGg5aa>jw|3<9q2|z{$@4gjf`LZhj}L!iYSG8 zzdE)cFMryU3$7@gE7IFBo)+n4xSrKaV;wjO1znIU38ODe$#eh-(1Q(vDUZv1_(_ck!(f00^ z&wnQF*p=qQVq#`${q68ZS8fR`J5u&3g!^9IF#cswz{2`kMmO6@IxF#w-&UK5B5P#nc zfo5Is`T{dZlSS1mm5s?9GDGC9K8uaX9I|2B(`I4Q@xnc!!KWYIeJCJ(k9pCh>vfau zkn5Y#)WX2vX|r1z6afqjB&3$6^X6TtMup1BOE-Mb&b(T(GUgrfDLr!_L?YW5kxOAkGAl^9q-Au-sm`i@mF5^SO@cSxc2WzB;j( z7@L?UKYFk|iRE@6 z!Ka8Tg`YJZ)%zo-meE>?fx*-6B{a2=(7QgP7HPB7Fd;}lIP}b=wXtW6Ql6M0mo4@x z@ZL32tz`2pQmXQ2;H9l=(rV21ov#To`{`Nv!Wo-kjM&l@D4jsC>iO`BU7wb}cy`vM zCoEgMH+RQ^so>TLbWfVnOey%96HU)D{C@5Wi ztc1=8BGQ4U!(U=YS(65qTZ#cW9D*;kUKQP69qv%TSa$g9$LHct*5_=649G!xyhQ9K z5}5fOc8CvCpqqHH5%1fjp9&sG*tGtA^5%R)PCv>G5JS9vac0HXO+2s(G{_M-7E*PC;{FRy*fcYoo$CzYzb zN!3}E$fX3820?~hU)IxAA3Ar8W9RCzgt}cS%U2%EJuPCRt(9SFP&yH1EEXy5U4!6# zS?92m+rIvk@|$+dx9638Q&7L9*zCB2&e#lN#Fk1xu@1rVlj>dgc|99nAKSsM`fV2f zS?`N6PArC&CWbf44%`q+3wX6+da+hu=xJW(!h_!6wgvRA7*BU?HYO88urYQwMB#VE z*!8bW*=!-Q*ZWt)juLT+*WxEv9r&22kDOZQ+qUp@cO~%<7Ed~?StF}Xc`niUeQOWb zeJ9iKo9ABlqcE)BHBerw} zj$$zJZ0og%N!K6iN_=_T&=%DuYZ78M!->Vr$jE5s%v3vzYiW}^PTnyRRF(a>ae7T2 z(sZKhzlX3xeLOuQ;nRuk7SG{_`Z(NP4nNdK`KAqg+lIT}Yer3WzXhL}wjEV$Sg}^D zSklM;)h6WhM30)s)3X>lort*fj!LWP2d?IEo1x_`a_14(!iFUVfH-OM@MW`*~9!b!+SSkidsvBPGfs&)3A z3-u$HF8}PBFXW8PFh*>N4V-$wgvFk0^NBKfN9IK4p0)fkQF4#Iyd!!GE_ezpu3P@8pFjM|L1pWxj8ST1HFB;O#J~%D&yo%l}!E6SP^a zL^HzZU250WkL!@rjh{ERs?0|?%1BCU4@a-1*WZM_zn0g|ILvIP;Ec^MMrDzj6Kd34*F*cZ;A$_QclTWC9O@7bv>+7}mDo+7-prJR; zyR|E^F_}RQYxfLLvDu?OLq3GzPU4F2?J}}!q6*WOmm`-fLnnoJ2H4SPfj(J{omX$y zFErWsYD=f+L2mn{&&3|Gq@e6k4amiwLVj?ryvtjcZ1&4WZ^hgAm^%{!7@j+0GmH^i zS^_5yFfoT~1*d!aRMnlwCRjfCnA{#^ z9-!}5cp`B{kGgoGeUF&Vo~iSxl_orc+@M>%5NB87pYoxk)EH!GB1wJr))ofeg@K*M zLG4c+_b1!$Oh7I*f*P@>39q*|KA$laE%#qiT=q+QSGc&Wg{w0*!x*up9&mC16Kj4v z`zFY^?5JtJ@#@nBla8ys)IEXRE^*(m27Vc@`#wGRWxVb_%VC%Cx?hZjwM#62$^M%? z`(|vDUg*Vrq6e>F&RN7b)==-*_ezW+rM0v zIkPdDK-5TP2f+`Rb7@a*n8y>Sv)1Oo+5OXIO65h~JI1$ZCvvGWnpUtMABHWhc!sq= z514b9VwF<&LNxz;(Z*AE+TQZY{CyL*W|1h4v=Vk5DXo-Gc9JMu-pU-o7;@Wqd7t{x zZ|Tg=*bHODma4$X1Wa`B@*hh05F3A@^&5*G7X#n*Pi?Qj)5XwrN^BMvVe6FaKE8*q zQ*zs}9kx!%qk6%MJtq&?Oyy9T7xHQrpV+Hg9uKB&MNS<}zb~mg`u{~ID^~_?klh15E*+EJY$jVxWub@jlAOmr{E=ur=%hqi2t)~oYmQ={jAe>a96+)LaI)r@{vQeAlEL;*kk-t}Y zcAqmg!x*t8DsU7ugt8fuV z?m>=k=if;7ui3sOUuN~BSNB3)t|J#86s3unpU@_&=g3PFKQ}c$3b-m?RJxdH1KT3k z&T|j{IulM4u_hs`PV={F94nhprg*MI>X?ky)7Uy^Y=$vnOFiJ^04DZ)y4^O%>ob=@ z({YA3Vjs(2e!IK_Tzo)JpmbA|V`DOb%n6D+TEkDE^jNfpjmZ>JtO%S-gP%aDv`fNx zEw}miz-r}-mreP~FX>HkQZ&p&PAkKuA>tX&OY=r6N<)P6Z3o-xlQpt|JD=X3{gmf| zvhiw^@qMK3O?(2pArfoyrA2i{t999?HT^4gDc@o64dC`RnrM2!og&QP1s`K)OQ5s4NhIV}Do`!bS_Vw<4u(Y=3^uMm2 zn1|MS>o4KpKk@roUs|kh%L2&lMk4@2M`vt?F=9(S@Fc;IQ@eY{&bww;gKYo*sM^^2?4j^H zPbU_03k&l-+j&D(+>XS}mT{=bW03w-wy7o=QXfHvPMm(S!G~9PcMHRZSFBzd!iQHp z(@(;OSKRV7yVWn*AFk}Ms(yO1{dVU(r}pwziP2O9iVVc*OGI~|(;q{JSKQ~C_iLxt ztr30st<~e0^Lyd9az`!+>Jv^y8D=ZRc#@XeJ=IuL@nI4FMBAhJHVku}u^GmQExmyp z4#6)Kw!A1v{C4uHq~)=^OH&1;=4@@DWQvfdte%a@9FopFco-}nt@70TwrpeA71_zz zsm7MdmlvX(>xNV#W$}|ZML42sB*EwM?RtNYT4lFAtoUEgeg5(e7Axd*la+_9M#?ag zbh>(C=GJ#lm3HrKm3HeZZ~3xwr873e7_p@=NSXnWs#U+0O3p;6PrR@HWc~|xmE`9c z8^9BRSoZmFJoYx}wPas#bf3!7ypsyfpRMi1TGbR#$`8bTWn$AojyrUp&xlS3=HW|n zUI`h#$vEH{(k63?RZ?o<736e~Q-(bqXf2DaJ9F&Mfgm;i`_Dw9WVtz|Dx9$y#)vJ& zfKmVie^{fex@|8r)1Dh`I!jyiXWsc2HPMO1#Khd3MI)^6Q-bKk!@PX&zNKXc+*@|+ zGIA|M>L9;op8u_UjfbC)teWDwnSJhprOAS&^Ak~~4u^Q(n!f#_yi8~<|*55~?y+ar2bmK@xd3)gfq71VvskoopQZ8NIeErT-(-SidclJ+ha>iyD zBewJgNkJfz^V8JzaUXg1O?rCB%dAE1?;=@uEpYo5y0Zt@UJbF_udA}Yy!*ltbi8?w(WSK~56| z7vLoeN}8B*Ogu;^K<hwnzTAS|qzCcbN!?5FA z@(8y2fZB70$X%WV&X(`Qn3V*yPH#EGCU~KwGA0^jA_#l>DAnAN+P_%w{?=pRHiEll zMY(FbQiXmwV>65qTS@|@3Hj_yPi>kv?NSzUH6(NQ9(>Cn$Fz9(mO;;QrcWs^**${_e-|+L`#q`fO_!f= zW+`%N87)m17(B~mVAT-(`ZBER50INC>z6orP0Kr;=@%oO^C&*ELS-@4>_S#9)P!ZP!igHmopO<&Jwxh_vPsC z?$*nPb0zmrbH-*EBeo<7N@5WFdgkxnK5=Jk-bJjOqZqjU$61+AJDpf8OwCPK&EntA z_(;3I)bW^}-o0a9%z3e)ke(D|k%MRTOg1KC$ZRBWiyXX8ZJxU++b#8EcAbBCOrQh|Rr^+0icj>t5yP|d1J?E+tPDC}VOix*TTCNvg z*mC8i$YkZx2^E~NCC=CkW5kx+APERW1{a&3xRRRNrX%!xiuy@q?daMDJ0})H6ARN7 zH5;=z=JJK_?qg}UU}E1YQy1}`f<)w5d(W#fRIymLNOp4U-5CZ}v(#sLD}9N$rP$6OWX7BPXYZnb<0} zIxjc3?$6op5>>5s-+j}e^i|Y;k^eeD}D-W9L5RI6euy5QS2#&~B)BD5is^B4Q6+xMi;~ zYnktYiS1&sUlxB_|13)-7Gz_j%m$79JdRk^QgCKt}y$D}$h&%_y?~B(03$AB+F=eh4XPCFWTH3^@OARI6z#A!^Z4;mqkRB%`nIVpI z%~EB7usn82vO-xY{IH3qk=)WPo2=jIeLosEI&R1}v;4Ow-(t1p?nkPc84yTYPuz^R(Hbf_|rtiJUp$ zG8s8ljI_}j&yGiupg?6{K%84j)@Y5!9$mHusRu^-U3#^Tqu)PS!F})rj#Saf3LmX$ zdtVk6QaC@trs-BgYe1xR>$eHoO9h;<8ODe${Xm=!BG2hnRHRLAU0CZfd$Z8a#t(m4 zpRqf!n3ZBgy9*F5hS5|LAg=ZGjbJiC5KfP$5Q!R>PbG=)&O;N{?SA&#%HS9?YI zb7~cn^&J|0+fj}HL#l6(Qb@OYa=qxWC45Hny;?JVDoB_)@&8=@*BP5(jM&l=#1kNL zno(`2;!>^uQ`a`6Iq?_9-{n4cO-{Va@6?%8X)BCf<*kw^RjSSB6#IsjQ z02Cw)4DOq`U>A{HJOkb5?0%?C7$QshToTpF6Kl>`m&I4=RNMZTpUV7_eW5M1^fiw1 zq&E~^o^-4CtXa`7C{^ZlBl+8bmkH4;H_xq%cE)BHBerw}@ivHTdB2*0=}TGr!8_0R z)+X;{=gSeE15Ojrea;Str^7dmFxQvBH;u6Eco*4s(sL>2<4G)A3gwlSe`&a={14^u zI7-rlXTKh7;U$&l7l%Naxb-PFUVWMT^_-t(%uH{eu>7=1jl_{A`ZJNz1jmkehrb+8 zh3j<#Ok|%Nzrw!bPopz7!x*up9#Cq4;Q2e&e&3`S*z?re$hN6@s?)qBhVPwNOij!! zA_|T>(tR%faqp@m7fA1vI%7uGY3V!RzyF6cIHp+q6Nc9a; zYMD6w*Id)LYO}T(m|ZdFnf_DZ-DAHCZ=JCj#)vIlK~f5coVl(slA|^9>!hh~KXbKx zm{rlx?hI~sm_TX|p0$73m@FY%jPxc;`>NK>oT~bv_{B#CWuy7LRc`YUq}1@7 zT)+$R4g-TnaTXth<^Es^KZG>|N{!enx3=N^{#hcKefhfun@fABZ5*MjEqsRsTI)nr|Yf< z(Do;V;~lD=h8lq;QKt(Fd*^y?cwVOZ;$a|iI+(f~KHh)v0oJm_wjG&1^@8E;U#lvAZz@fAyj38@ZMWnn=cy<&b=cFv z^z}uF;Y@cL=Y95-zqaA|BZ)H$cGS#r#%35JwiE+N10b^4v`6y3=+lLT@t0y(wcnCA znpLd@P6t>PP#YMSaX0*k4y=%TGV}e9>jM1VKeJywMX49am>rqf0UO7{e`?NP8WpF0 zc_66rw|3=WPLY^#LG%N zjd-xk8Jl5@*isBA1winYr;;0*`+dr*#nLwFU)L+Pe6nx{@?;zGwNCOArokuMEUsm- zF_}QdJUzO(*qBV9qg#@n*qAIJ?FrG-&9GG@YX7C!m@FYf9cqbJCrsffn525>~Jg zuN!OPwyCkF7tpC#nLPnE*@orR$RS^>lunOcbXB3^`j(o^Q*92iU*h&Ttt6bB=CEDZ zB%c1dWu;p{!MCfnycc9nrN#I-V>65qTf&1RB@j7d_oLnjb@t>aj>mofJcO6teY~a= zy!a7%TndhTq|EHSNc%|F=-6(w2;OIP=VJ2o6U$|emRl}#M@b!|H$H|=VKetWY#%B0 z3!4bPGv7ej=N;%Ioo8c$o_C=4 zcq{z81GNl4_<08&hbF+!J8;rBTYGK#lY=L+g%=#HlQ~##w(a}3!o4VIg?0@Tx|SrK z^Z!E6JMg4W17*|HgRf70xOYyVLge-Tb(xl~B2P_`OA_p9WkEpqiWc8bqB5C#*#%35Jwp0a4Cm>R}_ikync}aP}-t(4=`Q|>U$ar(qiN(m=z)+lPcS8e9 zE%SUK+bt8PcAuTQ=2RMZn8Or0Pi3rQnrlVILD#!2N*T`& z?RVO96(zL{%96!%ku$V8i#Yw7^uzx=X<4$cZM<^X-_2XphAaQrYJZJb?$$p$kWtY9%jw`;-qjZffvcHW#`WziviqEa=|)L6b#7^`N6epU$6c9X1^CV42w;6*v`}@GkMi59O-7+ANb(ff`D0p zxdFEe8^ctr&Ye<>oW1_j<=>~Au^GmQEro$n3o^ye1ncm`4$2YYs2tPd! zxn1L8eTURCX0tTA>+fZq^4D53FWsn5kW-ZY_-$C0F)Oapw~S#tx!ABay13OS?#73g zyNtA_%&$f%V^(Uw%NUfj^6p0GivFvOD|VgB&Yg8v`m~{<*%oJPhB0DGRgiQ7B5U&( zF&fH6HFS3!DtQq-SuXSMy4T==7wB?C&B-U>cR;ZSe_4EG($~-SF{~+zKbSEczjB9b za%U|{Iv8!=BHtXhni0Aj(Npa+^mZ5b9w|9cz%wv-BCm4x`k%+G*JvWYFcS8cD;X958P8Wf()v-K5=1VGJ;IfxNdP`V={)cZWTI}*qAIKTY20Sp4E0l z<;NMkW?(YXzWHfu-{DI&a@$bS#~^CadamV!4$zX(qNR5^@jiy>YcJQHg$puQyw#sC zE!6Ot`y z?V-ju!&w$DGUaNH#?&^ZIf_RR4gZJ_hsnAn(LL-^}8 z;Zu69zpD4`eRbW1dwYl-`g^A+HQLbShML z{Vf%4vcB=ef67_QY!&1bvc3p=3i-r+X+~YSOm0@xSG)Q5PQ+BQGiW-7?ODUigF906656Q;^rSjaPzZus=KO?*HTLHSdddrdG(w zY2!ic$?5r*plPQb?7jBNA^NDZfO~jE(BBiz*bHODmheCc34$lhpXRWqDRW|166eHO zeL9EYjzxcSVlgx@HQZwP|D5JCgNL7TUCvzFkh=ZG{k>M;0T(mKI6tfG6E-F@NL6L^ zb}1W^1!Oaz=jK^z4L%Qy4h96ddjFoX`(RLsvB8END5+(TH(xwAZy{>_kV?aI#5Z5A zxJ_zv-}+T{Y5SUrqb)Z29Uk*438$9L?|di~b;mf4H=&iZ;_|gwXwbRbn3}eKWdO)cGg8%7#nYvI^H8EV%v%*Jg zzw+u$4dG5qCT8oWwO#gebkN<=5z;BHtvyf6(a#aw)HQ`1)W)Ch1HW?J<9r1hlLe%C zYw}nXejgWUx&b#eKb<*ag41rE8MwSK^uXY}@7h88_ z^3)0ZCYGJ~rxIpf03IDaYROK0M`k?h=8g9Q8J<)qI&R|8Qx1TCXMM9MpC9 z+}h*bGRP^1qSf^HSFuoKl8B62XqO%=<-pHUA$oNq@wL#I=lTb#`s9P9k8FRxTtMLx z-*&INgj3G0Qjf+`%}1Wkcij?Z2w3s$YyiWzCE?E43}eKW#z1KXg3q)4tm??J-*%Tn zQ)b15G~VvQXjAYckwHRz&VvfoDGQYaKB}^x%WaugxTqYQa-iL7&pm#`bgzw%F(xkE z`>fwPUZBy*$mN~v?<&-N7_{qNliu3hlQDF<*F5ZkckjqM>^`_EtyuN( z*eM>#9gpsB+UlF=#A0D&YG$_~So2KE%Fvg+Pn6e}$~OqGCpIIe99Ihsc*@~_QVAcJ z@!Zz|ADB@}V_EtrXTQhh`DZdV#;>)ojfi@^{Nq>TGG{Q=R-XG7!BP$ddot)$TdB-m zefB>4n(p?r(rwbe1@ATIPq#)cbC6QbzL)UYYFDX?cEV3NsYHRNFAggn-1zTy!*lmp z&e#lN#FoZDX$FG1%F@NBYl+>>6RL0V~d;1G0@$dmOOY?A2tHrOOl;x*_bkteZ> zUxs&y<66MJ`{CyuKOUEPf1PMjXka2`6^xv24l2S+9F%mk?dz-9y5-JOr2baKubrr5 zmGUC|kTW*J7+tWWFi4sKk&9bjUy0ec`pzlCr!Kx1#O)V-{7~=2Vq$D$v{|K{`B81> zVVUc5zXV$(&nfu&;1Z-Sh1tLMJoF2>f8FkJGH{~UG0zphzlir=YyW7whk*qpwG8(D z^x%3#TlDnjM!2YB%OfBlJnaGjyx(5 ztd5y27rS89mhhz3JWz`TdLXICrzAEebI9zG@$v>XCQC@STYi}@8f)+)|@et^Nr0xm5oFLaTFnCg@lQdY165oXWc~8oA9xqe- zB=w4Y(yc|SH+)7eO0Xx7N^-b$6a#O`pW>jLk4cYzYYxv>@`? zX8u){e=B$Vv@JXo=lFhKDZi8esKLSrNfI7Pi`W<;1GXBazuB0KA*q9Nk~$lcDP%5^ z?I9lleobT3p+785reKuHIQ z-i3g6laubuPasyo2UNQyyAB#qr4mgQ8{}`#ca(vbu(>+TPQ^Pt>v;`*~Wt<|o zi`l%_8Jl5@*wPm$y+E*f?6EMHO_Kt@EU(Sp!Fc_fz5l<1PAn!yW=2YZLN(6nb00HG zif^tjlstYjD_jtH-pPLMHu%AlZZ8_)TLxG!OTxDdxTk!AZy9jfehD$}bb2Lh%Yb&w zL->{f^~}dFuLOR)u(I=4XockAV>>^Hwyn(VL{4b5>rZ)}J`9_8(p7;bG>?apJdkk0 zws>kt^`}}-Pxft!NVudE<@t>3L-(=otFAR57f(nD?TjV7KXrW8`CdJdWeOMb7Ol9p z?DPHB(s!z>Je{!_#)vIRLIMv&R(}2ZOwQ+}|HMZvG8M*a+ZEQBD}xurVA+|dq+kCb zpsu|(pu;@)K+K=B4QGNk9GTXHoDS&HKN|P~=bR996qsr|6FYhsmvCDO`cMB?c46cB zC}-z|#||K;gL97XRt!oyu(ecu?fF8~t5o>(gQvGFl-aKMGC5;2j1gOk0i^&4cC#&= z`mwXA(!Og_mt}zTj$Q@%*c{)+@Oy#!b|Pa!SjL%tno6uO9x%u-{)AZ!u6VTvhPJq zYSO8;lr+JSDlQ<-KR!N-HGJvWl!!+G)7-3*BdwSA#i(CA>Ws}WMr`Q^k|IFlj!j&j zvUTL5gBrTKe@~IlQCqJ=)x!v5y3!JeT#)vJwfzl5IcRkPEz+`9SckA9CF~4Z;Uy)betp&F) zOd%Z_cg+)QOlFXdj_T@Ybs-Daf}<&G_AQx_Y$=hbe7yKx2}(Mk&WIWvy1|~;ity}s zM_RE$pAj|by3DD9n><;zygrt3?Tt{Lyr>q+2^iSZ!L@~+8#G_@@Hj5kKcK+A*4=zt zc-@;B&e#lN#FkxP9Nn-c>c~z?G!yj|buy3lTknCkw(@n@_ zz>T@sYLaUU-xX~7^H}>z;)DXWH8UNreG8m*snr>qVT{;P2`JVfcuri$3e)Kumg_xT znKJkD+r<^K>5Gud0A@Y`cp2bvaZ~k?%fYjGcNN-mExI}P=aa1spF>bKUkshrr01V2JT*Ga-DTZUI1+n6USjv6brb%tyJFmtFb>_8<$NA3K3}eKWVjyV%L~f4ff6D!|h27>|?5_OmngvfP)D=L38s?_kc3Mj> zJl-Q!#?i{X>geyJ>kr~zP;F4-P92UxjS`M~?X%BD?i7n?u4;A2m3ivG{v5f$pU4 zGDCi=eW-{=Sv-4R2VNbaq>jD2R65qTRMWI3=k<1 zwe$6Xf(@IT+_k23T3Dp5RE>>yVlgqWun=PXFZCpdl`|ZSeI6A;n!KRQU zk)97(*_g~ABlMQ)pq)UFhO5Vk|67lLj<$GqpW8d2>aNfpZqpiR-yF)*A)LDP)9{8qfPNCSN=$YmxljI!)>F_hZ4LdnXG%>YdT@Y5J08 zzNG*3ruU?=MonC$Xq@381R&c!nZJB!PbAY!@*{nXZF=`CS{jfzgCRmiCYYpL;iC$weifqzNs&}nN>ztnJS*_XG-O*7t~ z*Q@GcjWGWbTVr12)bjcZywpHREhlE?Y$-jzQlp;z>J-tJ!R?|iZTg+D8ODe$T|rU` zh&+){DEg`K<6$jk@uL$pc)0mIQp=H67P;@f2U}UhX+IghvdB6Dv9buVHVx7;@f2Ug z#$*9mStPLR{~77T+RNOWtj&BL!l6?c7&@#E-9}C|bSY!ro`o*>7)E7`r*v23iGV;x z86m5Nvqis*73D%c;Yc;_w2;aefzDHLlbcUnR&`oduJmDo!S~kaWM^!KF=9(!p!5R4 zV&9GwH{W>NB>QInDZW^T`#WS7Rzk)`AgxlJvII6JBS?Q&i{S|yBc$4qIIy3M$pX?? zb(pwaIVS4(<=dO3Ri{b%aGhv*G_~eQ9XZLv^8+(0#9jCgQ^HyW4aem1Zr!GRH#t8o zxi_JqZ25COr(XAcD7yiX3Y8C@NXf%Ij%lYtMVZkx?>iC43PSo~72{4iV>65qTS9_F z0f;>Ry`#J@N>Tag!JYui@6{Xq_RbLk&H9=c?S9ffKds<7-xME~*xwiS*Een#Ujc5U zKpU%`pOldA&?%gJ%EgB9`J&^#d|Tx$GliF~sY^jlA)X^+K;)ARw6RLy4jtlm{Yjne zILB4(|D`bazN~=3x13Afu1|0jAV?|XQ?^^#wv6h?E8*XYXMQj9y}O^~=>cA6Y=$vn zOG}`%0l}RYPyV~SJ8Xva!MB`kEru4$6I3gmSWFEqO(R3pel;1C-A%H})H3&aezr%p zTnXGrF@vlY!MQ8_i_2|+HUHk*3)I(|TTf$uWG`oX;Efz|Y9Y3|8P?^=mpIaQrI(+# zo!e0^*%9=E(NALirt7w%U*vJ5mM=5m<;kb)8&!9tqV`<1<^DS{hb?DjN}}fjWoK-L zF=9(skdy)v-+VSkbqz5hHQR4mQCeIUfS>(iGYH4cB9C7o+E2Rt4cV^Anc{j6b z9-q+9Dd36-x-XrW-Nl~YiVk>oEVRn@`1#}NZ0Dl_uOnmgd8QzzoMBkbeCxs7T}=IQ zX3d{6)%%VQ1K6bE<2zHG?R!5MRufJ+-!9AKTQ{Cei0n)kI=f+W7DzH>+zT;D*?$ag>SfsM%&(m|G7)GYnnFt~zy z^R!R~hDpo2u8BxLZ#;~g4oELSJb$dgbG+k_Y>|*tf-IZzSyg@E*RAqbUQ4ho*vMva zh!y2RYNQs)kK6DP3wElQZK>+O}6a(9Id$F9e6a2F+8EAUVM zQNP=K=3`{w-+kvZrv9G1LN|HZ^AFC&_mRt$-`enQGfH|AbFdKXNIlCQx%YdL%Iy2E zzi}0AaK>gBBes+WN=XnL`>L5c{^;!UpH8H`+!&$$bi?#B383>X%uG+0@%zV|z46Rp zvRMCe@%c@Evfc`V(i4*rq-*5)mxYqO#eC`gGnvnY<#aJ$+9{TxaLf5-{4E?Q>aQGZ zZ!xt8VuoXinqpFx75tcC=O4)gCNW#_yj5!=qmWb7-&*V`>dv9P&+qlkeqo;3D0z5E zX1BLlTcR^I!x*upJxFQ-k!C^ehGy2aqPFhhn+!Q^>sHwIxPsCRbc+`e12NK3sqk_L zZ6Jo(+T%=xyl+zUM6MKWe!j&*MTULIsfI4~+W#9-Gs(2uH%jz^S^6}8o8GlPdbonwvgqZkqSONWtzFI2QBJi+DpU~3!;A6K z_3gU7x&%?083kF%r`DOc5 zE&jLe*AM^7I-E6wtljTjAR^_k@Z4vq@h<5Of97j^CVZK$!LOq$*&aG$GmH^i8Uv*n z2=4QJpmhIR%jM|JPb3;HE@e3B`l1>#3}Xydz@ohbeqf})&1U$47S5N0V$KF+zT6<& zt?){9@4V`bF_yaXexsxb{Srp784R9-vWeow`V@Mg1%Vqn=-ud5seaYFuI~8JeI6D2 zJIxM@M%dlsL#k}N*c9MR6r|FGg{ML(j_drCB+-+35qtOxwr9sU6y9{kW*8&3)B}ks z5cz4x!|UJfO11P^SZpxYy!4tk)#wj6O+eQw8S-4lwN@#r*T%zbm&r4;{`t3-$*=zZ zNzNMAWt1eR2`~1a#I04LpxHWT)5MdGpA{wAQTKH>_%U|7{SJ)?`ZxhOO>mfCPZLX; zLe9_Enwj%+&edYAm+udCZ}++9jLk4cY^ev78X#C$G<4nFa*vJ47}E7|IkuaP$rLgb#KaN6#$*Ozd+JBAF+wH{MQ)hJ-u(Y&Pa)r} zJw^tvs#U*UZ4#_bMlL?QxOmAfK1Os>NeOwXu`X>_jOMJ2s5xFf%ja5m%|=ctT=CeG zijmIZ&M(K$$nyS_*e_&a88DlrYpydk!x*t8Do8Q`kuMMZcyqyK?X$3V=O_HOncr+Z zr+T#$i?NxZiN!7^wNN36M{b(x4Y(T_&4XErziCjju%f5v=xhWJ>+mKW8`<-6f`$c`0s9! z;P&y*?an^t$V12phi3-%gyU^dm255d`E{S&hLSY4lAN}h=J(Fn3}eKW#6U>~f+u9j z&1<}J@1la_+(9q4*UosIwC>mluKh{D%H+V!uTdBdba(@4txhH5V7 zpJx>=Zv0a(4qTe>;wvO^0B+FMJHq-0c`e8Q7T2A%py4xnDbX{jGKXvy5HSE+OY}=0lHN!e?fUrU_7>B33|p z3ADnd35nlq{%%IYJJquGFJ|+eY5reWpwXM1D}$LJr@4Dd-T(Vn&u2^YNXkd^h$VryhZ;lL86Is*R@~Wk z`?bPC$7jF)s-7^Ae7A9zuh>wJdoQ7x(95tremjUjg2I!6z6n`zU)XE3ny*W&#qf)E z_)bw#bFn+UeaLYyveNZutj^dBW5kw9Af5%0s(RCZ z_DFqf-)Loj(>IGFCe7y9XXJLM^7ha0b|`mt6ucek;iV66hdKuZ!P=qjGBIDO_#%X_ z%4J7J3trLu*DZ5#-@Ia!q#`mE)(*vT)f-}gEMheQ8FPWdam@5&+MWBcPjtCwOI2qn zb)8b|xMGaFgVYO=RJ=r5h# zNFaD;%)ck94wJfzl*~eoGwpMiP_R(|Cl%*Gvw-nwK z>xD;ns(CM;SHOWfD?^oaO4J!ZrDPb)OY8vjJLuqeu~KXYie zDsuTj$)LKI#2e_4#|TUl8>*%m99-AU$W`!CO-H7}rARG*CgC(8sV-bo{8z5`+~rla zi?4FuJGseurt1P{Y=$vnOFf{}0Kre(k0qC~hO-1#7p3j~w5%pk#`Pt*{D2O5;Hql4 zXI{Zk)jW&L+Mv7Xa%(oTk3f!y@yy_@N4_8@6)$Oq(W-{5>AAkwOC6phJV~2z?AzaR zA;~i{4oKlhD$+slszy?s>%V7s;*)JVdu|m-S!xcHgvCST=poG zoLQQCtl(?dv8x8k3;`!uS_r2W*@j&AMr{$lg&j&CwZcnxDeac(T2bhX%`ir6=?aui zAUIe`YS*z6 zM2>rEmlR&|k(?06c_Mag4aY`lGq*wPqkw~(B4tYVR6n_t8`x&YgCp+cYv3h?Y{M$v zuxJkvCZ5D^foHp4S__9ay*uuV%`ir6sRRua*aiFH z*Clywzcb;*ytkfteJOgbXH;iorZwkYl58E`<%E}VENnqDu@`NT)1t5zh%i%6o&N59 zZLP!W@G@P)+nbe;%L%0Pp}YjCoZveoG3Un7dDkpv+c`*cRlX0C-Eznon_-ODQW7L> zfXH1_{6#j&PYG6EsXaU3b(uVaBli+;9RWQ|Q*rAdr`rE@kq>f<9D1G9geQ6P{d=#u z06FeQZu`JXwH9^+n$2$5_$Kk2X8sgEP#3Igx>qjh%~cd<#{9WZ3T2E7d)%uo*lb|8 ziJ>T6zv-;Tu|@N}*8BaM@ax=g0eon-`$7APQ7Un|Am}B22*>}OLHl7eU~SeE3iC?JVuXB^~l4b znRqkU$P=`zZ3YH4X&blr|uEk$~PUH(jA)|L1?cbYRmI&Yi|Pwjm$N zN$L&vy6dkaZW^gHfE~(dTc`oQX@vhtCF7sz({sN4PJj4OVbQsO&=r?9{&%ELa`H0J zg&oTI3%2iyqVDnFN>2MFVn2OBFuYS zqSQZq&2Fg`St^Bc$f?LpQI3tt1hUXw+|e371MIPA4LlVIoJ)hJA}^B_FWBavH`KkD zTr=s*HVX&$d;j7^`%y|9Do^21GB8U?L)pvZ5HuChsiC~`+=OG-$_B{t3wDPuYW%hJV&CnI%`ir6=?#*CK&1W@zGvT? z%eW3J#Y~!*e$+&^_U?Ko7BdSY^V9Liv!Xp?(ogT%(s0Nyu7CE66fdM5dtPSmU`Ho; zdPc&JPI9++4!@Mm;r4R)jy>g@Ht?g9-2GlF->kQO_oMVc)S?gTBU?+7y*oG(kkb=A zN+mCI4(N_OSN&|*!o}$gyr5uVU~ucs=Yz1YttcS6V@~fs5oN(VQVoWbp3GBUD!uQIZr#-Ss6~F|gxMQU8W*N~a>iyDBes+W2`CV0^`_}y z&zZ$li2+|dVZmOO zc5F;WkW)~krQF$=j3I00U6whsF_}QrNM;AIF_}T?InO+Q^R7dicb$#cv?nb*?(~8; z|7Y#GiE_fyaOu9&qg3*;jF1OKAOnNL6sxRD{N*>kTv_ocUUl=O-zT1zhPWZ$MC^r> ziY!;dOC|HvP;T|*$s(-t&vhC5WvP{4msk_TI@a> zlQ|>}@jvp;?XuEHKecm04^wv3E<5e1Ya9X?v6ntx)-AAI=0qMu?L}mpXjqm$9B~}Q zPgM37#tQE(d-vnhitt-W2{>vqq;zBb*l}vg4x{OM_Cf1dukZDmIxRj>q}CamVT{;P z7%0U+u;LQEM>k~KEHWe;TU9rGS5m3y)O2DoGB+~z-I{k%m95f<^Uvu!6GJRDzMnLS z1EnbF{&O$eJ+Rsg*A=6lxX;1Z$2Ie%Kf{A>B+Q3QnW#t`@F?xwYR5_ zCpzBbdfecQ%`ir6DG!pCK;(fPCexRCsJ$1=Z|@IO2x>Mi>ShGjS!50t@-3ggFKoff z%Ud00-U(c^ep~D8_viUv(rId&&S}Mg2ilUR(_mpN4~L$qsZIRN%_}|cT)L;v>%C|# za$0eK@Bi{bNh>@%Px}VWncw+g@f5E^)!7$rJbYi~jLk4cY^e&AN+8(hYug6JT(0gDmw&i$s&{UY&(}%J(+9BpaI%24 zhKW2!2eFOE3;%cyz0<_}AkUB%vkjYGznR~7TCToz!Hl%a$Z5i<7<>8Q9+F>l=*sbb zf`vxU54Fbh=l1l;Ib$=75nJkkqz4fB<2jE()T@+4?Z@t&QMq?S!zH<`!Q}^;ZC=SU z(b7B4em-gLwD;?db2F9+&$H(=JoXtSt&H}>89a$x`rzf_gJ|=LX|2w``TASxES*Es zR4$yEr&2l%W$X_rt+>pGw|T7}2PE=t*tKOt_+ReN7wcIPx&rHS;+?S>#)vIdfl>(s zzuuyE&vD)4*Y_uIT|E6|e*){C06!-dGZRAt9Vvz%xAMeP&)<>qnpZq~Rq86yvyfB- z8N+eku!fDv7|PzK$Hrs~*$n38R>8&yX#jgBTCy=h+QpW?WLZKN|C64!OpR-yXSCWx z>4LiKFDN%j4()!Em)j)hHX*w7n~>9x?a{r;ZvS5GRkdErn5VQZVNKsrWgO*=+he3O z)Rc8Fs*64SUz!?Un9Wc7y{V^<>~Y3s7$dgS21!34lJTCo@yFs-o7j#%2%a8rv^ZT~ zFTry*!d26<%J%VQ6GOc2k=^6KFK$!GP# zj!k{D`{pLpD80yE_M*%p2Au+thx^@c zbu<|vCl4xhioBUH_N!xU=nkJo4VPAPn{>hIbr+vJb|^PKcJBDolPi&vhqnj3QG-;- zcxvwY^h;S>*y{AZUqSAd!;?}rR$dEo#%35JwuFR89xIbL&9_WH_oO%On8Y=fnDf8B z#ea2TF*LIvdu(brBL9% zr3+_Y-6QQ^x_Wyy$`RS4RTTsA%^hEBM04kgzQ~MzufT;YFEW1!Md-@PAdD@L@w@pVaS-gWvYITGd9B*v86XeDhetL_OXzk#oKWuM7D9; zx0$QoG?Y29SQ=Owifq}~x#-ocKFdw|Kd-1>Tdt77@*H_i-G1&iHYOuT`Q!GYk&Vd& zG7#wHpU%c)0%`BKr+i{#GJ!OBoVH&=%&FtN=u+Iy@N&EOwSq-e&mOAAUse%amBWrw zT+ysu?d9JHn^Pxp>jCLATy$;|At$u|-|~JfjEO(JG-m7mb368AF-Whi!%?`TE|7H4dRF=9)Sh=jJ<^j)yd!jHR)W;6ZEVLU5QTa~-a ziN)O1(8MW8MdSHrR)I8;6AtOMmt~%)s74`=2@;;+@(R3wYlbVeV`{%yQ^Y;pz?=n< zy36us>sT`&rzg6!jsjmn#{_9O!$t4bQMB`4{i;UG^&jp`FkH%|Hci(+2W3$hQo)6k zo`T#bM!D#4=*L{iUoP?Gty7Gp)r%=s&e#lN#Fp|9=_&NsF0)-LuQNJC9Nxa(Xamck zxO6k*aUSNIN8#fa;OZH;G~pGZ02}9_ z_N*tp(?kmQ&b5p(cRx8!HKx4C6Vo19}cS;tVjak=Hb4UHUwF z)kgCu5%+0qyW=Xa2+73PAg6<{WO&mUscZ;|zV^Ud+VTD^o`ok_K6Uy#$CZBh*Y1qX zFh*=C29XZjC#-m0Fh@@GR^~$Yf0FZ4dj5X*2A2)ctqKl@r^ENtGuM~E_tSIk@sef8 zH1D$htPo@TdevrqF_GY3j3`?bC~4?=Mc6>MDtHzhhIW?_D{O{&`-6!w!0xa2^M4P` zV?R&qjN_Vh`#KwrG!an_Z-0bDZ~BzxYs@d~${;A+RqFVpBfj}SpffhZ7_p@uM4Gtk zTDVtkY9e>huUAZ89`LkW=m?T@Vlgo>F^v24@~**|y9>l*kFVN%%Cctty8C|M)M5&0 z+ z*f*Cm7H(m)vMb@q?kI7_W*8&3bOi|%5E*24->>+m+@UFJD^5JGu{^;y`uyAb`phZhA_jXJN;FyH zA&?((Qrf3nboXz`Qx49ta*7X~u^GmQEwzDC4+Kk2yYO`BGq)2jcoO*R=VfX~?4CZ! ziN(a&$b4aJdEe_aYqnP@rrRGaU<_{6dEf)?@|ZvxDW0O1Y)qDr^yHPyd;jAnmiZNb z#Py1wrbe8tzkRlqbJ<`>AzsPqR9NskfGI@GqHVX$a`t^-9%;U%}wHuLFJsgHjsHsY$;! zZ1mOsCVck90g)JnPq!R$-XbTQLDerx^?+{CC8MQF@74>uW!t13$-!p&wZZZVfv4Tx zum6~hBjKd>!&@)OVMc4?e`)S@@R;&tarc{V0-oObwr$SX3}eKW#6U>~f+sY;PKpwb zkL`bWR%s1$l7vs#?zf=yLBcGf_3<9X)hnKE__{yy%e%t{W-C}bz2n=&QIZFBS}*At z&~CG*HXroFpkY4CsCQE2bcmkdt+fqG1r_^FH9qve?u?u~($~RTFDS{w(`wtAdz0ip zOc4ESuw1G8zG266C1-4gF=9(dkfZ@3@7xtzR_b!!CCBRi+q6otS$`Kb{G-+^5L;$B zY-go*%tJONOUMDb>Y0yMOlO=Fr}pO7B*&}nZx&87IPjrvB}#IlUB5cBozz*Np;X$G zixzmei>K=ZKUHZ9_YBuKlh*qHM{>&ii&WbDzjyR|=Z8qvJvPOs?AmP74dc%(b;f2G zBesMGN=OjAOa1v}kB!@wPClRUsPEqEhF@Jl;Z7_@CKhJ>mYLmWjvw9MuraV?_I|q# z_|dw&E=usDb=kfb!p}Q&e{=+Pw616Ey)>o!JnwhxkoOO9xDv|z z?oFm^%2t#_l>GsE-XRSa#=xh35Ut@M-_}{KrL(s(GU(#xlWJGaRYts6y+)^ra3aca z>TCJkDlM_)|x4>)5pj1gOMgCrmj$+m4v@SJ7-Czs0ds%%xVpJ;r( zp$OdOHG~u(61rh*Os0_buj^G^AJ%}me4h?Z{GM{C?yXL{&+CX<6O?o?S~oEu&V}&G zla>JmG6REiP>w8w<-S5x4$4CAS+{2`;-CAJY3aAaS2ZRGY%1QM>WX}Olvkb?ylz4& zOmdtUP0bJAHTAbX?|QfOLUZhSrGsS?ov|6lh%LoH90DRInM;XWFlL_`d`8PNAZB*R z|AqHzr(dKkhK2u8_|O|-(Ni*vRjku(m`E~(Dnv}V3d?Hv`dTv<$>xybMm#t zUp0`a)s)jTW1S~grBk$N6LN`xJ*5dx2ISXZEp6yZ8kOOX;t~v zpyn^^Bs>POST-gz$jTOv$GU7x77(^qkuUrtJolYTRX#k_^b6g=q4vG>ON@a|5BnEO z)U$PmT^Zw5luq{9GbEHTJ#|ZzlI~wgh+icUG+VRg;Z07NiO4CZ2+{sUDq{*t_WBDo zHcZ?uz4Xq`+DRr6C51HsJ=^giL<$?OYr~NlIf~So@eQpK@2CtHKT$7A?jH_-Z%;GwKT-PS0 z?dsIOQ;vN@S(HLiXS!q|zDdU6-MlSMTg@pZHuFu)!nAJ>7VN5EmA-6=Bej&=fj4gp zO1$46D!KVNqvXiP>phG8Yt2u^8Y(zrGmH^ix&oyW2u_}zP!ZTP!THn)i@+(4d!+ZS zoX7@lnP3@>lU{!0-q}3n54~$LUM;=)hnkL)6Mh0ra)RIkj>9dKiS|baK-Lkg>SOAdT9vXWbc`N628ga zEnkyq!oT+!o>nQBXWOyKXv@4YJmqgXnpQx8P5J>cUKM+x^F!`)%~Rs{eOuk^>m0AU zKq!LsdFRiUrvC}2l}Z7f6CB!tzvK1i?%ggtU+Q_c?lyxWXKaQsVoOyZheNPu>K)~y zZa)sBuRHtNucYr`NZ95-;4%ZcXi0q~FY=V zcY(dz^!G$<^nRkW^YUaFUVGMZXKaQsVoNcQGyo#=79{FT*LdU4(|z^En=Jhf)1YaM z$Rll@hV$X;t>q_7gRi%?xRwQ9Z|%{|1z&INDftP$-dgl@Gi;XnLo1efu zR=eC&`5#T}X13;Uz9?~g8ftQ)S(nGF<|A~Z%?sNg$q=l9P>PlBIkx8xuavO;Zx_d_ ztET&E=I6~z2`8u8^z)y}W!M|uvIGd-3*6`YI6mM;6T34u!x*t8JWxV{;MWIV+H@O8 zxy709k4Z6{?gnNxr)KuC;W>`)&KvDqjE4&Jd?ulguxfrIUaDzA~;SY7HXQ~Bv#@K?n` zZU&)eyVfKmEj)lDh17S#8>_YHoR4R(S^s$6YRmK{jwu=KQByAY&U40Q7$df{1W6qr zQY`SdyI{o1N|u7H^Ou@#V{e!Es{p#T-O&8bs##InMQ;hYw{Li{PDqMPQ@n33a`VNj zF$vy$aSOGCH(%K9orE`Ege=40%@>i&Pmg^nxnmx^vvDjKb} zh#rLVYOH}aUp!l;NX1X^c695DV2aqnl0Eg{59SVsxyY%g@jSfRLP*aChfLP zqcnaN@6T_@U7mVz(g*89zkXeeDkxOxMlO`Fr=qqL&t&Bn@i_#<5+}jGV79 zyXcMNZBxF=eaFI3N)}4eM29VOY!2IndUS3O(>qP<)(v>^pj$9Lh9|#c{$`g&;jbQ| z9Mp|Ubs4ezxT07-ORYtgtk41=Hw(7C<&e#lN#Fly>=>bHpGuW}xczK^<(Z0-k z%WUem=J9fygKtT*oS&L=;`8gc$tN#7`Ld=z{Jzn2xfPUDVP0KWfwTQa1hjSGcFLiMJ_vU$T_Uv1(?p~>u$hFhm1iA3(dWfwG z>!=XQQ{JNPvFs_Q^ND3&7Th|w?>_HiXKaQsVoQ>sBnH6_idr>myY|V5tUhE_w4h*$ zB>VKO;ED>i{ho-{vw7JRc+}JJ?$3MN~ z)w2uHdakS~sfi15)}FVl&O9Y?e^FrKd6b)9dwH>^m8aF2E5zUTu}$BxvBLY+ccqt_ z?|q!H8ODe$Re>B1!99-{&qYTvs%1FZeXh5+OK>R2+79lE8$p&bfKOdDhb(1K{A7FR z@NSuiKYwO_S>7vB*KOzdJTUU>$V&%aea|Ey!RNZ`fh2@QVLB+@Z8Cf3Vc~0Uba!)B zrMYd3agh0gTxRr(VowLF?&p{*BnGveQ{r5$^=ryP?zwaIoUs|kh%LoHoDL#o?Rf+Q zL@!SbGQ7oDyQy)xVaKX`Cl+Hv3$v$|9GdZ}3g&aS71$qgk^OZhgP{genm`sgc-Y*6 zFLLm>vjx6Mz-z)g*d_tJMUJpd0#2(+4;MaPqNXWewk=p@$4yTuxq2zPX%#Wl3wUfN=}e|Flz zb>dQ|ws>^Dx$TV2Fh*>t4U~Ey_^PC{e$59ig=g&YyL+V9C#)9>z3#+fY+z(*QRsf& zceUupkm~S8S^?J!W$EpgQu^GmQErmh6 z10v@?+hi+vK4Wg)&hRH|I~i*KK0EaiQU^iyymD+$Wn;30>}8YAsh%i&W==zkYkW(E ztIze^#>I->$G)SagVFI|0!IOPP0fNXr$gDtXjAy?t$z6Rm`e}T?};WRPQEw4Y#xqu zFm)z;Jb3a%H^aW=YI9c2dysc$gXavk-tNA;kDaj@#)vJ&fKmViFMpGM>rH;}TVdwX z=$5ygvnOTPoC1{+B6XZO44g8X|d7k_UCVHPeeQcLLC% zTQh*wi__iJI`$5(u_iv^+Lj7ZGmfq;XhTjO(|5qD7nJ02`=DNwv~2FJ3%`>;p9xR; z&aO0Zx-&Mz7_lWJNYVh2Q(N|Sq@I}NXnxSsB}7Cq)7Cn4ZYh8!~5~6pq;{vlu1rN2>@1Pa^LGMU1C;&79b>gqz>kbJf9j@1MJEuF1cg zQ*q0TaNN(_BA54_X{FM&d(U@!X0I-0{%#hwBG(z4VT{;P2`JVfSn-O)`Ad`96R$Gt z{U8#(VPV1lgnDolVF+m{aH-B|WTlB7<`K297F1W2StUq6e46qB$>TsR#PZe4KX&<(e9#GGO)|coi{o%jAnP zkwL%T^6mH&-{5#$VZq(0ziXYb8ODe$#X!;kh)i{nHxX*C&(4?QyK!4Vmmbp-o1rbyvMi+7kC# zvdrYZvgc0W?Iw;bEKMj~jk!nQbpc8`m^Wo>Mov?cqpcJFzvGE6QP)C}7@e^h#)vJ& zfKmVi|E^rvb3CdjUgmkhyYq(g>R1-Pg?35}zzV#w5u0_`41|c-tW)xTaq#JVE4CHg zn(ZMUc*<}0<*iRplFIzKs@%woT%KVa8*)&>*mYq*DsvC`r+gL&&qko zRR{K@GXK5%t?%~CyB=n?vAF(;P5h-3c$oQ-M=0H zzvOIGiC$js$pBjZ2PEK-M8HS^z3U0j^&{7Lff45{*zyKm;L(eS^d=#0%UMr11-e(y*mCk^?lgr9=hhvpe<=F%ZT_SAobMYz z{S+qXXoh>}8rW!tTf=tvXa+NTFKjf!YY9VMMfDASucBkee0=TFJP)#5-tprFO1c@w zRg>2eDd=d17xk;AKib>>&uTiEIR6U^*S5ctTV{AjeMC+-OAz;eprjimzHsjq1))io zgF9tEy19oO+IBg>8Jl5@*islM#Xzuwiup{0&Yf)nN*&N%tVH)T z_^H{RW@>CqmXHB1&!UxVOqP(MNBWYcVOZV<_rE7syyD%eaX-&1F(v{>0FEU>ms#a!f3-knDchM!klo+ciEBY7;VLn>BeX3hJxfA;z) z&91byNgpjj4g5InIAb%65nDonBn=R$qnhTcH2HGG^5C8AF3O8qkNe+G231FlkcNx< z?t8Ecs5tE>!>>~mt8Rl|rzjnj3O{VtQ+yHpIz@qH|MlK(=#oy)Q&4zpu%68{<>x4a$Ts*4r>>6vtP(t^+Lw* zj6*fA6N{;Vp+#f5U;hGshM@lj(-*rGsVPr-$^h8~20c8`d7Ts+lNqF3@mkf(#sob) z&|~5=!9Cl(&(y5CWwT*VH?O0!XzZ3v6Hrpi{K44d^;)$YdUzoI%Qw9cyMM5(G@)se zH+z{t%cJl8j2aF1?%$8!r}THF^HjpAW!0mX=QKGzChd5dhNhf#-yp{Nk6{%&ZyU1w8Bm) z<|%v1l~|NiLx-BlYt8QASH`T|_xuObYIg6?6Ed2UQx$cbUuRb1NHuFE;APCJN9Whf zOu8fI_k7tsrF(N6bUCA?+qImr8ODe$eSy*o1n)@AYq1Ma$#Lh%`;=*x{uI4wdY?sXy3^5^-fsdh}f+{gK{XIrfu9++6jyq{5%RXw$)ecmr2kXou7jT=%5==dDi|#90#{i zX4^dHNi~}N50>2X-;)+xeZk^;bT>*08KA<%YopoFZm>j!`%d+I-MQ~{XjZ@rl~1OQ z_e$b%q>zoNNQH^URTKLs-mJ0#*Cg8d-Pr0Td|7nc8Jl5@*wPXxZ9s4Z-}!UzDps91 zdwtDjF=nNhn*Ox;PAn!CMy3i|PrRMX!y#`L;1y+fH##Y$RwNJ9KY|^2puSBJe&B(< z<$d^p2cEk`;0GRfZMI|Zo|#hoOmBC?SEa|5`#&b%laXabNjbx=@#3{P0(#&9O&c%5 ztXrNQf4sl##R~m=HGz-ZO%2!o5>7dr=d(!tyL?s2?&#?_mv?U#Gd+`hxUbO}n_-OD z(ikMwfJnn_BGnFO{jQ$QI&=N4uyTIU>I`9U2?8DB_xz*;AL8d)<@4}TbWi6!_crw} zrJodqC!gv+dKk4iG9uD}*VYQ?5I=QRg?P=J_&42d`@xAkTQB<0bS~nq(R2{zK)Ev$ zsg6M^LAEYGQpv{ogyzQcFP~CRy12zEIAb%65nGA@r2q(aOYrWl-?O0MdGz)4 zzhD3D_qy?5h7*gqnTY|{qQ_^9t@!rKgsk>%6-$!2$`BI*X{bPkQoL|nFXgqp0lqs7 z`38B(Gtut0QGN1}Uo~{C;@6aHp9Njt>M+I1Vd;fw8@`J5 zad6q4FuQ1YXT9d69XLvp?Qh}r(AMS08d!>R)(NdVeAU=B%!6}Un%!;&XKaQsVoPt3 z6a*r9=hxo-C7kcq<=vkw{HaPgu|IRJ6N`zNu^CH|l)cQC!>8S$K4_G#N=k9vD)&67ajr9ouRpU}E`Ddb=E7o}cGUi(5;sc8GMXkBy!P-&Lju}! zH6!%!H&3~Z4t{$dIKv|Msdl%*4kxrwReVXkv`jy9F- zH5JxQ_Piq6Ybh$4S`JM#pi<{csZ~od4PEiNeZk@Jg_1-`0 zPR*N|?Q`~{L7OJuH$G=qu}-nY?l{_tzfT1ZRxjW=gjiW__Og&1&i^$2luyS zP3}iYMWf{s@vY!P3lOc~eJu+QZN2nh*2RLP?7N{A%jT@U8iOMh9r_F}mkzA`@Nk7q z+$PPukP5-_lQ)E%x*n`gaK>gBBewJgN=l9^yCRCa&-r){Uz zyUT8w60dw3XA@30N3})G#9n4z?lZ+VLsy0_v!?aqU)%*@rfp>ME5c{8$xP60%~yoHI7V7_lWu zP!fY+`Np{E)&E_L@(0A-{2nJ>1Oer1Ahu?US2Xfw4(j{y?gTiy_EOkNH-_X zAf=mU7ms%O%3pcE@$=6!#v9yw!c&`@>O`n-cM(CE=NfR12iG&b$Tgu zy2)c!7Ia^L=bjAcB{H6ioM9^-Sf4_#OZ3uH6#@kS1A~{)OkpSs@77bAPDt`e?tge; zwf*A{N{#1qqYqC{t@yGYIUSt70-umXNe8zj?!13CN1IE2)21q+J>Nb`d|j;NjLk4c zY$*ofZ4l{c($}wlRq%znvANKKqU+q>@}92)cgD>iyGq?RePClUgKT4Ww+9W{LAqT! zsiKk`*MxRE_pSS|vC5_@FHPc9LT@Wdnn2VkgR*S!I=dE{COq+9p-Hogg}e~k36blR zMN@n0dFr#D+|D_Z+4Aj|$;NY6#BijEvoDa!2I=Jn?Pnf5TVn9KDbx45$v5pqpVFMM z8ODe$^?*_X1Y1p-c*LT%E%k!Yq1>y5Sq$$Y&RzpgG(xXM)G14VUyG>4@C0@(B6uv% z0WXzyH>VIPCo0Ful9T^-6pb zWb6cz?@8P~#2RX7J0=R0EmTYqQ*)u^GmQEm1*| z35eWfccSoX`=+?8qqpSQfA}i#wuwZ7lM0#Bglb$tYx#;FsWMA?i)rm!Rax<3kGyBY z;bECpuCbFnO-R;YZT|`7>n7sy4sy~*UfP-^7S~LkA4NE=T#Jgf3w1wNw_Z=6?#{y5 zBAt8QavhrCjLk4cY^e&AN+5XkQvJBt=G?VU_b8lkJI=M(_Uzo3PArxtrWO;lUj;1r zdh}4H)~xd$lNJT;kZhU-psqiB0PNj~;(# zW!Qp}h;H}}j{=9@iO6@|Zr)(Q4ynB9kH4hGm_`4#GT%!$5#5-t;P7&K>oM6=8@+Fz zZjZfkN`=pW*BP5(jM$PJBmsfQtyg6~NBZ0l`fgwT(doU`soe$My-qA91{UUaO457< z8%wGtl`!~JGu+kv>h$Lb)7Rd!x*upD^NOt;KpB7bv!jjbI)_VniTk;t?yr5YAk4-rJ-rQ zKQm|HgLN;mUU}wN2F~j$-`KSU(*1#~Ss-GU;+4VrzjiiX+FHS7RMg|sl z*PP;1b~yC;wI6%9S4&_LSJC4SC{@)x#5Mrps;ccLtd`$uzuYTgz@)Bkba{P>llL2x zM0D@RXjMhd5}3pM7it^Mtyx*LO-8vX>BsWEjJ3Rk6VZLIE1j>VzhbaBu2S&e?As=f z96JG->CV^;W5kx+K*A!9z_#HhLtDNk8!wn_sv*6E8xaq&lKcT^RNM1(R1G`HNDum ze0R)`(+6~?obNuy&Qy5N%Nd(tjM&l_B*lQp3CfYZdQ3kAcN^|Dzbmrfjbo@qAb89k z%k8NSQxwXi*K82_;A41icGwc5I)A+lEP3{$=>QavSdSci90^@Ohwb)Ml%r>vqpu%1 zq4PH=^@v+`sr}A3KXVLzAg6=J9oW-B+R~e@8>WXSuh`%CTU)4a?$?!K+nuo)#)vJ& zfE*6NoO_Jg8qUh3MunHGDNQ_?S3h}+juVTarG`f``Q)=HN&x z&ws-EN>9(8Wq4&|KXKXiX$e=88uy&pBhRR<=#0%UMr^4H;$RTjAy(NHFS~8xl8Cnb zx7ZA)Jy4wX20Y>qJwTAxExw6>sL1>Hgu-CC=vB%xWlcKUz+Zvs(M*rPZg3 zf398lMbEK(vPI6(KQ=6;8I^?N{^i%}wg0c}lZMxi@#muajE5w@;(qXuAswHZ1d)E^m)$NUX{jpE!4rLcyHXWOhvC>z)BD-dlT{R z10iF8_vNM9(DQ|YON^2pZAtm|LSt{u!W4FtIYXo-3sMR4#=7fof$q&KlPkW=&FY*q$E#%OL^=sn58bSj@~!Ouo!7ceEn+z2NiF z6aorj#97w(Q;63)J z=!z?P&vIsYdFxDHa;@j9kKaqeRnmu!ZS8^|W&A$P_|Vq-?@RZ!z$Ug8+RoSvW5kxI zAjt$oZam+yXUXAp@?WNe1x)P>e!eBQ!4W*1Zwfin)?=Ro8 zj6q68mG$iGThC3n(ah*GyS1&MD`7H9n!qwP;`J#Jy4}NzItObEov{((`^3!?QVcro zG{-79Ex+RSFW#0RtpnxK)K7EZePW~v=0iuu?|zpl9=Db)<53Q|KKYN8kz&hRXKaQs zVoN=s)BwSMHtk?LsDH$xa{Z;0F5RIrbu=9yUuyZK6xvlGI5uLq`S#hyUvr(@96T1u9&_(Gyu=~`xor5d1baHz zbo)?&TT|1&w=Ir&ImI?9^WO>I z08R(c<^=MU2#gB+_lsAFU%a#-=a9-z&1FUkM_TiH@3g z5;i6y$e6iTsy-W&u>n}K=e`a$CQC>?V$NgWV*W+_;r7*akM1tH_+#q&_Q`%*=M38P z@uL;G?%69U3%2f=*y&%|4QXIcA1|jj^tDL`zOuO}GIhP4!p*z0bX9Pa6F(5^-#>JC zOm;S$Eg{gy-rU}H=EGdAdwN$5ov|6lh%F_7qZmv`FIKO!XP)N$`*l|J%;lHT>aAp_ zfW}ab&Hqh#D$OjuDp2q50mYyL#n)~hKfDjzy1=p`+UwU+iaeXilEmQCs+A7f;_d>l45BJbuR^$uksE}-=KbNOCJCd-}VY3?D?Vr`8- zCY-R?U3>;5ozbrK^5+d~H`mZ<#S-6o=}~`I8GmNSlK(-B_a{ACBzX8ms04C4`Rl|xU`&VQXJbcDg z7~E5NqzE}Vc^b}VV={u&RPqz1u`!uIYATCspySseHJfZ~2OEXDr*0w*qAIKbZR|~uKRo9j6cgAKIBesMGPDx-wWSwYRMTLz; zi_iDPA5*{1vcAJK9oz_lZsd?r`2*j`A$B4Lwvhuo-2>go!TtHY?nT>B2di?;86A4I z6RrHCr9daoz9TtaW;I+~VEt z8egXFkUNW1+ITZwz*gG)-?;mPo?2eu-ulM#-kLw>uT#AJ$?%vnHp3XPB_wdl0287s zFLK_VVbT2m@V9Trb_Xu{C@IO{#A0M>Y8-QP-j18q)!EH@lJZH1|F_(6;mQXm98<`s z3V*&2{HQ^1=9O$r7Lam?U9ca1)S&0~J3A5r0NIb$=75nCDqCmJx}`Qgo6h2-gr6MNq%Y|FC#K3h%S8ZuZ5 z*)_s_VON`aC7k5FDev(4{O&n(`(iSBiVPmEpCf6C zl2V3r739tO765eFJITgm0#So@rS|Ks6F)}X)avT@J00XY*FXDBRQ5}hv@%*B5j}S2 z&A|&jY{j!>O8ZrL%M?vUld z=$>?m>Mig+>C(%Otlglvy{p3bk<&?uZwF!sb6HZM**bt_MyrY@ zOACwMymQmrI+*-|Me`3XT0}S`LdJy;xG99v~Xeis1al8w~i^$8Jl5@ z*wPy~0f7li$#qj6RQg*QeZJbESbcoUywv{lxJna&neWwh{#bRPF8T1+V)biN&)tz< zvEaTtN;(**(uA*lXqP4#)32@SW_odB1J4eY?2RkS5^AfEZ-7CrRglsF-?r@*bM8H3 zPvvIeX^Z;s_3e$aO}ERPu^GmQEyaM70GN>PH@&@Z%gTNEhNW+wxwX}8cXHS@3-5B^OrU5YmYgBBeoORZAV_-`sC=g<9XO8)G}r?tq@<=2pvb%H4{^ekN2;S6_oonZA!<}e@YG0 zj%~tG*9c1?r4>!PUWOSw^9=PrqzN2&ua@I?>(?h|Y=$vnOI6@x0w#De9bdpE^4qm&<5dNbZ4 zpD|XXjE=4`Frf5i?myx_suN_P+aRs#_G`OuXUq9RA;@V$R1e;pK}i$*JzUOC=U-F^ zx#ub_tE>Jbwu7_K8Jl5@*isKTIe-c8r_1019f+H0aqo{hDx2!_v~ZJ$QFQp-tN-T5Ib$=75nGA@Cjl^V z^W#abJfS(CG>Mw#@Jc`RxBLiwxp&xfU2bx0m-s33S6 z+i01=z<_P_lD8y3v>x$nnW8cCfAQsP2K8x0P8FToZmOMApYk6$tw_S>|GbgP3~{qW zx%FM!j8833O+Bk3{fo~#Vy*+1Gd9B*v85_-G654^>1`F?3T+o%y_$SUCUk*^{lzP% zomebQO^lo;@A%66ri#rczIevdDaFr@EC}qzm5RKjtqG2!d2N)jF?gi(>huckrb8)} zv;IueFFDF`AEm?@t$BzaN0Sakq@vI7Zl+!7**$TG`h>49r)oV*TPab7oQkAZV5@n= z&AeF43JOElPIHUcbv#*XXQ$lpyLryo3}eKW-oOb6O!U4Je!<0+{HVTj@oFU_t}kc! zoF;(oyfiZkxTz>{IH)#6>EE2_Y0j6uk7So0gQOzJoU-!v&+yY!xU-|+H`RH|HnK69 zK_-lygMwg-tlec|gkLZ3RH^vP@+Z}5g^%qR?wR?z99!`Ed}UnXrUnx4xz z{hRq5(VAw$$w|RRL1Jsi^o7OoUo;;i$>tU%vy|80cgAKIBesMGPDx;5<>F0~HCn^o zIf$=v4?K2V`}ogGao{b47Lb)Hyd`fYx9|t}Y3p!0O*&z4AoVb>VGQ3Pl(-+U^^v!d zD0KU%mq06Y`=}S*RZZT=_0b!vg!is0c>*iS{x^tRXn%AoOB~;;c10=jlAz-%7Kcu^GmQEtP+BQIgRzfKX3JMG#w0=%=piOZC80 zk9&VQgr47Af8OKd4iV%s0DC%6ahSYX<*&G*opzCo?W*8&36a!8I zV1m`Yg4JT;yDsO5#0N`uOcx9PFzu}qi@C9d`SpwIIgj4eo>}*&Pf2%IM(TzM7AeS; zjklU4eBGPdi$?gmH!uHmHYO7ju<7n8pWu~^)Amd7b#J&2#W#N|=2B%9e@nU8#Cz(x zwNBkX?30lT9NM*Ayw!|hl?}0n;t%$rTa>m-`w;{FnbH?;pDlILQ%YQ%d>|TS0ud>p zsjY+$$Ei3>RPt@{m?UG?sPAy0lfD0Tl<~QyQDC?Wg+3}M-K4@q6 zZL_cUZvOqD@eaANVG0gk<*K;Qfg&&x59Wpo&g4LwQ>Z>>7$N?FgR ziLjNj*lt}ON+rgWw;MLF&DuCyWu~Ki?SrL`R((7taikip+ejtG9lrKMoLXCtO}VD? zZDv7xpuVJ*l`}TO7_p@@(4FL@}Q z=}4fk#Ov~$YzFtN_sGdfR|{SUp(Ll*2_M#Nmos^Px=FN1PS(G&r1ZVHGd9B*u_Zik zN&*uFYc5zQPf^lXx=3td(|jEP>(D(?kQOgw428S!4DwaXt95q^U*DvbeZNlP9!HPY zhxR@H1X0q#h-mS8>oY?S&cSvSGyX#jys@`gY==u zfPaOcV=pW%4Ai)KCO$hj*Qj98Y4M&F$uB-Wa_a@p7(y?>G~~I=#$*9$*$SO)gI|K_ zZOA=A-0J$*V*!Qx_k3AB^Ri$Y$E&F~P*Mv8O&4!NRXpqQhk2<{xiXY}otm$`N}6I4 z+wyHO3m#`8?_u{gM67>ADmC&qWE|D4#;upYeX9=csaAbcZyy9VxiH;jI1iLAS46F=vB-Ek& zYMN&8<=mg2E)Px~&`lZY+Z5rOGVCqy!#8Dk?h=7-%8;_~Pfj~FG57n@k6HKgWu?BQ z_I+XC`hrq?478a8dNrWbbC(OoR&DFk*l}&(Di1ElUokGCY(M@ z=PwNZrniBi@j(BXS9e9KHT5j6T@7)@W*8&3lmt#1VB&+vwQV`}yj+P3GuBVE*%386 z@96?i`e20Y&2hB)#l~a~nddQD_>PUq60*A9i^qbE$r7?LkZrlbv$NVSA`Y47PQLGb zbdke8{&(V8uTYW)RcaS+^9l~IqZvH4`8Xl0VP3n;byzIS@^;cIeHlr^uI}2E`!^_| zv`NkP!P}%r#fRzq)!(1w&Cu8|@9pRJ0>@faD)+5C(&dcJFh*<%2@X)Ve zXEI1`oWtG~eQ)+{vpb;V!2~TnaP8@G+4~G$e0XlZ6IdB(zH-S!{YzcR%NI`;&GC8o zgcUh`48!Whayqp5pwc0a*eCpUTOV60+$)!KGgO|@?38@}`zdRYPekxWN*|W@;MI%i z{7I(`mc-30{+#pbTH%5n>Zfo24e@ctW*8&3lmto{5L`X|N&MUCuTCv@wXWMX?dz|A zj8%u7SS*Z;&HPlpUPyFb{kw95?(1i>yl=NZY5WeEHHPf=^02uD-|gjbXA69{m)C@M zu-#tX*4tsby_{B+E;HX*WpO2h|DCzeiTCf9E#&}y_gzffn z;DH_USCkG-Ltc1KsHU*r%T~vr@b|t{lw*h6Js+O;YRmOju_9MNHcId^1|<#s{h?TO zIoMYJ^K!G=^qGP0IKsS+I%6}85nF15q#qEu?uFTO{Yqwy$di^orJqkSWO^ZV6x^$U zo}Iz}@hki`L4lji@Ut_VF9+qS2|Jux7rmpDX_@QolpTSen;JTYQkw9#{S7@k!wbs| zlLMG0qW(K(b)Q<~Y_2zP`{X@GpXg5(>_<)$c4pYqL}_1S*?dl>>R`tk+ZV6=cs9!V z@>yqWhB0DGJ)qP8!6()hCMxXw@T!twLA&FJugRwy`vgJt4zyXKE20l?mKZN@fHzCn z!l%HSC1M47Yjcvl^2^h!m^Yn~y~LrwaJstVCra|5N~_h|fgjo|aZl)lHA@C)VE~<4 zt-5Q%UY|O;&EUzb+J#YzKV7cq5M(2qJRCxGmRl`8<>Koy=g_WhuJv}R8;kgBoUs|k zh%F&Ok_L!;|3qe$?*s2Ae`huv+HW_lFC{VboD++=rJ==(7v`UhW8>7O7DOx(y;KvC zr}Ls1lyH~~Axj2~HU6v2T=91DfcADMI+GfEb7fP=Jt-~QrPXG77k)i$yB{gx@)`N!Yj31t z#ip;YbmZ8qN1`S%-OktyW5kxiKq&@-Hx)?7Og{DYZ{N#D zKH5v093LOQ;+Oo=}}M}x1=9ZIRi+ieZB z!Giz#W4fmn-TyX*8RnZS?LRUcyY+NF-=^bpkxwErO)bol|4Ti+ zU(~f>)$fStg)-k}gswc@0!cWKW-Obd|^VMF|u%u6QiS6FL zxI5Z`{HvdMN6U?rbmQ&I4{gTMV9@^WRi_8n@{Nt%|6Zz0ikR{#=GA01Kcq8HuopPK zA-(}Czf7AUEKuLE;Kjyz!D_?zy=R@V8ODe$g+bB`h-4OUFLV-@u1){6@NDZzF6*>? zbHbfi3{A}pb2ATpFpo9X-;R)uN#`L-rl%@&tScMUP)`&d>rN@^M8WBA_w?$D;mAR9}W{rQvNzdf(#)=C_7p0Z_b+V+2k4D^6metQq55&x5)$NS^({(!b5ASa0lg`)-W5kxi zAZZ3fCc6LpEz5Fy|9f_Elb@0cL?@c)$~dtYo0wWYWBec6wn{qhvbKwG&+0h}Ash66 zf@&w|=o~SVhTg%G4W|9SE>@&JHy~Pp=UIK6iGufo#mEVVN(1`AYoVia)SfgPv;|I4 zqAP>n^>gXI^Wv_|^pIiRYc%sYa>5Dz3@>m{63)X<0zy@9uE%*hDZU6ToN{4@;{GmY zY=$vnOJblT1Hr4L-zrS^THAW;L5TJ&#*X(>Uitk*?jQ5HnZO71(JGxQ?yhYP#y7RnJw9owJ!?zYtLBW&Fh*>t2a+B@=M{H#i$}8#X13OAIJ&;;nHW0R1*tHR=$-~2>i0BLgAet47OjL2 z^?Qdus1-aFblYhD$FG@^SFg@Y_|Wo;7v<_~>eNEs;lH4TiI;pNY^Wc;ErXH;OoO%- zvhodY3cGcV^X!5avcq@zc#2xWclnUM$Xa{0 zcFoLB(ZBx){H;;#_%iwC=LwJKR5wLQQely`_h2oD&K)V}GGyBxAS?Li?KHv6!{%+9 zULYr@sD5}kgp!ZuublsY9S4V}(jnXnV&RXKaQsVoP|Cqy!=(zrMG7H!tz! zw%%pB&R&WeIlo&d1zn8#9WYA8xe)7V8*;~g7=F}6bColZGOX9rS zwGU(^kC+VTh>R!vbZY|D)bLIo!o{%*4kS7(*V*mtaeP|W(YuYkp~%T2W*zqAaVqlV z74!cOr<_xGk#{e|P+#?dgwsmgt&RIyg=S1z{qmW}#TP!7*Pc!9{U+s% z%`ir6sS1)#KxEn#r~jv(TIVlGD{+1{^R~RyQ?Yh%Q3Aa!$a9Y${I(z=PtbYRkad&_ zol5ZAg4`9J<@+cyM|sq*5acztRo)=sSUq%o)U51#={FC9)$19)hHgaMyHZ?SOleT@ib(hCQHPwH6q947Ei<$7f5M0|p zuP;>#xd%U4$K}{=_{lm<90Bl?b@;3+U?=N%r`!(QBqqM&!~9>;i%#^1&3kyWr1FRZ zN+L@63O!lJ^RFCqFb?Y>U!#Qy1Ilq2ZcR}6XA_=7PhnXiZuUDv}4d&Q+nrcN;?+kw%uU(p8o+xtFlUWNdHBi#T9N{Y~3f6o~{Pgj} zKfj&ZDiSI^O`WkB#)vKTK%xaiGS5{}T6jzOTEqcOLG~M0*ObLOGJ>XlpywK>@l1!E zYvAb_2|w4s-Qqd?Tm!Gb3v5j0kOh;MM@ z@gSEZ^jMbQogD@}*T4&Y0~ocB-J*NPhCOHn9M9k2)?(?39>YG0%ro65qTlxZ}7YMfAbJ@o==fgK+-!Rp)3!Uygee5Og z#A0q@VjiV+h$ z{%HuMTW&Y<{oQ#*rj=<{+hk{KhB0DGOOVt7A~*fmVzl9z)F!*{!N%IHoo9Iew%!Mo zE3heL1J(8LDP<4GF!+?RXqX{q`+JiZ4H!`1^Dau%%T<}jPVd(85}e zULT>Po3&4JjNbgyNM4raZdvalXZB^fK&vx0!x*upFi?tt;DDO*vKcn-te4N;lbF)) zEWP%Xo2e6vk&&roU{A)iADh}_d&BfkSWo#n=dDrQElBGHGHBv@RhNy)%o1#jci}TO zCQEZL+jEho!r4VeH|qZN9Xh98%;lbAyiAuDWgdBOrWWrahQU67vhns*XXEbT7m{~( zKYH-F^#8&&(>^1omLhBHsYOUpXs)ZS+WbRbmcLxIc8@j-?<6*7Y=$vnOIP4%1rxLW zSt|G0&#_k9IQ77X#V5+zUFIBfVllBWGFkld?p?>+g86R>OZb<4GzbitlJ*{wS|CF! z?(6E=n9LyiIo!5&!rQvuB_a_quddEW`dXmNweioJ>fn@u+ys=vLb26J-X(glwr+hC z3)pQ8_?N3t)c+ZpbyC(gonO;jR3i0fG5@t{KlpXu?ft88q?Qsy|0jEM$blNw6U}pP zUwVJYcE+AQo43J}J~?AEj1gP9fqVZBulgCc1E;nNgofOBW(^*WC1I;F zvw+t1HOAjI7EaTReS1=W!-E|bj5>>c5Nfjw@$^yV1l?wee?JF>%bETyS*PCp{i2|% zIad>hx>r$}gis5P^ikG{)MigU1)L{S`5J4d@&lvH1{ZyzUxpXKaQsVoO(`bOOPW{xhUA^7cO3 zu};|~?fDPI+x>Hk!Tn(9H7&@86KiPq$jL~(ENPo^rGD2m!Lz?brt-{satt{gjE
lI3^Ifrq$Q>?Mu;}S`F6@ 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%0Ak;@aL)Z!zERL4B4o%zJQ=KcPceu`!?I^EN( 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

    FdN|WNu{X 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 z z&FN3duTMBAYf-7SZQti|mIFZU16Y#Tza@hV^0%u zjKP}IY$Dz*3OntkeOHld+Cx)CXKaQsVoN=c^Z+8?71z&A*ULD1;HS4++Kg>~f(){> zkgqXOwtdaUWCW>2n72-VUt_|0;WFa3@m;ssm`ot$hxPFuHYN*5$>ZO!h>a1lvPo1c z5`Lhozj9)rfLBD%aqmAr@EFyhjkaqZR4~XUI}tHfgb1@xYq@GX7n&>#Rx4s zu}k6%>WERfr#{m7cX0eg&KFzdOtyZcpEIrs8y3 z)aI-GOl6JMkHy?k(hAKwM8mKs@m_=&sXZX;#yg|j>oA|@$2OK*TQ<%JsYJf=CI~65 zcz;DIN*uM{PB(k}YM^XX_v3_@A1Ga z+8VW+SO1DlwR1k2Vt8W9W@l`MF=9(Skn{i|Qy2@cKN4Z=e{JO^p}S{G>Q=|>Rwouq zQ$r)?>lFqzOV@nm$vbAPE28FXVQgdtPA$+QxHzMH;RA3%{*T~CaQUsBv3n~Q=UauB zOX|B54hMW=2z|A`NeU&k49XHD$p6n^98y6pL7Ky|4z7A|tnJ3DTl%N}L``m<_5t}E z;2@;b5@3#0f>fki%WTbCHrc3P*2Cx9BYx#rUzz5N%`ir6=?auiAei^<-zTlxHjM!2PBn^PbMEjms&jWXz zUh1CNv_bN9)&FW&1`xH83=PL+`)n|6lG-!QmP3lMM^a#zp9p4pA?_WH~*o_&L8^@xQR|MbH-*EBewJf zN-q%n>wTA!+wwX3=9*W-B3ilPr{u~Afx0qGMvyeYvtSb&lMy5xcrmYLV={)cKSUyO z*qAIK!?A%g6sM)hXgl^d7sc3n>X@I9Hk~BYVu4bs45D$@pfEpvi01>B_dshG|4FXU zQ|1E$rb17d_qzB1cFKIW7Hl+)-cx>u^6svgr@q*YYY~$GJ#yjz<_PpH9ZFJhg2fk>h}JRhW^c6 z45#G91y<;3XEFg^+-(um9UiVG&N__dI?p9fS>UN~bX(eUUwMc`!oCu0JJ~%6z zB?>13XV&~lx*{j`Ebsc88)^B%HwdSRSf)&;={rqJ7FntK`fG2Oo)WWg+j@CtY=$vn zOFfYE03v(EY|D;je&uA)`naUiIr|yQq}P2;%oZkQGMyG0hBwd5>Na0f6@7MfBV+l2 zb>PGT9VIcX-U}ZkG2FBfK1vc4cbg&W{w|eEx0NT$vrYQR!@h-|?*z)x)A$GB@fRRL zabJk)?~u`Q9sC8zhYj`~9i7XLXuWe|ow2;{neWR>DC_T$S|;)O@B$>3$>`|ZTUY-r z?_BZ6O5jrXQ;%)4`$U|v8ODe$S%H!X1gHDEO7Ob8jt$gVbgOn*oqzbi7^QVpcmI(N*n|<$?O9qE5_a=4P_&&0XC$q|Ui~b+vbX z`AvAggQ6fY-JhUj6XfpCvu}RIX^$mloK3M<-M=gD>9j}MC|BnM4W@*X?2FO;8B{eA za>Du3*xAi?O~&{Kqt4aMOD?4*Dk?Y;PB_U^4j+kMs-MEe&$)9=jpe)RjE^Vk+dE@3 zj1gNB10@*<{+Pzno4>iIGj_Ae#z$BCn69sz-{{0*VrXpAZJqk+S;OlkC4J2@fjf$yKBAIK>r6|w#isc1=_a;0`s$YN)!%5>ZH zMW2!!PTlbHRdmK?7$df{1W6qrvbFSxdq+_0NsULTmRmNgp1y0--uvKm03Ci+U&#v} zeiaM2y?jac4ZG!YU4k>t%rV=sIX*#EQ=Is85R~2z9ezcuqaRHN3=9DsX*-yvNbH+9 zTSi>(U(=jgRt+ERg<{C*AblTv(gr0R#J_acmHDCa;}NGc^R)Av7kSiAXF6juj1gOk z0i^&4?*H1fDd)X{ver|B|4HX>ef)I6`51W8#?Vu4_morDRZbKh^IYuzsy}@R>x>4_ zz$}vyq~RgTsldi$3>iuj-SC@@$pl(zWKL&eGKG{Ts^RQxOy-awIdg|nHYRgOBS&!m z#x4I&T;1f&9-LkB=uO9mkCG`YpEyub6ugHVl(`W)Y7#JY2K2n@(FQI9ga65uu=8_} zd&sMzKRgv%8u&s-_}me8_3Ya#!e%31@)v}ZqOt_w4cz1@9CE_!9GA@lZR7(=LZiM~ z@p^16aK>gBBet{$NlhTKlv(@9 zJHy;CXTzuBFFS9)R#n|Tt=EgaC%N}HN}9md9?5^b3*`Zl{WdnKf*TG%<-2B{T&g-xDm&s; zG`J;;g7%c2^Q5<=}0n49WT_Pn;e{8^mq% zWLD<%G0~5x(bT-VY4#odeay%yCoc|OKcS?Y+qWnGKTvcb`?2YQ$7fttiOsw6_^vZH z!x*upF-WQbk*S*=?v_jRN;#yZ)6&r9q@wc^Y? zkNre&4;9$CH7PjmZ$w?g%Qfzf!6r(^27l z`(fUKCc9Vje*UVwdJrX5jFt`ru875U8e33NY<4n)mZCs%&LYZ`K@ zD5}9$IuxX-{+f65`PHd+R_m&tn4_|@{sl|JBxh`fF=9(UkQ4zTKX0sT4NMiXR(ZN< zhehrw+3Hg&^`LVVKYdGx3YW+i79kt2(b=l6=$$YP~W-X8F{3ro)yMFeXoe zFDvl-69HdV5L6NhUsk~6v>3juz}micQs8~t_cOfP3v2zPZ~0}EzLH)Zgp!`D;BL{2JY-?0@vC1;ii)u%W{SJoIloUR_C)_ZBYa>RURY=$vn zOH`0#0wU|&rDH_TZ`b2qdV87t(vV#1KhJ)E8?LYwC@=ltD^SD(D&Z?o{Pm{5hhTZ; z$b?(k`)@zY{mZoBQnTdQ_DFM^s8*EpF^IasK@}IEL$E=Ef1c+oW6Be+41TfW<}V&e z{*>6HHj!f+j`UF}4(|q+oOw9?``ehpXKCMxr*3zd*}uj%Zc4f{Hp3XPr6f?wfZ#W} zm#ztEZGZeSsaSTizBX4MLx{c;i;0=3Nvp}uc=aQdThHFoclL7B%a%`%E{7B{kWMi% z7s3TqeSojC_furtXqPni`!9peFs-j0j9;tg7U{l!j*^N-OBv!DIMrOx8K9t|$P){U zm)y@>XjH&m(jDJ1ldGiv`9|baR2>U1Wl&O)#MSLt&z|o*Q}k=gIo*v;OO7>EaXVu( zj1gOUgQOr3dH=`mpWn(H4eRuure|;6rtI=|ksYX%fo|C$=1Nk2M|m~FV-xw01=T(I zzgbW;sp5mB=Ur8l^q?O@P zl+=epPeBQy-AD>@Q6jbQkZ1Dgjm|Mu+0DOas+@E9BfAzkt<jd`6+jGoUs|kh%JeMk_-g@+PO66(XXHf-QsF*H+{P4wC$k9 z8c6bhO!DBk-q<;;0O@+;fQ`bQi*^;2zgduc@z}1#um2tl%t9$vhI19vybF4abzq$( z^g^e=v!c)oodTTy!LC!EI8Pc9; z>QuEx;Yc0L|KU|oGP%1bUym%Nvi!%*gE_2Q&w|lY=$vnOGgkVfk^*ZyWTR^ za%$Q3oe=YXHI*gsh3@n?8f zJJ;=B@dW+5Asd*aPt`6=(XL$k6eZQrp)v|;y#XC)q2XR*dRIn&OgDUduW^3ea~I(o zTp21F7SS~-$f>5y6kZvjq?&&Ab80IeY!w&ZRF$qMto z()I<-Q7@{N@CB7m+`!tk_{eYYu)ZlI9dJb5U}G|a4B!S7Ox~jUY>VL1BQ4Bn-#=eB zaL$t1HR&NrIv6sgM^FbJbe~4x=S|Rk8UzkjqGjnZvCUij+8cGPSE)vS=8C%{-ME^o zg(Dqw*dmo4nM&rrzns(%%3{}ajZJQvo^@N_@Ld}WSy9e3@s|ujk^D-c}6&&s|sGlpv(>ib zML{p89mA18y5f)$$f7D1X0M)>u=t?kNt0`Q?539R7&&7zj1gN>0woOyu6+FA^tr{Q zB03g_e%#|U@!9#~-4`boV?#^JwJH--J113?Dl?~tUz6Q?#rm^oC8*+otxs`G+znr! z66k2g23w!v!t4oOpJFJ(17Dvax+Vp_J|(Ef{F|B>OMS>3a~uC>e+s;LK8FAPy9TAm zfmc02J%ON4{tr+&!s7cqk}>jT!jqS&&02pG#@!d^=yDwJt!%v zI=sc=>hZ%FuX}#>S~5h4+?4+7?TpPZMr>&hlA1uIXU)x^`!A-NHk+*rTX)grtzzYt z2qzXxGh++JNv8AvUcd9aIqH1F?cLjh7ax%>1^1>6Ap>*7EX@w;>x2)?1)MzAzxs?p z8p{-(Wtt{@ah8t9V*2Nz+^CLqg)O!fEu)O1(1E#tXr-wc?Ps%3o+MW>wqj%v+Yu*bHODmfk?=2ZDbWtqZs( zXc4I^xHWpdkA4cL=r&t$rwF=k#aiq>{7Me7yI0}sR-~VPgaCy&=V9wsNN(7WP;cE7*S6ta*O{QKc)zglA5XNL)X@bv zN|}jb@OrE7o95D0rs8LQxvRxocy&a6x4vZa%LC5X3}eKWk|1dVME?HYoL9ov9lB`4 z)qRgY9^tN>>T(u&6`ZKkQur!3-_xFKOqP(wu2A9$?X0uWej9t2uipM#C24)zgoAB{ zK7`Ul(4_aUng{Pu2S{6g=rCGKY-5*BX(EZkVVT@2WvS|KHN25O*Z;fuG-U^lG%;BV zDNP&+wU*aUj}8=EtrYpHapk$=Wm{{Vu^GmQE%ks>0|dAKQ@g+J@TFhrZ;XR?x}FRx z7Th!)+@^)zfo*Ej2)_f{??N(rP3V)@lU&g$%a$okaejQhcXj)%k(UmFrZN*XWI{sO zP;L5c`CtAVmN%PkCfB~|mAlZuwE{;vm}-QS4h|jDNV#dCdcHp--FRPx=)%(Ty_(M0 z3}eKWVjyV%L^5jk@5p*)6`r5|{Q3qd<5&5nziL1&SLoUlB8E(?znZ|;rl1X(G~SiD zVUu~;udG?~>A`DrtX7=qT7{Bo=+SPS&OQ8wOtc!#IVC;+JUvujV8Yk_H3uI(H_|{( zHPbWT?N*djbGK{JQxEs4y?8r zN;XGz`df^BjQ%Th?yGLqSuqJEtqhmBp4nBO8*G z^i8_zZr4IMt;{~#*IZ%kyY3F^)f>1XxU{_+E(G-$>ROkqAGGOX z?lS1ACd9cqL~ksmclwBMOeiO&cR61|Y;|7!zGIVO2 z`45O1(Z|-wp+RjkA^pO91$k2j4%gF8>)OlaNlu>XjU$CD;D^^XbKgn|>M(yuJi0OH zNWd1G;B{R-E@#S|u^GmQEiHl41_a;U81wIceB`a~%q8-z_cA~9tG;u0Vlgu@Gd^Q_ zUq9R0@7=pUKW7~)xWQ9>De@_}9x{ZiAwW5KY2gbZPF{N8;`!CbOZmQvV8rdo6|YvS zWhtCMNkog7V2f)JCoc`u=-N;!X5{1_*6gqnm!30=^~Qvyx8}~zFP~315iJS{W}3Oz zG+q*cqE)jM$PJBmsd)oomyJ{nt-*U-&Wm#R-$gSGW5LSCE=i z^pY;ZE&>b8+g;qJe@kvgjLqi6RZmxPU#?jbaK{fNsVvbQO)5_lq3aI zef4UKrN5aoHp3XPB`Q!NfnW#6<_(IL_w>^xSMv0yR@vk$C_ye+hYrL#E@+1j#0DNb z2_J}+JST_H4;)y46YZuIF z$>~auwE0}{C~o^)XKaQsVoOPov;iW|Ns1JkuHVXeZmH|l_xnFSo}tb1+KI*3)WURv zb@#a!?g?5^0l%3N`6M2+=^nnm;>i1IrpAJMju$QM z(u;9B@(K0ogke|8&@dIPn1q<_c`ET}7n^SSrIk)AxAMeCEMb_|=1Mpft$3<-aJRyW zw|~nPlo+m6y`Zx4nd|mEXKaQsVoPtJ^aH_DwJQE@mDzEKVSrd>Qq$Tx9# zbaTOP;tdJGQc0Ee4V{wHiJG<3?*0CF{(Cypf442y zd_xju9Uz>XR-1@iQE0!qZ1ICvB`s|?duHjds7b$a#%35JwuA>sN+9yLQTIl6CiPV( zcAj6nW9H1ls~^;*oLEdPjZ8M(P)wY6eT%ck^C#K-FVl3w+AZ5p{YTkMgfcw!sjgtm6> zg0u~iU(W9g6nGor-%#(jw&1Lrtur>m7_lWuP!fY+n`bX888>sC-?87i@lKHBx#lH| zn&9yq=+Ln1`+oS)Fxy9N*wC;%?{)alF!$&8-nV31BQAvNNfqlBOZvVJzQ{812TD0a z(J? zaF`bp3&jjpAJ+F@%ptlp^i|MotGCWaRufJK8;?{lU%3#v`wYv$j1&JFwx8~sRx#m= zGd9B*v85PL3V`6vLbY2Xzvxcc7F==U{r9-4z(oR6oLEfFObr_OJe%rnL~r;0rXO&8 z(Okx}e96#t43I&a06$Oo)g7Kz>F}#Nf;P`xzQc89=ZA+!_;~mg_tZCBk=0SzH270X z(B|#XGmuFi1g2B#CFEjN+>+@6HfMrbPTk0f_P=jugK|+6_EKZ>r^R)8jjbz8Ymd#| zKjlJ98HdW|R#j(ghB0DGSCEtfB0XH^Wp$@_#UROJgJBExQkI zSHD?!e5dS;fQ~9Fj@>spA!k2954=Ub7AR=zY50M+0S_1N3pp~;o^98xiFf8|U91dn zeB_?`7$vn(Qpaq43On!?@3msXvX1dp6f5=CoxXF6bADOSDW+Wy_AW-LW40+^t7A5Q zI&yJMnpT`m$sXVIkx;(e_Vc#O5E&s{E&3oX{A|m{U+j+lyqSBS+82WcWy~#SuWk*D zJ$Lc?GRZnMam5!d9KWks!0YDBAe+qs|FEzznL|z>4B7=cqY`rJV8Ff$S6|Kb_!0E= z?w4CjqSm_EbY+Avpl&f6EkPK9cBw;$c>U*#LWg+$+oPaEyhulFAn#n=S|u)A_r!VA zf{PdCP1(JAyYI2SD&*9%D+ykLprjV_&fjl@wO(c8pS=&!1rOAbuz&%4J*ovHt*|?=M%+B$t8-Antw*SC z%FVuOWooj^l2B@!LD`ZeqiwRs8oGdiPHht=7RlDEDc`4k(_p^-N?>F5yH`yo38$4k zeKiTp)1Q0oO#Y!Od+VhVla*<~r$A?HhB0DGRgiQ7BGY|?-^d%^m~L~q{+yZkBNoNb zidJx1F@y}ZxmM3%V={)YiMnum)$O@i|IWT|x3x^@%G=jBPdeDP1SO>m?NVi5I_!!d z3br7URjSeO^MWfyrTq#2UI3!alEk z)3n7ZUDp|#VT{<)6ex{AFiZNgO>v9G%UHJmmD@5kA|X$DcNB6;vHGG2PbonPvGA+e zh2&jfSF`)hk%C>#Zh7rb+~!o_%d4a(pZb4mg`?}LL@8?Xt!1lOoXKr!wy)P zf@Li~4VE+<;f)Hc*_?Fjeq6k+Tx0Osqgn?WaHNz2kKnD9J$-fa79IY1Zo}iL_Fodx zbWgY{8uHS4Ug@l3fzzK%K}k4Nsf>aSU4N|B0{j)lWh#Oa^(i6LjPY^s=A;`7O}(Q2`kNupQ3>SM5}B?l^XHS>?^kl@9g^ z1z%&|Po9HvF4$3hc(sF6m>iboRgC^|wKv?SfFrzd!IN0~o0b=~oUs|kh%NPiQUe4( zUOM%|mP_Fi!#*z)T(i9_a{H|#d7!HqER1;{eEGNW7ke9H`0lxDZy6`DokK^ z8U`KbfS)KACts2`JU+4N$WnI-DomfmP3@uh{ z6P3vlmD*BX9}`%%ar3sw+ z5p}AelQAQ$8rrFKhO>Tsw%wJA2WAWI&$5bc&qp~!8+*bzxoCUWuK!mi{G634Q25NE zYvY!*oedM6u^GmQEs24W3_BAk)&;K97kItIQOuma0B`M{ zTr~I2lymVnx`p`JcfYd_KG))5ShLU>n_-OD(iJ47fXMvAJscICpFR{CyxDDV|5U@? z$vz7LSg#=JEMaN6-WC zssiZQJ>JW&!O!lIS*ySH`8|{8KQA7sj1gd5+v4^4*s%|TcHDm88>~SWUlTiS|9FAF zeJA&NLxCx?Pn|Z6@cJwHA{jXyT#|w}SW(hJ%%A#sKh8S{6b0E=uX$+UJl*7rrZYCf z7_p@oPzr$H=Nyj&G^ewhPQLwZa*gx7`OmMMHAGGa$Y(h5rD; z-*p$77N5u*Ee}9Ji8vwrn&{?U5uQJnw4n< zx~T%7?g^}8tGCDz-m&#!UJXAg9c@$L&PgFJlTUDFFF5LPWP6#P5VPK@lPKw9F!fKa z{)TmINncMw?>U=BY4#=eJu-J0<}Hdz`pl~(!pT2{aQe9Bq@kF0MD2pKbzTU2bBd5! z#!+3nFlTIrF=9(ekhB3J#TAboY`!OLeU^LaOIbnJgBQ&XM?0|?TNoM^CVV|+CFpmt z=b_01igcf)HA+V>9_`U$S!g8?VPXy-vAX_E+d;A*ZMtQ{XiZQi*fT z$uf0y@kb_|gsf9f!yoI0#MwS_RCmT^7$df{2TDs2yyR<;=d-Ols+Mb4^{tyf|HwtD zS>~V=Wn>{F5W0K5Ld^G5Yr4+Gmjx(||hr@r=nZ8u&1IGEk9>)h|gUZDVnLrDif06b^YiM zXKaQsVoPt36a*suHg8;c=h@7>!{?LaXZM#0W#2mJ3R)FuXq;NNsrk+E$lc8!uedk` z?9;!h!`22)MbNFRL3cK@F&RTrOAwB&tf>1Ft@(~^dQ^Nz*w?eq)#BzZ-!)TN@1PV# zcg~WyKM~u~+92u-z73_y?XTsfV^58<^w)nmeYGaUd0xC<;~Bz<=&n4|qm0{P%t4-=|&v_Tw@G;%x9#5bC`=P%o6 zzDh`W-KFW@FGcUx{pDGKazQgv;d4J6-e|rnzt(tHNuGj^L6-cynW0X*mc}2>KIV+g zFh*=C43cI*73~Y*WqeT2R$^v)tuJ)=>Ae)|FTu)7WWO|lE3cr1u^VKNjZb5#Chm7behv)oIg7z zWPMmMZP6~Hvir}g|Ja{8ilf9qN;wZF?*864nc?W%NaG*dl3W8>)x@0QWSp@X#)vJA zfzk{FZ`m7jeeacC5ii#0OYAR`>_z8!u{*Jtm{=GZA2G5tOm|tW&>!Bd+Z6ZY$xUlk zaJ2<({4fQ&u`!uI=B5LbcfcDzfucv?jh~>$S@6aW^MtFh1|0QO8AZxh|M80#`Pc-y z-Cm1YZw;67=Wz?H@k8>W7qU9-r#v``XM*&tKN>b;vv8BIzdJjLk4cZ0QY>f-T8@xlgcxuZ}Ri@YC23h{oL_&^4ar0RkC#to^{4%7$des1xh3kEU@&~ z#gvaqXAX0IKAUiD3DYJ{zxSXcUrY=&7k7G2T)1xbPu>6Ta`Gpw{5(UKmDI*h(DU2y zGrH04kk{PuZ|SZSu+cHY;UsT;w(0_?emCe?;i(ui#vJ z9<<}$&}@UjF<(LheZB;K}k>a7#n&slc>{JDH>s<_t;PkcaQun#cE&wcQeclvqQVw0=`W`PET*X z!N-P>N~l-Mnlrzt3EkSr5tp?3Ucp}dwKIiZJ3C`Dj1gPPgQO)8X*zLx;IN?VF2GcZVB0^q&C%1Am(Uw&Gs9;4;sT8Jx}N!IK4x#o~CjC?mTo^Z{Vq8 zutODwW8A+j{A3?u*bdI?}tJeZ{^vxZa;pXy>_aI z$|mn!&e#lN#Fk1xu@1ovhC9B@_BVP`DY@)#x)CRX)_U7K$eIVpf=tPhXk0rQxdctC z7^P-;TsrdhJx|E#8@uwg|D&Xd!P#Q@a2mQelfaHf#HuNJw^%HvDz$U$-Cfkw%_;lX zUt-sgz3WnZ1K8ODe$^+3`Ch}r`qx*L?;ZjA>$0n6cYt$7-FRO|2K~*QeQsc)5L11=TOGIV?(A zEJ2^{_Z|Dyx+Z@`IwMp5PEE^y<#Coas2y-bi{;bL(H0B-gYA%yoSL6I;nX4%A7O#C zqi3@-E{ZsK7IVQ*?X0ghwme~S&*(dWP1sZ zi9H*W5u_eMKDaFCt05bc2}BLr!DSM`!dG`L=l|2OCH(B1_(|oq3*!!=luM(jh=J(i z@4k8?4la9W6jh!gG>dP+w25MSin3Oi?Dfp`V_@chwl0H^>MEpi>Fd0{<4RjTC_LHv zMPb>RQ@dB%vx?+QbH-*EBewJgNkJgel{L%Fc8%cN@JrVx`n7NT(I#>E1$Ye(mJ?ni z7-zcs$UaS-EAVB{;)J>K9aU}fxBtwbFdcj^$2j4IO4Cq-z5j!p4sIO0q-J}sbNi1a zU90T+l9@$L2B7q)v8RLY%gkQb+?aMCp!lxF|I*nE%XvQ>Y!r3IW*8&36az{D5Nx=V z`*RS_cE4ETmb=A#*RRdecQpW~1L*P00>NSM3m45<^DB-{{lagBBeoO+Ndq9#ZGqRR4>S9uA9tS<3!Tch z>U+d#Stk}Vb5nDclM}pl^Ud_8=$4?M@5`j#CEB%nrhHlJ?tLh6>C84J<_kj3*bHODmi9nt34+B}OxSsY z!TQ-$qun)E8N*j!yR)_%G#v@GiD8c{d=ISmv7TB|>c7f+@^^7wlby7|a|{S##gbfDM$`t>l6DF2Ki;7s3kk zY2|~kf+{Y+W+MlG@^Gw_Kicm-w=VX7rNr)Ux2CL3mPENI4=H*4lSfJ(#?}JHzo(RE zP4wM*p`urAmeBTDs?OL9W5kw_AOQs;*-luAcTBs{uV6H}TU%sLYu)nOjL3~u^>^1u zZLF4jv)K`=vGxDQ4LekuqG}YM{$Nu?Nh_o`R!43l<^K;vW3_mmQ=72~?|N%J))^Do z3U(jcTzwu#<%CEp!3^HJQ$*yS{<|BSVkR&z{mMEOjlTZL&e#lN#FnZ+sRV*^F7N&q zc1-LEYkomfM*atJ-e+?*JF!@r8=F4ZU7vENKj;6tohPmD@$H^$uvY&Law-Zky$4T4 zfi1=GvziSy$HKcj(zDjWujUM9Qen8TmATs3IRgO6an<4_^gk$2E?Ubg@DOdoikeHw+!Us&0 zfS(BOd`uI5B0P)hQuvARzE)ujimBUdyM_9_%WmA8#n*E^V3GoAgJsw?frDAHU?;+B ze1@I~A0+u7b|U=xHt31)L2SLy6XD5P*7@dt-r17--bO)Rx6eG&`N=%G0XoYnngG2%!`=G^@0N*}7m2 zoRWNK11Ip=ZD<20aP1>#11G4!9M-@Y>^*DbO3Sj_-&;+1-Z@7(Cxh-{3BQaxtnx_3 z4UXi*&cNnTwEuTNy?jIJpS-F|KPOA<|Nqn(n_-OD5*{Qefyh<6ycWN^ml*i7IcjVC zf2#^xp&7!EstGb1;IPmKz80AKvIYEF8~>bFY)od5)#U;y&)|2J%vtpyn$`Tngw6I} zEFDg7i_m!FBQDj1oK%82ZbBEz1X0pe8hJHS@Z+9Yho-nsZ?V7eXQO^R%VmwL$n6{C zq{68UubJ2x+PhqqxuN9gD92j1Oo(D1_R zGPjWYjAxDV`<++}Ei5f2T#;as78ly@;kZI=i-M)MOuzI^P@M(sLQ zA>ylWUG+x zY|W7U_(Ju^F8^L_Z}8|HmYaheOlCijEfJL9_-)tlHaTqWPs{U$8?JDSymS!EYYT0< z1fCUzHeE>HNr{pUSdK8t`&tHNe>;=HPBe(%%Iu7S)vLvDBF{`?+( ztGHG_=%g3Ot>V5@Q#Iu!gjQS?K3#Zo+ADV>{Z;!dZ>k`ti6AWPk6?aR=x%%O?}u3+ zP6$G*Y$CGLJj~l4=2xR`JFE^`l3)_<@Bb!^Nt=Hq^3^oRWdl;0;BV-jdG=fTI<8a! z*R?EPPdv<2T&ynOjLk4cY^etl86eV@XH{|`&z|P^V{tmVzit}0Y}Mc4#A0k|Zffaf zlUvc}cCF>=t9?2-W=V1Xe(b?fsRRo~;u@KA>zGi8NSp3jU`MBdUTTU-U6Xc{K`~==*MoB6!e@s-GZ_~jyd8LcD zp18~Q+?)Knov|6lh%He;k_m`hf3fiBv!IV>%3Thyi1;1tXMQndrW1>WiLv2qe%~1! zE$@>#!(C_l6q@arJ%wo+av3AK7e4wQg!|~RI~sDwb6>4(NYsCCv+a^%V8^nTIJO1^ z!56WRUO5GeUWb-3h!Ze}dF7P4alL~pr%QM0tMvG#2D?oI9IM?3Cmb=^MthzoHowlF z_cQ*VAiH;>io(Uk`<$^E#)vJ6fszaqD^IcAzi7YE!gBtvC5bCO-{t+x4N4wN(EEp2 zvbM9quBH!2%z)iL6x7%VzkkTvN$-=Uh(g)~JC{XY8WNNL*m4<$3jISaSBP!91dD%z z-9Ln-?J@$BhgZ_#sJjsh=A=sIyY-&jRhD$|Y&zlOAz^dvZ{@vQ=S@C06=zjXV7v5U z!-eGx&e#lN#FmhtNrQob;l;Bv?*pgh&tspjBY5x~i}7W-z!-291l^E^d^Nq@rVWS< zY1&cn4QXg6yDxljbX(_CZu=s6FW%5KyIuy@aqthvv=S^O3fqvjjAj>kB9F7pHBo3? zQmuGVTmQPMkdoSysdYC#5l$;o8P+1V-fgm1+PY_>?O|Dt%JzNri|;yPGmH^iszRid z#|rK|SKU8P-T&NZuBTH^T>0uXd%-KN4IzCT0b!f+W1`mrU&&<5Ey%1o@!31-MS_$w za@>zLRT&tF-HeFn_Xf*2PT$`7O}Mn>ig-iO<>$LQG}yzekyqOXBeg$d5aSRS|3$^ z`j%qf6zl8q`HNnyk$q(EjLk4cY$*(pZYqLI7hu2Xrcs z!MTH&slZG-SMK|qxeq@55porGQlD_gjB&#-Pag`U^q30de!;`^M7%5|w7pyN(yIx# zbY`xwL9SC2;P)Q}qoj|^UVm-5*q0i85?;V5W|y%}K?VuVQU7~}PRU7SD~VIZLn=9S`Buvm@dWQnEfI4{I;6h2n{!Py z;pC*MZS}GtfdAUDUx|#-3RiE6YH4p>(ddlLFh*<%50RWsoxR}Hb0R;eFHeuFAnK*_ zrH_CAgQsx}A?qMDHgd2rnM0<8ouh?ZigleI+P|Oepy5(=@*nT7-!Fcm+zW!gIUB6b z0&AAcjD~i51G0Rei}8ct2jq^lk=I}u$IS+3UoTfTHe7XrL0!n#Mr7CaAKp09fx0n# z%gS^+iPjX?{bEjag7)wC^ z1WhqWI)F^$@HeZmFkL&=vOAt~!9J>U$dhsz@#l~a=nf4DnwFbTt$y3yl zjmZSkLD-wWC=-5(oVVxsys{T3QDy$ zRx58fr#eIA!0wb^$jK>~X1$$YZ4p@YLX~~V#P00~rcZ0Ov}O5c;R6ebIz{;p`ZjPG z<|SU(j$Ev0cfor*D9MTAo8;!=@4F69?>hZwj5R=VMr`Q~k&24mKU8ChFS|7L zzA)?VnfFE42r|C`?GQ3It6TJ!VItd2mhZ=u7Orr+y!zhD-!~xD7Nl%JKF>Q?e`WsB zugd3No%prJQ{S#)Y2fZd;T{FZDP*+yf;<`*tbbSr5((JO^F|qs+wxw`Q>@3Cdv)gB zdlfSbov!=rIf5gF=zoGYUvw{gt$6m~a(Y$w)2kd6p_%>09}nHT?u^YaMr>&b;y4ib zsf_c-EaUX1()oq+&HY;$cO4fNb7C>KFf`Sky2CR2n#qR#X;m9FRJZQCEqS6FT+SFm zcOBzcrXOs08rL%YD?3=??umH|q<&c>n;h`^-mIp8hoh+o6b;zcG7(5chEJi(^n+y_ z+3P)R=7xJJF0Am7cgy~YzU>vE)$O0)9)vYXf7!%NUaie5o#Jn5A46BwlM>}IP zj1gOU134Um_h=i$ykd{kl8WZ}Xz=OzCYSg((~!sWgI?)gE>rHlesz0Eg7>U0v$TH~ zS(udNk>h@}j$t5vSNeb0MxS64!SFtl6ITq@E-{+ja>sD`4c=*M7p)*1_a-Jbj7n{L z+*hgo|I}{j^mcZ7uiH;CXKaQsVoN2Ecn6VY8?S71m_5~EiMG%d>(e`=6XX|Nb7C!$9M z;I;pfx3PRPV+)tJb;f2GBes+WN=Xnbw&lY72f8bdRHRJFlHZwYZyR`^3R3StI!}!8 zo8U{Ch&Yd%Bk)^;A#34d5s{>q*DU0wZrbx_I>#53qXmO4Vqr^}@UBQ9W68lVZr%o) z2revovOq&!WXhYIoM+uDm}V9luQMf_R4mrpC%WrDFlUi zQ3Wq<^Yeu#KmA?G(r|{!@GiKIgYCSOeG{MmNIzuIy-llYb*QE>gKa<0Klzm?>44;7 zBG_g*bci-^}4J+4)=K@}2EPvq|k|vbl$Oc}6Zv<&`=#_xhDM8vOY+bw9n9Lw`P_W(lq}sJ! znl<^dO!)?%tV7rxZ#{n8f|6S3I`S55cM`S-@CO5Q4`86eap*uU{?i}_*~r`7=Vj@O zWHgO_`5pMkl4#VBpv6^;oLcNz;3IEHrH0Kly@QW;ZM0G|e3f?e>E`Gfo%=JsZg9qC z7$dfH1xhCnyvDTn>iw1ewj9sAcLc;d?yPh?SOD(JKu?2|hzRhQqt3AVI#;<-%SMy) zJYsB`eC2ac;vVm&KEz}Wu{B1p!(EI6E{0`|p&1)->!~{bEt8V<+5faBoH+0Q?J|zI zcZ8pR5^QsA*Ah0v&xRWqrc6|?)D(GFJ28@9*%_N*jM!2MB;G+JU+B7}8kfu;JrvU0 zbS~@NeD1T?3!GRiP0h`=cdU>!I-m2T{I)YT!x*upB~aRc zV96y)u{OG=Uq^c#VvD)()U|J(*azfk9%b9t@M#|KYE~1-G$8AR%ZO>7UAN)WJl4m1 z;L|*MM_pmlJfd2lJv@-1Sbycjgs-PPPZ#m&E%f#ZO|#o}-~_CvpmL zpA0W>P*RBP0;?HeMOvXx4%R(S6m>qiWclG2&e#lN#FmyI4gryJ#g1zWHhntfx{PPP z{U!eo2gBc&L54#hO;nW&^Vpb-A#8uKgKSL3kV=Tdav~ceWE3sX%#4i@GOHZeEpY1g zoM6u!5m2x(Fa*QE(P;h&x)PzbxTOYnju@FE>E2DJ~(REO;?-4{D z^!k(Y^;v;|U+$;n#;u!j?M;~d1ast)#ZMet9pwGmb>lPfnC*5a;td_1rJi87`pl^Q z#u=MojM!2YIJ&{atmcm6cf>U!FQ#Nzmu7oQyyU&5>BM4eWNNazSo)jrRlmy(&%Ss~ zKFI87sFJG#Nkx!>5@H7HgZ)3i_8oHse&gEgU%7N$l-k7~746c;UK{4`Ns&fLL;+kR z4%QE*Q8?;UPh=H1?FAOLK9b*qg!jxzO&7YQViKV$O*jz+#5{4^uVGZYXwE!N!E7;4ZmtxXS_JHpwk(7u-^53KYXyB?ISmA zuwI_`I()F+kS#xTd;aTt)8|_}?zeklFZrcgI_icFO7bAGj0p}hg$~va=Z-c0b}mX8 zv-5btebWak3M@D4rMy`*xp1oAisi`3Bd8i%850oW7x3tXq=k=GTTjUCd`+3p7N6gl zI%6}85nDn6rwlN$xa{6q-V)XY>SmYTKFXOC-w|@*C9XD#;AJu7HcI&u1~uJGj|yMdiL&Gd5-h~-O>}MY-4&45>68#{Z5TL z#r97(JH?;;<-FzIcf5M8v$r~9GmH^i>H#MQ2%*Itwq3U-V12FamKe5q+?f`KZi0tm z%^|%RTOV$oFiV%&t5#Xmb2Pntxc17G0}O&!MsnN-hh;#IM?z|!k`wn$!JW>&f1gMm zdOT6h`)u)!6GtuV2*-U`x6=ci4UDH&@4FaX99nznZlrF)1WRXZhB0DGC6H(bk-P_1 zrLSmK6k5DmIm~#2v9y41>pdqH6LT~3`G;Q>e%D;eF_G)aUC-IV{?er(C<_FFBT@)1 z5I}8n7`AxW1%_xo5V2Nze&+tWuAHLsDwISNQ8%L698^n0il#3YZO5y9Qd#b z{~^#lgpgsC;HZ_bVHKHwO0Z!S{=a4n+n={C$a|{LSD^AUqMUSNBqokoB-7pD` zIt(3F34-6UK*>sc5*j9FPi`qT@_j4jEX8;2vPEpQv6F!kazPX=f~{c^apA{$JC$cH z&CGGje5=L7edcYJJ$TR=n_-ODQX3@wfJlSayXH(5%?~fkZ+&9)p!MG2Pdj2EDFxES zA*Q(TJzI{{#rdPysTNfc^xtLvXYu@{y`SozC(c4iDlu z^cjt`&izNfZ|x?WRATM>&qzjkKCoLK*>~hk>tohyhgyZUIb$=75nG}HB@zfeaU!wB zYp1;bxlN57+gS4a81gg}omebQjEtIhOv_2UY>=+p!p)Jn+tzr|?%WrkrI4_T!-%<% zBRF0He&_-6<+(w>+jkngabv&rg;P04;m(qmT2+gFe>jhlqTusG!SP1WLl1)B7jjTC zAwA6Jhpu0E+vEA+Y}%T6b0$n-Uac3gj^QSb6cvv+|2)>7QTU0jUyiY6+^@g2y)P5> zE-+8ukl$0}= z%A&*;61TgPKHNgJrq6|0Su2-*)>4lAxOidHfq&u0eVtL3 zoACFlL+OpXyI)$)jeG8l%`ir6X$+KRAh_@F#cv9~)fb5C%{%_*nYX!4QCpZ3i-o1J zWzfs0%bOcg_V)9+Tt9tz#m>9GB$RQ^EG92GF1drL$|n5R-vs-1oxg9BE+|bT>%fe` zIpRX~hE4K5JTr?ZBQ9lg{63$VzS?_d+!a09sJZqw;(tPs%a-J~@P-Xa3K0!hxc!Zw z=<@i`+x|S0j@-I-#q@+THp3XPr6ow}0FklJa-OplTyeZ_|NE=E)AE;sr~cn^Vlgzg zG&SF|eq+_@;|He}y#M!6UVN4F!isI+CJ*!|ui(^UY)mGQhBA>`40SeN3#qlQi935{ z`&pU$`2kC>9ojuC%bC;%L~SvoS~>GwUW(^~#Ob|>djIa++G6%@$)t~Egi}$P@u9P_ zT9)BCug)4M%xvtmZDBWHe&vkKFh*?Y4U~Q$_+`+umgmR)W=(bTd6BqVx^}gcDx)U@ zGaHi`Bz?Fjma#FJLFSJ9vi#VXEFjA%1-vrs=3hB|fP11TvybfcZ9%vCgrNBkpcm5xe%>Su6(jNjT^elR2!B7Z@nG%kp1;@DF&>kSeWKg65oIhF zsbtA;hp%c$Gd?{-^^Mc_UkBrtR4aGiwdp#kcjvk@Hp3XPr5=d4L1b_7#1|K(CdCzS z&7P(sW^thLpHr<9i;1C;$y}EYE^M>%xgIejMZb7%!&s-b-VEGofv(s`K0`7%O93_s zfOdvt&_Wj;nbYq3d$?R@W_ji9a&BN(M@cxuHd?Z*V3Po}Td7S+qlMmu$qt4CRl;xG z^`D+#pT7CPFJ29+cN{nh6QqQb)lf3Y{p*XZ8!l)~RheUd{{=^ew#idxY=$wO#*)N9 zNd|(~IQw!d+Zx<|RA*VW`hm@DgU1)wBCoFV=;ng2uA|^O7w_GN;fE;bnN65}jIrwV zo0}X{8gIO~@Mc=u{1aRA>6DyuBB876g79AFg0%g8C?%)kJMRU#*Hj#B-dMj*LC9iB zoalpgBBev87N(~Ua+y2Vrz5jlkkbC@EhC`2K&g3h3R>-{{Oa34> zCR0dzC0KuDy!ssfvk6;HsZQSe?Z#KG6W^ZhU5b(pM%ySz$B+gW?1A=vupWGXyk)(v z{WzC*_q1}8j7VlnMfLU5E;}J#rX7sbMk#m=Z=>Wru5Vhcv$G`qO4ibvX^gog1*dhA z7C2)wj1gOkfusQt**3#cC|dX6-A<>iE^D<{1&4n~=mDn#=rt_5=Q7!t%pvK(YWE!_ zi>=X)EHGP7%?r$$_Pg7^w0fxabJ<8WyVcUoxEd<=LM$Yy9p` z?)g`;{=|*cJYgK=0a7|B`aHev*Y}?JFMr*) zY*ji7hlDdLO0hz_*`ks&uqFrm+$L)84;jEgm0O#nvdy;UsFY~CU9Herc}u7!7Wu-; z;8G{}pbAQIa^U>cu9R|xYsI-wx?ww#`w~n2vYoLR#)vK9L6Q=P43z#eXUPH%+kfw8 zr9Sgfep7Lq`#iW_CDu&0B~TdMyp?s?Fcz!32? z!YX{$)wyr?IAb%65nGA@r2q&vRMo#Ukzq}|(~i>D3_dQ$6fPLZII$QRnHe9R{)z9F+677H?H;HPoktJI#g4^mA24RF@{k!6|j2#O80kaCcl`D z9V+$Pf6sI_rzPR^R5|Nf(}YQZ3ynONZQp(`^}flY+1?90ov|6lh%Mzo(h`U~Icrat z?eRJ0Grhd6b2mO;nots1>BM4UW@2!E&a_e!p1^-ymHM$fOC_GJc`DitUL<7#ou95Q z){bMi9KW$~pX&v+gP+U4ulfBb{_kk200k@lMN+}lz0l1;zQ!+Mn}d)S@!xwj!P2+x z5yuMg_usZ%sOgw^*?k7#R8hU*O8NPZGgGx|Er0ih7ERQum{H6Y=8VlSMr`Q^njTyCd_i$F+wc zKeWvGPFRRM_&#+%=l&9BY=$vnOEDmaLvV@Ki=6I|_eXdd-fl?``FH%8ib0kWi?Nxx z#pYa5^YXcCqbAo>RWkl>Iv+jtX%e+Y)Pn0L!uG48ji@c>+^7Dycg572Uw6LrY1K$p zM!!J4w32q!Q2lCX^LFS|LnI`$x$#rfzkHecKx3&{);F7lJEgQMQ05G=H)|RcH7(mh z%g*1M@#kV)-6t95V77<)Z=JCj#)vIRLJ}E>ESux7+Uj+MxS5{#y`Og@q6cl%Rmio8i_mOK2!|vVl^)A;l77mz@gHrfVFp?77 z_zQNt3jFRt#Gwh)S))Sd*&gCYQl6>5)x5p(jxmGegU_daDe&L?*oLx78!1gRnZid> z8Wg*|>@H|Ov(B~5T=pfx#A)^PM@v>YV>65qTj~L&1_)MoBH(y=$9K-F*H=6fP~D~S z>SVwqaGEfM#JyfuBO8+$Wcj4#mX~ZymXMw`1A{l~O2&d^Pj}AZYg*KN?1;>L$t{P< zQPKq7Zty^Le}Y^11R!1yI`RcJ1NgHZIs+Jx5dfV59Kdcc^Zxjofh^B#Hgrac8alHc z-*o>6%E??Up78DuN}9O%H1*H_4+gqbI;SGOyBMq!k4=$w#%35Jw$uX&6c8ydC3JSS zh_(KVX2y5wpYj&Li{yGVOc278L$z z-FbfL2a}@z8f7AM3Zq1Io-)}_E$%=HIIi{_$ zu0u!%xxs>zKH4&o%8b8Tvf0+yNldSJE}Z;1JuYoxG~;S#Y=$vnOG%)V0m0QJ;qh;d zR_;Ds^UI;GCDfa3Zg?JOhS-$`w-1a~;W57^)r zmV=MS;cl?l38($96T13BV`G3)!H#`}>U!CoC<%>r4VI3W;oM+}zvJZ>DS9NLd}A_e zuJpnk{$-oH2tMBHp3XPB}qsk1CdYubCo<) zy)*6029F-*%SB(WI)?897evroqZ}8s!*7iWJb03g$-)SvjX_A}4jYpNWGl4)#s?)c zYSSNV=q_IOJnWH8zwm!;*Vs$LJADLqt%ltiC1)=V4ig4qhyO`v&@MNQTh?Z-mlM6p zJ>*@Ns_0&!OSOd4N7tu#X)e>~4F|V*@vMzIAZVX?Wi{ zSbyafj-wqXwA;JZnfWSfKRVCx-*wViloT>rRUuCl_B@65tqD#Pa%$dZZ+zW)T{T|z za!S{$zf;adY`~F1dPU$>Ro5qRi!aIH&b)e!ng$`}pQC)9>4nuhV>65qTUr984G6Z+ zyu4DZ{I%HP-+F324};C;P5pZkyciOC4m$Ed3H&@kY)rM`Gp>y%N5*_ z(@MVsyxEJAR@CG_x}=sV&<(z%Hb8j? z;?@q)Bk;YP>J z+6m`jbyD*#Se?Xc3!Rb8DzL*|Ko5 z7Bk~_AMnS+#CCU03kdDl+qf@_ODit}o& zY83r8U4HwKRtN=NkfnxP!JJ!y#!C+&cx14{5CB(Qqc?*q*SCV z@ucF?_C?m&IW60s%-Fd*J^KB2XKaQsVoPrzheL4Rnz_vBR+oRZ9Xuhb9#Zh8F@lfF ziN(;=+`wDp?uk?dfs}HOmQmJK@IJ9=cwiSfVWe##`ktv&3XZ^jryz6YEXZk&-*Y$DX3OG{BtRSS+ zB0ZP)M5OMQEBpU2@I)MT;178{C)^pEVT{<)6(psANbU10iu;UL2#L*pY5zn1OVeZC zqGe7jrUs@KUrij@*c$m`OC9PfdPO`Z={T^Jf=6bcTS0>7XcKWB6cfW^W&c#gDK$&N z^{s4|TzS}F{U0Ua5ZjfS;|kjfLhM1y6fB?`q%#P}U8!A5eio$kYX(1CH$U;!^1YA3 zdpMUOC!9Im@U9d}!jW-Uv;C3Y%lDUsRPKsxUU4F19(&rkn&KnHY;^g?UrD}CLFS=?f zuIj6M%IuU|vq~ICs+hMBsW{<$Y5eHG^WKMw9KsiSFBP2H*BRg8jLk4cZ0QG*B0wbH zBhCtSag`6|rR{rWPM>0Z+|X+_cu>w1(%7|Ayurp~2AO{jntyDe_Z1N)f&afQ{(2~L z`-y$;^Sq+Gp_vYX7gRwzJ%}BK16Zx71UFGQ;}t-}{B&veFS7$de614;o9yvz2L!CFIsg}lra@hcyd-Fh!R zvjx&%h0G%|81%!>fO6Q<#>Qj{SrDaR&Bn%L24NetzK0#k!rpzfI5emD|Dr~%OqRGC zLRA83@?n;;C`n~e6ZBA)U^!dp5gGwHmCO+LAWcP&RwN9;$Q4O+^!z6agKF;^d8*0^ zYropH{CfLNx+$q@HZUlJqi#A0l0VRXFpD%-62<=Hv`uk^#_Jl??C*S->5m_UzM z4_>ksF~Xm`Wcx+8C7&~QEPIr^W&I}3T{7MLra_}A1Qf(UY`xH$kn`cZu@cH<}K;#s%TG^Y+e}VfgShfiYFFS|4O>jxXn<|f0 zryeQ4yz%x{f--Yw{?UCXX@b6^YRk?OwM}pcjH>+%-uzDMWt6SBg>#j(yi9 zoF*C7=QWJE;$-8J~}*g-2Q;IlqKUk%~MV=Hc+0v{0xIC<>ulw}%eml30;RNBdveL}7 zGVrjK{O4&CtBgyvS6`U$mzDpbGd9B*v85`I!y)+Dxt+V*7I432z8|-I{?@+NGoJCw zJF%FWnV7{~2>tv>ygs1z|6Ea?yM?w@GJOi*u8J|F2@<@Tf8tTIiPN&#JosFKPORG< zx$yQ0nS(<;RRpir9FTE&lvJ@}=U28ZYV5Yx8eUA=y3cLGQhR4B!l`1lkNJ^I&l_L$ zdzov5d5S#J=0!&_S2|-ej1gP{;RfyVfgSl4 zxBzsjBxJRTzceo!lL=&I&&PTi8y^`ZGgMiw2Yb2+UaJaiuLkqGLffm}-w(5Z9Lc~CO!^rZ9avT@QKjY?6zQhg z_@_fcK&@1WZ-3|yg-=g@bL0yVPB&{?d^c}!k`!#-mQZKBM?pxX^=6NPkux^K7_p@= zNMwM>e=nL2zTB+9KkJtB9%t6V2b!_GZ=G0-%?&IS+TB*R?K=GK&)(yGH{WvaXKA*& zgi@NUk9B)y#by}jf8mYJY2WwTOZ)R1mH1Io#SrYp1g|d_1_cZQ1JxJQ65mD@bF+`x zzq0!4-pYb&i(KE&Y~1rQE-_|3PZ7dDD#{9ZXnW;;ugGd9B* zv85k~w?U-YTAe-TW`t}zW;Mo85Ud=D3pu&60`NE1az(#GHhb^(w4+wlZ$K>?9=86 zmOM}tKi(Fy%-O{0&vlffvU%r_8#Wmf1($g<<#2|+y>HjmAYuAt4CjNiS>x|7XMr?@+l1xD4o#*>Dd}2NR`b*+QrHz6; z_2>PjKs!K?q@v-t1fEp5FI&Jz*!*)|!AIBxQl7y^*aGLQiZ~e9B^8>_WF~C-x`1Ux zp1a<(qbNyb>l0W~A^DJ6tQ&x6HYh*HN)_{?ea|?BUx@tqAy}*VGH3m(&3w~vB$aJu zNTtfA#%8HEemN7=w=B{Qygh4+h>?haGd9B*yRalGP$Gfg)|@ThMN^JD-!9yF^n1(8 z|64U8K7+^6j36yq-Ahl|m@FYH12nXIut z`guRS(R8os+wg^_f;Fx=V>65qTZ)0C0T3yE$vwYV_gu8$E&e5ik#8>P&C%Wo>hVBN zHn7uYgPm*;Y{m;e*?@uTDg0yumG|xNlMMo`Ho;FekkOp@vfS`P{G24mLjOxePv<-d zowYLd5K5|{N9nOk9D1@rkljk?NLzr9BkaCypH}F7+xVyS23hH$#J{mM(ylY>WY4Vz z@xpqaW}R0k2Nffwnq4LE(qo6+vh%hr_W}$jELy3>(&@GD{Q{@*KhD?;W5kxeKX^)$(}4$S*?Mi2HLX&DGhzuesk}JuD5sQ>8$dZ(x%kEqG8`EXKaQsVoPn1^aCQz z7z&!iZk^KY*z2O4VY1_lY_iz_a1CSvS&Pr8BF@HS37H}mVr%$zsB6N#4JT$*b8UUm zl^6f%{(r4^DCuB;8m+y$_hL}VhC9hAk1HN;BV;T^W}TrMNd*>oACC>*|6Ms!J}~x z3O-6^@q!P`RBXADy70jVxfLDvQbSjD+jO0pk8*bGfj!vczRFuBrcF^Icoiq(GD-bK zPxO=n+MKZ&#)vJIfE*6Njep;>Dz)8y|C`OAQP*LI7yqF*OinDOmgbi0l1|NdF1V55 zQT%Lu{a|euYrzZO!KDLip7+pH#5}M5%Js&X3THR)|NMS$+S_!2{j0R9G&)dH$k1+S zP`j2mv>rOoi*+X#^5};~z?y&a78qrSOS8H)n#$SSSr&^cg&abxf8JqN^(@`5r{Vez zo;xyu;=v8e)}KES?2OGYMr>&bk~%=-hELp&&mUNRV>-LNXQ21_$18g`>VVp(un~FW zOISFfZoo(6EnI)VN96Hb!V;UX@dk&1*CRKE#^C1TvnAA8&pgGEZjNk+j>r>x2@BEv zTiUfy2QJ;134OR{8EDM5V*jKNo#2;F=X=})kZTpBlI5rvQtQI&jhx88DgR6sv3W6w zPuf_$*kN{;Gd9B*v86Cjih`neR@(kE!Wu@kA;Pl}aTw~6Qk`D0pZ-bA$AMrCYIQqBp_qv=u_aD^`ZWU|J zk&{uM@K->Qa5^|HXZyM@_-0S?l;Yi+_0C+44RD+MdZsfr!x*up7)TlbkrSTZPh>qL zAR;StYo*rm+~)!-J=mRCOf3uyUVf7kRKF@9dE?Yfw;t(@%F}BP-Xru9JDiUh-9rP6_R#Am*V3LvRWZM?!1dKFQ>%$e}~)xC6z{hy027 zb#3!|!U^qU`@C*(VnisjO-*e=Vn^dFWmc+kKEEc8)=36iGyUgqI z^$hD^s}u?TxUr(}j62F^i?cJ>n2aEc5rSqq!tUL0xh4j`eB1VBN@?>mhtv}hF$>Nc zzIYY>{QGqat!XF;2hlRd-@-Y&3A))LAj^jh*&py0&guPIecLuXzEGaMl1BV(BrTC>we$i&yB!(yoTMn!E*4Ei%^GC@Bgt z5_A4Fv?!v-s_UUW5)*u2rdPnO`l%Z6-G6p6~KrHhCGiD8h0ySnwrfTt|bw`yDD?@wcX zx9)D;hLUmyQ(1J$7V~H@_!b|m^8o|b+iG>tGuHPyc~)ls^~rbR!=B!iFe=88axS$X zl|?`1&1CZ|H1V+4EG*55k(xE_vV^NMHp3XPr7=jV0g;>sec7MKn!i}aaenI2wB5%} z&9naq9`%Q=XVHy!ho6)YbSoErQihRP3H+oCeo+(ndKT}dHwLwD7e7lZVte>raP#h+ z#vGI1#c-mem0?oK1Ye1Tu4f5WD21Jrq461dQbv&Ee+f_kGcW|KZ-btcLE)I+)F#2W ztIO;pR%yDbGkYD~(aZGXFLGMBvH?EkhmuxO7ni<|=U?s4HgVS#<_ES$>}N%?oUs|k zh%Hq?JOLt)$9dPDv}jp>YwHogEU6&ZG)1$|;PGDQ`da<2T#>y~a&7f@3SG9mSo=*y zp{tR5mi&;9`)i#TE8^%L_s$=G%xd7MeizlK%KEJD$1cO-`F`wzAEm-VrXG% z+9jOI`9r*PrcmwYSKbP#$D;)U4j}i&DY?=k_(m)2%ws)0b@(k}(oVWARW62n@6OoV zan>#>i~2fe-M;RZbV_J9=0khqL0GQzpr|P`7!um$_$8Z;Ev;VJdA=-6BwqRU?fHKh zkQ3TXQS1pVHDC6Y;-AKqaSf-G`x8S871N!zIAb%65nGakBr*{B&a)#e?9~~Oz=aF4 zuE|z)8@jXwI5C@A>t2Fy zy<=lChm02n?7Ltv*X+>N6;?<7E6o3NP$Q>hU3oa_STXHtq#=`7f^V}+gTkMIA(+T@ zy1@r#%6wSt`ph(Uj)|K3`N{{Wc6Lhf<;aQUwiEWmq8F^HdM88fLT~)dAGWd9`$WH= zUG9v{Fh*?23gS!<*|JqOF$pNmn_gDwS(`w!_WCbJ5oD-*%xW|`9)G! zpDmHCRcbQ~m~aF2Y{9{qTJ9&p&iTS}q;@d2YKY#c<&FD?fOnsYc?|?7Rx;eRNhpf6 z=toX1_vc_wEy8-9C&F&ms($xu%D8uON0|NghE!*4hB0DGSCEtfB6(MwJ~8F+)38NO z!4qqK7udHbS@b(GTNqjF5`FWBeR1Z(I_A44S<;xYS4RA@gCrKnunhO-_iRjNkc~sZ z4?$=0Ll#5$PEFnY$>f@y{VJ0M+_qhDZ`WIMpT2VqrOkqvszQteKkS2UA{reDW?;ZE zgP{3u$t~7nPW%fOnR!k6QYv?GtN2~QiRIzRr*m_5#=J2~WxO%zedjEhIl4FVlbx{{ z#)vIhfszRXKb+<-W56Naw`E1arQ4Iz%ovT6A&2Wgk3F^)yAMD1SnTdq__4=&9Jk@e z9!suPiZEg>>fyM(&`JGFy2jiWhjsaluArokVK>MU{CE+p<4pPylf*BD*!{zoIhLC5M-9LZ^aFN-66JbnouWO;ZpVMo-Sn8wSyIsJJ%LS9w!X;&Y+=#0%UMrJRaPEd*6@O*5K7}uNs9tbcrO?w1 zCGLk}Me_6zX2+S{6^Z|EJJUZMf+;eOesF8ueOT|PmS%<=_fMa~D-x8rk3A%@M|bu0 z`iFTXrAL~+<~S85%y7nL7$de+0*ZAA)||Os$7ScQEbf#A{S%)_@_e201H3U6x=dR= z&l9#xJD_AEe3`bd93Om{w)IyN_%dxqDFOI0ZGVP$(bj3|?{-;9Kb72&^te(~{cZlu z8}v>!!O!5RyjM&l_B*lP8{e=!EZRUO2u>6Qp_|XZA6^yU_ zo#Dh{WN2n)G_B0ZZ2b#Y0okgH%N{tyDqPLEfjmVN{PGJWQ$z>YZYASR*o}(|Pnz^NV>65qTiOGqB?z9=#bbM7$F1pNlUO-AJ}hK=EEHxB zUX}?x%S#|Q41ShZpqZIBpT!NXWO4VJ)AFWCdsrj0#TUB_&2$j_#tnLwSMXpcSvG&! zzW?)jugP`%i}{K{Mwg|7-nJ{pR2eml74 zveiA^*5?a9%iTdeh6#V4<((h-%j<^s>Xn;uYkoAdsK=bYHM7Qk&OF_FCBMUwYZ&b5 z;9c#zqpjPlE36kVPM6Nw>{nsCIpXhCXKaQsVoNcg6ac~Z%)9vZT{>DidA`4f?vl@P zha5uoIuYp2HW1D+;dPr%U3K? zz1ZZY?jGTLS^CLcGJg9}N{RvMwFG}CfNk$UY!#!*)G(cTEsI>|rn1$@814Ez-TD0D z5OGJ-!Uh~EivIz*pFES++)!Y9-<9KXnN4r%CTDDhF=9(gkkkPp%jDNB z&pKl9$}gKspx*jH*Pf_52azXs^rz~uF&RPjC(B9uu`!uIMnJrtCbBV^Kt?@+NnU38 zRY{K9e;JEF&wle0dn6icf+v|Ppd=^S6*!+Npc6Ytmst*$eOM#OdqEwo)2u1s6Jbd?r+({?u`!uL>Z8D~>)03}1M>1KCO=aZ-S+#_BUYa8-)|X& zYY3i@ORz;r9mBYO3I53mU7bY9-Euev;q_d#r$}GO^_#NixblzS_}2_imF5#p9Y6g_ zuYBAWs;@ci;JeqH0g8)m=-8MabjD^FBerw|Nf{vWT$hvP?+eHGd`OE@H@9oZHVb8a z4X#C?H;0jWs|Nqh2Zi^h-}HaW-=22y>6PghXY8Amu+IP`t&G+p$hXYlACUj84m(3q z#&MfjbHBdkJ<9~1FZYu6PPtrn?*;vhu`?iORvc`FSJ(t%H z9i6cm#)vIdfl>(sm#6Z6@!qJ$wPNjFtDkm5t-!aO!6V+h+{>>&KC z12H#q*eyPRW@fNkd;+@#F4koReXGiSRaUT6cJcEqSLUso*NBo*hIXm)HyC!-0haro zXj-aNO*nD>f$zsM&AA(Q z>`mTIpGEbnK988x@xPXKb zzq#bdgdFx$FM}5SVs^%67$dfH1WFeW%wIcOe3E#d>dZ&HEnfDCx)s`2s-0LY3{5Q- zOl|FIJ91(3Z{=@-3mO!k$S?nt4jyKMp3>w!=R5qArVz&2!Kw}=E;@CG4O_1Kmdl-J zvi*LmA4&=tZL=~2<6WT^!nhT7N)!A%{NMvKB@Rsc!f$zVlj4r&l482;yQlH8R3fF2 z5XL9)HY-w1^Z$_2z1Ai}UT%A)D!$uxx~rak+~dC38Jl5@*wPXtb%02xthc9cYAw9> z>G7}H=GQ`AXFN8tBiA%cnG4`G4gVp~8MTmAi@{MVVKt4+KP6aA!~fUJt6RP2-ZDS! zl-X|+5`zzFuHHFe+3-mzAxz1$W_2jrB( z!iPPja6OON^e@i;R;f9AfT7Hj`S*()emY|_j1gO!0;LfMPQMv{;NU(nUfykGh0Ol0 zbywyT&H>jnBrGB^NVt3Qfa1wNhw9BG5;J<|%PjSvoY_^v^7hf>6@!Qbr#%Hlgh|E$#yZ8Kd}WO^jeLbzoXN{Itc zQ6U_P&?#Z8Cv8x9A1c)c_~Bz|bV^Y#Ob)KqW#0R@ozZR11@Yp|CoOvZ;Yd*&4M-{K zMe^#mrO6H7F05B}i+iaa+3-vAyfZe#7_p^2P+EfElL2>F?!Gv=&y;Ohcx1?hJ99;? za-CR=jSP)g*t6{~nA=okSWWuAcGprpt*CznkXj2ejza1!+#y_%LQRU3ik7MVGObl8 z_%|uzl4JJ^W|UMkq+2-jt+ztBieY`}12ZiiR{uKuW!)p|hYG709@-w?u~97uITdjo zgVkFhD5=OfLFn1#p6F2KH@A<3a=+OsCOI$G8Jl5@*wPy$1%XI+kJtn$X^zkR;R25% z8D=uf)C^OFq!q~25Q(Q8TRmt{`9CkqZ& z-JG!*#)vIZff5M>|I~cG#lhFkV`9%8zO#P6PyU*CYb$7*vayLwfB)9z^^q+EP z6HJFex)6aku+@^(o?6B~NJq0cftO_TXpAbwlN#2K4mjM&l_D7`>1>$0QWHeVw1Z++T)$51SKjayK7AfyU{ zG*?I+`e#%TU-V7<(}}GMPcVhgakN_{@HaA5j~ykgj5d0S9{LXvR)RHGWE}OvxxXLu z_`X!F&Ma42Wvf8!u_w6Fif}2c(HkP@x%}9_=8N||H_p3|_5JLJeakM@?(=iTW*8&3 zR0T;VAhOYLnyF8mYr*5_wYJmR1s)z+x}pksRg1FiYxt@b=B*Rpt6EquT!yb|aheM{ z6ag~nXnnkgjmZKsRiJm&6}DYjR4Wp`UD;nb@j+p7+g_urH8yW-GrD{}w0#UKF{e** z3K8{#t!lw?TH#RaL!l(6jSJViZPfPO*Q*hrn)YLFbwNVh9~?!G=nk0eOQSDoi}q{SG-Ri>nfQ8Fu5-p_7$dfX1PNpiS@DZ?s>|%ihaZUH9`0>|&L-p*%ZvV^Q(;F%-yDs10GKVjDUW(n*k8jeiZGH>}i)O%lO zRvVFCe1u5uA^-RtIt;;}6d!sSyHp})-`2hUb6?or3h#yl6=hZ&=|hScUVMl@p2qe# z_9*}JFNTj*j_*5_q{7!mwl`J3GER3X4gWBTXIzSq_B z-rER?oM76nk5Yn+rVs+{l@RG~&&9A1ryd(?gv@Hz;$Pm*4Jtp0LImj~f=AgBA?aFuWX`?`LSEj|5JPAul;Cgw}mKl2MIyx@I%k+bQF z&e+4JjSO>OWgtFiw#2* zis9ocNTrFK?q9uC$rtRNT+^88AmI_C)js?3+z@AMhB0DGZ;%uOB4YwB*6z^{uvTR+ z&n}wu>0f2;DFx834+B#RhLZ;)mCv|om8>)3ef{jj%!`b{CKdHd2Cn_-ODk|ZdJL9k28ta}U$0%4YS z+5dZqCe2%Q*k?NUm<(gc#t!&X*MQH$ZP?(P@V*vf!GmYv%hm$ugPyz z{pLNtRsJKj3ZD>_tt zzN<`n11Ci7B<*Vid=Y#hh`*PnIn_-OD(h(?KKyY)#oW@^L@QL@ zBGdJ@>Z?@uo7~|)wPUX=W&k&VVK>SwSqr~WCPd?TIY)Ul|8*XR7YYHhpC{e5Y+ajj z8aahf(s&tu5=Lxy(? zB>jBw@gBBerw}N+%F}C*oyg)z8u<&&p7ykJ1JWv80ws&CIig#%zChgTU0&j}em&rb|Db=?NLryEY zUGSC(N?O@e6>s;~%&m`esbbEIsUD3j3Q8)@*bHODmZ~7>1VnDRvE=oI|EpP7I`wHy zcHf?CW%4}^Y1)~BLweNbDeZpi>0}!tQ;~Y4^^nT0Td8_S&KM(?F!V?@A^OR%X=l5W z(7RMgKcolSene`wXGuskKfdz^3w(n=9BO8+?q~B{RJMnY5ctvfw$x0{gO=myd4*vDu@jS}y+}O&75aWfg zBO%MBVaKb?afMC%Iemss{1Mw$9hPN-=rWGf{Trs|-1)WSgVEnIRjyF!&B$rO_zt{A zK}i#FS0=IdKjXg9mpNyCyD6JgPe%irGd9B*v85hRYJlJ?-R%7-&MZ&nYlMW)aW0r1 z7w4DZ#A0b|Y¥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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.1.suffix b/vendors/irmin/test/irmin-pack/data/version_3_minimal_gced/store.1.suffix new file mode 100644 index 0000000000000000000000000000000000000000..7fa4cb187a72c9a5bafc82940dcd824cc29cc871 GIT binary patch literal 42 kcmY#-7 + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +include Irmin.Export_for_backends diff --git a/vendors/irmin/test/irmin-pack/test.ml b/vendors/irmin/test/irmin-pack/test.ml new file mode 100644 index 000000000000..8b35dbfa8f7b --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test.ml @@ -0,0 +1,21 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Lwt_main.run + @@ Irmin_test.Store.run "irmin-pack" ~misc:Test_pack.misc + ~sleep:Lwt_unix.sleep + (List.map (fun s -> (`Quick, s)) Test_pack.suite) diff --git a/vendors/irmin/test/irmin-pack/test.mli b/vendors/irmin/test/irmin-pack/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-pack/test_async.ml b/vendors/irmin/test/irmin-pack/test_async.ml new file mode 100644 index 000000000000..94b3becc996e --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_async.ml @@ -0,0 +1,43 @@ +(* + * Copyright (c) 2023-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common +module Async = Irmin_pack_unix.Async.Unix + +let check_outcome = Alcotest.check_repr Async.outcome_t + +let test_success () = + let f () = assert true in + let task = Async.async f in + let* result = Async.await task in + check_outcome "should succeed" result `Success; + Lwt.return_unit + +let test_exception_in_task () = + let f () = assert false in + let task = Async.async f in + let* result = Async.await task in + check_outcome "should fail" result (`Failure "Unhandled exception"); + Lwt.return_unit + +let tests = + [ + Alcotest_lwt.test_case "Successful task" `Quick (fun _switch -> + test_success); + Alcotest_lwt.test_case "Exception occurs in task" `Quick (fun _switch -> + test_exception_in_task); + ] diff --git a/vendors/irmin/test/irmin-pack/test_async.mli b/vendors/irmin/test/irmin-pack/test_async.mli new file mode 100644 index 000000000000..8bfc894f64e3 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_async.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2023-2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_corrupted.ml b/vendors/irmin/test/irmin-pack/test_corrupted.ml new file mode 100644 index 000000000000..43a54e00d198 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_corrupted.ml @@ -0,0 +1,89 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let root = Filename.concat "_build" "test-corrupted" + +module Conf = Irmin_tezos.Conf + +module Store = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) +end + +let config ?(readonly = false) ?(fresh = true) root = + Irmin_pack.config ~readonly ?index_log_size ~fresh root + +let info () = Store.Info.empty + +let read_file path = + let ch = open_in_bin path in + Fun.protect + (fun () -> + let len = in_channel_length ch in + really_input_string ch len) + ~finally:(fun () -> close_in ch) + +let write_file path contents = + let ch = open_out_bin path in + Fun.protect + (fun () -> output_string ch contents) + ~finally:(fun () -> + flush ch; + close_out ch) + +let test_corrupted_control_file () = + rm_dir root; + let control_file_path = Filename.concat root "store.control" in + let* repo = Store.Repo.v (config ~fresh:true root) in + let control_file_blob0 = read_file control_file_path in + let* store = Store.main repo in + let* () = Store.set_exn ~info store [ "a" ] "b" in + let* () = Store.Repo.close repo in + let control_file_blob1 = read_file control_file_path in + assert (not (String.equal control_file_blob0 control_file_blob1)); + assert (String.length control_file_blob0 = String.length control_file_blob1); + let split_write_at = 3 * String.length control_file_blob1 / 4 in + let control_file_mix = + String.sub control_file_blob1 0 split_write_at + ^ String.sub control_file_blob0 split_write_at + (String.length control_file_blob0 - split_write_at) + in + assert (String.length control_file_mix = String.length control_file_blob1); + assert (not (String.equal control_file_blob0 control_file_mix)); + assert (not (String.equal control_file_blob1 control_file_mix)); + write_file control_file_path control_file_mix; + let* error = + Lwt.catch + (fun () -> + let+ r = Store.Repo.v (config ~fresh:false root) in + Ok r) + (fun exn -> Lwt.return (Error exn)) + in + (match error with + | Error (Irmin_pack_unix.Errors.Pack_error (`Corrupted_control_file s)) -> + Alcotest.(check string) + "path is corrupted" s "_build/test-corrupted/store.control" + | _ -> Alcotest.fail "unexpected error"); + Lwt.return_unit + +let tests = + [ + Alcotest_lwt.test_case "Corrupted control file" `Quick (fun _switch -> + test_corrupted_control_file); + ] diff --git a/vendors/irmin/test/irmin-pack/test_corrupted.mli b/vendors/irmin/test/irmin-pack/test_corrupted.mli new file mode 100644 index 000000000000..fa903bf99cab --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_corrupted.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_dispatcher.ml b/vendors/irmin/test/irmin-pack/test_dispatcher.ml new file mode 100644 index 000000000000..de572c535af0 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_dispatcher.ml @@ -0,0 +1,103 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common +module S = Test_gc.Store +module Dispatcher = Irmin_pack_unix.Dispatcher.Make (File_manager) + +let root = Filename.concat "_build" "test-dispatcher" +let src = Logs.Src.create "tests.dispatcher" ~doc:"Test dispatcher" + +module Log = (val Logs.src_log src : Logs.LOG) + +let setup_store () = + rm_dir root; + let config = S.config root in + let* t = S.init_with_config config in + let* _ = S.commit_1 t in + let* t, c2 = S.commit_2 t in + let* t = S.checkout_exn t c2 in + let* t, _c3 = S.commit_3 t in + [%log.debug "Gc c1, keep c2, c3"]; + let* () = S.start_gc t c2 in + let* () = S.finalise_gc t in + let* () = S.close t in + Lwt.return config + +type t = { off : Int63.t; len : int; hex : string } + +(* predefined values based on [setup_store]. *) +(* node_1 belongs to commit_1, it is removed from the store. *) +let node_1 = { off = Int63.of_int 30; len = 26; hex = "" } + +(* node_2 belongs to commit_2, it is in the prefix. *) +let node_2 = + { + off = Int63.of_int 240; + len = 35; + hex = + "db1998ebe97d8ddffef5fcc7a235f16f33f3ccb6520d000108016100000000000000cd"; + } + +let commit_2 = + { + off = Int63.of_int 275; + len = 42; + hex = + "8fcdbb49a171d9f5eb578c094d24a3ccaaa156c444140000000000000000f00000000000000000000000"; + } + +(* node_3 belongs to commit_3, it is in the suffix. *) +let node_3 = + { + off = Int63.of_int 346; + len = 46; + hex = + "2b5a114440d5fcef4b20b85171af8d140dfc7eca5218000206016400000000000000b3060166000000000000013d"; + } + +let check_hex msg buf expected = + Alcotest.(check string) + msg expected + (Bytes.to_string buf |> Hex.of_string |> Hex.show) + +let test_read () = + let* config = setup_store () in + let fm = File_manager.open_ro config |> Errs.raise_if_error in + let dsp = Dispatcher.v fm |> Errs.raise_if_error in + let _ = + Alcotest.check_raises "cannot read node_1" + (Irmin_pack_unix.Errors.Pack_error + (`Invalid_sparse_read (`Before, Int63.of_int 30))) + (fun () -> + let buf = Bytes.create node_1.len in + let _ = Dispatcher.read_exn dsp ~off:node_1.off ~len:node_1.len buf in + ()) + in + let test_accessor msg obj = + let buf = Bytes.create obj.len in + let _ = Dispatcher.read_exn dsp ~off:obj.off ~len:obj.len buf in + check_hex msg buf obj.hex + in + test_accessor "node_2" node_2; + test_accessor "commit_2" commit_2; + test_accessor "node_3" node_3; + + File_manager.close fm |> Errs.raise_if_error; + Lwt.return_unit + +let tests = [ Alcotest_lwt.test_case "read" `Quick (fun _switch -> test_read) ] diff --git a/vendors/irmin/test/irmin-pack/test_dispatcher.mli b/vendors/irmin/test/irmin-pack/test_dispatcher.mli new file mode 100644 index 000000000000..4acc26805b83 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_dispatcher.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_existing_stores.ml b/vendors/irmin/test/irmin-pack/test_existing_stores.ml new file mode 100644 index 000000000000..ae9b4a88fbef --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_existing_stores.ml @@ -0,0 +1,351 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let src = Logs.Src.create "tests.integrity_checks" ~doc:"Test integrity checks" + +module Log = (val Logs.src_log src : Logs.LOG) + +let config ?(readonly = false) ?(fresh = true) + ?(indexing_strategy = Irmin_pack.Indexing_strategy.always) root = + Irmin_pack.config ~readonly ~index_log_size:1000 ~indexing_strategy ~fresh + root + +let archive = + [ + ("bar", [ ([ "a"; "d" ], "x"); ([ "a"; "b"; "c" ], "z") ]); + ("foo", [ ([ "b" ], "y") ]); + ] + +let root_v1_archive, root_v1, tmp = + let open Fpath in + ( v "test" / "irmin-pack" / "data" / "version_1" |> to_string, + v "_build" / "test_pack_version_1" |> to_string, + v "_build" / "test_index_reconstruct" |> to_string ) + +module Test (S : Irmin.Generic_key.KV with type Schema.Contents.t = string) = +struct + let check_commit repo commit bindings = + commit |> S.Commit.key |> S.Commit.of_key repo >>= function + | None -> + Alcotest.failf "Commit `%a' is dangling in repo" S.Commit.pp_hash commit + | Some commit -> + let tree = S.Commit.tree commit in + bindings + |> Lwt_list.iter_s (fun (key, value) -> + S.Tree.find tree key + >|= Alcotest.(check (option string)) + (Fmt.str "Expected binding [%a ↦ %s]" + Fmt.(Dump.list string) + key value) + (Some value)) + + let check_repo repo structure = + structure + |> Lwt_list.iter_s @@ fun (branch, bindings) -> + S.Branch.find repo branch >>= function + | None -> Alcotest.failf "Couldn't find expected branch `%s'" branch + | Some commit -> check_commit repo commit bindings + + let commit_of_string repo c = + match Irmin.Type.of_string S.Hash.t c with + | Ok x -> ( + let* commit = S.Commit.of_hash repo x in + match commit with + | None -> Alcotest.fail "could not find commit in store" + | Some x -> Lwt.return x) + | _ -> Alcotest.fail "could not read hash" + + let bin_string_of_string c = + let s = ref "" in + let f x = s := !s ^ x in + let () = + match Irmin.Type.of_string S.Hash.t c with + | Ok x -> Irmin.Type.(unstage (encode_bin S.Hash.t)) x f + | _ -> Alcotest.fail "could not read hash" + in + !s +end + +module Small_conf = struct + let entries = 2 + let stable_hash = 3 + let contents_length_header = Some `Varint + let inode_child_order = `Hash_bits + let forbid_empty_dir_persistence = false +end + +module V1_maker = Irmin_pack_unix.Maker (Small_conf) +module V2_maker = Irmin_pack_unix.Maker (Conf) + +module Schema_v2 = struct + open Irmin + module Metadata = Metadata.None + module Contents = Contents.String_v2 + module Path = Path.String_list + module Branch = Branch.String + module Hash = Hash.SHA1 + module Node = Node.Generic_key.Make_v2 (Hash) (Path) (Metadata) + module Commit = Commit.Generic_key.Make_v2 (Hash) + module Info = Info.Default +end + +module V1 () = V1_maker.Make (Schema_v2) +module V2 () = V2_maker.Make (Schema_v2) + +module Test_store = struct + module S = V2 () + include Test (S) +end + +module Test_reconstruct = struct + module S = V2 () + include Test (S) + + let setup_test_env () = + setup_test_env ~root_archive:root_v1_archive ~root_local_build:root_v1; + setup_test_env ~root_archive:root_v1_archive ~root_local_build:tmp + + let test_reconstruct () = + let module Kind = Irmin_pack.Pack_value.Kind in + setup_test_env (); + let conf = config ~readonly:false ~fresh:false root_v1 in + (* Open store in RW to migrate it to V3. *) + let* repo = S.Repo.v conf in + let* () = S.Repo.close repo in + (* Test on a V3 store. *) + S.test_traverse_pack_file (`Reconstruct_index `In_place) conf; + let index_old = + Index.v_exn ~fresh:false ~readonly:false ~log_size:500_000 tmp + in + let index_new = + Index.v_exn ~fresh:false ~readonly:false ~log_size:500_000 root_v1 + in + Index.iter + (fun k (offset, length, kind) -> + [%log.debug + "index find k = %a (off, len, kind) = (%a, %d, %a)" + (Irmin.Type.pp S.Hash.t) k Int63.pp offset length Kind.pp kind]; + match Index.find index_new k with + | Some (offset', length', kind') -> + Alcotest.(check int63) "check offset" offset offset'; + Alcotest.(check int) "check length" length length'; + Alcotest.(check_repr Kind.t) "check kind" kind kind' + | None -> + Alcotest.failf "expected to find hash %a" (Irmin.Type.pp S.Hash.t) k) + index_old; + Index.close_exn index_old; + Index.close_exn index_new; + [%log.app + "Checking old bindings are still reachable post index reconstruction)"]; + let* r = S.Repo.v conf in + check_repo r archive >>= fun () -> S.Repo.close r + + let test_gc_allowed () = + setup_test_env (); + let conf = config ~readonly:false ~fresh:false root_v1 in + let* repo = S.Repo.v conf in + let allowed = S.Gc.is_allowed repo in + Alcotest.(check bool) + "deleting gc not allowed on stores with V1 objects" allowed false; + S.Repo.close repo +end + +module Test_corrupted_stores = struct + let root_archive, root = + let open Fpath in + ( v "test" / "irmin-pack" / "data" / "corrupted" |> to_string, + v "_build" / "test_integrity" |> to_string ) + + let setup_env () = setup_test_env ~root_archive ~root_local_build:root + + module S = V2 () + include Test (S) + + let test () = + setup_env (); + let* rw = S.Repo.v (config ~fresh:false root) in + [%log.app + "integrity check on a store where 3 entries are missing from pack"]; + let* result = S.integrity_check ~auto_repair:false rw in + (match result with + | Ok `No_error -> Alcotest.fail "Store is corrupted, the check should fail" + | Error (`Corrupted 3) -> () + | _ -> Alcotest.fail "With auto_repair:false should not match"); + let* result = S.integrity_check ~auto_repair:true rw in + (match result with + | Ok (`Fixed 3) -> () + | _ -> Alcotest.fail "Integrity check should repair the store"); + let* result = S.integrity_check ~auto_repair:false rw in + (match result with + | Ok `No_error -> () + | _ -> Alcotest.fail "Store is repaired, should return Ok"); + S.Repo.close rw + + let root_archive, root_local_build = + let open Fpath in + ( v "test" / "irmin-pack" / "data" / "version_3_minimal" |> to_string, + v "_build" / "test_corrupt_minimal" |> to_string ) + + let setup_env () = setup_test_env ~root_archive ~root_local_build + + module IO = Irmin_pack_unix.Io.Unix + + let write_corrupted_data_to_suffix () = + let path = Filename.concat root_local_build "store.0.suffix" in + let io = IO.open_ ~path ~readonly:false |> Result.get_ok in + let corrupted_node_hash = + (* the correct hash starts with '9', modified it to have an incorrect hash + on disk. *) + "1b120e5019dcc6cd90b4d9c9826c9ebbebdc0023" + in + let s = bin_string_of_string corrupted_node_hash in + let len = String.length s in + assert (len = 20); + IO.write_exn io ~off:(Int63.of_int 54) ~len s; + IO.close io |> Result.get_ok + + let test_minimal () = + setup_env (); + [%log.app "integrity check on a good minimal store"]; + let config = + config ~fresh:false + ~indexing_strategy:Irmin_pack.Indexing_strategy.minimal root_local_build + in + let* rw = S.Repo.v config in + + let* commit = + commit_of_string rw "22e159de13b427226e5901defd17f0c14e744205" + in + let* result = S.integrity_check ~heads:[ commit ] ~auto_repair:false rw in + let () = + match result with + | Ok `No_error -> () + | Error (`Cannot_fix err) -> Alcotest.failf "Store is corrupted %s" err + | _ -> Alcotest.fail "Unexpected result of integrity_check" + in + let* () = S.Repo.close rw in + [%log.app "integrity check on a corrupted minimal store"]; + write_corrupted_data_to_suffix (); + let* rw = S.Repo.v config in + let* result = S.integrity_check ~heads:[ commit ] ~auto_repair:false rw in + let () = + match result with + | Ok `No_error -> Alcotest.fail "Store is corrupted, check should fail" + | Error (`Cannot_fix err) -> + let err = String.sub err 0 33 in + Alcotest.(check string) + "corrupted store" "Inconsistencies found: Wrong_hash" err + | _ -> Alcotest.fail "Unexpected result of integrity_check" + in + + let* () = S.Repo.close rw in + Lwt.return_unit +end + +module Test_corrupted_inode = struct + let root_archive, root = + let open Fpath in + ( v "test" / "irmin-pack" / "data" / "corrupted_inode" |> to_string, + v "_build" / "test_integrity_inode" |> to_string ) + + let setup_test_env () = setup_test_env ~root_archive ~root_local_build:root + + module S = V1 () + include Test (S) + + let test () = + setup_test_env (); + let* rw = S.Repo.v (config ~fresh:false root) in + [%log.app "integrity check of inodes on a store with one corrupted inode"]; + let c2 = "8d89b97726d9fb650d088cb7e21b78d84d132c6e" in + let* c2 = commit_of_string rw c2 in + let* result = S.integrity_check_inodes ~heads:[ c2 ] rw in + (match result with + | Ok _ -> + Alcotest.failf + "Store is corrupted for second commit, the check should fail" + | Error _ -> ()); + let c1 = "1b1e259ca4e7bb8dc32c73ade93d8181c29cebe6" in + let* c1 = commit_of_string rw c1 in + let* result = S.integrity_check_inodes ~heads:[ c1 ] rw in + (match result with + | Error _ -> + Alcotest.fail + "Store is not corrupted for first commit, the check should not fail." + | Ok _ -> ()); + S.Repo.close rw +end + +module Test_traverse_gced = struct + let root_archive, root_local_build = + let open Fpath in + ( v "test" / "irmin-pack" / "data" / "version_3_minimal" |> to_string, + v "_build" / "test_reconstruct" |> to_string ) + + let setup_test_env () = setup_test_env ~root_archive ~root_local_build + + module S = V2 () + include Test (S) + + let commit_and_gc conf = + let* repo = S.Repo.v conf in + let* commit = + commit_of_string repo "22e159de13b427226e5901defd17f0c14e744205" + in + let tree = S.Commit.tree commit in + let* tree = S.Tree.add tree [ "abba"; "baba" ] "x" in + let* commit = S.Commit.v repo ~info:S.Info.empty ~parents:[] tree in + let commit_key = S.Commit.key commit in + let* _launched = S.Gc.start_exn ~unlink:false repo commit_key in + let* result = S.Gc.finalise_exn ~wait:true repo in + let* () = + match result with + | `Running -> Alcotest.fail "expected finalised gc" + (* consider `Idle as success because gc can finalise during commit as well *) + | `Idle | `Finalised _ -> Lwt.return_unit + in + S.Repo.close repo + + let test_traverse_pack () = + let module Kind = Irmin_pack.Pack_value.Kind in + setup_test_env (); + let conf = + config ~readonly:false ~fresh:false + ~indexing_strategy:Irmin_pack.Indexing_strategy.minimal root_local_build + in + let* () = commit_and_gc conf in + S.test_traverse_pack_file `Check_index conf; + Lwt.return_unit +end + +let tests = + [ + Alcotest_lwt.test_case "Test index reconstruction" `Quick (fun _switch -> + Test_reconstruct.test_reconstruct); + Alcotest_lwt.test_case "Test gc not allowed" `Quick (fun _switch -> + Test_reconstruct.test_gc_allowed); + Alcotest_lwt.test_case "Test integrity check" `Quick (fun _switch -> + Test_corrupted_stores.test); + Alcotest_lwt.test_case "Test integrity check minimal stores" `Quick + (fun _switch -> Test_corrupted_stores.test_minimal); + Alcotest_lwt.test_case "Test integrity check for inodes" `Quick + (fun _switch -> Test_corrupted_inode.test); + Alcotest_lwt.test_case "Test traverse pack on gced store" `Quick + (fun _switch -> Test_traverse_gced.test_traverse_pack); + ] diff --git a/vendors/irmin/test/irmin-pack/test_existing_stores.mli b/vendors/irmin/test/irmin-pack/test_existing_stores.mli new file mode 100644 index 000000000000..4acc26805b83 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_existing_stores.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_flush_reload.ml b/vendors/irmin/test/irmin-pack/test_flush_reload.ml new file mode 100644 index 000000000000..021af25aa4eb --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_flush_reload.ml @@ -0,0 +1,240 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common +open Test_upgrade + +let suffix_mem repo e = + let k = key_of_entry e in + try + match e.k with + | `c -> Store.S.Internal.suffix_commit_mem repo k + | `n -> Store.S.Internal.suffix_node_mem repo k + | `b -> Store.S.Internal.suffix_contents_mem repo k + with Irmin_pack_unix.Pack_store.Invalid_read _ -> + (* In RW mode, [mem] will raise an exception if the offset of the key is + out of the bounds of the pack file *) + false + +let check_suffix repo model = + List.iter + (fun e -> + let got = suffix_mem repo e in + let exp = Hashtbl.mem model.Model.suffix e.o in + match (got, exp) with + | false, false -> () + | true, true -> () + | true, false -> + Alcotest.failf "Pack entry with hash:%a off:%d shouldn't be there" + pp_hash e.h (Int63.to_int e.o) + | false, true -> + Alcotest.failf "Pack entry with hash:%a off:%d is missing" pp_hash e.h + (Int63.to_int e.o)) + pack_entries + +let check_ro t = + match t.ro with + | None -> assert false + | Some (model, repo) -> + check_dict repo model; + check_index repo model; + check_suffix repo model + +type phase_flush = + | S1_before_flush + | S2_after_flush_dict + | S3_after_flush_suffix + | S4_after_flush +[@@deriving irmin ~pp] + +let write1_dict model = + Model.preload_dict model; + Model.write1_dict model + +let write1_suffix model = + write1_dict model; + Model.preload_suffix model; + Model.write1_suffix model + +let write1_index model = + write1_suffix model; + Model.preload_index model; + Model.write1_index model + +let reload_ro t current_phase = + [%logs.app + "*** reload_ro %a, %a" pp_setup t.setup pp_phase_flush current_phase]; + match t.ro with + | None -> assert false + | Some (model, repo) -> + let () = + match current_phase with + | S1_before_flush -> () + | S2_after_flush_dict -> write1_dict model + | S3_after_flush_suffix -> write1_suffix model + | S4_after_flush -> write1_index model + in + Store.reload repo + +let write1_no_flush bstore nstore cstore = + let* _ = Store.put_borphan bstore in + let* _ = Store.put_c0 bstore nstore cstore in + let* _ = Store.put_c1 bstore nstore cstore in + let* _ = Store.put_borphan' bstore in + Lwt.return_unit + +(* These tests always open both RW and RO without any data in the model. *) +let start t = + let* () = start_rw t in + let* () = open_ro t S2_before_write in + let rw = Option.get t.rw |> snd in + let ro = Option.get t.ro |> snd in + Lwt.return (rw, ro) + +(* Open both stores. RW writes but does not flush - we do this by running the + rest of the test inside the [batch]. Then reload the RO at different phases + during the flush. *) +let test_one t ~(ro_reload_at : phase_flush) = + let aux phase = + let () = check_ro t in + if ro_reload_at = phase then reload_ro t phase; + check_ro t + in + let* rw, _ = start t in + let* () = + Store.S.Backend.Repo.batch rw (fun bstore nstore cstore -> + let* () = write1_no_flush bstore nstore cstore in + let () = aux S1_before_flush in + let hook = function + | `After_dict -> aux S2_after_flush_dict + | `After_suffix -> aux S3_after_flush_suffix + in + let () = + Store.S.Internal.( + File_manager.flush ~hook (file_manager rw) |> Errs.raise_if_error) + in + let () = aux S4_after_flush in + Lwt.return_unit) + in + Lwt.return_unit + +let test_one_guarded setup ~ro_reload_at = + let t = create_test_env setup in + let* () = test_one t ~ro_reload_at in + close_everything t + +let setup = + (* We are using indexing strategy always here to have more entries in index + for the flush/reload tests. *) + { start_mode = From_scratch; indexing_strategy = `always; lru_size = 0 } + +let test_flush () = + let t = test_one_guarded setup in + let* () = t ~ro_reload_at:S1_before_flush in + let* () = t ~ro_reload_at:S2_after_flush_dict in + let* () = t ~ro_reload_at:S3_after_flush_suffix in + let* () = t ~ro_reload_at:S4_after_flush in + Lwt.return_unit + +type phase_reload = + | S1_before_reload + | S2_after_reload_index + | S3_after_reload_control + | S4_after_reload_suffix + | S5_after_reload +[@@deriving irmin ~pp] + +let write1_index model = + Model.preload_index model; + Model.write1_index model + +let write1_suffix model = + Model.preload_suffix model; + Model.write1_suffix model + +let write1_dict model = + Model.preload_dict model; + Model.write1_dict model + +let write_all model = + write1_index model; + write1_suffix model; + write1_dict model + +let flush_rw t (current_phase : phase_reload) = + [%logs.app + "*** flush_rw %a, %a" pp_setup t.setup pp_phase_reload current_phase]; + let () = + match t.ro with + | None -> assert false + | Some (model, _) -> ( + match current_phase with + | S1_before_reload -> write_all model + | S2_after_reload_index -> + write1_dict model; + write1_suffix model + | S3_after_reload_control | S4_after_reload_suffix | S5_after_reload -> + (* If the control has not changed, suffix and dict are not reloaded. *) + ()) + in + match t.rw with None -> assert false | Some (_, repo) -> Store.S.flush repo + +let test_one t ~(rw_flush_at : phase_reload) = + let aux phase = if rw_flush_at = phase then flush_rw t phase in + let* rw, ro = start t in + let reload_ro () = + Store.S.Backend.Repo.batch rw (fun bstore nstore cstore -> + let* () = write1_no_flush bstore nstore cstore in + let () = aux S1_before_reload in + let hook = function + | `After_index -> aux S2_after_reload_index + | `After_control -> aux S3_after_reload_control + | `After_suffix -> aux S4_after_reload_suffix + in + let () = + Store.S.Internal.( + File_manager.reload ~hook (file_manager ro) |> Errs.raise_if_error) + in + let () = aux S5_after_reload in + Lwt.return_unit) + in + let () = check_ro t in + let* () = reload_ro () in + let () = check_ro t in + Lwt.return_unit + +let test_one_guarded setup ~rw_flush_at = + let t = create_test_env setup in + let* () = test_one t ~rw_flush_at in + close_everything t + +let test_reload () = + let t = test_one_guarded setup in + let* () = t ~rw_flush_at:S1_before_reload in + let* () = t ~rw_flush_at:S2_after_reload_index in + let* () = t ~rw_flush_at:S3_after_reload_control in + let* () = t ~rw_flush_at:S4_after_reload_suffix in + let* () = t ~rw_flush_at:S5_after_reload in + Lwt.return_unit + +let tests = + [ + Alcotest_lwt.test_case "Reload during flush stages" `Quick + (fun _switch () -> test_flush ()); + Alcotest_lwt.test_case "Flush during reload stages" `Quick + (fun _switch () -> test_reload ()); + ] diff --git a/vendors/irmin/test/irmin-pack/test_gc.ml b/vendors/irmin/test/irmin-pack/test_gc.ml new file mode 100644 index 000000000000..44d6de13c092 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_gc.ml @@ -0,0 +1,1501 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let src = Logs.Src.create "tests.gc" ~doc:"Test gc" + +module Log = (val Logs.src_log src : Logs.LOG) + +let test_dir = "_build" + +let fresh_name = + let c = ref 0 in + fun () -> + incr c; + let name = Filename.concat test_dir ("test-gc" ^ string_of_int !c) in + name + +let create_v1_test_env () = + let ( / ) = Filename.concat in + let root_archive = "test" / "irmin-pack" / "data" / "version_1_large" in + let root_local_build = "_build" / "test-v1-gc" in + setup_test_env ~root_archive ~root_local_build; + root_local_build + +let create_from_v2_always_test_env () = + let ( / ) = Filename.concat in + let root_archive = "test" / "irmin-pack" / "data" / "version_2_to_3_always" in + let root_local_build = "_build" / "test-from-v2-always-gc" in + setup_test_env ~root_archive ~root_local_build; + root_local_build + +let create_test_env () = + let ( / ) = Filename.concat in + let root_archive = "test" / "irmin-pack" / "data" / "version_3_minimal" in + let root_local_build = "_build" / "test-gc" in + setup_test_env ~root_archive ~root_local_build; + root_local_build + +let tc name f = Alcotest_lwt.test_case name `Quick (fun _switch () -> f ()) + +module Store = struct + module S = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) + end + + type t = { + root : string; + repo : S.Repo.t; + parents : S.Commit.t list; + tree : S.tree; + } + + let config ~lru_size ~readonly ~fresh ?lower_root root = + Irmin_pack.config ~readonly ?lower_root + ~indexing_strategy:Irmin_pack.Indexing_strategy.minimal ~fresh ~lru_size + root + + let info = S.Info.empty + + let start_gc ?(unlink = false) t commit = + let commit_key = S.Commit.key commit in + let* _launched = S.Gc.start_exn ~unlink t.repo commit_key in + Lwt.return_unit + + let finalise_gc_with_stats t = + let* result = S.Gc.finalise_exn ~wait:true t.repo in + match result with + | `Running -> Alcotest.fail "expected finalised gc" + (* consider `Idle as success because gc can finalise during commit as well *) + | `Idle -> Lwt.return_none + | `Finalised stats -> Lwt.return_some stats + + let finalise_gc t = + let* _ = finalise_gc_with_stats t in + Lwt.return_unit + + let commit ?(info = info) t = + let parents = List.map S.Commit.key t.parents in + let+ h = S.Commit.v t.repo ~info ~parents t.tree in + S.Tree.clear t.tree; + h + + let set t key data = + let* tree = S.Tree.add t.tree key data in + Lwt.return { t with tree } + + let del t key = + let* tree = S.Tree.remove t.tree key in + Lwt.return { t with tree } + + let checkout t key = + let* c = S.Commit.of_hash t.repo (S.Commit.hash key) in + match c with + | None -> Lwt.return_none + | Some commit -> + let tree = S.Commit.tree commit in + Lwt.return_some { t with tree; parents = [ commit ] } + + let checkout_exn t key = + let* o = checkout t key in + match o with None -> Lwt.fail Not_found | Some p -> Lwt.return p + + let init ?(lru_size = 0) ?(readonly = false) ?(fresh = true) ?root + ?(lower_root = None) () = + (* start with a clean dir if fresh *) + let root = Option.value root ~default:(fresh_name ()) in + if fresh then ( + rm_dir root; + Option.iter rm_dir lower_root); + let+ repo = S.Repo.v (config ~readonly ~fresh ~lru_size ~lower_root root) in + let tree = S.Tree.empty () in + { root; repo; tree; parents = [] } + + let config root = + config ~lru_size:0 ~readonly:false ~fresh:true ~lower_root:None root + + let init_with_config config = + let+ repo = S.Repo.v config in + let root = Irmin_pack.Conf.root config in + let tree = S.Tree.empty () in + { root; repo; tree; parents = [] } + + let close t = S.Repo.close t.repo + + (** Predefined commits. *) + let commit_1 t = + let* t = set t [ "a"; "b" ] "Novembre" in + let* t = set t [ "a"; "c" ] "Juin" in + let+ h = commit t in + (t, h) + + let commit_2 t = + let* t = set t [ "a"; "d" ] "Mars" in + let+ h = commit t in + (t, h) + + let commit_3 t = + let* t = set t [ "a"; "f" ] "Fevrier" in + let+ h = commit t in + (t, h) + + let commit_4 t = + let* t = set t [ "a"; "e" ] "Mars" in + let+ h = commit t in + (t, h) + + let commit_5 t = + let* t = set t [ "e"; "a" ] "Avril" in + let+ h = commit t in + (t, h) + + let commit_del t = + let* t = del t [ "a"; "c" ] in + let+ h = commit t in + (t, h) + + let commit_1_different_author t = + let info = S.Info.v ~author:"someone" Int64.zero in + let* t = set t [ "a"; "b" ] "Novembre" in + let* t = set t [ "a"; "c" ] "Juin" in + let+ h = commit ~info t in + (t, h) +end + +include Store + +let lru_hits () = + let open Irmin_pack_unix.Stats in + let { pack_store; _ } = get () in + let pack_store_t = Pack_store.export pack_store in + pack_store_t.from_lru + +(** Wrappers for testing. *) +let check_blob tree key expected = + let+ got = S.Tree.find tree key in + Alcotest.(check (option string)) "find blob" (Some expected) got + +let check_none tree key = + let+ got = S.Tree.find tree key in + Alcotest.(check (option string)) "blob not found" None got + +let check_tree_1 tree = + let* () = check_blob tree [ "a"; "b" ] "Novembre" in + check_blob tree [ "a"; "c" ] "Juin" + +let check_1 t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo for check_1" + | Some commit -> + let tree = S.Commit.tree commit in + check_tree_1 tree + +let check_2 t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo for check_2" + | Some commit -> + let tree = S.Commit.tree commit in + let* () = check_blob tree [ "a"; "d" ] "Mars" in + (* c2 always contains c1 tree in tests *) + check_tree_1 tree + +let check_3 t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo for check_3" + | Some commit -> + let tree = S.Commit.tree commit in + check_blob tree [ "a"; "f" ] "Fevrier" + +let check_4 t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo for check_4" + | Some commit -> + let tree = S.Commit.tree commit in + check_blob tree [ "a"; "e" ] "Mars" + +let check_5 t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo for check_5" + | Some commit -> + let tree = S.Commit.tree commit in + let* () = check_blob tree [ "e"; "a" ] "Avril" in + (* c5 always contains c1 and c4 trees in tests *) + let* () = check_tree_1 tree in + check_blob tree [ "a"; "e" ] "Mars" + +let check_del_1 t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo for check_del_1" + | Some commit -> + let tree = S.Commit.tree commit in + check_none tree [ "a"; "c" ] + +let check_not_found t key msg = + let* c = S.Commit.of_hash t.repo (S.Commit.hash key) in + match c with + | None -> Lwt.return_unit + | Some _ -> Alcotest.failf "should not find %s" msg + +module type Gc_backend = sig + val init : + ?lru_size:int -> + ?readonly:bool -> + ?fresh:bool -> + ?root:string -> + unit -> + t Lwt.t + + val check_gced : t -> S.commit -> string -> unit Lwt.t + val check_removed : t -> S.commit -> string -> unit Lwt.t +end + +let rec check_async_unlinked ?(timeout = 3.141) file = + if timeout < 0.0 then false + else if Sys.file_exists file then ( + Unix.sleepf 0.2; + check_async_unlinked ~timeout:(timeout -. 0.2) file) + else true + +module Gc_common (B : Gc_backend) = struct + (** Check that gc preserves and deletes commits accordingly. *) + let one_gc () = + (* c1 - c2 *) + (* \---- c3 *) + (* gc(c3) *) + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c1 in + let* t, c3 = commit_3 t in + [%log.debug "Gc c1, c2, keep c3"]; + let* () = start_gc t c3 in + let* () = finalise_gc t in + let* () = B.check_gced t c1 "gced c1" in + let* () = B.check_removed t c2 "gced c2" in + let* () = check_3 t c3 in + S.Repo.close t.repo + + (** Check that calling gc twice works. *) + let two_gc () = + (* gc(c4) gc(c5) *) + (* c1 - c2 --- c4 -------- c5 *) + (* \---- c3 *) + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c1 in + let* t, c3 = commit_3 t in + let* t = checkout_exn t c2 in + let* t, c4 = commit_4 t in + [%log.debug "Gc c1, c2, c3, keep c4"]; + let* () = start_gc t c4 in + let* () = finalise_gc t in + let* t = checkout_exn t c4 in + let* t, c5 = commit_5 t in + let* () = check_5 t c5 in + [%log.debug "Gc c4, keep c5"]; + let* () = start_gc t c5 in + let* () = finalise_gc t in + let* () = check_5 t c5 in + let* () = B.check_gced t c1 "gced c1" in + let* () = B.check_gced t c2 "gced c2" in + let* () = B.check_removed t c3 "gced c3" in + let* () = B.check_gced t c4 "gced c4" in + S.Repo.close t.repo + + (** Check that calling gc on first commit of chain keeps everything. *) + let gc_keeps_all () = + (* c1 - c2 - c3 *) + (* gc(c1) *) + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + [%log.debug "Keep c1, c2, c3"]; + let* () = start_gc t c1 in + let* () = finalise_gc t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + (** Check that adding back gced commits works. *) + let gc_add_back () = + (* c1 - c_del - c3 ------ c1 - c2 ------- c3 *) + (* gc(c3) gc(c1) *) + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c_del = commit_del t in + let* t = checkout_exn t c_del in + let* t, c3 = commit_3 t in + [%log.debug "Gc c1, c_del, keep c3"]; + let* () = start_gc t c3 in + let* () = finalise_gc t in + let* () = B.check_gced t c1 "gced c1" in + let* () = B.check_gced t c_del "gced c_del" in + let* () = check_3 t c3 in + let* () = check_del_1 t c3 in + [%log.debug "Add back c1"]; + let* t = checkout_exn t c3 in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* () = check_1 t c1 in + let* t, c2 = commit_2 t in + let* () = check_2 t c2 in + [%log.debug "Gc c3, keep c1, c2"]; + let* () = start_gc t c1 in + let* () = finalise_gc t in + let* () = B.check_gced t c3 "gced c3" in + let* () = check_2 t c2 in + [%log.debug "Add back c3"]; + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = check_3 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + (** Check that gc and close work together. *) + let close () = + (* c1 ------ c2 *) + (* gc(c1) gc(c2) *) + (* close close close *) + let* t = B.init () in + let store_name = t.root in + let* t, c1 = commit_1 t in + let* () = start_gc ~unlink:false t c1 in + let* () = finalise_gc t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = S.Repo.close t.repo in + Alcotest.(check bool) + "unlink:false" true + (Sys.file_exists (Filename.concat store_name "store.0.suffix")); + let* t = B.init ~readonly:true ~fresh:false ~root:store_name () in + let* () = S.Repo.close t.repo in + Alcotest.(check bool) + "RO no clean up" true + (Sys.file_exists (Filename.concat store_name "store.0.suffix")); + let* t = B.init ~readonly:false ~fresh:false ~root:store_name () in + let* () = S.Repo.close t.repo in + Alcotest.(check bool) + "RW cleaned up" true + (check_async_unlinked (Filename.concat store_name "store.0.prefix")); + let* t = B.init ~readonly:false ~fresh:false ~root:store_name () in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = S.Repo.close t.repo in + let* t = B.init ~readonly:false ~fresh:false ~root:store_name () in + [%log.debug "Gc c1, keep c2"]; + let* () = start_gc ~unlink:true t c2 in + let* () = finalise_gc t in + let* () = S.Repo.close t.repo in + Alcotest.(check bool) + "unlink:true" true + (check_async_unlinked (Filename.concat store_name "store.1.suffix")); + let* t = B.init ~readonly:false ~fresh:false ~root:store_name () in + let* () = B.check_gced t c1 "gced c1" in + let* () = check_2 t c2 in + S.Repo.close t.repo + + (** Check that gc works on a commit with two parents. *) + let gc_commit_with_two_parents () = + (* gc(c3) *) + (* c1 - c3 *) + (* c2 -/ *) + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let t = { t with parents = [ c1; c2 ] } in + let* t, c3 = commit_3 t in + let* () = start_gc t c3 in + let* () = finalise_gc t in + let* () = B.check_gced t c1 "gced c1" in + let* () = B.check_gced t c2 "gced c2" in + let* () = check_3 t c3 in + S.Repo.close t.repo + + (** Check that gc preserves and deletes commits from RO. *) + let gc_ro () = + (* c1 ---- c3 ------------------- c4 - c5 *) + (* \- c2 *) + (* gc(c3) gc(c4) *) + (* reload reload reload reload *) + let* t = B.init () in + let* ro_t = B.init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c1 in + let* t, c3 = commit_3 t in + S.reload ro_t.repo; + [%log.debug "Gc c1, c2, keeps c3"]; + let* () = start_gc t c3 in + let* () = finalise_gc t in + [%log.debug "RO finds everything before reload"]; + let* () = check_1 ro_t c1 in + let* () = check_2 ro_t c2 in + let* () = check_3 ro_t c3 in + S.reload ro_t.repo; + [%log.debug "commits gced for RO after reload"]; + let* () = check_3 ro_t c3 in + let* () = B.check_gced ro_t c1 "c1" in + let* () = B.check_removed ro_t c2 "c2" in + let* t = checkout_exn t c3 in + let* t, c4 = commit_4 t in + let* t = checkout_exn t c4 in + let* t, c5 = commit_5 t in + S.reload ro_t.repo; + [%log.debug "Gc c3, keep c4, c5"]; + let* () = start_gc t c4 in + let* () = finalise_gc t in + [%log.debug "RO finds c3, c4, c5 before reload"]; + let* () = check_3 ro_t c3 in + let* () = check_4 ro_t c4 in + let* () = check_5 ro_t c5 in + S.reload ro_t.repo; + [%log.debug "RO finds c4, c5 but c3 gced after reload"]; + let* () = check_4 ro_t c4 in + let* () = check_5 ro_t c5 in + let* () = B.check_gced ro_t c3 "c3" in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check that RO works if reload is called after two gcs. *) + let ro_after_two_gc () = + (* c1 ------- c2 *) + (* gc(c1) gc(c2) *) + (* reload *) + let* t = B.init () in + let* ro_t = B.init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + S.reload ro_t.repo; + let* () = start_gc t c1 in + let* () = finalise_gc t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + [%log.debug "RO finds c1, but c2 gced before reload"]; + let* () = check_1 ro_t c1 in + let* () = check_not_found ro_t c2 "c2" in + [%log.debug "RO finds c2, but c1 gced after reload"]; + S.reload ro_t.repo; + let* () = check_2 ro_t c2 in + let* () = B.check_gced ro_t c1 "c1" in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check that gc and close and ro work together. *) + let ro_close () = + let* t = B.init () in + let* ro_t = B.init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = S.Repo.close ro_t.repo in + let* () = start_gc t c2 in + let* () = finalise_gc t in + [%log.debug "RO reopens is similar to a reload"]; + let* ro_t = B.init ~readonly:true ~fresh:false ~root:t.root () in + let* () = check_2 ro_t c2 in + let* () = B.check_gced ro_t c1 "gced c1" in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + S.reload ro_t.repo; + let* () = check_3 t c3 in + let* () = check_3 ro_t c3 in + let* () = B.check_gced ro_t c1 "gced c1" in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check opening RO store and calling reload right after. *) + let ro_reload_after_v () = + let* t = B.init () in + let* t, c1 = commit_1 t in + let* ro_t = B.init ~readonly:true ~fresh:false ~root:t.root () in + S.reload ro_t.repo; + let* () = check_1 ro_t c1 in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check that gc works when the lru caches some objects that are delete by + consequent commits. See https://github.com/mirage/irmin/issues/1920. *) + let gc_lru () = + let check t c = + S.Commit.of_key t.repo (S.Commit.key c) >>= function + | None -> Alcotest.fail "no hash found in repo" + | Some commit -> + let tree = S.Commit.tree commit in + check_blob tree [ "a"; "b"; "c" ] "b" + in + let* t = B.init ~lru_size:100 () in + let* t = set t [ "a"; "b"; "c" ] "b" in + let* c1 = commit t in + let* t = checkout_exn t c1 in + let* t = set t [ "a"; "d"; "c" ] "b" in + let* c2 = commit t in + let* t = checkout_exn t c2 in + let* t = del t [ "a"; "d"; "c" ] in + let* c3 = commit t in + let* t = checkout_exn t c3 in + let* t = set t [ "a"; "b"; "e" ] "a" in + let* c4 = commit t in + let* () = start_gc t c3 in + let* () = finalise_gc t in + let* () = check t c4 in + S.Repo.close t.repo + + (** Check that calling gc during a batch raises an error. *) + let gc_during_batch () = + let* t = B.init () in + let* t, c1 = commit_1 t in + let* _ = + Alcotest.check_raises_lwt "Should not call gc in batch" + (Irmin_pack_unix.Errors.Pack_error `Gc_forbidden_during_batch) + (fun () -> + S.Backend.Repo.batch t.repo (fun _ _ _ -> + let* () = start_gc t c1 in + finalise_gc t)) + in + S.Repo.close t.repo + + (** Add back commits after they were gced. *) + let add_back_gced_commit () = + (* c1 - c2 - c3 *) + (* gc(c3) *) + (* c1 - c2 *) + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + [%log.debug "Keep c3 gc c1 c2"]; + let* () = start_gc t c3 in + let* () = finalise_gc t in + let* () = B.check_gced t c1 "gced c1" in + let* () = B.check_gced t c2 "gced c2" in + let* t, c1_again = + commit_1 { t with tree = S.Tree.empty (); parents = [] } + in + Alcotest.check_repr S.Hash.t "added commit has the same hash as gced one" + (S.Commit.hash c1_again) (S.Commit.hash c1); + let* () = check_1 t c1_again in + let* t = checkout_exn t c1_again in + let* t, c2_again = commit_2 t in + Alcotest.check_repr S.Hash.t "added commit has the same hash as gced one" + (S.Commit.hash c2_again) (S.Commit.hash c2); + let* () = check_2 t c2_again in + let* () = check_3 t c3 in + S.Repo.close t.repo + + let gc_similar_commits () = + let* t = B.init () in + let* t, c1 = commit_1 t in + let* () = start_gc t c1 in + let* () = finalise_gc t in + let* t = checkout_exn t c1 in + let* t, c1_again = commit_1_different_author t in + let* () = start_gc t c1_again in + let* () = finalise_gc t in + let* () = check_1 t c1_again in + S.Repo.close t.repo + + (** Check [Gc.latest_gc_target]. *) + let latest_gc_target () = + let* t = B.init () in + let check_latest_gc_target expected = + let got = S.Gc.latest_gc_target t.repo in + match (got, expected) with + | None, None -> () + | Some got, Some expected -> + Alcotest.check_repr S.commit_key_t "oldest_live_commit" got + (S.Commit.key expected) + | _ -> Alcotest.fail "Check of oldest_live_commit failed" + in + + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + check_latest_gc_target None; + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + check_latest_gc_target (Some c2); + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = start_gc t c3 in + let* () = finalise_gc t in + check_latest_gc_target (Some c3); + S.Repo.close t.repo + + (** Check Gc stats. *) + let gc_stats () = + let check_stats (stats : Irmin_pack_unix.Stats.Latest_gc.stats) = + let objects_traversed = stats.worker.objects_traversed |> Int63.to_int in + Alcotest.(check int) "objects_traversed" objects_traversed 8; + let files = + List.map (fun (f, s) -> (f, Int63.to_int s)) stats.worker.files + in + let compare a b = String.compare (fst a) (fst b) in + Alcotest.(check (slist (pair string int) compare)) + "test" + [ + ("mapping", 72); + ("prefix", 316); + ("old_mapping", 48); + ("old_prefix", 267); + ] + files + in + + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = start_gc t c3 in + let* stats = finalise_gc_with_stats t in + check_stats (Option.get stats); + S.Repo.close t.repo + + (** Check that a GC clears the LRU *) + let gc_clears_lru () = + let* t = init ~lru_size:100 () in + (* Rreate some commits *) + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + (* Read some data *) + let* () = check_2 t c2 in + let* () = check_3 t c3 in + (* GC *) + let count_before_gc = lru_hits () in + let* () = start_gc t c2 in + let* () = finalise_gc t in + (* Read data again *) + let* () = check_3 t c3 in + Alcotest.(check int) "GC does clear LRU" count_before_gc (lru_hits ()); + S.Repo.close t.repo + + let tests = + [ + tc "Test one gc" one_gc; + tc "Test twice gc" two_gc; + tc "Test gc keeps commits" gc_keeps_all; + tc "Test adding back commits" gc_add_back; + tc "Test close" close; + tc "Test gc commit with two parents" gc_commit_with_two_parents; + tc "Test gc ro" gc_ro; + tc "Test reload after two gc" ro_after_two_gc; + tc "Test ro close" ro_close; + tc "Test ro reload after open" ro_reload_after_v; + tc "Test lru" gc_lru; + tc "Test gc during batch" gc_during_batch; + tc "Test add back gced commit" add_back_gced_commit; + tc "Test gc on similar commits" gc_similar_commits; + tc "Test oldest live commit" latest_gc_target; + tc "Test worker gc stats" gc_stats; + tc "Test gc_clears_lru" gc_clears_lru; + ] +end + +module Gc = struct + include Gc_common (struct + let init = init ~lower_root:None + let check_gced = check_not_found + let check_removed = check_not_found + end) +end + +module Gc_archival = struct + let gc_behaviour = + let pp fmt = function + | `Archive -> Format.pp_print_string fmt "Archive" + | `Delete -> Format.pp_print_string fmt "Delete" + in + Alcotest.testable pp Stdlib.( = ) + + let gc_availability_recent () = + let lower_root = create_lower_root ~mkdir:false () in + let* t = init ~lower_root:(Some lower_root) () in + Alcotest.(check gc_behaviour) + "recent stores with a lower use archiving gc" (S.Gc.behaviour t.repo) + `Archive; + Alcotest.(check bool) + "archiving gc allowed on recent stores with a lower" + (S.Gc.is_allowed t.repo) true; + let* () = S.Repo.close t.repo in + let* t = init () in + Alcotest.(check gc_behaviour) + "recent stores without a lower use deleting gc" (S.Gc.behaviour t.repo) + `Delete; + Alcotest.(check bool) + "deleting gc allowed on recent stores without a lower" + (S.Gc.is_allowed t.repo) true; + S.Repo.close t.repo + + let gc_availability_old () = + let root = create_v1_test_env () in + let lower_root = create_lower_root () in + let* t = init ~root ~fresh:false ~lower_root:(Some lower_root) () in + Alcotest.(check gc_behaviour) + "old stores with a lower use archiving gc" (S.Gc.behaviour t.repo) + `Archive; + Alcotest.(check bool) + "archiving gc allowed on old stores with a lower" (S.Gc.is_allowed t.repo) + true; + let* () = S.Repo.close t.repo in + let root = create_v1_test_env () in + let* t = init ~root ~fresh:false () in + Alcotest.(check gc_behaviour) + "old stores without a lower use deleting gc" (S.Gc.behaviour t.repo) + `Delete; + Alcotest.(check bool) + "deleting not allowed on old stores without a lower" + (S.Gc.is_allowed t.repo) false; + S.Repo.close t.repo + + let gc_reachability_old () = + let root = create_v1_test_env () in + let lower_root = create_lower_root () in + [%log.debug "Open v1 store to trigger migration"]; + let* t = init ~root ~fresh:false ~lower_root:(Some lower_root) () in + let* main = S.main t.repo in + [%log.debug "Run GC on commit that is now in lower"]; + let* head = S.Head.get main in + let () = + match Irmin_pack_unix.Pack_key.inspect (S.Commit.key head) with + | Direct { volume_identifier; _ } -> + Alcotest.(check bool) + "after migration, head is in lower" + (Option.is_some volume_identifier) + true + | _ -> assert false + in + let* () = start_gc t head in + let* () = finalise_gc t in + S.Repo.close t.repo + + module B = struct + let init ?lru_size ?readonly ?fresh ?root () = + let root = Option.value root ~default:(fresh_name ()) in + let lower_root = root ^ ".lower" in + init ?lru_size ?readonly ?fresh ~root ~lower_root:(Some lower_root) () + + let check_gced t c s = + let* c = S.Commit.of_key t.repo (S.Commit.key c) in + Alcotest.(check bool s true (Option.is_some c)); + Lwt.return_unit + + let check_removed = check_not_found + end + + let gc_archival_multiple_volumes () = + let* t = B.init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* t = checkout_exn t c1 in + let* t, c3 = commit_3 t in + let* t = checkout_exn t c2 in + let* t, c4 = commit_4 t in + [%log.debug "Gc c1, c2, c3, keep c4"]; + let* () = start_gc t c4 in + let* () = finalise_gc t in + [%log.debug "Add a new volume"]; + S.add_volume t.repo; + let* t = checkout_exn t c4 in + let* t, c5 = commit_5 t in + let* () = check_5 t c5 in + [%log.debug "Gc c4, keep c5"]; + let* () = start_gc t c5 in + let* () = finalise_gc t in + let* () = check_5 t c5 in + let* () = B.check_gced t c1 "gced c1" in + let* () = B.check_gced t c2 "gced c2" in + let* () = B.check_removed t c3 "gced c3" in + let* () = B.check_gced t c4 "gced c4" in + let* () = + Alcotest.check_raises_pack_error "Cannot GC on commit older than c5" + (function `Gc_disallowed _ -> true | _ -> false) + (fun () -> start_gc t c4) + in + S.Repo.close t.repo + + module Gc_common_tests = Gc_common (B) + + let tests = + [ + tc "Test availability of different gc modes on recent stores" + gc_availability_recent; + tc "Test availability of different gc modes on old stores" + gc_availability_old; + tc "Test archiving twice on different volumes" + gc_archival_multiple_volumes; + tc "Test reachability on old stores" gc_reachability_old; + ] + @ Gc_common_tests.tests +end + +module Concurrent_gc = struct + (** Check that finding old objects during a gc works. *) + let find_running_gc ~lru_size () = + let* t = init ~lru_size () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + [%log.debug "Gc c1 keep c2"]; + let* () = start_gc t c2 in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = finalise_gc t in + let* () = check_not_found t c1 "removed c1" in + let* () = check_2 t c2 in + S.Repo.close t.repo + + (** Check adding new objects during a gc and finding them after the gc. *) + let add_running_gc ~lru_size () = + let* t = init ~lru_size () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + [%log.debug "Gc c1 keep c2"]; + let* () = start_gc t c2 in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = finalise_gc t in + let* () = check_not_found t c1 "removed c1" in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + (** Check adding new objects during a gc and finding them after the gc. *) + let several_gc ~lru_size () = + let* t = init ~lru_size () in + let* t, c1 = commit_1 t in + let* () = start_gc t c1 in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = finalise_gc t in + let* () = start_gc t c2 in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = finalise_gc t in + let* () = start_gc t c3 in + let* t = checkout_exn t c3 in + let* t, c4 = commit_4 t in + let* () = finalise_gc t in + let* () = start_gc t c4 in + let* t = checkout_exn t c4 in + let* t, c5 = commit_5 t in + let* () = finalise_gc t in + let* () = check_not_found t c1 "removed c1" in + let* () = check_not_found t c2 "removed c2" in + let* () = check_not_found t c3 "removed c3" in + let* () = check_4 t c4 in + let* () = check_5 t c5 in + S.Repo.close t.repo + + let find_running_gc_with_lru = find_running_gc ~lru_size:100 + let add_running_gc_with_lru = add_running_gc ~lru_size:100 + let several_gc_with_lru = several_gc ~lru_size:100 + let find_running_gc = find_running_gc ~lru_size:0 + let add_running_gc = add_running_gc ~lru_size:0 + let several_gc = several_gc ~lru_size:0 + + (** Check that RO can find old objects during gc. Also that RO can still find + removed objects before a call to [reload]. *) + let ro_find_running_gc () = + let* t = init () in + let* ro_t = init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + [%log.debug "Gc c1 keep c2"]; + let* () = start_gc t c2 in + S.reload ro_t.repo; + let* () = check_1 ro_t c1 in + S.reload ro_t.repo; + let* () = check_2 ro_t c2 in + let* () = finalise_gc t in + let* () = check_1 ro_t c1 in + let* () = check_2 ro_t c2 in + S.reload ro_t.repo; + let* () = check_not_found ro_t c1 "removed c1" in + let* () = check_2 t c2 in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check that RO can find objects added during gc, but only after a call to + [reload]. *) + let ro_add_running_gc () = + let* t = init () in + let* ro_t = init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + [%log.debug "Gc c1 keep c2"]; + let* () = start_gc t c2 in + S.reload ro_t.repo; + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + S.reload ro_t.repo; + let* t = checkout_exn t c2 in + let* t, c4 = commit_4 t in + let* () = finalise_gc t in + let* () = check_not_found ro_t c4 "not yet loaded c4" in + let* () = check_1 ro_t c1 in + let* () = check_2 ro_t c2 in + let* () = check_3 ro_t c3 in + S.reload ro_t.repo; + let* () = check_not_found ro_t c1 "removed c1" in + let* () = check_4 ro_t c4 in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check that RO can call [reload] during a second gc, even after no reloads + occured during the first gc. *) + let ro_reload_after_second_gc () = + let* t = init () in + let* ro_t = init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + [%log.debug "Gc c1 keep c2"]; + let* () = start_gc t c2 in + let* () = finalise_gc t in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + [%log.debug "Gc c2 keep c3"]; + let* () = start_gc t c3 in + let* () = finalise_gc t in + S.reload ro_t.repo; + let* () = check_not_found ro_t c1 "removed c1" in + let* () = check_not_found ro_t c2 "removed c2" in + let* () = check_3 t c3 in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + (** Check that calling reload in RO will clear the LRU only after GC. *) + let ro_reload_clears_lru () = + let* rw_t = init () in + let* ro_t = + init ~lru_size:100 ~readonly:true ~fresh:false ~root:rw_t.root () + in + (* Create some commits in RW *) + let* rw_t, c1 = commit_1 rw_t in + let* rw_t = checkout_exn rw_t c1 in + let* rw_t, c2 = commit_2 rw_t in + let* rw_t = checkout_exn rw_t c2 in + let* rw_t, c3 = commit_3 rw_t in + (* Reload RO to get all changes, and read some data *) + S.reload ro_t.repo; + let* () = check_3 ro_t c3 in + let count_before_reload = lru_hits () in + (* Reload should not clear LRU *) + S.reload ro_t.repo; + let* () = check_3 ro_t c3 in + Alcotest.(check bool) + "reload does not clear LRU" true + (count_before_reload < lru_hits ()); + (* GC *) + let count_before_gc = lru_hits () in + let* () = start_gc rw_t c2 in + let* () = finalise_gc rw_t in + (* Reload RO to get changes and clear LRU, and read some data *) + S.reload ro_t.repo; + let* () = check_3 ro_t c3 in + Alcotest.(check int) "reload does clear LRU" count_before_gc (lru_hits ()); + let* () = S.Repo.close rw_t.repo in + S.Repo.close ro_t.repo + + (** Check that calling close during a gc kills the gc without finalising it. + On reopening the store, the following gc works fine. *) + let close_running_gc () = + let* t = init () in + let* t, c1 = commit_1 t in + let* () = start_gc t c1 in + let* () = S.Repo.close t.repo in + let* t = init ~readonly:false ~fresh:false ~root:t.root () in + let* () = check_1 t c1 in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + let* t = checkout_exn t c2 in + S.Repo.close t.repo + + (** Check that the cleanup routine in file manager deletes correct files. *) + let test_cancel_cleanup () = + let* t = init () in + (* chunk 0, commit 1 *) + let* t, c1 = commit_1 t in + let () = S.split t.repo in + (* chunk 1, commit 2 *) + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let () = S.split t.repo in + (* GC chunk 0 - important to have at least one GC to test + the cleanup routine's usage of generation *) + let* () = start_gc t c2 in + let* () = finalise_gc t in + (* chunk 2, commit 3 *) + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let () = S.split t.repo in + (* Start GC and then close repo before finalise *) + let* () = start_gc t c3 in + let* () = S.Repo.close t.repo in + (* Reopen store. If the cleanup on cancel deletes wrong files, the + store will fail to open. *) + let* t = init ~readonly:false ~fresh:false ~root:t.root () in + (* Check commits *) + let* () = check_not_found t c1 "removed c1" in + (* commit 2 is still around because its GC was interrupted *) + let* () = check_2 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + (** Check starting a gc before a previous is finalised. *) + let test_skip () = + let* t = init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = start_gc t c3 in + let* () = finalise_gc t in + let* () = check_not_found t c1 "removed c1" in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + let kill_gc t = + let repo : S.Repo.t = t.repo in + if S.Internal.kill_gc repo then true + else Alcotest.failf "running_gc missing after call to start" + + let test_kill_gc_and_finalise () = + let* t = init () in + let* t, c1 = commit_1 t in + let* () = start_gc t c1 in + let killed = kill_gc t in + let* () = + if killed then + Alcotest.check_raises_pack_error "Gc process killed" + (function + | `Gc_process_died_without_result_file _ -> true | _ -> false) + (fun () -> finalise_gc t) + else Lwt.return_unit + in + S.Repo.close t.repo + + let test_kill_gc_and_close () = + let* t = init () in + let* t, c1 = commit_1 t in + let* () = start_gc t c1 in + let _killed = kill_gc t in + S.Repo.close t.repo + + let tests = + [ + tc "Test find_running_gc" find_running_gc; + tc "Test add_running_gc" add_running_gc; + tc "Test several_gc" several_gc; + tc "Test find_running_gc_with_lru" find_running_gc_with_lru; + tc "Test add_running_gc_with_lru" add_running_gc_with_lru; + tc "Test several_gc_with_lru" several_gc_with_lru; + tc "Test ro_find_running_gc" ro_find_running_gc; + tc "Test ro_add_running_gc" ro_add_running_gc; + tc "Test ro_reload_after_second_gc" ro_reload_after_second_gc; + tc "Test ro_reload_clears_lru" ro_reload_clears_lru; + tc "Test close_running_gc" close_running_gc; + tc "Test skip gc" test_skip; + tc "Test kill gc and finalise" test_kill_gc_and_finalise; + tc "Test kill gc and close" test_kill_gc_and_close; + tc "Test gc cancel cleanup" test_cancel_cleanup; + ] +end + +module Split = struct + let two_splits () = + let* t = init () in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + [%log.debug "created chunk2, find in chunk1"]; + let* () = check_1 t c1 in + let* t, c2 = commit_2 t in + let () = S.split t.repo in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + [%log.debug "created chunk3, find in chunk1, chunk2, chunk3"]; + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + let ro_two_splits () = + let* t = init () in + let* ro_t = init ~readonly:true ~fresh:false ~root:t.root () in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + [%log.debug "created chunk2, find in chunk1"]; + S.reload ro_t.repo; + let* () = check_1 ro_t c1 in + let* t, c2 = commit_2 t in + let () = S.split t.repo in + let* t = checkout_exn t c2 in + S.reload ro_t.repo; + let* t, c3 = commit_3 t in + [%log.debug "created chunk3, find in chunk1, chunk2, chunk3"]; + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = check_not_found ro_t c3 "c3 is not yet reloaded" in + S.reload ro_t.repo; + let* () = check_3 t c3 in + let* () = S.Repo.close t.repo in + S.Repo.close ro_t.repo + + let load_commit t h = + let hash = + match Irmin.Type.(of_string Schema.Hash.t) h with + | Error (`Msg s) -> Alcotest.failf "failed hash_of_string %s" s + | Ok hash -> hash + in + let+ commit = S.Commit.of_hash t.repo hash in + match commit with + | None -> Alcotest.failf "Commit %s not found" h + | Some commit -> commit + + let check_preexisting_commit t = + let h = "22e159de13b427226e5901defd17f0c14e744205" in + let* commit = load_commit t h in + let tree = S.Commit.tree commit in + let+ got = S.Tree.find tree [ "step-n01"; "step-b01" ] in + Alcotest.(check (option string)) "find blob" (Some "b01") got + + let v3_migrated_store_splits_and_gc () = + let root = create_test_env () in + let* t = init ~readonly:false ~fresh:false ~root () in + let* c0 = load_commit t "22e159de13b427226e5901defd17f0c14e744205" in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let () = S.split t.repo in + [%log.debug + "chunk0 consists of the preexisting V3 suffix and c1, chunk1 is c2"]; + let* () = check_preexisting_commit t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + [%log.debug "GC at c0"]; + let* () = start_gc ~unlink:true t c0 in + let* () = finalise_gc t in + let* () = check_preexisting_commit t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + Alcotest.(check bool) + "Chunk0 still exists" true + (Sys.file_exists (Filename.concat t.root "store.0.suffix")); + [%log.debug "GC at c1"]; + let* () = start_gc ~unlink:true t c1 in + let* () = finalise_gc t in + let* () = check_not_found t c0 "removed c0" in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + Alcotest.(check bool) + "Chunk0 removed" true + (check_async_unlinked (Filename.concat t.root "store.0.suffix")); + [%log.debug "GC at c2"]; + let* () = start_gc ~unlink:true t c2 in + let* () = finalise_gc t in + let* () = check_not_found t c0 "removed c0" in + let* () = check_not_found t c1 "removed c1" in + let* () = check_2 t c2 in + S.Repo.close t.repo + + let close_and_split () = + let* t = init () in + let root = t.root in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + [%log.debug "created chunk1, chunk2"]; + let* () = S.Repo.close t.repo in + let* t = init ~readonly:false ~fresh:false ~root () in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let () = S.split t.repo in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + [%log.debug "created chunk3"]; + let* () = S.Repo.close t.repo in + let* t = init ~readonly:true ~fresh:false ~root () in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + S.Repo.close t.repo + + let two_gc_then_split () = + let* t = init () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + let* () = start_gc t c3 in + let* () = finalise_gc t in + let () = S.split t.repo in + let* t = checkout_exn t c3 in + let* t, c4 = commit_4 t in + let* () = check_not_found t c1 "removed c1" in + let* () = check_not_found t c2 "removed c2" in + let* () = check_3 t c3 in + let* () = check_4 t c4 in + S.Repo.close t.repo + + let multi_split_and_gc () = + (* This test primarily checks that dead byte calculation + happens correctly by testing GCs on chunks past the first + one. When the calculation is incorrect, exceptions are thrown + when attempting to lookup keys in the store. *) + let* t = init () in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + + let () = S.split t.repo in + let* () = start_gc t c1 in + let* () = finalise_gc t in + + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + + let () = S.split t.repo in + let* () = start_gc t c2 in + let* () = finalise_gc t in + + let* t = checkout_exn t c3 in + let* t, c4 = commit_4 t in + + let* () = check_not_found t c1 "removed c1" in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + let* () = check_4 t c4 in + S.Repo.close t.repo + + let split_and_gc () = + let* t = init () in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + let* () = check_2 t c2 in + let* () = check_not_found t c1 "removed c1" in + S.Repo.close t.repo + + let another_split_and_gc () = + let* t = init () in + let* t, c1 = commit_1 t in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c1 in + let* () = finalise_gc t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + S.Repo.close t.repo + + let split_during_gc () = + let* t = init () in + let* t, c1 = commit_1 t in + let* () = start_gc t c1 in + let () = S.split t.repo in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = finalise_gc t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + S.Repo.close t.repo + + let commits_and_splits_during_gc () = + (* This test primarily ensures that chunk num is calculated + correctly by intentionally creating chunks during a GC. *) + let* t = init () in + let* t, c1 = commit_1 t in + + let () = S.split t.repo in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + + let* () = start_gc t c2 in + let () = S.split t.repo in + + let* t = checkout_exn t c2 in + let* t, c3 = commit_3 t in + + let () = S.split t.repo in + let* t = checkout_exn t c3 in + let* t, c4 = commit_4 t in + + let* () = finalise_gc t in + let* () = check_not_found t c1 "removed c1" in + let* () = check_2 t c2 in + let* () = check_3 t c3 in + let* () = check_4 t c4 in + S.Repo.close t.repo + + let split_always_indexed_from_v2_store () = + let root = create_from_v2_always_test_env () in + let* t = init ~readonly:false ~fresh:false ~root () in + let* _c0 = load_commit t "22e159de13b427226e5901defd17f0c14e744205" in + let* t, _c1 = commit_1 t in + let f () = S.split t.repo in + Alcotest.check_raises "split should raise disallowed exception" + (Irmin_pack_unix.Errors.Pack_error `Split_disallowed) f; + Alcotest.( + check bool "is_split_allowed should be false" false + (S.is_split_allowed t.repo)); + S.Repo.close t.repo + + let tests = + [ + tc "Test two splits" two_splits; + tc "Test two splits for ro" ro_two_splits; + tc "Test splits and GC on V3 store" v3_migrated_store_splits_and_gc; + tc "Test split and close" close_and_split; + tc "Test two gc followed by split" two_gc_then_split; + tc "Test split and GC" split_and_gc; + tc "Test multi split and GC" multi_split_and_gc; + tc "Test another split and GC" another_split_and_gc; + tc "Test split during GC" split_during_gc; + tc "Test commits and splits during GC" commits_and_splits_during_gc; + tc "Test split for always indexed from v2 store" + split_always_indexed_from_v2_store; + ] +end + +module Snapshot = struct + let export t commit = + let commit_key = S.Commit.key commit in + S.create_one_commit_store t.repo commit_key + + let snapshot_rw () = + let* t = init () in + let* t, c1 = commit_1 t in + let root_snap = Filename.concat t.root "snap" in + let* () = export t c1 root_snap in + [%log.debug "store works after export"]; + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + let* () = S.Repo.close t.repo in + [%log.debug "open store from import in rw"]; + let* t = init ~readonly:false ~fresh:false ~root:root_snap () in + let* t = checkout_exn t c1 in + let* () = check_1 t c1 in + let* () = check_not_found t c2 "c2 not commited yet" in + let* t, c2 = commit_2 t in + let* () = check_2 t c2 in + S.Repo.close t.repo + + let snapshot_import_in_ro () = + let* t = init () in + let* t, c1 = commit_1 t in + let root_snap = Filename.concat t.root "snap" in + let* () = export t c1 root_snap in + let* () = S.Repo.close t.repo in + [%log.debug "open store from import in ro"]; + let* t = init ~readonly:true ~fresh:false ~root:root_snap () in + let* t = checkout_exn t c1 in + let* () = check_1 t c1 in + S.Repo.close t.repo + + let snapshot_export_in_ro () = + let* t = init () in + let* t, c1 = commit_1 t in + let* () = S.Repo.close t.repo in + [%log.debug "open store in readonly to export"]; + let* t = init ~readonly:false ~fresh:false ~root:t.root () in + let root_snap = Filename.concat t.root "snap" in + let* () = export t c1 root_snap in + [%log.debug "store works after export in readonly"]; + let* t = checkout_exn t c1 in + let* () = check_1 t c1 in + let* () = S.Repo.close t.repo in + [%log.debug "open store from snapshot"]; + let* t = init ~readonly:false ~fresh:false ~root:root_snap () in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + S.Repo.close t.repo + + (* Test creating a snapshot in an archive store for a commit that is before + the last gc target commit (ie it is in the lower) *) + let snapshot_gced_commit () = + let lower_root = create_lower_root ~mkdir:false () in + let* t = init ~lower_root:(Some lower_root) () in + let* t, c1 = commit_1 t in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = start_gc t c2 in + let* () = finalise_gc t in + let root_snap = Filename.concat t.root "snap" in + let* () = export t c1 root_snap in + let* () = S.Repo.close t.repo in + [%log.debug "open store from snapshot"]; + let* t = init ~readonly:false ~fresh:false ~root:root_snap () in + let* t = checkout_exn t c1 in + let* t, c2 = commit_2 t in + let* () = check_1 t c1 in + let* () = check_2 t c2 in + S.Repo.close t.repo + + let tests = + [ + tc "Import/export in rw" snapshot_rw; + tc "Import in ro" snapshot_import_in_ro; + tc "Export in ro" snapshot_export_in_ro; + tc "Snapshot gced commit" snapshot_gced_commit; + ] +end diff --git a/vendors/irmin/test/irmin-pack/test_gc.mli b/vendors/irmin/test/irmin-pack/test_gc.mli new file mode 100644 index 000000000000..adfd50df434e --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_gc.mli @@ -0,0 +1,51 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Gc : sig + val tests : unit Alcotest_lwt.test_case list +end + +module Gc_archival : sig + val tests : unit Alcotest_lwt.test_case list +end + +module Concurrent_gc : sig + val tests : unit Alcotest_lwt.test_case list +end + +module Split : sig + val tests : unit Alcotest_lwt.test_case list +end + +module Snapshot : sig + val tests : unit Alcotest_lwt.test_case list +end + +module Store : sig + module S : Irmin_pack.S + + type t + + val config : string -> Irmin.config + val init_with_config : Irmin.config -> t Lwt.t + val close : t -> unit Lwt.t + val start_gc : ?unlink:bool -> t -> S.commit -> unit Lwt.t + val finalise_gc : t -> unit Lwt.t + val commit_1 : t -> (t * S.commit) Lwt.t + val commit_2 : t -> (t * S.commit) Lwt.t + val commit_3 : t -> (t * S.commit) Lwt.t + val checkout_exn : t -> S.commit -> t Lwt.t +end diff --git a/vendors/irmin/test/irmin-pack/test_hashes.ml b/vendors/irmin/test/irmin-pack/test_hashes.ml new file mode 100644 index 000000000000..62968c126ef6 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_hashes.ml @@ -0,0 +1,321 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let root = Filename.concat "_build" "test-irmin-tezos" + +let conf = + Irmin_pack.config ~readonly:false ~fresh:true ~index_log_size:1000 root + +let zero = Bytes.make 10 '0' + +let hash_zero = + "d81e60258ecc8bd7064c8703888aececfc54e29ff94f7a2d9a84667a500548e1" + +let bindings steps = List.map (fun x -> ([ x ], zero)) steps + +let check_string ~msg ~expected ~got = + let got = Hex.of_string got |> Hex.show in + Alcotest.(check string) (Fmt.str "%s" msg) expected got + +let check_iter iter_type (iter : 'a -> (string -> unit) -> unit) v checks = + let counter = ref 0 in + iter v (fun x -> + match List.nth_opt checks !counter with + | None -> Alcotest.failf "No more calls to %s left" iter_type + | Some (msg, expected) -> + let msg = Fmt.str "Check %s:%s" iter_type msg in + check_string ~msg ~expected ~got:x; + incr counter); + if !counter <> List.length checks then + Alcotest.failf "More calls to %s expected" iter_type + +module Test + (Conf : Irmin_pack.Conf.S) + (Schema : Irmin.Schema.Extended + with type Contents.t = bytes + and type Metadata.t = unit + and type Path.t = string list + and type Path.step = string + and type Branch.t = string + and module Info = Irmin.Info.Default) = +struct + module Store = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) + end + + include Store + + let build_tree steps = + let bindings = bindings steps in + let tree = Tree.empty () in + let+ tree = + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree bindings + in + tree + + let persist_tree tree = + let* repo = Repo.v conf in + let* init_commit = + Commit.v ~parents:[] ~info:Info.empty repo + (Tree.singleton [ "singleton-step" ] (Bytes.of_string "singleton-val")) + in + let h = Commit.hash init_commit in + let info = Info.v ~author:"Tezos" 0L in + let* commit = + Commit.v ~parents:[ Irmin_pack_unix.Pack_key.v_indexed h ] ~info repo tree + in + let tree = Commit.tree commit in + Lwt.return (repo, tree, commit) + + let check_hardcoded_hash msg expected got = + let got = (Irmin.Type.to_string Store.Hash.t) got in + Alcotest.(check string) + (Fmt.str "Check hardcoded hash: %s" msg) + expected got +end + +module Test_tezos_conf = struct + module Store = Test (Irmin_tezos.Conf) (Irmin_tezos.Schema) + module Contents = Store.Backend.Contents + module Node = Store.Backend.Node + module Commit = Store.Backend.Commit + + let hash_root_small_tree = + "83722c2791a1c47dada4718656a20a2f3a063ae9945b475e67bbb6ef29d88ca4" + + let contents_hash () = + let h0 = Contents.Hash.hash zero in + let encode_bin_hash = Irmin.Type.(unstage (encode_bin Contents.Hash.t)) in + encode_bin_hash h0 (fun x -> + check_string ~msg:"Check encode_bin: h0" ~expected:hash_zero ~got:x); + let encode_bin_val = Irmin.Type.(unstage (encode_bin Contents.Val.t)) in + let checks = + [ ("header of zero", "0a"); ("zero", "30303030303030303030") ] + in + check_iter "encode_bin" encode_bin_val zero checks; + let pre_hash_val = Irmin.Type.(unstage (pre_hash Contents.Val.t)) in + let checks = + [ + ("header of zero", "000000000000000a"); ("zero", "30303030303030303030"); + ] + in + check_iter "pre_hash" pre_hash_val zero checks; + Store.check_hardcoded_hash "contents hash" + "CoWHVKM5r2eiHQxhicqakkr5FwJfabahGBwCCWzRPCNPs79CoZty" h0; + Lwt.return_unit + + let some_steps = [ "00"; "01" ] + + let checks_bindings_pre_hash steps = + let nb_steps = Fmt.str "%016x" (List.length steps) in + let checks = + List.fold_left + (fun acc s -> + let hex = Hex.of_string s |> Hex.show in + let check_step = + [ + ("node type is contents", "ff00000000000000"); + ("len of step ", "02"); + (s, hex); + ("len of contents hash", "0000000000000020"); + ("hash of contents", hash_zero); + ] + |> List.rev + in + check_step @ acc) + [] steps + |> List.rev + in + ("len of values", nb_steps) :: checks + + let inode_values_hash () = + let* tree = Store.build_tree some_steps in + let* repo, tree, _ = Store.persist_tree tree in + let* root_node = + match Store.Tree.destruct tree with + | `Contents _ -> Alcotest.fail "Expected root to be node" + | `Node x -> Store.to_backend_node x + in + let h = Node.Hash.hash root_node in + let encode_bin_hash = Irmin.Type.(unstage (encode_bin Node.Hash.t)) in + encode_bin_hash h (fun x -> + check_string ~msg:"Check encode_bin: node hash" + ~expected:hash_root_small_tree ~got:x); + let pre_hash_val = Irmin.Type.(unstage (pre_hash Node.Val.t)) in + let checks = checks_bindings_pre_hash some_steps in + check_iter "pre_hash" pre_hash_val root_node checks; + Store.check_hardcoded_hash "node hash" + "CoVeCU4o3dqmfdwqt2vh8LDz9X6qGbTUyLhgVvFReyzAvTf92AKx" h; + let* () = Store.Repo.close repo in + Lwt.return_unit + + let commit_hash () = + let* tree = Store.build_tree some_steps in + let* repo, _, commit = Store.persist_tree tree in + let commit_val = Store.to_backend_commit commit in + let h = Commit.Hash.hash commit_val in + let encode_bin_hash = Irmin.Type.(unstage (encode_bin Commit.Hash.t)) in + encode_bin_hash h (fun x -> + check_string ~msg:"commit hash" + ~expected: + "c20860adda3c3d40d8d03fab22b07e889979cdac880d979711aa852a0896ae30" + ~got:x); + let checks = + [ + ("hash of root node", hash_root_small_tree); + ("len of parents", "01"); + ( "parent hash", + "634d894802f9032ef48bbe1253563dbeb2aad7dc684da83bdea5692fde2185ae" ); + ("date", "0000000000000000"); + ("len of author", "05"); + ("author", "54657a6f73"); + ("len of message", "00"); + ("message", ""); + ] + in + let encode_bin_val = Irmin.Type.(unstage (encode_bin Commit.Val.t)) in + check_iter "encode_bin" encode_bin_val commit_val checks; + let checks = + [ + ("len of node hash", "0000000000000020"); + ("hash of root node", hash_root_small_tree); + ("len of parents", "0000000000000001"); + ("len of parent hash", "0000000000000020"); + ( "parent hash", + "634d894802f9032ef48bbe1253563dbeb2aad7dc684da83bdea5692fde2185ae" ); + ("date", "0000000000000000"); + ("len of author", "0000000000000005"); + ("author", "54657a6f73"); + ("len of message", "0000000000000000"); + ("message", ""); + ] + in + let pre_hash_val = Irmin.Type.(unstage (pre_hash Commit.Val.t)) in + check_iter "pre_hash" pre_hash_val commit_val checks; + Store.check_hardcoded_hash "commit hash" + "CoW7mALEs2vue5cfTMdJfSAjNmjmALYS1YyqSsYr9siLcNEcrvAm" h; + let* () = Store.Repo.close repo in + Lwt.return_unit +end + +module Test_small_conf = struct + module Conf = struct + let entries = 2 + let stable_hash = 3 + let contents_length_header = Some `Varint + let inode_child_order = `Seeded_hash + let forbid_empty_dir_persistence = true + end + + module Store = Test (Conf) (Irmin_tezos.Schema) + module Node = Store.Backend.Node + + let many_steps = [ "00"; "01"; "02"; "03"; "04"; "05" ] + + let checks = + [ + ("inode tree", "01"); + ("depth", "00"); + ("len of tree", "06"); + ("d", "02"); + ("e", "00"); + ("g", "aa670a7e66b80a4d5f0e2e35b0c7fc4fa8d3e2d62a8b90eb2ff1d184dde9d0fa"); + ("b1", "01"); + ( "hash ", + "821707c86f7030b1102397feb88d454076ec64744dfd9811b8254bd61d396cfe" ); + ] + + let inode_tree_hash () = + let* tree = Store.build_tree many_steps in + let* repo, tree, _ = Store.persist_tree tree in + let* root_node = + match Store.Tree.destruct tree with + | `Contents _ -> Alcotest.fail "Expected root to be node" + | `Node x -> Store.to_backend_node x + in + let h = Node.Hash.hash root_node in + let pre_hash_hash = Irmin.Type.(unstage (pre_hash Node.Hash.t)) in + pre_hash_hash h (fun x -> + check_string ~msg:"node hash" + ~expected: + "e670a325ac78b2b6949b8f9fa448b17aa708ef39eb29c9e364be473f988329ea" + ~got:x); + let pre_hash_val = Irmin.Type.(unstage (pre_hash Node.Val.t)) in + check_iter "pre_hash" pre_hash_val root_node checks; + Store.check_hardcoded_hash "node hash" + "CoWPo8s8h81q8skRqfPLTAJvq4ioFKS6rQhdRcY5nd6HQz2upwp4" h; + let* () = Store.Repo.close repo in + Lwt.return_unit +end + +module Test_V1 = struct + module Schema = struct + include Irmin_tezos.Schema + + module Commit + (Node_key : Irmin.Key.S with type hash = Hash.t) + (Commit_key : Irmin.Key.S with type hash = Hash.t) = + struct + module M = Irmin.Commit.Generic_key.Make (Hash) (Node_key) (Commit_key) + module Commit = Irmin.Commit.V1.Make (Hash) (M) + include Commit + end + end + + module Store = Test (Conf) (Schema) + module Commit = Store.Backend.Commit + + let many_steps = [ "00"; "01"; "02"; "03"; "04"; "05" ] + + let commit_hash () = + let* tree = Store.build_tree many_steps in + let* repo, _, commit = Store.persist_tree tree in + let commit_val = Store.to_backend_commit commit in + let checks = + [ + ("len of node hash", "0000000000000020"); + ( "hash of root node", + "3ab1c8feb08812cd1ffd8ec1ca4f861a578b700fa7dd9daab4c63d4e86638f99" ); + ("len of parents", "0000000000000001"); + ("len of parent hash", "0000000000000020"); + ( "parent hash", + "634d894802f9032ef48bbe1253563dbeb2aad7dc684da83bdea5692fde2185ae" ); + ("date", "0000000000000000"); + ("len of author", "0000000000000005"); + ("author", "54657a6f73"); + ("len of message", "0000000000000000"); + ("message", ""); + ] + in + let encode_bin_val = Irmin.Type.(unstage (encode_bin Commit.Val.t)) in + check_iter "encode_bin" encode_bin_val commit_val checks; + let* () = Store.Repo.close repo in + Lwt.return_unit +end + +let tests = + let tc name f = Alcotest_lwt.test_case name `Quick (fun _switch -> f) in + [ + tc "contents hash" Test_tezos_conf.contents_hash; + tc "inode_values hash" Test_tezos_conf.inode_values_hash; + tc "inode_tree hash" Test_small_conf.inode_tree_hash; + tc "commit hash" Test_tezos_conf.commit_hash; + tc "V1 commit hash" Test_V1.commit_hash; + ] diff --git a/vendors/irmin/test/irmin-pack/test_hashes.mli b/vendors/irmin/test/irmin-pack/test_hashes.mli new file mode 100644 index 000000000000..5502f37745f8 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_hashes.mli @@ -0,0 +1,24 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list + +val check_iter : + string -> + ('a -> (string -> unit) -> unit) -> + 'a -> + (string * string) list -> + unit diff --git a/vendors/irmin/test/irmin-pack/test_indexing_strategy.ml b/vendors/irmin/test/irmin-pack/test_indexing_strategy.ml new file mode 100644 index 000000000000..dc08546f1714 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_indexing_strategy.ml @@ -0,0 +1,116 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let src = + Logs.Src.create "tests.indexing_strategy" ~doc:"Test indexing strategy" + +module Log = (val Logs.src_log src : Logs.LOG) + +module Store = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) +end + +let config ~indexing_strategy ?(readonly = false) ?(fresh = false) () = + let root = Filename.concat "_build" "test_indexing_strategy" in + Irmin_pack.config ~readonly ~indexing_strategy ~fresh root + +let test_unique_when_switched () = + let value = "Welt" in + let get_contents_key store path = + let* k = Store.key store path in + match Option.get k with + | `Node _ -> assert false + | `Contents contents_key -> Lwt.return contents_key + in + let get_direct_key key = + match Irmin_pack_unix.Pack_key.inspect key with + | Direct { offset; hash; length; _ } -> (offset, hash, length) + | _ -> assert false + in + let get_key_offset key = + let offset, _, _ = get_direct_key key in + offset + in + let check_hash msg a b = + let _, hash_a, _ = get_direct_key a in + let _, hash_b, _ = get_direct_key b in + Alcotest.(check_repr Store.hash_t) msg hash_a hash_b + in + + (* 1. open store with always indexing, verify same offsets *) + let* repo = + Store.Repo.v + @@ config ~indexing_strategy:Irmin_pack.Indexing_strategy.always ~fresh:true + () + in + let* store = Store.main repo in + let* first_key = + let first_path = [ "hello" ] in + let* () = + Store.set_exn ~info:(fun () -> Store.Info.empty) store first_path value + in + get_contents_key store first_path + in + let* second_key = + let second_path = [ "salut" ] in + let* () = + Store.set_exn ~info:(fun () -> Store.Info.empty) store second_path value + in + get_contents_key store second_path + in + Alcotest.(check int63) + "offsets should be equal when using always indexing" + (get_key_offset first_key) + (get_key_offset second_key); + + let* () = Store.Repo.close repo in + + (* 2. re-open store with minimal indexing, verify new offset *) + let* repo = + Store.Repo.v + @@ config ~indexing_strategy:Irmin_pack.Indexing_strategy.minimal + ~fresh:false () + in + let* store = Store.main repo in + let* third_key = + let third_path = [ "hola" ] in + let* () = + Store.set_exn ~info:(fun () -> Store.Info.empty) store third_path value + in + get_contents_key store third_path + in + Alcotest.(check bool) + "offsets (3rd, 1st) should not be equal when using minimal indexing" false + (Int63.equal (get_key_offset third_key) (get_key_offset first_key)); + Alcotest.(check bool) + "offsets (3rd, 2nd) should not be equal when using minimal indexing" false + (Int63.equal (get_key_offset third_key) (get_key_offset second_key)); + + (* 3. verify all hashes are equal *) + check_hash "hashes are equal (1st, 2nd)" first_key second_key; + check_hash "hashes are equal (2nd, 3rd)" second_key third_key; + + Store.Repo.close repo + +let tests = + [ + Alcotest_lwt.test_case "test unique when switching strategies" `Quick + (fun _switch () -> test_unique_when_switched ()); + ] diff --git a/vendors/irmin/test/irmin-pack/test_indexing_strategy.mli b/vendors/irmin/test/irmin-pack/test_indexing_strategy.mli new file mode 100644 index 000000000000..3c5b234dea0c --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_indexing_strategy.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_inode.ml b/vendors/irmin/test/irmin-pack/test_inode.ml new file mode 100644 index 000000000000..199a626fc03a --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_inode.ml @@ -0,0 +1,911 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let root = Filename.concat "_build" "test-inode" +let src = Logs.Src.create "tests.instances" ~doc:"Tests" + +module Log = (val Logs.src_log src : Logs.LOG) + +let check_iter = Test_hashes.check_iter + +module Inode_modules + (Conf : Irmin_pack.Conf.S) + (Schema : Irmin.Schema.S) (Contents : sig + val foo : Schema.Contents.t + val bar : Schema.Contents.t + end) = +struct + module Key = Irmin_pack_unix.Pack_key.Make (Schema.Hash) + + module Node = + Irmin.Node.Generic_key.Make_v2 (Schema.Hash) (Schema.Path) (Schema.Metadata) + (Key) + (Key) + + module Index = Irmin_pack_unix.Index.Make (Schema.Hash) + + module Inter = + Irmin_pack.Inode.Make_internal (Conf) (Schema.Hash) (Key) (Node) + + module Io = Irmin_pack_unix.Io.Unix + module Errs = Irmin_pack_unix.Io_errors.Make (Io) + module File_manager = Irmin_pack_unix.File_manager.Make (Io) (Index) (Errs) + module Dict = Irmin_pack_unix.Dict.Make (File_manager) + module Dispatcher = Irmin_pack_unix.Dispatcher.Make (File_manager) + + module Pack = + Irmin_pack_unix.Pack_store.Make (File_manager) (Dict) (Dispatcher) + (Schema.Hash) + (Inter.Raw) + (Errs) + + module Inode = + Irmin_pack_unix.Inode.Make_persistent (Schema.Hash) (Node) (Inter) (Pack) + + module Contents_value = + Irmin_pack.Pack_value.Of_contents (Conf) (Schema.Hash) (Key) + (Schema.Contents) + + module Contents_store = + Irmin_pack_unix.Pack_store.Make (File_manager) (Dict) (Dispatcher) + (Schema.Hash) + (Contents_value) + (Errs) + + module Context = struct + type t = { + store : read Inode.t; + store_contents : read Contents_store.t; + fm : File_manager.t; + (* Two contents values that are guaranteed to be read by {!store}: *) + foo : Key.t; + bar : Key.t; + } + + let config ~indexing_strategy ~readonly ~fresh name = + let module Index = Irmin_pack.Indexing_strategy in + let indexing_strategy = + if indexing_strategy = `always then Index.always else Index.minimal + in + Irmin_pack.Conf.init ~fresh ~readonly ~indexing_strategy ~lru_size:0 name + + (* TODO : remove duplication with irmin_pack/ext.ml *) + let get_fm config = + let readonly = Irmin_pack.Conf.readonly config in + + if readonly then File_manager.open_ro config |> Errs.raise_if_error + else + let fresh = Irmin_pack.Conf.fresh config in + let root = Irmin_pack.Conf.root config in + (* make sure the parent dir exists *) + let () = + match Sys.is_directory (Filename.dirname root) with + | false -> Unix.mkdir (Filename.dirname root) 0o755 + | true -> () + in + match (Io.classify_path root, fresh) with + | `No_such_file_or_directory, _ -> + File_manager.create_rw ~overwrite:false config + |> Errs.raise_if_error + | `Directory, true -> + File_manager.create_rw ~overwrite:true config |> Errs.raise_if_error + | `Directory, false -> + File_manager.open_rw config |> Errs.raise_if_error + | (`File | `Other), _ -> Errs.raise_error (`Not_a_directory root) + + let get_store ~indexing_strategy () = + [%log.app "Constructing a fresh context for use by the test"]; + rm_dir root; + let config = config ~indexing_strategy ~readonly:false ~fresh:true root in + let fm = get_fm config in + let dict = Dict.v fm |> Errs.raise_if_error in + let dispatcher = Dispatcher.v fm |> Errs.raise_if_error in + let store = Inode.v ~config ~fm ~dict ~dispatcher in + let store_contents = Contents_store.v ~config ~fm ~dict ~dispatcher in + let+ foo, bar = + Contents_store.batch store_contents (fun writer -> + let* foo = Contents_store.add writer Contents.foo in + let* bar = Contents_store.add writer Contents.bar in + Lwt.return (foo, bar)) + in + [%log.app "Test context constructed"]; + { store; store_contents; fm; foo; bar } + + let close t = + File_manager.close t.fm |> Errs.raise_if_error; + (* closes dict, inodes and contents store. *) + Lwt.return_unit + end +end + +module Conf = struct + let entries = 2 + let stable_hash = 3 + let contents_length_header = Some `Varint + let inode_child_order = `Seeded_hash + let forbid_empty_dir_persistence = false +end + +module String_contents = struct + let foo = "foo" + let bar = "bar" +end + +module S = Inode_modules (Conf) (Schema) (String_contents) +open S +open Schema + +type pred = [ `Contents of Key.t | `Inode of Key.t | `Node of Key.t ] +[@@deriving irmin] + +let pp_pred = Irmin.Type.pp pred_t + +module H_contents = Irmin.Hash.Typed (Hash) (Schema.Contents) + +let normal x = `Contents (x, Metadata.default) +let node x = `Node x +let check_hash = Alcotest.check_repr Inode.Val.hash_t +let check_values = Alcotest.check_repr Inode.Val.t + +let check_int pos ?(msg = "") ~expected actual = + Alcotest.(check ~pos int) msg expected actual + +(* Exhaustive inode structure generator *) +module Inode_permutations_generator = struct + type step = string + type content = Inode.Val.value + type inode = Inode.value + + module StepMap = Map.Make (struct + type t = step + + let compare = compare + end) + + module StepSet = Set.Make (struct + type t = Path.step + + let compare = compare + end) + + module StepSetMap = Map.Make (struct + type t = StepSet.t + + let compare = StepSet.compare + end) + + type t = { + steps : step list; + content_per_step : content StepMap.t; + steps_per_tree : StepSet.t list; + trees : inode list; + tree_per_steps : inode StepSetMap.t; + } + + (** [gen_step index_list] uses brute force to generate a step such that + [Inter.Val.index ~depth:i] maps to the ith index in the [index_list]. *) + let gen_step : int list -> Path.step = + let tbl = Hashtbl.create 10 in + let max_brute_force_iterations = 100 in + let letters_per_step = (max_brute_force_iterations + 25) / 26 in + fun indices -> + let rec aux i = + if i > max_brute_force_iterations then + failwith "Could not quickly generate a step" + else + let s = Common.random_letters letters_per_step in + let is_valid = + indices + |> List.mapi (fun depth i -> (depth, i)) + |> List.for_all (fun (depth, i) -> Inter.Val.index ~depth s = i) + in + if is_valid then s else aux (i + 1) + in + match Hashtbl.find_opt tbl indices with + | Some s -> s + | None -> + let s = aux 0 in + Hashtbl.add tbl indices s; + s + + (** List all the steps that would fill a tree of depth [maxdepth_of_test]. *) + let gen_steps entries maxdepth_of_test : step list = + let ( ** ) a b = float_of_int a ** float_of_int b |> int_of_float in + List.init (entries ** maxdepth_of_test) (fun i -> + List.init maxdepth_of_test (fun j -> + let j = entries ** (maxdepth_of_test - j - 1) in + (* In the binary case (Conf.entries = 2), [j] is now the mask of the + bit to look at *) + i / j mod entries)) + |> List.map gen_step + + let powerset xs = + List.fold_left + (fun acc x -> acc @ List.map (fun ys -> x :: ys) acc) + [ [] ] xs + + let v ~entries ~maxdepth_of_test = + let ( ** ) a b = float_of_int a ** float_of_int b |> int_of_float in + let steps = gen_steps entries maxdepth_of_test in + let content_per_step = + List.map + (fun s -> (s, H_contents.hash s |> Key.unfindable_of_hash |> normal)) + steps + |> List.to_seq + |> StepMap.of_seq + in + let steps_per_tree : StepSet.t list = + powerset steps |> List.map List.to_seq |> List.map StepSet.of_seq + in + Alcotest.(check int) + "Size of the powerset" + (List.length steps_per_tree) + (2 ** entries ** maxdepth_of_test); + let trees : Inode.value list = + List.map + (fun steps -> + let steps = StepSet.elements steps in + let contents = + List.map (fun s -> StepMap.find s content_per_step) steps + in + List.combine steps contents |> Inode.Val.of_list) + steps_per_tree + in + let tree_per_steps : Inode.value StepSetMap.t = + List.combine steps_per_tree trees |> List.to_seq |> StepSetMap.of_seq + in + { steps; content_per_step; steps_per_tree; trees; tree_per_steps } + + (** [steps t] is a list of length [entries ^ maxdepth_of_test] (8) containing + the necessary steps to fill a tree of depth equal to [maxdepth_of_test] + (3). *) + let steps : t -> step list = fun { steps; _ } -> steps + + let content_of_step : t -> step -> content = + fun { content_per_step; _ } s -> StepMap.find s content_per_step + + (** [trees t] is a list of length [2 ^ (entries ^ maxdepth_of_test)] (256) + containing pairs of steps set/inode tree. This list is formed from the + powerset of [steps t], it contains all the possible structural + permutations for an inode tree of depth equal to [maxdepth_of_test] and + width equal to [entries]. *) + let trees : t -> (StepSet.t * Inode.value) list = + fun { trees; steps_per_tree; _ } -> List.combine steps_per_tree trees + + (** [tree_of_steps t ss] is the inode tree associated to [ss] in [trees t]. + + E.g, [tree_of_steps t StepSet.empty] is the empty inode. *) + let tree_of_steps : t -> StepSet.t -> Inode.value = + fun { tree_per_steps; _ } steps -> StepSetMap.find steps tree_per_steps +end + +let check_node msg v t = + let hash = Inter.Val.hash_exn v in + let+ key = Inode.batch t.Context.store (fun i -> Inode.add i v) in + let hash' = Key.to_hash key in + check_hash msg hash hash' + +let check_hardcoded_hash msg h v = + h |> Irmin.Type.of_string Inode.Val.hash_t |> function + | Error (`Msg str) -> Alcotest.failf "hash of string failed: %s" str + | Ok hash -> check_hash msg hash (Inter.Val.hash_exn v) + +(** Test add values from an empty node. *) +let test_add_values ~indexing_strategy = + rm_dir root; + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + check_node "hash empty node" (Inode.Val.empty ()) t >>= fun () -> + let v1 = Inode.Val.add (Inode.Val.empty ()) "x" (normal foo) in + let v2 = Inode.Val.add v1 "y" (normal bar) in + check_node "node x+y" v2 t >>= fun () -> + check_hardcoded_hash "hash v2" "d4b55db5d2d806283766354f0d7597d332156f74" v2; + let v3 = Inode.Val.of_list [ ("x", normal foo); ("y", normal bar) ] in + check_values "add x+y vs v x+y" v2 v3; + Context.close t + +let test_add_values () = + let* () = test_add_values ~indexing_strategy:`always in + test_add_values ~indexing_strategy:`minimal + +let integrity_check ?(stable = true) v = + Alcotest.(check bool) "check stable" (Inter.Val.stable v) stable; + if not (Inter.Val.integrity_check v) then + Alcotest.failf "node does not satisfy stability invariants %a" + (Irmin.Type.pp Inode.Val.t) + v + +(** Test add to inodes. *) +let test_add_inodes ~indexing_strategy = + rm_dir root; + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + let v1 = Inode.Val.of_list [ ("x", normal foo); ("y", normal bar) ] in + let v2 = Inode.Val.add v1 "z" (normal foo) in + let v3 = + Inode.Val.of_list + [ ("x", normal foo); ("z", normal foo); ("y", normal bar) ] + in + check_values "add x+y+z vs v x+z+y" v2 v3; + check_hardcoded_hash "hash v3" "46fe6c68a11a6ecd14cbe2d15519b6e5f3ba2864" v3; + integrity_check v1; + integrity_check v2; + let v4 = Inode.Val.add v2 "a" (normal foo) in + let v5 = + Inode.Val.of_list + [ + ("x", normal foo); + ("z", normal foo); + ("a", normal foo); + ("y", normal bar); + ] + in + check_values "add x+y+z+a vs v x+z+a+y" v4 v5; + check_hardcoded_hash "hash v4" "c330c08571d088141dfc82f644bffcfcf6696539" v4; + integrity_check v4 ~stable:false; + Context.close t + +let test_add_inodes () = + let* () = test_add_inodes ~indexing_strategy:`always in + test_add_inodes ~indexing_strategy:`minimal + +(** Test remove values on an empty node. *) +let test_remove_values ~indexing_strategy = + rm_dir root; + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + let v1 = Inode.Val.of_list [ ("x", normal foo); ("y", normal bar) ] in + let v2 = Inode.Val.remove v1 "y" in + let v3 = Inode.Val.of_list [ ("x", normal foo) ] in + check_values "node x obtained two ways" v2 v3; + check_hardcoded_hash "hash v2" "a1996f4309ea31cc7ba2d4c81012885aa0e08789" v2; + let v4 = Inode.Val.remove v2 "x" in + check_node "remove results in an empty node" (Inode.Val.empty ()) t + >>= fun () -> + let v5 = Inode.Val.remove v4 "x" in + check_values "remove on an already empty node" v4 v5; + check_hardcoded_hash "hash v4" "5ba93c9db0cff93f52b521d7420e43f6eda2784f" v4; + Alcotest.(check bool) "v5 is empty" (Inode.Val.is_empty v5) true; + Context.close t + +let test_remove_values () = + let* () = test_remove_values ~indexing_strategy:`always in + test_remove_values ~indexing_strategy:`minimal + +(** Test remove and add values to go from stable to unstable inodes. *) +let test_remove_inodes ~indexing_strategy = + rm_dir root; + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + let v1 = + Inode.Val.of_list + [ ("x", normal foo); ("y", normal bar); ("z", normal foo) ] + in + check_hardcoded_hash "hash v1" "46fe6c68a11a6ecd14cbe2d15519b6e5f3ba2864" v1; + let v2 = Inode.Val.remove v1 "x" in + let v3 = Inode.Val.of_list [ ("y", normal bar); ("z", normal foo) ] in + check_values "node y+z obtained two ways" v2 v3; + check_hardcoded_hash "hash v2" "ea22a2936eed53978bde62f0185cee9d8bbf9489" v2; + let v4 = + Inode.Val.of_list + [ + ("x", normal foo); + ("z", normal foo); + ("a", normal foo); + ("y", normal bar); + ] + in + let v5 = Inode.Val.remove v4 "a" in + check_values "node x+y+z obtained two ways" v1 v5; + integrity_check v1; + integrity_check v5; + Context.close t + +let test_remove_inodes () = + let* () = test_remove_inodes ~indexing_strategy:`always in + test_remove_inodes ~indexing_strategy:`minimal + +(** For each of the 256 possible inode trees with [depth <= 3] and + [width = Conf.entries = 2] built by [Inode.Val.v], assert that + independently, all the possible [Inode.Val.add]/[Inode.Val.remove] + operations yield a tree computable by [Inode.Val.v]. + + In other words. Let [T] be the set of all possible trees (256). Let [O] be + the set of unitary [tree -> tree] operations (8). If all the combinations of + [T] and [O] yield trees in [T] then, by induction, the representation is + unique. + + Caveats + + If something breaks at [depth > 3 || entries <> 2], this won't be caught + here. + + If a corrupted tree is constructed using [Elt.decode_bin] and [Val.of_bin], + this won't be caught here. + + If a corrupted subtree is loaded through the [find] function when an inode + lazily loads subtrees, this won't be caught here. *) +let test_representation_uniqueness_maxdepth_3 () = + let module P = Inode_permutations_generator in + let p = P.v ~entries:Conf.entries ~maxdepth_of_test:3 in + let f steps tree s = + (* [steps, tree] is one of the known pair built using [Val.v]. Let's try to + add or remove [s] from it and see if something breaks. *) + if P.StepSet.mem s steps then + let steps' = P.StepSet.remove s steps in + let tree'_ref = P.tree_of_steps p steps' in + let tree'_new = Inode.Val.remove tree s in + check_values + "The representation of the received tree obtained through [remove] \ + differs from the expected one obtained through [v]." + tree'_ref tree'_new + else + let steps' = P.StepSet.add s steps in + let c = P.content_of_step p s in + let tree'_ref = P.tree_of_steps p steps' in + let tree'_new = Inode.Val.add tree s c in + check_values + "The representation of the received tree obtained through [remove] \ + differs from the expected one obtained through [v]." + tree'_ref tree'_new + in + List.iter + (fun (ss, t) -> List.iter (fun s -> f ss t s) (P.steps p)) + (P.trees p); + Lwt.return_unit + +let test_truncated_inodes ~indexing_strategy = + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + let to_truncated inode = + let encode, decode = + let t = Inode.Val.t in + Irmin.Type.(encode_bin t |> unstage, decode_bin t |> unstage) + in + let encode inode = + let buf = Buffer.create 0 in + encode inode (Buffer.add_string buf); + Buffer.contents buf + in + let decode str = decode str (ref 0) in + inode |> encode |> decode + in + let with_failure f = + Alcotest.check_raises + "Iteration on that Truncated inode with broken pointers was expected to \ + fail." + (Failure + "Impossible to load the subtree on an inode deserialized using Repr") f + in + let s00, s01, s11, s10 = + Inode_permutations_generator. + ( gen_step [ 0; 0 ], + gen_step [ 0; 1 ], + gen_step [ 1; 1 ], + gen_step [ 1; 0 ] ) + in + let iter_steps f = + List.iter (fun step -> f step |> ignore) [ s00; s01; s11; s10 ] + in + let iter_steps_with_failure f = + List.iter + (fun step -> with_failure (fun () -> f step |> ignore)) + [ s00; s01; s11; s10 ] + in + (* v1 is a Truncated inode of tag Values. No pointers. *) + let v1 = + Inode.Val.of_list [ (s00, normal foo); (s10, normal foo) ] |> to_truncated + in + Inode.Val.list v1 |> ignore; + (iter_steps @@ fun step -> Inode.Val.find v1 step); + (iter_steps @@ fun step -> Inode.Val.add v1 step (normal bar)); + (iter_steps @@ fun step -> Inode.Val.remove v1 step); + (* v2 is just a Truncated inode of tag Tree. The pointers are built after + the call to [to_truncated], they are [Intact]. *) + let v2 = Inode.Val.add v1 s01 (normal foo) in + Inode.Val.list v2 |> ignore; + (iter_steps @@ fun step -> Inode.Val.find v1 step); + (iter_steps @@ fun step -> Inode.Val.add v1 step (normal bar)); + (iter_steps @@ fun step -> Inode.Val.remove v1 step); + (* v3 is just a Truncated inode of tag Tree. The pointers are built before + the call to [to_truncated], they are [Broken]. *) + let v3 = + Inode.Val.of_list + [ (s00, normal foo); (s10, normal bar); (s01, normal bar) ] + |> to_truncated + in + (with_failure @@ fun () -> Inode.Val.list v3 |> ignore); + (iter_steps_with_failure @@ fun step -> Inode.Val.find v3 step); + (iter_steps_with_failure @@ fun step -> Inode.Val.add v3 step (normal bar)); + (iter_steps_with_failure @@ fun step -> Inode.Val.remove v3 step); + Context.close t + +let test_truncated_inodes () = + let* () = test_truncated_inodes ~indexing_strategy:`always in + test_truncated_inodes ~indexing_strategy:`minimal + +let test_intermediate_inode_as_root ~indexing_strategy = + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + let s000, s001, s010 = + Inode_permutations_generator. + (gen_step [ 0; 0; 0 ], gen_step [ 0; 0; 1 ], gen_step [ 0; 1; 0 ]) + in + let v0 = + Inode.Val.of_list + [ (s000, normal foo); (s001, normal bar); (s010, normal foo) ] + in + let* h_depth0 = Inode.batch t.store @@ fun store -> Inode.add store v0 in + let (`Inode h_depth1) = + match Inode.Val.pred v0 with + | [ (_, (`Inode _ as pred)) ] -> pred + | l -> + let l = List.map snd l in + Alcotest.failf + "Expected one `Inode predecessors, got [%a], a list of length %d." + Fmt.(list ~sep:(any " ; ") pp_pred) + l (List.length l) + in + + (* On inode with depth=0 *) + let* v = + Inode.find t.store h_depth0 >|= function + | None -> Alcotest.fail "Could not fetch inode from backend" + | Some v -> v + in + if Inode.Val.list v |> List.length <> 3 then + Alcotest.fail "Failed to list entries of loaded inode"; + let _ = Inode.Val.remove v s000 in + let _ = Inode.Val.add v s000 (normal foo) in + let* _ = Inode.batch t.store @@ fun store -> Inode.add store v in + + (* On inode with depth=1 *) + let* v = + Inode.find t.store h_depth1 >|= function + | None -> Alcotest.fail "Could not fetch inode from backend" + | Some v -> v + in + if Inode.Val.list v |> List.length <> 3 then + Alcotest.fail "Failed to list entries of loaded inode"; + let with_exn f = + Alcotest.check_raises + "Write-only operation is forbiden on intermediate inode" + (Failure "Cannot perform operation on non-root inode value.") (fun () -> + f () |> ignore) + in + with_exn (fun () -> Inode.Val.remove v s000); + with_exn (fun () -> Inode.Val.add v s000 (normal foo)); + let* () = + Inode.batch t.store (fun store -> + with_exn (fun () -> Inode.add store v); + Lwt.return_unit) + in + Lwt.return_unit + +let test_intermediate_inode_as_root () = + let* () = test_intermediate_inode_as_root ~indexing_strategy:`always in + test_intermediate_inode_as_root ~indexing_strategy:`minimal + +let test_concrete_inodes ~indexing_strategy = + let* t = Context.get_store ~indexing_strategy () in + let { Context.foo; bar; _ } = t in + let pp_concrete = Irmin.Type.pp_json ~minify:false Inter.Val.Concrete.t in + let result_t = Irmin.Type.result Inode.Val.t Inter.Val.Concrete.error_t in + let testable = + Alcotest.testable + (Irmin.Type.pp_json ~minify:false result_t) + Irmin.Type.(unstage (equal result_t)) + in + let check v = + let len = Inter.Val.length v in + integrity_check ~stable:(len <= Conf.stable_hash) v; + let c = Inter.Val.to_concrete v in + let r = Inter.Val.of_concrete c in + let msg = Fmt.str "%a" pp_concrete c in + Alcotest.check testable msg (Ok v) r + in + let v = Inode.Val.of_list [ ("a", normal foo) ] in + check v; + let v = Inode.Val.of_list [ ("a", normal foo); ("y", node bar) ] in + check v; + let v = + Inode.Val.of_list [ ("x", node foo); ("a", normal foo); ("y", node bar) ] + in + check v; + let v = + Inode.Val.of_list + [ + ("x", normal foo); ("z", normal foo); ("a", normal foo); ("y", node bar); + ] + in + check v; + Context.close t + +let test_concrete_inodes () = + let* () = test_concrete_inodes ~indexing_strategy:`always in + test_concrete_inodes ~indexing_strategy:`minimal + +module Inode_tezos = struct + module S = + Inode_modules (Conf) (Irmin_tezos.Schema) + (struct + let foo = Bytes.make 10 '0' + let bar = Bytes.make 10 '1' + end) + + let encode_bin h v = + let v1 = S.Inter.Val.to_raw v in + S.Inter.Raw.encode_bin + ~dict:(fun _ -> None) + ~offset_of_key:(fun _ -> None) + h v1 + + let hex_encode s = Hex.of_string s |> Hex.show + + let test_encode_bin_values ~indexing_strategy = + rm_dir root; + let* t = S.Context.get_store ~indexing_strategy () in + let { S.Context.foo; _ } = t in + let v = S.Inode.Val.of_list [ ("x", normal foo); ("z", normal foo) ] in + let h = S.Inter.Val.hash_exn v in + let hash_to_bin_string = + Irmin.Type.(unstage (to_bin_string S.Inode.Val.hash_t)) + in + let key_to_bin_string = + Irmin.Type.(unstage (to_bin_string S.Inode.Key.t)) + in + let hex_of_h = h |> hash_to_bin_string |> hex_encode in + let hex_of_foo = foo |> key_to_bin_string |> hex_encode in + let checks = + [ + ("hash", hex_of_h); + ("magic R", hex_encode "R"); + ("data length", "48"); + ("Values", "00"); + ("length", "02"); + ("contents-x-dd", "09"); + ("Direct", "01"); + ("x", "78"); + ("hash of contents", hex_of_foo); + ("contents-x-dd", "09"); + ("Direct", "01"); + ("z", "7a"); + ("hash of contents", hex_of_foo); + ] + in + check_iter "encode_bin" (encode_bin h) v checks; + S.Context.close t + + let test_encode_bin_values () = + let* () = test_encode_bin_values ~indexing_strategy:`always in + test_encode_bin_values ~indexing_strategy:`minimal + + let test_encode_bin_tree ~indexing_strategy = + rm_dir root; + let* t = S.Context.get_store ~indexing_strategy () in + let { S.Context.foo; bar; _ } = t in + let v = + S.Inode.Val.of_list + [ + ("x", normal foo); + ("z", normal foo); + ("y", normal bar); + ("w", normal bar); + ("t", normal bar); + ] + in + let h = S.Inter.Val.hash_exn v in + let to_bin_string_hash = + Irmin.Type.(unstage (to_bin_string S.Inode.Val.hash_t)) + in + let hex_of_h = h |> to_bin_string_hash |> Hex.of_string |> Hex.show in + let checks = + [ + ("hash", hex_of_h); + ("magic R", hex_encode "R"); + ("data length", "48"); + ("Tree", "01"); + ("depth", "00"); + ("nb of leaves", "05"); + ("length of entries", "02"); + ("index", "00"); + ("Direct", "01"); + ( "hash of entry", + "8c81eb0a729858e10a8aed80f4ad638b26e80cf713be980a83620e22516001bf" ); + ("index", "01"); + ("Direct", "01"); + ( "hash of entry", + "461a30b373e7d98e23dc963934a417d7c5aceb14fa2fb6da6950438fd54c9aa9" ); + ] + in + check_iter "encode_bin" (encode_bin h) v checks; + S.Context.close t + + let test_encode_bin_tree () = + let* () = test_encode_bin_tree ~indexing_strategy:`always in + test_encode_bin_tree ~indexing_strategy:`minimal +end + +module Child_ordering = struct + (** Tests of the relative ordering of Inode children (which can be configured + by the user). *) + + module Step = struct + type t = Schema.Path.step [@@deriving irmin ~short_hash] + + module Hash = + Irmin.Hash.Typed + (Schema.Hash) + (struct + type nonrec t = t + + let t = t + end) + + type nonrec hash = Hash.t [@@deriving irmin ~to_bin_string] + + let hash : t -> string = fun s -> hash_to_bin_string (Hash.hash s) + end + + module type S = Irmin_pack.Inode.Child_ordering with type step := Step.t + + let make ?entries:(entries' = Irmin_tezos.Conf.entries) + (t : Irmin_pack.Conf.inode_child_order) : (module S) = + let module Conf = struct + include Irmin_tezos.Conf + + let entries = entries' + let inode_child_order = t + end in + let module T = Inode_modules (Conf) (Schema) (String_contents) in + (module T.Inter.Child_ordering) + + let check_child_index pos (module Order : S) ~expected ~step ~depth = + let msg = + Fmt.str "Short hash of child at { depth = %d; step = %S }" depth step + in + let actual = Order.key step |> Order.index ~depth in + check_int pos ~msg ~expected actual + + let check_max_depth_exception pos (module Order : S) ~step ~depth = + match Order.key step |> Order.index ~depth with + | index -> + Alcotest.failf ~pos + "Expected [Max_depth %d] to be raised, but got a computed index of \ + %d instead" + depth index + | exception Irmin_pack.Inode.Max_depth _ -> () + + (* Get the bit at index [n] in a string: *) + let get_bit str n = + let chosen_byte = Bytes.get_uint8 (Bytes.unsafe_of_string str) (n / 8) in + let bit_index_in_byte = n mod 8 in + (* Selects only the chosen bit from our byte: *) + let mask = 1 lsl (7 - bit_index_in_byte) in + let masked_byte = chosen_byte land mask in + let chosen_bit = masked_byte lsr (7 - bit_index_in_byte) in + assert (chosen_bit = 0 || chosen_bit = 1); + chosen_bit + + let test_seeded_hash _switch () = + let entries = Irmin_tezos.Conf.entries in + let reference ~depth step = + abs (Step.short_hash ~seed:depth step) mod entries + in + let (module Order) = make `Seeded_hash in + + (* Test some hard-coded samples to ensure stablility: *) + check_child_index __POS__ (module Order) ~expected:23 ~step:"a" ~depth:1; + check_child_index __POS__ (module Order) ~expected:2 ~step:"b" ~depth:2; + check_child_index __POS__ (module Order) ~expected:10 ~step:"foo" ~depth:42; + + (* Should match reference implementation for some random samples too: *) + for _ = 1 to 1_000 do + let step = random_string 8 and depth = Random.int 10 in + let expected = reference ~depth step in + check_child_index __POS__ (module Order) ~expected ~step ~depth + done; + Lwt.return_unit + + let hash_bits_max_depth ~log2_entries = + (* For a given [depth], the final bit of the corresponding index is at + * position [log2_entries * depth + log2_entries - 1] in the hash. If this + * is out-of-bounds in the hash, then we expect computing the ordering to + * fail (since we don't use modular indexing of the hash). *) + let rec aux depth = + if log2_entries * (depth + 1) > 8 * Hash.hash_size then depth - 1 + else aux (succ depth) + in + aux 0 + + let test_hash_bits _switch () = + (* [entries] is required to be a power of 2 greater than 1 and less than + 2048, so we test every possible value here: *) + for log2_entries = 1 to 10 do + let entries = 1 lsl log2_entries in + let max_depth = hash_bits_max_depth ~log2_entries in + let (module Order) = make ~entries `Hash_bits in + [%log.app + "Testing hash_bits with { log_entries = %d; entries = %d; max_depth = \ + %d }" + log2_entries entries max_depth]; + + (* Index is computed by reading [log2_entries] consecutive bits from the + hash of the step, starting at the [log2_entries * depth]-th byte. *) + let reference ~depth step = + let hash = Step.hash step in + let index = ref 0 in + for i = 0 to log2_entries - 1 do + let selected_bit = get_bit hash ((log2_entries * depth) + i) in + index := (!index lsl 1) lor selected_bit + done; + !index + in + + for _ = 1 to 100 do + let step = random_string 8 in + (* We compute the valid index for this step at every depth up to + [max_depth]: *) + for depth = 0 to max_depth do + let expected = reference ~depth step in + check_child_index __POS__ (module Order) ~expected ~step ~depth + done; + (* Beyond [max_depth], the index computation should fail: *) + check_max_depth_exception __POS__ + (module Order) + ~step ~depth:(max_depth + 1) + done + done; + Lwt.return_unit + + let test_custom _switch () = + let entries = 16 in + let square_index ~depth step = + let a = depth and b = int_of_string (Bytes.unsafe_to_string step) in + a * b + in + let (module Order) = make ~entries (`Custom square_index) in + check_child_index __POS__ (module Order) ~depth:1 ~step:"1" ~expected:1; + check_child_index __POS__ (module Order) ~depth:2 ~step:"2" ~expected:4; + check_child_index __POS__ (module Order) ~depth:3 ~step:"3" ~expected:9; + (); + Lwt.return_unit +end + +let tests = + let tc_sync name f = Alcotest_lwt.test_case name `Quick f in + let tc name f = tc_sync name (fun _switch -> f) in + (* Test disabled because it relies on being able to serialise concrete inodes, + which is not possible following the introduction of structured keys. *) + let _ = tc "test truncated inodes" test_truncated_inodes in + let _ = tc "test encode bin of trees" Inode_tezos.test_encode_bin_tree in + [ + tc "add values" test_add_values; + tc "add values to inodes" test_add_inodes; + tc "remove values" test_remove_values; + tc "remove inodes" test_remove_inodes; + tc "test concrete inodes" test_concrete_inodes; + tc "test representation uniqueness" + test_representation_uniqueness_maxdepth_3; + tc "test encode bin of values" Inode_tezos.test_encode_bin_values; + tc "test intermediate inode as root" test_intermediate_inode_as_root; + tc_sync "Child_ordering.seeded_hash" Child_ordering.test_seeded_hash; + tc_sync "Child_ordering.hash_bits" Child_ordering.test_hash_bits; + tc_sync "Child_ordering.custom" Child_ordering.test_custom; + ] diff --git a/vendors/irmin/test/irmin-pack/test_inode.mli b/vendors/irmin/test/irmin-pack/test_inode.mli new file mode 100644 index 000000000000..4acc26805b83 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_inode.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_lower.ml b/vendors/irmin/test/irmin-pack/test_lower.ml new file mode 100644 index 000000000000..b0409bc0761b --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_lower.ml @@ -0,0 +1,554 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let src = Logs.Src.create "tests.lower" ~doc:"Test lower" + +module Log = (val Logs.src_log src : Logs.LOG) +module Io = Irmin_pack_unix.Io.Unix + +let ( let$ ) res f = f @@ Result.get_ok res + +module Direct_tc = struct + module Control = Irmin_pack_unix.Control_file.Volume (Io) + module Errs = Irmin_pack_unix.Io_errors.Make (Io) + module Lower = Irmin_pack_unix.Lower.Make (Io) (Errs) + module Sparse = Irmin_pack_unix.Sparse_file.Make (Io) + + let create_control volume_path payload = + let path = Irmin_pack.Layout.V5.Volume.control ~root:volume_path in + Control.create_rw ~path ~tmp_path:None ~overwrite:true payload + + let test_empty () = + let lower_root = create_lower_root () in + let$ lower = Lower.v ~readonly:false ~volume_num:0 lower_root in + Alcotest.(check int) "0 volumes" 0 (Lower.volume_num lower); + let _ = Lower.close lower in + Lwt.return_unit + + let test_volume_num () = + let lower_root = create_lower_root () in + let result = Lower.v ~readonly:false ~volume_num:1 lower_root in + let () = + match result with + | Error (`Volume_missing _) -> () + | _ -> Alcotest.fail "volume_num too high should return an error" + in + Lwt.return_unit + + let test_add_volume () = + let lower_root = create_lower_root () in + let$ lower = Lower.v ~readonly:false ~volume_num:0 lower_root in + let$ _ = Lower.add_volume lower in + Alcotest.(check int) "1 volume" 1 (Lower.volume_num lower); + let$ _ = Lower.reload ~volume_num:1 lower in + Alcotest.(check int) "1 volume after reload" 1 (Lower.volume_num lower); + let _ = Lower.close lower in + Lwt.return_unit + + let test_add_volume_ro () = + let lower_root = create_lower_root () in + let$ lower = Lower.v ~readonly:true ~volume_num:0 lower_root in + let result = Lower.add_volume lower in + let () = + match result with + | Error `Ro_not_allowed -> () + | _ -> Alcotest.fail "cannot add volume to ro lower" + in + let _ = Lower.close lower in + Lwt.return_unit + + let test_add_multiple_empty () = + let lower_root = create_lower_root () in + let$ lower = Lower.v ~readonly:false ~volume_num:0 lower_root in + let$ _ = Lower.add_volume lower in + let result = Lower.add_volume lower |> Result.get_error in + let () = + match result with + | `Multiple_empty_volumes -> () + | _ -> Alcotest.fail "cannot add multiple empty volumes" + in + let _ = Lower.close lower in + Lwt.return_unit + + let test_find_volume () = + let lower_root = create_lower_root () in + let$ lower = Lower.v ~readonly:false ~volume_num:0 lower_root in + let$ volume = Lower.add_volume lower in + let payload = + Irmin_pack_unix.Control_file.Payload.Volume.Latest. + { + start_offset = Int63.zero; + end_offset = Int63.of_int 42; + mapping_end_poff = Int63.zero; + checksum = Int63.zero; + } + in + let _ = create_control (Lower.Volume.path volume) payload in + let volume = Lower.find_volume ~off:(Int63.of_int 21) lower in + Alcotest.(check bool) + "volume not found before reload" false (Option.is_some volume); + let$ _ = Lower.reload ~volume_num:1 lower in + let volume = Lower.find_volume ~off:(Int63.of_int 21) lower in + Alcotest.(check bool) "found volume" true (Option.is_some volume); + let _ = Lower.close lower in + Lwt.return_unit + + let test_read_exn () = + let lower_root = create_lower_root () in + let$ lower = Lower.v ~readonly:false ~volume_num:0 lower_root in + let$ volume = Lower.add_volume lower in + (* Manually create mapping, data, and control file for volume. + + Then test that reloading and read_exn work as expected. *) + let volume_path = Lower.Volume.path volume in + let mapping_path = Irmin_pack.Layout.V5.Volume.mapping ~root:volume_path in + let data_path = Irmin_pack.Layout.V5.Volume.data ~root:volume_path in + let test_str = "hello" in + let len = String.length test_str in + let$ sparse = + Sparse.Ao.open_ao ~mapping_size:Int63.zero ~mapping:mapping_path + ~data:data_path + in + let seq = List.to_seq [ test_str ] in + Sparse.Ao.append_seq_exn sparse ~off:Int63.zero seq; + let end_offset = Sparse.Ao.end_off sparse in + let$ _ = Sparse.Ao.flush sparse in + let$ _ = Sparse.Ao.close sparse in + let$ mapping_end_poff = Io.size_of_path mapping_path in + let payload = + Irmin_pack_unix.Control_file.Payload.Volume.Latest. + { + start_offset = Int63.zero; + end_offset; + mapping_end_poff; + checksum = Int63.zero; + } + in + let _ = create_control (Lower.Volume.path volume) payload in + let$ _ = Lower.reload ~volume_num:1 lower in + let buf = Bytes.create len in + let _ = Lower.read_exn ~off:Int63.zero ~len lower buf in + Alcotest.(check string) + "check volume read" test_str + (Bytes.unsafe_to_string buf); + let _ = Lower.close lower in + Lwt.return_unit +end + +module Store_tc = struct + module Store = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) + end + + let test_dir = "_build" + + let fresh_roots = + let c = ref 0 in + fun ?(make_root = true) () -> + incr c; + let name = + Filename.concat test_dir ("test_lower_store_" ^ string_of_int !c) + in + Common.rm_dir name; + let$ _ = if make_root then Io.mkdir name else Ok () in + let lower = Filename.concat name "lower" in + Common.rm_dir lower; + (name, lower) + + let config ?(readonly = false) ?(fresh = false) ?lower_root root = + Irmin_pack.( + config ~readonly ~indexing_strategy:Indexing_strategy.minimal ~fresh + ~lower_root root) + + let init ?(readonly = false) ?(fresh = true) ?(include_lower = true) () = + let root, lower_root = fresh_roots () in + let lower_root = if include_lower then Some lower_root else None in + config ~readonly ~fresh ?lower_root root |> Store.Repo.v + + let count_volumes repo = + let open Store.Internal in + file_manager repo + |> File_manager.lower + |> Option.map File_manager.Lower.volume_num + |> Option.value ~default:0 + + let volume_path repo offset = + let open Store.Internal in + let lower = file_manager repo |> File_manager.lower in + let volume = + match lower with + | None -> Alcotest.fail "expected lower" + | Some l -> File_manager.Lower.find_volume ~off:offset l + in + match volume with + | None -> Alcotest.fail "expected volume" + | Some v -> File_manager.Lower.Volume.path v + + let generation repo = + let open Store.Internal in + let ({ status; _ } : Irmin_pack_unix.Control_file.Payload.Upper.Latest.t) = + file_manager repo |> File_manager.control |> File_manager.Control.payload + in + match status with + | Gced { generation; _ } -> generation + | _ -> Alcotest.fail "expected gced status" + + (* Reads all objects from the repo by iterating its index and folding its commit trees. *) + let read_everything repo = + let fm = Store.Internal.file_manager repo in + let index = Store.Internal.File_manager.index fm in + let commits = ref [] in + let () = + Store.Internal.Index.iter + (fun hash (_offset, _len, kind) -> + match kind with + | Irmin_pack.Pack_value.Kind.Commit_v2 -> commits := hash :: !commits + | _ -> ()) + index + in + Lwt_list.map_s + (fun hash -> + [%log.debug "read %a" Irmin.Type.(pp Store.Hash.t) hash]; + let* commit = Store.Commit.of_hash repo hash in + match commit with + | None -> Alcotest.fail "failed to read commit" + | Some commit -> Store.Tree.fold (Store.Commit.tree commit) ()) + !commits + + let test_create () = + let* repo = init () in + (* A newly created store with a lower should have an empty volume. *) + let volume_num = count_volumes repo in + Alcotest.(check int) "volume_num is 1" 1 volume_num; + Store.Repo.close repo + + let test_create_nested () = + let root, lower_root = fresh_roots ~make_root:false () in + let* repo = config ~fresh:true ~lower_root root |> Store.Repo.v in + let volume_num = count_volumes repo in + Alcotest.(check int) "volume_num is 1" 1 volume_num; + Store.Repo.close repo + + let test_open_rw_lower () = + let root, lower_root = fresh_roots ~make_root:false () in + let* repo = config ~fresh:true root |> Store.Repo.v in + let* () = Store.Repo.close repo in + let* repo = config ~fresh:false ~lower_root root |> Store.Repo.v in + let volume_num = count_volumes repo in + Alcotest.(check int) "volume_num is 1" 1 volume_num; + Store.Repo.close repo + + let test_add_volume_during_gc () = + let* repo = init () in + let* main = Store.main repo in + let* () = + Store.set_exn + ~info:(fun () -> Store.Info.v ~author:"tester" Int64.zero) + main [ "a" ] "a" + in + let* c = Store.Head.get main in + let* _ = Store.Gc.start_exn repo (Store.Commit.key c) in + let* () = + Alcotest.check_raises_lwt "add volume during gc" + (Irmin_pack_unix.Errors.Pack_error `Add_volume_forbidden_during_gc) + (fun () -> Store.add_volume repo |> Lwt.return) + in + Store.Repo.close repo + + let test_add_volume_wo_lower () = + let* repo = init ~include_lower:false () in + let* () = + Alcotest.check_raises_lwt "add volume w/o lower" + (Irmin_pack_unix.Errors.Pack_error `Add_volume_requires_lower) + (fun () -> Store.add_volume repo |> Lwt.return) + in + Store.Repo.close repo + + let test_add_volume_reopen () = + let root, lower_root = fresh_roots () in + let* repo = Store.Repo.v (config ~fresh:true ~lower_root root) in + let* main = Store.main repo in + let info () = Store.Info.v ~author:"test" Int64.zero in + let* () = Store.set_exn ~info main [ "a" ] "a" in + let* c1 = Store.Head.get main in + let* _ = Store.Gc.start_exn repo (Store.Commit.key c1) in + let* _ = Store.Gc.finalise_exn ~wait:true repo in + let () = Store.add_volume repo in + Alcotest.(check int) "two volumes" 2 (count_volumes repo); + let* _ = Store.Repo.close repo in + let* repo = Store.Repo.v (config ~fresh:false ~lower_root root) in + Alcotest.(check int) "two volumes after re-open" 2 (count_volumes repo); + Store.Repo.close repo + + let test_migrate () = + let root, lower_root = fresh_roots () in + (* Create without a lower *) + let* repo = Store.Repo.v (config ~fresh:true root) in + Alcotest.(check int) "volume_num is 0" 0 (count_volumes repo); + let* main = Store.main repo in + let info () = Store.Info.v ~author:"test" Int64.zero in + let* () = Store.set_exn ~info main [ "a" ] "a" in + let* () = Store.Repo.close repo in + (* Reopen with a lower to trigger the migration *) + let* repo = Store.Repo.v (config ~lower_root root) in + Alcotest.(check int) "volume_num is 1" 1 (count_volumes repo); + let* main = Store.main repo in + let* a = Store.get main [ "a" ] in + Alcotest.(check string) "migrated commit" "a" a; + Alcotest.(check bool) + "no latest GC commit" true + (Option.is_none (Store.Gc.latest_gc_target repo)); + let* () = Store.set_exn ~info main [ "a" ] "b" in + let* () = Store.Repo.close repo in + (* Reopen with the same lower and check reads *) + let* repo = Store.Repo.v (config ~lower_root root) in + Alcotest.(check int) "volume_num is 1" 1 (count_volumes repo); + let* main = Store.main repo in + let* b = Store.get main [ "a" ] in + Alcotest.(check string) "upper commit" "b" b; + let* main_commit = Store.Head.get main in + let parent_key = List.hd @@ Store.Commit.parents main_commit in + let* parent = Store.Commit.of_key repo parent_key in + let previous_tree = Store.Commit.tree @@ Option.get parent in + let* a_opt = Store.Tree.find previous_tree [ "a" ] in + Alcotest.(check (option string)) "upper to lower" (Some "a") a_opt; + let* _ = read_everything repo in + Store.Repo.close repo + + (* Tests that dead header is handled appropriately *) + let test_migrate_v2 () = + let ( / ) = Filename.concat in + let root_archive = + "test" / "irmin-pack" / "data" / "version_2_to_3_always" + in + let root = "_build" / "test_lower_migrate_v2" in + setup_test_env ~root_archive ~root_local_build:root; + let lower_root = root / "lower" in + (* Open store and trigger migration. This should succeed. *) + let* repo = Store.Repo.v (config ~fresh:false ~lower_root root) in + let* _ = read_everything repo in + Store.Repo.close repo + + let test_migrate_v3 () = + (* minimal indexing *) + let ( / ) = Filename.concat in + let root_archive = "test" / "irmin-pack" / "data" / "version_3_minimal" in + let root = "_build" / "test_lower_migrate_v3_minimal" in + setup_test_env ~root_archive ~root_local_build:root; + let lower_root = root / "lower" in + (* Open store and trigger migration. This should succeed. *) + let* repo = Store.Repo.v (config ~fresh:false ~lower_root root) in + let* _ = read_everything repo in + let* _ = Store.Repo.close repo in + + (* always indexing *) + let ( / ) = Filename.concat in + let root_archive = "test" / "irmin-pack" / "data" / "version_3_always" in + let root = "_build" / "test_lower_migrate_v3_always" in + setup_test_env ~root_archive ~root_local_build:root; + let lower_root = root / "lower" in + (* Open store and trigger migration. This should succeed. *) + let* repo = Store.Repo.v (config ~fresh:false ~lower_root root) in + let* _ = read_everything repo in + Store.Repo.close repo + + let test_migrate_then_gc () = + let root, lower_root = fresh_roots () in + (* Create without a lower *) + let* repo = Store.Repo.v (config ~fresh:true root) in + Alcotest.(check int) "volume_num is 0" 0 (count_volumes repo); + let* main = Store.main repo in + let info () = Store.Info.v ~author:"test" Int64.zero in + let* () = Store.set_exn ~info main [ "a" ] "a" in + let* () = Store.Repo.close repo in + (* Reopen with a lower to trigger the migration *) + let* repo = Store.Repo.v (config ~lower_root root) in + Alcotest.(check int) "volume_num is 1" 1 (count_volumes repo); + (* Add two commits *) + let* main = Store.main repo in + let* () = Store.set_exn ~info main [ "b" ] "b" in + let* main = Store.main repo in + let* b_commit = Store.Head.get main in + let* () = Store.set_exn ~info main [ "c" ] "c" in + (* GC at [b] requires reading [a] data from the lower volume *) + let* _ = Store.Gc.start_exn repo (Store.Commit.key b_commit) in + let* _ = Store.Gc.finalise_exn ~wait:true repo in + let* _ = read_everything repo in + Store.Repo.close repo + + let test_migrate_then_gc_in_lower () = + let root, lower_root = fresh_roots () in + (* Create without a lower *) + let* repo = Store.Repo.v (config ~fresh:true root) in + Alcotest.(check int) "volume_num is 0" 0 (count_volumes repo); + let* main = Store.main repo in + let info () = Store.Info.v ~author:"test" Int64.zero in + let* () = Store.set_exn ~info main [ "a" ] "a" in + let* a_commit = Store.Head.get main in + let* () = Store.set_exn ~info main [ "b" ] "b" in + let* () = Store.Repo.close repo in + (* Reopen with a lower to trigger the migration *) + let* repo = Store.Repo.v (config ~lower_root root) in + Alcotest.(check int) "volume_num is 1" 1 (count_volumes repo); + (* [a] is now in the lower but GC should still succeed + + Important: we call GC on a commit that is not the latest in + the lower (ie [b]) to ensure its offset is not equal to the start + offset of the upper. *) + let* _ = Store.Gc.start_exn repo (Store.Commit.key a_commit) in + let* _ = Store.Gc.finalise_exn ~wait:true repo in + Store.Repo.close repo + + let test_volume_data_locality () = + let root, lower_root = fresh_roots () in + let* repo = Store.Repo.v (config ~fresh:true ~lower_root root) in + let* main = Store.main repo in + let info () = Store.Info.v ~author:"test" Int64.zero in + [%log.debug "add c1"]; + let* () = Store.set_exn ~info main [ "c1" ] "a" in + let* c1 = Store.Head.get main in + [%log.debug "GC c1"]; + let* _ = Store.Gc.start_exn repo (Store.Commit.key c1) in + let* _ = Store.Gc.finalise_exn ~wait:true repo in + let () = Store.add_volume repo in + [%log.debug "add c2, c3, c4"]; + let* () = Store.set_exn ~info main [ "c2" ] "b" in + let* () = Store.set_exn ~info main [ "c3" ] "c" in + let* c3 = Store.Head.get main in + let* () = Store.set_exn ~info main [ "c4" ] "d" in + let* () = Store.set_exn ~info main [ "c5" ] "e" in + let* c5 = Store.Head.get main in + [%log.debug "GC c5"]; + let* _ = Store.Gc.start_exn repo (Store.Commit.key c5) in + let* _ = Store.Gc.finalise_exn ~wait:true repo in + let get_direct_key key = + match Irmin_pack_unix.Pack_key.inspect key with + | Direct { offset; hash; length; volume_identifier } -> + (offset, hash, length, volume_identifier) + | _ -> assert false + in + (* NOTE: we need to lookup c3 again so that its volume + identifier is on its key *) + let _, hash, _, _ = get_direct_key (Store.Commit.key c3) in + let* c3 = Store.Commit.of_hash repo hash in + let c3 = Option.get c3 in + let _, _, _, identifier = get_direct_key (Store.Commit.key c3) in + let identifier = Option.get identifier in + [%log.debug "Check c3 tree items are in volume %s" identifier]; + let* c3 = Store.Commit.of_key repo (Store.Commit.key c3) in + let tree = Store.Commit.tree (Option.get c3) in + let* () = + let get_volume_identifier key = + let _, _, _, identifier = get_direct_key key in + match identifier with + | None -> Alcotest.fail "expected volume identifier" + | Some v -> v + in + (* Check every item of c3's tree to ensure it is in the first volume. *) + Store.Tree.fold + ~tree:(fun _p t a -> + let kinded_key = Store.Tree.key t in + let key_identifier = + match kinded_key with + | None -> assert false + | Some (`Contents (k, _)) -> get_volume_identifier k + | Some (`Node k) -> get_volume_identifier k + in + [%log.debug "identifier: %s" key_identifier]; + Alcotest.(check string) + "key is in expected volume" identifier key_identifier; + Lwt.return a) + tree () + in + Store.Repo.close repo + + let test_cleanup () = + let root, lower_root = fresh_roots () in + [%log.debug "create store with data and run GC"]; + let* repo = Store.Repo.v (config ~fresh:true ~lower_root root) in + let* main = Store.main repo in + let info () = Store.Info.v ~author:"test" Int64.zero in + let* () = Store.set_exn ~info main [ "a" ] "a" in + let* c1 = Store.Head.get main in + let* _ = Store.Gc.start_exn repo (Store.Commit.key c1) in + let* _ = Store.Gc.finalise_exn ~wait:true repo in + let volume_root = volume_path repo Int63.zero in + let generation = generation repo in + let* () = Store.Repo.close repo in + [%log.debug "test volume.1.control is moved to volume.control"]; + let volume_cf_gen_path = + Irmin_pack.Layout.V5.Volume.control_gc_tmp ~generation ~root:volume_root + in + let volume_cf_path = + Irmin_pack.Layout.V5.Volume.control ~root:volume_root + in + let$ () = Io.move_file ~src:volume_cf_path ~dst:volume_cf_gen_path in + let* repo = Store.Repo.v (config ~fresh:false ~lower_root root) in + let () = + match Io.classify_path volume_cf_path with + | `File -> [%log.debug "control file exists"] + | _ -> Alcotest.fail "expected conrol file" + in + let () = + match Io.classify_path volume_cf_gen_path with + | `No_such_file_or_directory -> [%log.debug "gc control file unlinked"] + | _ -> Alcotest.fail "expected conrol gen file to not exist" + in + Store.Repo.close repo +end + +module Store = struct + include Store_tc + + let tests = + Alcotest_lwt. + [ + quick_tc "create store" test_create; + quick_tc "create nested" test_create_nested; + quick_tc "open rw with lower" test_open_rw_lower; + quick_tc "add volume with no lower" test_add_volume_wo_lower; + quick_tc "add volume during gc" test_add_volume_during_gc; + quick_tc "control file updated after add" test_add_volume_reopen; + quick_tc "add volume and reopen" test_add_volume_reopen; + quick_tc "create without lower then migrate" test_migrate; + quick_tc "migrate v2" test_migrate_v2; + quick_tc "migrate v3" test_migrate_v3; + quick_tc "migrate then gc" test_migrate_then_gc; + quick_tc "migrate then gc in lower" test_migrate_then_gc_in_lower; + quick_tc "test data locality" test_volume_data_locality; + quick_tc "test cleanup" test_cleanup; + ] +end + +module Direct = struct + include Direct_tc + + let tests = + Alcotest_lwt. + [ + quick_tc "empty lower" test_empty; + quick_tc "volume_num too high" test_volume_num; + quick_tc "add volume" test_add_volume; + quick_tc "add volume ro" test_add_volume_ro; + quick_tc "add multiple empty" test_add_multiple_empty; + quick_tc "find volume" test_find_volume; + quick_tc "test read_exn" test_read_exn; + ] +end diff --git a/vendors/irmin/test/irmin-pack/test_lower.mli b/vendors/irmin/test/irmin-pack/test_lower.mli new file mode 100644 index 000000000000..416b7dce2128 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_lower.mli @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2023 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Store : sig + val tests : unit Alcotest_lwt.test_case list +end + +module Direct : sig + val tests : unit Alcotest_lwt.test_case list +end diff --git a/vendors/irmin/test/irmin-pack/test_mapping.ml b/vendors/irmin/test/irmin-pack/test_mapping.ml new file mode 100644 index 000000000000..4b93a67ce861 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_mapping.ml @@ -0,0 +1,112 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Int63 = Optint.Int63 +module Io = Irmin_pack_unix.Io.Unix +module Errs = Irmin_pack_unix.Io_errors.Make (Io) +module Sparse_file = Irmin_pack_unix.Sparse_file.Make (Io) + +let test_dir = Filename.concat "_build" "test-pack-mapping" + +let rec make_string_seq len () = + if len <= 0 then Seq.Nil + else + let quantity = min 8 len in + Seq.Cons (String.make quantity 'X', make_string_seq (len - quantity)) + +(** Call the [Mapping_file] routines to process [pairs] *) +let process_on_disk pairs = + let mapping = Irmin_pack.Layout.V5.mapping ~root:test_dir ~generation:1 in + Io.unlink mapping |> ignore; + let data = Irmin_pack.Layout.V5.prefix ~root:test_dir ~generation:1 in + Io.unlink data |> ignore; + let sparse = Sparse_file.Ao.create ~mapping ~data |> Errs.raise_if_error in + List.iter + (fun (off, len) -> + Format.printf "%i (+%i) => %i@." off len (off + len); + let str = make_string_seq len in + let off = Int63.of_int off in + Sparse_file.Ao.append_seq_exn sparse ~off str) + (List.rev pairs); + let mapping_size = Int63.to_int (Sparse_file.Ao.mapping_size sparse) in + Sparse_file.Ao.flush sparse |> Errs.raise_if_error; + Sparse_file.Ao.close sparse |> Errs.raise_if_error; + let sparse = + Sparse_file.open_ro ~mapping_size ~mapping ~data |> Errs.raise_if_error + in + let l = ref [] in + let f ~off ~len = l := (Int63.to_int off, len) :: !l in + Sparse_file.iter sparse f |> Errs.raise_if_error; + Sparse_file.close sparse |> Errs.raise_if_error; + !l |> List.rev + +(** Emulate the behaviour of the [Mapping_file] routines to process [pairs] *) +let process_in_mem pairs = List.rev pairs + +let test input_entries = + let output_entries = process_on_disk input_entries in + let input_entries' = process_in_mem input_entries in + Alcotest.(check (list (pair int int))) + "Comparison between Mapping_file result and the in-memory equivalent" + input_entries' output_entries + +(** Produce an array of contiguous offset/length pairs starting from offset 0 *) +let produce_suffix_segmentation len seed = + let rng = Random.State.make [| seed |] in + let _, elts = + List.init len Fun.id + |> List.fold_left + (fun (totlen, l) _ -> + let len = Random.State.int rng 10 + 1 in + (totlen + len, (totlen, len) :: l)) + (0, []) + in + List.to_seq elts |> Array.of_seq + +(** Randomly produce a subset of the [full_seg] segmentation. *) +let produce_suffix_segmentation_subset full_seg ~seed = + let rng = Random.State.make [| seed |] in + List.filter_map (fun (off, len) -> + if Random.State.bool rng then None + else + let len = Random.State.int rng len |> max 1 in + Some (off, len)) + @@ Array.to_list full_seg + +let test ~full_seg_length ~random_test_count = + (* [mkdir] may fail if the directory exists. The files in it will be + overwritten at computation time. *) + Io.mkdir test_dir |> ignore; + + let seg = produce_suffix_segmentation full_seg_length 42 in + let rec aux i = + if i >= random_test_count then () + else + let subset = produce_suffix_segmentation_subset seg ~seed:i in + if subset <> [] then test subset; + aux (i + 1) + in + aux 0; + Lwt.return_unit + +let tests = + [ + Alcotest_lwt.test_case "test mapping on small inputs" `Quick + (fun _switch () -> test ~full_seg_length:10 ~random_test_count:1000); + Alcotest_lwt.test_case "test mapping on large inputs" `Quick + (fun _switch () -> test ~full_seg_length:10000 ~random_test_count:100); + ] diff --git a/vendors/irmin/test/irmin-pack/test_mapping.mli b/vendors/irmin/test/irmin-pack/test_mapping.mli new file mode 100644 index 000000000000..4acc26805b83 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_mapping.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_nearest_geq.ml b/vendors/irmin/test/irmin-pack/test_nearest_geq.ml new file mode 100644 index 000000000000..badc02241349 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_nearest_geq.ml @@ -0,0 +1,27 @@ +open Irmin_pack_unix + +type geq = int option [@@deriving irmin ~pp ~equal] + +let geq = Alcotest.testable pp_geq equal_geq + +let test_nearest_geq () = + let arr = Array.of_list [ 1; 3; 5; 7 ] in + let get arr i = arr.(i) in + let lo, hi = (0, Array.length arr - 1) in + let nearest_geq key = Utils.nearest_geq ~arr ~get ~lo ~hi ~key in + Alcotest.(check geq) "0" (nearest_geq 0) (Some 0); + Alcotest.(check geq) "1" (nearest_geq 1) (Some 0); + Alcotest.(check geq) "2" (nearest_geq 2) (Some 1); + Alcotest.(check geq) "3" (nearest_geq 3) (Some 1); + Alcotest.(check geq) "4" (nearest_geq 4) (Some 2); + Alcotest.(check geq) "5" (nearest_geq 5) (Some 2); + Alcotest.(check geq) "6" (nearest_geq 6) (Some 3); + Alcotest.(check geq) "7" (nearest_geq 7) (Some 3); + Alcotest.(check geq) "8" (nearest_geq 8) None; + Lwt.return_unit + +let tests = + [ + Alcotest_lwt.test_case "test_nearest_geq" `Quick (fun _switch () -> + test_nearest_geq ()); + ] diff --git a/vendors/irmin/test/irmin-pack/test_nearest_leq.mli b/vendors/irmin/test/irmin-pack/test_nearest_leq.mli new file mode 100644 index 000000000000..01604e1617a5 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_nearest_leq.mli @@ -0,0 +1 @@ +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_pack.ml b/vendors/irmin/test/irmin-pack/test_pack.ml new file mode 100644 index 000000000000..8f738acd7327 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_pack.ml @@ -0,0 +1,580 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let test_dir = Filename.concat "_build" "test-db-pack" + +module Irmin_pack_store (Config : Irmin_pack.Conf.S) : Irmin_test.Generic_key = +struct + open Irmin_pack_unix.Maker (Config) + + include Make (struct + include Irmin_test.Schema + module Node = Irmin.Node.Generic_key.Make (Hash) (Path) (Metadata) + module Commit_maker = Irmin.Commit.Generic_key.Maker (Info) + module Commit = Commit_maker.Make (Hash) + end) +end + +let suite_pack name_suffix indexing_strategy (module Config : Irmin_pack.Conf.S) + = + let store = (module Irmin_pack_store (Config) : Irmin_test.Generic_key) in + let config = + Irmin_pack.config ~fresh:false ~lru_size:0 ~indexing_strategy test_dir + in + let init ~config = + let test_dir = + Irmin.Backend.Conf.find_root config |> Option.value ~default:test_dir + in + rm_dir test_dir; + Lwt.return_unit + in + let clean = init in + Irmin_test.Suite.create_generic_key ~name:("PACK" ^ name_suffix) + ~import_supported:false ~init ~store ~config ~clean () + +module Irmin_tezos_conf = struct + include Irmin_tezos.Conf + + (* The generic test suite relies a lot on the empty tree. Let's allow it. *) + let forbid_empty_dir_persistence = false +end + +module Irmin_pack_mem_maker : Irmin_test.Generic_key = struct + open Irmin_pack_mem.Maker (Irmin_tezos_conf) + + include Make (struct + include Irmin_test.Schema + module Node = Irmin.Node.Generic_key.Make (Hash) (Path) (Metadata) + module Commit_maker = Irmin.Commit.Generic_key.Maker (Info) + module Commit = Commit_maker.Make (Hash) + end) +end + +let suite_mem = + let store = (module Irmin_pack_mem_maker : Irmin_test.Generic_key) in + let config = Irmin_pack.config ~fresh:false ~lru_size:0 test_dir in + Irmin_test.Suite.create_generic_key ~import_supported:false ~name:"PACK MEM" + ~store ~config () + +let suite = + let module Index = Irmin_pack.Indexing_strategy in + let module Conf_small_nodes = struct + (* Parameters chosen to be different from those in [Irmin_tezos.Conf]: *) + let entries = 2 + let stable_hash = 3 + let contents_length_header = None + let inode_child_order = `Hash_bits + let forbid_empty_dir_persistence = false + end in + [ + suite_pack " { Tezos }" Index.minimal (module Irmin_tezos_conf); + suite_pack " { Small_nodes }" Index.always (module Conf_small_nodes); + suite_mem; + ] + +module Context = Make_context (struct + let root = test_dir +end) + +let flush fm = File_manager.flush fm |> Errs.raise_if_error +let reload fm = File_manager.reload fm |> Errs.raise_if_error + +module Dict = struct + let test_dict () = + let (d : Context.d) = Context.get_dict ~readonly:false ~fresh:true () in + let x1 = Dict.index d.dict "foo" in + Alcotest.(check (option int)) "foo" (Some 0) x1; + let x1 = Dict.index d.dict "foo" in + Alcotest.(check (option int)) "foo" (Some 0) x1; + let x2 = Dict.index d.dict "bar" in + Alcotest.(check (option int)) "bar" (Some 1) x2; + let x3 = Dict.index d.dict "toto" in + Alcotest.(check (option int)) "toto" (Some 2) x3; + let x4 = Dict.index d.dict "titiabc" in + Alcotest.(check (option int)) "titiabc" (Some 3) x4; + let x1 = Dict.index d.dict "foo" in + Alcotest.(check (option int)) "foo" (Some 0) x1; + flush d.fm; + let (d2 : Context.d) = + Context.get_dict ~name:d.name ~readonly:false ~fresh:false () + in + let x4 = Dict.index d2.dict "titiabc" in + Alcotest.(check (option int)) "titiabc" (Some 3) x4; + let v1 = Dict.find d2.dict (get x1) in + Alcotest.(check (option string)) "find x1" (Some "foo") v1; + let v2 = Dict.find d2.dict (get x2) in + Alcotest.(check (option string)) "find x2" (Some "bar") v2; + let v3 = Dict.find d2.dict (get x3) in + Alcotest.(check (option string)) "find x3" (Some "toto") v3; + Context.close_dict d; + let (d3 : Context.d) = + Context.get_dict ~name:d.name ~readonly:false ~fresh:false () + in + let v1 = Dict.find d3.dict (get x1) in + Alcotest.(check (option string)) "find x1" (Some "foo") v1; + Context.close_dict d2; + Context.close_dict d3 + + let ignore_int (_ : int option) = () + + let test_readonly_dict () = + let (d : Context.d) = Context.get_dict ~readonly:false ~fresh:true () in + let (d2 : Context.d) = + Context.get_dict ~name:d.name ~readonly:true ~fresh:false () + in + let check_index k i = + Alcotest.(check (option int)) k (Some i) (Dict.index d2.dict k) + in + let check_find k i = + Alcotest.(check (option string)) k (Some k) (Dict.find d2.dict i) + in + let check_none k i = + Alcotest.(check (option string)) k None (Dict.find d2.dict i) + in + let check_raise k = + try + ignore_int (Dict.index d2.dict k); + Alcotest.fail "RO dict should not be writable" + with Irmin_pack.RO_not_allowed -> () + in + ignore_int (Dict.index d.dict "foo"); + ignore_int (Dict.index d.dict "foo"); + ignore_int (Dict.index d.dict "bar"); + ignore_int (Dict.index d.dict "toto"); + ignore_int (Dict.index d.dict "titiabc"); + ignore_int (Dict.index d.dict "foo"); + flush d.fm; + reload d2.fm; + check_index "titiabc" 3; + check_index "bar" 1; + check_index "toto" 2; + check_find "foo" 0; + check_raise "xxx"; + ignore_int (Dict.index d.dict "hello"); + check_raise "hello"; + check_none "hello" 4; + flush d.fm; + reload d2.fm; + check_find "hello" 4; + Context.close_dict d; + Context.close_dict d2 + + let tests = + [ + Alcotest_lwt.test_case "dict" `Quick (fun _ () -> + Lwt.return (test_dict ())); + Alcotest_lwt.test_case "RO dict" `Quick (fun _ () -> + Lwt.return (test_readonly_dict ())); + ] +end + +module Pack = struct + let test_pack () = + let* t = Context.get_rw_pack () in + let x1 = "foo" in + let x2 = "bar" in + let x3 = "otoo" in + let x4 = "sdadsadas" in + let h1 = sha1_contents x1 in + let h2 = sha1_contents x2 in + let h3 = sha1_contents x3 in + let h4 = sha1_contents x4 in + let* k1, k2, k3, k4 = + Pack.batch t.pack (fun w -> + Lwt_list.map_s + (fun (k, v) -> Pack.unsafe_add w k v) + [ (h1, x1); (h2, x2); (h3, x3); (h4, x4) ]) + >|= function + | [ k1; k2; k3; k4 ] -> (k1, k2, k3, k4) + | _ -> assert false + in + + let test t = + let* y1 = Pack.find t k1 >|= get in + Alcotest.(check string) "x1" x1 y1; + let* y3 = Pack.find t k3 >|= get in + Alcotest.(check string) "x3" x3 y3; + let* y2 = Pack.find t k2 >|= get in + Alcotest.(check string) "x2" x2 y2; + let* y4 = Pack.find t k4 >|= get in + Alcotest.(check string) "x4" x4 y4; + Lwt.return_unit + in + test t.pack >>= fun () -> + let* t' = Context.get_ro_pack t.name in + test t'.pack >>= fun () -> + Context.close_pack t >>= fun () -> Context.close_pack t' + + let test_readonly_pack () = + let* t = Context.get_rw_pack () in + let* t' = Context.get_ro_pack t.name in + let* () = + let adds l = + List.map + (fun (k, v) -> + Pack.unsafe_append ~ensure_unique:true ~overcommit:false t.pack k v) + l + in + let x1 = "foo" in + let x2 = "bar" in + let h1 = sha1_contents x1 in + let h2 = sha1_contents x2 in + let[@warning "-8"] [ _k1; k2 ] = adds [ (h1, x1); (h2, x2) ] in + let* y2 = Pack.find t'.pack k2 in + Alcotest.(check (option string)) "before reload" None y2; + flush t.fm; + reload t'.fm; + let* y2 = Pack.find t'.pack k2 in + Alcotest.(check (option string)) "after reload" (Some x2) y2; + let x3 = "otoo" in + let x4 = "sdadsadas" in + let h3 = sha1_contents x3 in + let h4 = sha1_contents x4 in + let[@warning "-8"] [ k3; _k4 ] = adds [ (h3, x3); (h4, x4) ] in + flush t.fm; + reload t'.fm; + let* y2 = Pack.find t'.pack k2 in + Alcotest.(check (option string)) "y2" (Some x2) y2; + let* y3 = Pack.find t'.pack k3 in + Alcotest.(check (option string)) "y3" (Some x3) y3; + Lwt.return_unit + in + Context.close_pack t >>= fun () -> Context.close_pack t' + + let test_close_pack_more () = + (*open and close in rw*) + let* t = Context.get_rw_pack () in + let x1 = "foo" in + let h1 = sha1_contents x1 in + let k1 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false t.pack h1 x1 + in + flush t.fm; + Context.close_pack t >>= fun () -> + (*open and close in ro*) + let* t1 = Context.get_ro_pack t.name in + let* y1 = Pack.find t1.pack k1 >|= get in + Alcotest.(check string) "x1.1" x1 y1; + Context.close_pack t1 >>= fun () -> + (* reopen in rw *) + let* t2 = Context.reopen_rw t.name in + let* y1 = Pack.find t2.pack k1 >|= get in + Alcotest.(check string) "x1.2" x1 y1; + (*reopen in ro *) + let* t3 = Context.get_ro_pack t.name in + let* y1 = Pack.find t3.pack k1 >|= get in + Alcotest.(check string) "x1.3" x1 y1; + Context.close_pack t2 >>= fun () -> Context.close_pack t3 + + let test_close_pack () = + let* t = Context.get_rw_pack () in + let w = t.pack in + let x1 = "foo" in + let x2 = "bar" in + let h1 = sha1_contents x1 in + let h2 = sha1_contents x2 in + let* k1, k2 = + Pack.batch w (fun w -> + Lwt_list.map_s + (fun (k, v) -> Pack.unsafe_add w k v) + [ (h1, x1); (h2, x2) ]) + >|= function + | [ k1; k2 ] -> (k1, k2) + | _ -> assert false + in + Context.close_pack t >>= fun () -> + (*reopen in rw *) + let* t' = Context.reopen_rw t.name in + let* y2 = Pack.find t'.pack k2 >|= get in + Alcotest.(check string) "x2.1" x2 y2; + let* y1 = Pack.find t'.pack k1 >|= get in + Alcotest.(check string) "x1.1" x1 y1; + let x3 = "toto" in + let h3 = sha1_contents x3 in + let k3 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false t'.pack h3 x3 + in + Context.close_pack t' >>= fun () -> + (*reopen in rw *) + let* t2 = Context.reopen_rw t.name in + let* y2 = Pack.find t2.pack k2 >|= get in + Alcotest.(check string) "x2.2" x2 y2; + let* y3 = Pack.find t2.pack k3 >|= get in + Alcotest.(check string) "x3.2" x3 y3; + let* y1 = Pack.find t2.pack k1 >|= get in + Alcotest.(check string) "x1.2" x1 y1; + Context.close_pack t2 >>= fun () -> + (*reopen in ro *) + let* t' = Context.get_ro_pack t.name in + let* y1 = Pack.find t'.pack k1 >|= get in + Alcotest.(check string) "x1.3" x1 y1; + let* y2 = Pack.find t'.pack k2 >|= get in + Alcotest.(check string) "x2.3" x2 y2; + Context.close_pack t' >>= fun () -> Lwt.return_unit + + (** Index can be flushed to disk independently of pack, we simulate this in + the tests using [Index.filter] and [Index.flush]. Regression test for PR + 1008 in which values were indexed before being reachable in pack. *) + let readonly_reload_index_flush () = + let* t = Context.get_rw_pack () in + let* t' = Context.get_ro_pack t.name in + let test w = + let x1 = "foo" in + let h1 = sha1_contents x1 in + let k1 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false w h1 x1 + in + reload t'.fm; + let* y1 = Pack.find t'.pack k1 in + Alcotest.(check (option string)) "reload before filter" None y1; + Index.filter t.index (fun _ -> true); + reload t'.fm; + let* y1 = Pack.find t'.pack k1 in + Alcotest.(check (option string)) "reload after filter" (Some x1) y1; + let x2 = "foo" in + let h2 = sha1_contents x2 in + let k2 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false w h2 x2 + in + Index.flush t.index ~with_fsync:false |> Errs.raise_if_error; + let+ y2 = Pack.find t'.pack k2 in + Alcotest.(check (option string)) "reload after flush" (Some x2) y2 + in + test t.pack >>= fun () -> + Context.close_pack t >>= fun () -> Context.close_pack t' + + let readonly_find_index_flush () = + let* t = Context.get_rw_pack () in + let* t' = Context.get_ro_pack t.name in + let check h x msg = + let+ y = Pack.find t'.pack h in + Alcotest.(check (option string)) msg (Some x) y + in + let test w = + let x1 = "foo" in + let h1 = sha1_contents x1 in + let k1 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false w h1 x1 + in + flush t.fm; + reload t'.fm; + check k1 x1 "find before filter" >>= fun () -> + Index.filter t.index (fun _ -> true); + check k1 x1 "find after filter" >>= fun () -> + let x2 = "bar" in + let h2 = sha1_contents x2 in + let k2 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false w h2 x2 + in + flush t.fm; + reload t'.fm; + check k2 x2 "find before flush" >>= fun () -> + let x3 = "toto" in + let h3 = sha1_contents x3 in + let k3 = + Pack.unsafe_append ~ensure_unique:true ~overcommit:false w h3 x3 + in + Index.flush t.index ~with_fsync:false |> Errs.raise_if_error; + check k2 x2 "find after flush" >>= fun () -> + flush t.fm; + reload t'.fm; + check k3 x3 "find after flush new values" + in + test t.pack >>= fun () -> + Context.close_pack t >>= fun () -> Context.close_pack t' + + let tests = + [ + Alcotest_lwt.test_case "pack" `Quick (fun _switch () -> test_pack ()); + Alcotest_lwt.test_case "RO pack" `Quick (fun _switch () -> + test_readonly_pack ()); + Alcotest_lwt.test_case "close" `Quick (fun _switch () -> + test_close_pack ()); + Alcotest_lwt.test_case "close readonly" `Quick (fun _switch () -> + test_close_pack_more ()); + Alcotest_lwt.test_case "readonly reload, index flush" `Quick + (fun _switch () -> readonly_reload_index_flush ()); + Alcotest_lwt.test_case "readonly find, index flush" `Quick + (fun _switch () -> readonly_find_index_flush ()); + ] +end + +module Branch = struct + module Branch = + Irmin_pack_unix.Atomic_write.Make_persistent + (Irmin.Branch.String) + (Irmin_pack.Atomic_write.Value.Of_hash (Irmin.Hash.SHA1)) + + let pp_hash = Irmin.Type.pp Irmin.Hash.SHA1.t + + let test_branch () = + let branches = [ "foo"; "bar/toto"; "titi" ] in + let test t = + Lwt_list.iter_s (fun k -> Branch.set t k (sha1 k)) branches >>= fun () -> + let check h = + let+ v = Branch.find t h in + Alcotest.(check (option hash)) h (Some (sha1 h)) v + in + Lwt_list.iter_p check branches + in + let name = Context.fresh_name "branch" in + Branch.v ~fresh:true name >>= test >>= fun () -> + Branch.v ~fresh:true name >>= test >>= fun () -> + Branch.v ~fresh:true name >>= test >>= fun () -> + let* t = Branch.v ~fresh:false name in + test t >>= fun () -> + let x = sha1 "XXX" in + Branch.set t "foo" x >>= fun () -> + let* t = Branch.v ~fresh:false name in + let* v = Branch.find t "foo" in + Alcotest.(check (option hash)) "foo" (Some x) v; + let* br = Branch.list t in + Alcotest.(check (slist string compare)) "branches" branches br; + Branch.remove t "foo" >>= fun () -> + let* t = Branch.v ~fresh:false name in + let* v = Branch.find t "foo" in + Alcotest.(check (option hash)) "foo none" None v; + let* br = Branch.list t in + Alcotest.(check (slist string compare)) + "branches" + (List.filter (( <> ) "foo") branches) + br; + Lwt.return_unit + + let test_close_branch () = + let branches = [ "foo"; "bar/toto"; "titi" ] in + let add t = + Lwt_list.iter_s + (fun k -> + [%logs.debug "k = %s, v= %a" k pp_hash (sha1 k)]; + Branch.set t k (sha1 k)) + branches + in + let test t = + let check h = + let+ v = Branch.find t h in + Alcotest.(check (option hash)) h (Some (sha1 h)) v + in + Lwt_list.iter_p check branches + in + let name = Context.fresh_name "branch" in + let* t = Branch.v ~fresh:true name in + add t >>= fun () -> + test t >>= fun () -> + Branch.close t >>= fun () -> + let* t = Branch.v ~fresh:false ~readonly:true name in + test t >>= fun () -> + Branch.close t >>= fun () -> + let name = Context.fresh_name "branch" in + let* t1 = Branch.v ~fresh:true ~readonly:false name in + let* t2 = Branch.v ~fresh:false ~readonly:true name in + add t1 >>= fun () -> + Branch.close t1 >>= fun () -> test t2 + + let tests = + [ + Alcotest_lwt.test_case "branch" `Quick (fun _switch -> test_branch); + Alcotest_lwt.test_case "branch close" `Quick (fun _switch -> + test_close_branch); + ] +end + +module Layout = struct + let test_classify_upper_filename () = + let module V1_and_v2 = Irmin_pack.Layout.V1_and_v2 in + let module V4 = Irmin_pack.Layout.V4 in + let module Classification = Irmin_pack.Layout.Classification.Upper in + let c = Alcotest.(check (testable_repr Classification.t)) "" in + let classif = Classification.v in + c `V1_or_v2_pack (V1_and_v2.pack ~root:"" |> classif); + c `Branch (V4.branch ~root:"" |> classif); + c `Control (V4.control ~root:"" |> classif); + c `Control_tmp (V4.control_tmp ~root:"" |> classif); + c `Dict (V4.dict ~root:"" |> classif); + c (`Gc_result 0) (V4.gc_result ~generation:0 ~root:"" |> classif); + c (`Reachable 1) (V4.reachable ~generation:1 ~root:"" |> classif); + c (`Sorted 10) (V4.sorted ~generation:10 ~root:"" |> classif); + c (`Mapping 100) (V4.mapping ~generation:100 ~root:"" |> classif); + c (`Prefix 1000) (V4.prefix ~generation:1000 ~root:"" |> classif); + c (`Suffix 42) (V4.suffix_chunk ~chunk_idx:42 ~root:"" |> classif); + c `Unknown (V4.prefix ~generation:(-1) ~root:"" |> classif); + c `Unknown (classif "store.toto"); + c `Unknown (classif "store."); + c `Unknown (classif "store"); + c `Unknown (classif "store.00.prefix"); + c `Unknown (classif "store.01.prefix"); + c `Unknown (classif "./store.0.prefix"); + Lwt.return_unit + + let test_classify_volume_filename () = + let module V1_and_v2 = Irmin_pack.Layout.V1_and_v2 in + let module V5 = Irmin_pack.Layout.V5.Volume in + let module Classification = Irmin_pack.Layout.Classification.Volume in + let c = Alcotest.(check (testable_repr Classification.t)) "" in + let classif = Classification.v in + c `Control (V5.control ~root:"" |> classif); + c `Mapping (V5.mapping ~root:"" |> classif); + c `Data (V5.data ~root:"" |> classif); + c `Unknown (classif "store.toto"); + c `Unknown (classif "store."); + c `Unknown (classif "store"); + c `Unknown (classif "store.00.prefix"); + c `Unknown (classif "store.01.prefix"); + c `Unknown (classif "./store.0.prefix"); + Lwt.return_unit + + let tests = + [ + Alcotest_lwt.test_case "classify upper files" `Quick (fun _switch -> + test_classify_upper_filename); + Alcotest_lwt.test_case "classify volume files" `Quick (fun _switch -> + test_classify_volume_filename); + ] +end + +let misc = + [ + ("hashes", Test_hashes.tests); + ("dict-files", Dict.tests); + ("pack-files", Pack.tests); + ("branch-files", Branch.tests); + ("read-only", Test_readonly.tests); + ("existing stores", Test_existing_stores.tests); + ("inodes", Test_inode.tests); + ("trees", Test_tree.tests); + ("version-bump", Test_pack_version_bump.tests); + ("snapshot", Test_snapshot.tests); + ("upgrade", Test_upgrade.tests); + ("gc", Test_gc.Gc.tests); + ("concurrent gc", Test_gc.Concurrent_gc.tests); + ("gc archival", Test_gc.Gc_archival.tests); + ("split", Test_gc.Split.tests); + ("flush", Test_flush_reload.tests); + ("ranges", Test_ranges.tests); + ("mapping", Test_mapping.tests); + ("test_nearest_geq", Test_nearest_geq.tests); + ("layout", Layout.tests); + ("dispatcher", Test_dispatcher.tests); + ("corrupted", Test_corrupted.tests); + ("snapshot_gc", Test_gc.Snapshot.tests); + ("async tasks", Test_async.tests); + ("indexing strategy", Test_indexing_strategy.tests); + ("lower: direct", Test_lower.Direct.tests); + ("lower: store", Test_lower.Store.tests); + ] diff --git a/vendors/irmin/test/irmin-pack/test_pack.mli b/vendors/irmin/test/irmin-pack/test_pack.mli new file mode 100644 index 000000000000..599c43edf13d --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_pack.mli @@ -0,0 +1,18 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val suite : Irmin_test.Suite.t list +val misc : (string * unit Alcotest_lwt.test_case list) list diff --git a/vendors/irmin/test/irmin-pack/test_pack_version_bump.ml b/vendors/irmin/test/irmin-pack/test_pack_version_bump.ml new file mode 100644 index 000000000000..60e6d3a79c77 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_pack_version_bump.ml @@ -0,0 +1,160 @@ +(** These tests for issue #1658, which follows PR #1655 which introduces a store + version bump from V1 to V2 when a writer instance adds a V2-only pack entry + (including nodes and commits, but not contents). *) + +open! Import +open Common + +(** {2 Preamble} *) + +let src = Logs.Src.create "tests.version_bump" ~doc:"Test pack version bump" + +module Log = (val Logs.src_log src : Logs.LOG) + +(** Set up modules to allow access to "version_1" store *) +module Private = struct + (* The behaviour under test is independent of which [Conf] we pick: *) + module Conf = Irmin_tezos.Conf + + (* Note: the existing stores use a different hash from [Irmin_tezos.Schema] + (SHA1 rather than BLAKE2b) *) + module Schema = Common.Schema + + (* from test_existing_stores.ml; the V2 is because + test_existing_stores defines two different configs *) + module V2_maker = Irmin_pack_unix.Maker (Conf) + module V2 = V2_maker.Make (Schema) + + (* the following modules are necessary to expose the File_manager.*) + module Index = Irmin_pack_unix.Index.Make (Schema.Hash) + module Io = Irmin_pack_unix.Io.Unix + module Errs = Irmin_pack_unix.Io_errors.Make (Io) + module File_manager = Irmin_pack_unix.File_manager.Make (Io) (Index) (Errs) +end + +module Util = struct + (** Following are generic utils *) + + let exec_cmd = Common.exec_cmd + let ( / ) = Filename.concat + let tmp_dir () = Filename.temp_file "test_pack_version_bump_" "" + + (** Copy src to dst; dst is assumed to not exist *) + let copy_dir src dst = + assert (not (Sys.file_exists dst)); + (* don't check if it is empty; perhaps we should *) + Filename.quote_command "cp" [ "-R"; src; dst ] |> fun cmd -> + exec_cmd cmd |> function + | Ok () -> () + | Error n -> + Fmt.failwith + "Failed to set up test env; command `%s' exited with non-zero code %d\n" + cmd n + + (** Identify the root directory, by comparing st_dev,st_ino *) + let is_root = + let open Unix in + let root_stat = stat "/" in + fun s -> + let stat = Unix.stat s in + (stat.st_dev, stat.st_ino) = (root_stat.st_dev, root_stat.st_ino) + + (** Starting from ".", try to find a parent directory that has a given + property. *) + let find_parent_matching test = + let rec go path = + match test path with + | true -> Ok path + | false -> ( + match is_root path with + | true -> Error () + | false -> go (path / Filename.parent_dir_name)) + in + go Filename.current_dir_name + + (** More specific utils from here *) + + let v1_store_archive_dir = "test" / "irmin-pack" / "data" / "version_1" + + (** Find the project root, that contains the v1_store_archive_dir *) + let project_root () = + find_parent_matching (fun d -> Sys.file_exists (d / v1_store_archive_dir)) + |> function + | Ok s -> s + | Error () -> + Fmt.failwith + "Couldn't find project root containing path to %s, after examining \ + current directory %s and ancestors" + v1_store_archive_dir (Sys.getcwd ()) + + module Unix_ = Irmin_pack_unix.Io_legacy.Unix + + (** Get the version of the underlying file; file is assumed to exist; file is + assumed to be an Irmin_pack.IO.Unix file *) + let io_get_version ~root : [ `V1 | `V2 | `V3 | `V4 | `V5 ] = + File_manager.version ~root |> Errs.raise_if_error + + let alco_check_version ~pos ~expected ~actual = + Alcotest.check_repr ~pos Irmin_pack.Version.t "" expected actual +end + +open Util + +(** This sets up infrastructure to open the existing "version_1" store *) +module With_existing_store () = struct + let tmp_dir = tmp_dir () + let () = [%log.info "Using temporary directory %s" tmp_dir] + + (* Make a copy of the v1_store_archive_dir in tmp_dir *) + let () = + rm_dir tmp_dir; + copy_dir (project_root () / v1_store_archive_dir) tmp_dir; + () + + (* [S] is the functionality we use from Private, together with an + appropriate config *) + module S = Private.V2 + + (* Code copied and modified from test_existing_stores.ml; this is + the config for index and pack *) + let config ~readonly : Irmin.config = + Irmin_pack.config ~readonly ~index_log_size:1000 ~fresh:false tmp_dir +end + +(** {2 The tests} *) + +(** Cannot open a V1 store in RO mode. *) +let test_RO_no_migration () : unit Lwt.t = + [%log.info "Executing test_RO_no_migration"]; + let open With_existing_store () in + assert (io_get_version ~root:tmp_dir = `V1); + + let* () = + Alcotest.check_raises_lwt "open V1 store in RO" + (Irmin_pack_unix.Errors.Pack_error `Migration_needed) (fun () -> + let* repo = S.Repo.v (config ~readonly:true) in + S.Repo.close repo) + in + (* maybe the version bump is only visible after, check again *) + alco_check_version ~pos:__POS__ ~expected:`V1 + ~actual:(io_get_version ~root:tmp_dir); + Lwt.return () + +(** Open a V1 store RW mode. Even if no writes, the store migrates to V3. *) +let test_open_RW () : unit Lwt.t = + [%log.info "Executing test_open_RW"]; + let open With_existing_store () in + assert (io_get_version ~root:tmp_dir = `V1); + let* repo = S.Repo.v (config ~readonly:false) in + let* () = S.Repo.close repo in + alco_check_version ~pos:__POS__ ~expected:`V3 + ~actual:(io_get_version ~root:tmp_dir); + Lwt.return () + +let tests = + let f g _switch () = g () in + Alcotest_lwt. + [ + test_case "test_RO_no_migration" `Quick (f test_RO_no_migration); + test_case "test_open_RW" `Quick (f test_open_RW); + ] diff --git a/vendors/irmin/test/irmin-pack/test_pack_version_bump.mli b/vendors/irmin/test/irmin-pack/test_pack_version_bump.mli new file mode 100644 index 000000000000..01604e1617a5 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_pack_version_bump.mli @@ -0,0 +1 @@ +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_ranges.ml b/vendors/irmin/test/irmin-pack/test_ranges.ml new file mode 100644 index 000000000000..0fe759992b58 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_ranges.ml @@ -0,0 +1,38 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +module Int63 = Optint.Int63 +module Ranges = Irmin_pack_unix.Ranges + +let test () = + let input = + [ (90, 10); (80, 5); (70, 10); (87, 1); (60, 5); (50, 5); (65, 2); (55, 5) ] + in + let ranges = Ranges.make () in + List.iter + (fun (off, len) -> Ranges.add ~off:(Int63.of_int off) ~len ranges) + input; + let output = ref [] in + Ranges.iter + (fun ~off ~len -> output := (Int63.to_int off, Int63.to_int len) :: !output) + ranges; + let expected = [ (90, 10); (87, 1); (70, 15); (50, 17) ] in + Alcotest.(check (list (pair int int))) "out of order" expected !output; + Lwt.return_unit + +let tests = + [ Alcotest_lwt.test_case "test ranges" `Quick (fun _switch () -> test ()) ] diff --git a/vendors/irmin/test/irmin-pack/test_readonly.ml b/vendors/irmin/test/irmin-pack/test_readonly.ml new file mode 100644 index 000000000000..e4efb460771c --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_readonly.ml @@ -0,0 +1,124 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let root = Filename.concat "_build" "test-readonly" +let src = Logs.Src.create "tests.readonly" ~doc:"Tests read-only stores" + +module Log = (val Logs.src_log src : Logs.LOG) + +let index_log_size = Some 1_000 + +module S = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) +end + +let config ?(readonly = false) ?(fresh = true) root = + Irmin_pack.config ~readonly ?index_log_size ~fresh root + +let info () = S.Info.empty + +let open_ro_after_rw_closed () = + rm_dir root; + let* rw = S.Repo.v (config ~readonly:false ~fresh:true root) in + let* t = S.main rw in + let tree = S.Tree.singleton [ "a" ] "x" in + S.set_tree_exn ~parents:[] ~info t [] tree >>= fun () -> + let* ro = S.Repo.v (config ~readonly:true ~fresh:false root) in + S.Repo.close rw >>= fun () -> + let* t = S.main ro in + let* c = S.Head.get t in + S.Commit.of_hash ro (S.Commit.hash c) >>= function + | None -> Alcotest.fail "no hash" + | Some commit -> + let tree = S.Commit.tree commit in + let* x = S.Tree.find tree [ "a" ] in + Alcotest.(check (option string)) "RO find" (Some "x") x; + S.Repo.close ro + +let check_binding ?msg repo commit key value = + let msg = + match msg with + | Some m -> m + | None -> + Fmt.str "Expected binding [%a ↦ %s]" Fmt.(Dump.list string) key value + in + S.Commit.of_hash repo (S.Commit.hash commit) >>= function + | None -> Alcotest.failf "commit not found" + | Some commit -> + let tree = S.Commit.tree commit in + let+ x = S.Tree.find tree key in + Alcotest.(check (option string)) msg (Some value) x + +let ro_reload_after_add () = + let check ro c k v = + S.Commit.of_hash ro (S.Commit.hash c) >>= function + | None -> Alcotest.failf "commit not found" + | Some commit -> + let tree = S.Commit.tree commit in + let+ x = S.Tree.find tree [ k ] in + Alcotest.(check (option string)) "RO find" (Some v) x + in + rm_dir root; + let* rw = S.Repo.v (config ~readonly:false ~fresh:true root) in + let* ro = S.Repo.v (config ~readonly:true ~fresh:false root) in + let tree = S.Tree.singleton [ "a" ] "x" in + let* c1 = S.Commit.v rw ~parents:[] ~info:(info ()) tree in + S.reload ro; + check ro c1 "a" "x" >>= fun () -> + let tree = S.Tree.singleton [ "a" ] "y" in + let* c2 = S.Commit.v rw ~parents:[] ~info:(info ()) tree in + check ro c1 "a" "x" >>= fun () -> + let* () = + S.Commit.of_hash ro (S.Commit.hash c2) >|= function + | None -> () + | Some _ -> Alcotest.failf "should not find branch by" + in + S.reload ro; + check ro c2 "a" "y" >>= fun () -> + S.Repo.close ro >>= fun () -> S.Repo.close rw + +let ro_reload_after_close () = + let binding f = f [ "a" ] "x" in + rm_dir root; + let* rw = S.Repo.v (config ~readonly:false ~fresh:true root) in + let* ro = S.Repo.v (config ~readonly:true ~fresh:false root) in + let tree = binding (S.Tree.singleton ?metadata:None) in + let* c1 = S.Commit.v rw ~parents:[] ~info:(info ()) tree in + S.Repo.close rw >>= fun () -> + S.reload ro; + binding (check_binding ro c1) >>= fun () -> S.Repo.close ro + +let ro_batch () = + let* rw = S.Repo.v (config ~readonly:false ~fresh:true root) in + let* ro = S.Repo.v (config ~readonly:true ~fresh:false root) in + Alcotest.check_raises_lwt "Read-only store throws RO_not_allowed exception" + Irmin_pack_unix.Errors.RO_not_allowed (fun () -> + S.Backend.Repo.batch ro (fun _ _ _ -> Lwt.return_unit)) + >>= fun () -> + S.Repo.close ro >>= fun () -> S.Repo.close rw + +let tests = + let tc name test = Alcotest_lwt.test_case name `Quick (fun _switch -> test) in + [ + tc "Test open ro after rw closed" open_ro_after_rw_closed; + tc "Test ro reload after add" ro_reload_after_add; + tc "Test ro reload after close" ro_reload_after_close; + tc "Test ro batch" ro_batch; + ] diff --git a/vendors/irmin/test/irmin-pack/test_readonly.mli b/vendors/irmin/test/irmin-pack/test_readonly.mli new file mode 100644 index 000000000000..4acc26805b83 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_readonly.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val tests : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin-pack/test_snapshot.ml b/vendors/irmin/test/irmin-pack/test_snapshot.ml new file mode 100644 index 000000000000..5d2517bafdc6 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_snapshot.ml @@ -0,0 +1,311 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let root_export = Filename.concat "_build" "test-snapshot-export" +let root_import = Filename.concat "_build" "test-snapshot-import" +let src = Logs.Src.create "tests.snapshot" ~doc:"Tests" + +module Log = (val Logs.src_log src : Logs.LOG) + +module S = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) +end + +let check_key = Alcotest.check_repr Key.t + +let config ?(readonly = false) ?(fresh = true) ~indexing_strategy root = + Irmin_pack.config ~readonly ?index_log_size ~fresh ~indexing_strategy root + +let info = S.Info.empty + +let read_string rbuf ~len = + let buf, ofs = !rbuf in + if String.length buf - ofs < len then failwith "small buffer" + else + let res = String.sub buf ofs len in + rbuf := (buf, ofs + len); + res + +let set_int8 buf i = + let b = Bytes.create 1 in + Bytes.set_int8 b 0 i; + Buffer.add_bytes buf b + +let get_int8 rbuf = + let string = read_string ~len:1 rbuf in + Bytes.get_int8 (Bytes.of_string string) 0 + +let read_mbytes rbuf b = + let string = read_string rbuf ~len:(Bytes.length b) in + Bytes.blit_string string 0 b 0 (Bytes.length b) + +let encode_bin_snapshot = Irmin.Type.(unstage (encode_bin S.Snapshot.t)) +let decode_bin_snapshot = Irmin.Type.(unstage (decode_bin S.Snapshot.t)) + +let encode_with_size buf snapshot_inode = + let size = ref 0 in + let tmp = Buffer.create 0 in + encode_bin_snapshot snapshot_inode (fun x -> + size := !size + String.length x; + Buffer.add_string tmp x); + set_int8 buf !size; + Buffer.add_buffer buf tmp; + Lwt.return_unit + +let decode_with_size rbuf = + let size = get_int8 rbuf in + let b = Bytes.create size in + let () = read_mbytes rbuf b in + let b = Bytes.to_string b in + decode_bin_snapshot b (ref 0) + +let restore repo ?on_disk buf = + let on_disk = (on_disk :> [ `Path of string | `Reuse ] option) in + let snapshot = S.Snapshot.Import.v ?on_disk repo in + let total = String.length buf in + let total_visited = ref 0 in + let rbuf = ref (buf, 0) in + let rec aux last_key = + let _, read = !rbuf in + if read < total then ( + incr total_visited; + let elt = decode_with_size rbuf in + let* key = S.Snapshot.Import.save_elt snapshot elt in + aux (Some key)) + else Lwt.return (!total_visited, last_key) + in + let* result = aux None in + S.Snapshot.Import.close snapshot repo; + Lwt.return result + +let test ~repo_export ~repo_import ?on_disk tree expected_visited = + let* commit = S.Commit.v repo_export ~parents:[] ~info tree in + let tree = S.Commit.tree commit in + let root_key = S.Tree.key tree |> Option.get in + let buf = Buffer.create 0 in + let* total_visited = + S.Snapshot.export ?on_disk repo_export (encode_with_size buf) ~root_key + in + Alcotest.(check int) + "total visited during export" expected_visited total_visited; + let* total_visited, key = + Buffer.contents buf |> restore repo_import ?on_disk + in + Alcotest.(check int) + "total visited during import" expected_visited total_visited; + let () = + match (root_key, key) with + | _, None -> Alcotest.fail "No key imported" + | `Node key, Some key' -> check_key "snapshot key" key key' + | `Contents _, _ -> Alcotest.fail "Root key should not be contents" + in + Lwt.return_unit + +let tree2 () = + let t = S.Tree.singleton [ "a" ] "x" in + let* t = S.Tree.add t [ "b" ] "y" in + let* t = S.Tree.add t [ "c" ] "y" in + S.Tree.add t [ "d" ] "y" + +let test_in_memory ~indexing_strategy () = + rm_dir root_export; + rm_dir root_import; + let* repo_export = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_export) + in + let* repo_import = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_import) + in + let test = test ~repo_export ~repo_import in + let tree1 = S.Tree.singleton [ "a" ] "x" in + let* () = test tree1 2 in + let* tree2 = tree2 () in + let* () = test tree2 3 in + let* () = S.Repo.close repo_export in + S.Repo.close repo_import + +let test_in_memory_minimal = + test_in_memory ~indexing_strategy:Irmin_pack.Indexing_strategy.minimal + +let test_in_memory_always = + test_in_memory ~indexing_strategy:Irmin_pack.Indexing_strategy.always + +let test_on_disk ~indexing_strategy () = + rm_dir root_export; + rm_dir root_import; + let index_on_disk = Filename.concat root_import "index_on_disk" in + let* repo_export = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_export) + in + let* repo_import = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_import) + in + let test = test ~repo_export ~repo_import in + let* tree2 = tree2 () in + let* () = test ~on_disk:(`Path index_on_disk) tree2 3 in + let* () = S.Repo.close repo_export in + S.Repo.close repo_import + +let test_on_disk_minimal = + test_on_disk ~indexing_strategy:Irmin_pack.Indexing_strategy.minimal + +let test_on_disk_always = + test_on_disk ~indexing_strategy:Irmin_pack.Indexing_strategy.always + +let start_gc repo commit = + let commit_key = S.Commit.key commit in + let* launched = S.Gc.start_exn ~unlink:false repo commit_key in + assert launched; + Lwt.return_unit + +let finalise_gc repo = + let* result = S.Gc.finalise_exn ~wait:true repo in + match result with + | `Idle | `Running -> Alcotest.fail "expected finalised gc" + | `Finalised _ -> Lwt.return_unit + +let test_gc ~repo_export ~repo_import ?on_disk expected_visited = + (* create the store *) + let* tree1 = + let t = S.Tree.singleton [ "b"; "a" ] "x0" in + S.Tree.add t [ "a"; "b" ] "x1" + in + let* c1 = S.Commit.v repo_export ~parents:[] ~info tree1 in + let k1 = S.Commit.key c1 in + let* tree2 = S.Tree.add tree1 [ "a"; "c" ] "x2" in + let* _ = S.Commit.v repo_export ~parents:[ k1 ] ~info tree2 in + let* tree3 = + let* t = S.Tree.remove tree1 [ "a"; "b" ] in + S.Tree.add t [ "a"; "d" ] "x3" + in + let* c3 = S.Commit.v repo_export ~parents:[ k1 ] ~info tree3 in + (* call gc on last commit *) + let* () = start_gc repo_export c3 in + let* () = finalise_gc repo_export in + let tree = S.Commit.tree c3 in + let root_key = S.Tree.key tree |> Option.get in + let buf = Buffer.create 0 in + let* total_visited = + S.Snapshot.export ?on_disk repo_export (encode_with_size buf) ~root_key + in + Alcotest.(check int) + "total visited during export" expected_visited total_visited; + let* total_visited, key = + Buffer.contents buf |> restore repo_import ?on_disk + in + Alcotest.(check int) + "total visited during import" expected_visited total_visited; + let () = + match (root_key, key) with + | _, None -> Alcotest.fail "No key imported" + | `Node key, Some key' -> check_key "snapshot key" key key' + | `Contents _, _ -> Alcotest.fail "Root key should not be contents" + in + Lwt.return_unit + +let indexing_strategy = Irmin_pack.Indexing_strategy.minimal + +let test_gced_store_in_memory () = + rm_dir root_export; + rm_dir root_import; + let* repo_export = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_export) + in + let* repo_import = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_import) + in + let* () = test_gc ~repo_export ~repo_import 5 in + let* () = S.Repo.close repo_export in + S.Repo.close repo_import + +let test_gced_store_on_disk () = + rm_dir root_export; + rm_dir root_import; + let index_on_disk = Filename.concat root_import "index_on_disk" in + let* repo_export = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_export) + in + let* repo_import = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_import) + in + let* () = + test_gc ~repo_export ~repo_import ~on_disk:(`Path index_on_disk) 5 + in + let* () = S.Repo.close repo_export in + S.Repo.close repo_import + +let test_export_import_reexport () = + rm_dir root_export; + rm_dir root_import; + (* export a snapshot. *) + let* repo_export = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_export) + in + let tree = S.Tree.singleton [ "a" ] "y" in + let* parent_commit = S.Commit.v repo_export ~parents:[] ~info tree in + let parent_key = + Irmin_pack_unix.Pack_key.v_indexed (S.Commit.hash parent_commit) + in + let tree = S.Tree.singleton [ "a" ] "x" in + let* _ = S.Commit.v repo_export ~parents:[ parent_key ] ~info tree in + let root_key = S.Tree.key tree |> Option.get in + let buf = Buffer.create 0 in + let* _ = S.Snapshot.export repo_export (encode_with_size buf) ~root_key in + let* () = S.Repo.close repo_export in + (* buf contains the snapshot, we can rm root_export and import the snapshot in + a new store, with the key parent of type Indexed. *) + rm_dir root_export; + let* repo_import = + S.Repo.v (config ~readonly:false ~fresh:true ~indexing_strategy root_import) + in + let* _, key = Buffer.contents buf |> restore repo_import in + let key = Option.get key in + let* tree = S.Tree.of_key repo_import (`Node key) in + let tree = Option.get tree in + let* commit = S.Commit.v repo_import ~info ~parents:[ parent_key ] tree in + let commit_key = S.Commit.key commit in + let commit_hash = S.Commit.hash commit in + (* export the gc-based snapshot in a clean root_export. *) + let* () = S.create_one_commit_store repo_import commit_key root_export in + let* () = S.Repo.close repo_import in + (* open the new store and check that everything is readable. *) + let* repo_export = + S.Repo.v + (config ~readonly:false ~fresh:false ~indexing_strategy root_export) + in + let* commit = S.Commit.of_hash repo_export commit_hash in + let commit = Option.get commit in + let tree = S.Commit.tree commit in + let* got = S.Tree.find tree [ "a" ] in + Alcotest.(check (option string)) "find blob" (Some "x") got; + S.Repo.close repo_export + +let tests = + let tc name f = Alcotest_lwt.test_case name `Quick (fun _switch () -> f ()) in + [ + tc "in memory minimal" test_in_memory_minimal; + tc "in memory always" test_in_memory_always; + tc "on disk minimal" test_on_disk_minimal; + tc "on disk always" test_on_disk_always; + tc "gced store, in memory" test_gced_store_in_memory; + tc "gced store, on disk" test_gced_store_on_disk; + tc "import old snapshot, export gc based snapshot " + test_export_import_reexport; + ] diff --git a/vendors/irmin/test/irmin-pack/test_tree.ml b/vendors/irmin/test/irmin-pack/test_tree.ml new file mode 100644 index 000000000000..42ecbf3d93f1 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_tree.ml @@ -0,0 +1,721 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let root = Filename.concat "_build" "test-tree" +let src = Logs.Src.create "tests.tree" ~doc:"Tests" + +module Log = (val Logs.src_log src : Logs.LOG) +module Hash = Irmin.Hash.SHA1 + +type ('key, 'value) op = + | Add of 'key * 'value + | Del of 'key + | Find of 'key + | Find_tree of 'key + +module Make (Conf : Irmin_pack.Conf.S) = struct + module Store = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) + end + + let config ?(readonly = false) ?(fresh = true) root = + Irmin_pack.config ~readonly ?index_log_size ~fresh root + + let info () = Store.Info.empty + + module Tree = Store.Tree + + type context = { repo : Store.repo; tree : Store.tree } + + let export_tree_to_store tree = + let* repo = Store.Repo.v (config ~fresh:true root) in + let* store = Store.empty repo in + let* () = Store.set_tree_exn ~info store [] tree in + let+ tree = Store.tree store in + { repo; tree } + + let close { repo; _ } = Store.Repo.close repo + + let fold ~order t ~init ~f = + Tree.fold ~order ~force:`True ~cache:false ~uniq:`False + ~contents:(fun k _v acc -> if k = [] then Lwt.return acc else f k acc) + t init + + let init_bindings n = + let zero = String.make 10 '0' in + List.init n (fun n -> + let h = Store.Contents.hash (string_of_int n) in + let h = Irmin.Type.to_string Store.Hash.t h in + ([ h ], zero)) + + let init_tree bindings = + let tree = Tree.empty () in + let* tree = + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree bindings + in + export_tree_to_store tree + + let find_tree tree k = + let+ t = Tree.find_tree tree k in + match t with None -> tree | Some t -> t + + let find tree k = + let+ _ = Tree.find tree k in + tree + + let run_one tree = function + | Add (k, v) -> Tree.add tree k v + | Del k -> Tree.remove tree k + | Find k -> find tree k + | Find_tree k -> find_tree tree k + + let run ops tree = + let run_one op = + let* _ = run_one tree op in + Lwt.return_unit + in + let+ () = Lwt_list.iter_s run_one ops in + (tree, ()) + + let proof_of_ops repo hash ops : _ Lwt.t = + let+ t, () = Store.Tree.produce_proof repo hash (run ops) in + t + + let stream_of_ops repo hash ops : _ Lwt.t = + let+ t, () = Store.Tree.produce_stream repo hash (run ops) in + t + + let tree_proof_t = Tree.Proof.t Tree.Proof.tree_t + let stream_proof_t = Tree.Proof.t Tree.Proof.stream_t + let bin_of_proof = Irmin.Type.(unstage (to_bin_string tree_proof_t)) + let proof_of_bin = Irmin.Type.(unstage (of_bin_string tree_proof_t)) + let bin_of_stream = Irmin.Type.(unstage (to_bin_string stream_proof_t)) +end + +module Default = Make (Conf) +open Default + +type bindings = string list list [@@deriving irmin] + +let equal_ordered_slist ~msg l1 l2 = Alcotest.check_repr bindings_t msg l1 l2 + +let fold ~order ~force t ~init ~f = + Tree.fold ~order ~force ~cache:false ~uniq:`False + ~contents:(fun k _v acc -> if k = [] then Lwt.return acc else f k acc) + t init + +let equal_slist ~msg l1 l2 = + Alcotest.(check (slist (list string) Stdlib.compare)) msg l1 l2 + +let steps = + ["00"; "01"; "02"; "03"; "05"; "06"; "07"; "09"; "0a"; "0b"; "0c"; + "0e"; "0f"; "10"; "11"; "12"; "13"; "14"; "15"; "16"; "17"; "19"; + "1a"; "1b"; "1c"; "1d"; "1e"; "1f"; "20"; "22"; "23"; "25"; "26"; + "27"; "28"; "2a"; "2b"; "2f"; "30"; "31"; "32"; "33"; "35"; "36"; + "37"; "3a"; "3b"; "3c"; "3d"; "3e"; "3f"; "40"; "42"; "43"; "45"; + "46"; "47"; "48"; "4a"; "4b"; "4c"; "4e"; "4f"; "50"; "52"; "53"; + "54"; "55"; "56"; "57"; "59"; "5b"; "5c"; "5f"; "60"; "61"; "62"; + "63"; "64"; "65"; "66"; "67"; "69"; "6b"; "6c"; "6d"; "6e"; "6f"; + "71"; "72"; "73"; "74"; "75"; "78"; "79"; "7a"; "7b"; "7c"; "7d"; + "7e"; "80"; "82"; "83"; "84"; "85"; "86"; "88"; "8b"; "8c"; "8d"; + "8f"; "92"; "93"; "94"; "96"; "97"; "99"; "9a"; "9b"; "9d"; "9e"; + "9f"; "a0"; "a1"; "a2"; "a3"; "a4"; "a5"; "a6"; "a7"; "a8"; "aa"; + "ab"; "ac"; "ad"; "ae"; "af"; "b0"; "b1"; "b2"; "b3"; "b4"; "b6"; + "b8"; "b9"; "bb"; "bc"; "bf"; "c0"; "c1"; "c2"; "c3"; "c4"; "c5"; + "c8"; "c9"; "cb"; "cc"; "cd"; "ce"; "d0"; "d1"; "d2"; "d4"; "d5"; + "d7"; "d8"; "d9"; "da"; "e0"; "e3"; "e6"; "e8"; "e9"; "ea"; "ec"; + "ee"; "ef"; "f0"; "f1"; "f5"; "f7"; "f8"; "f9"; "fb"; "fc"; "fd"; + "fe"; "ff"; "g0"; "g1"; "g2"; "g3"; "g4"; "g5"; "g6"; "g7"; "g8"; + "h0"; "h1"; "h2"; "h3"; "h4"; "h5"; "h6"; "h7"; "h8"; "h9"; "ha"; + "i0"; "i1"; "i2"; "i3"; "i4"; "i5"; "i6"; "i7"; "i8"; "i9"; "ia"; + "j0"; "j1"; "j2"; "j3"; "j4"; "j5"; "j6"; "j7"; "j8"; "j9"; "ja"; + "k0"; "k1"; "k2"; "k3"; "k4"; "k5"; "k6"; "k7"; "k8"; "k9"; "ka"; + "l0"; "l1"; "l2"; "l3"; "l4"; "l5"; "l6"; "l7"; "l8"; "l9"; "la"; + "m0"; "m1"; "m2"; "m3"; "m4"; "m5"; "m6"; "m7"; "m8"; "m9"; "ma"; + "n0"; "n1"; "n2"; "n3"; "n4"; "n5"; "n6"; "n7"; "n8"; "n9"; "na"; + "p0"; "p1"; "p2"; "p3"; "p4"; "p5"; "p6"; "p7"; "p8"; "p9"; "pa"; + "q0"; "q1"; "q2"; "q3"; "q4"; "q5"; "q6"; "q7"; "q8"; "q9"; "qa"; + "r0"; "r1"; "r2"; "r3"; "r4"; "r5"; "r6"; "r7"; "r8"; "r9"; "ra";] +[@@ocamlformat "disable"] + +let version = + let version = Sys.ocaml_version in + Char.code version.[0] - 48 + +let some_steps = [ "0g"; "1g"; "0h"; "2g"; "1h"; "2h" ] + +let some_random_steps = + if version >= 5 then + [ [ "1g" ]; [ "0h" ]; [ "2h" ]; [ "1h" ]; [ "2g" ]; [ "0g" ] ] + else [ [ "2g" ]; [ "1h" ]; [ "0h" ]; [ "2h" ]; [ "0g" ]; [ "1g" ] ] + +let another_random_steps = + if version >= 5 then + [ [ "0g" ]; [ "0h" ]; [ "1h" ]; [ "2h" ]; [ "2g" ]; [ "1g" ] ] + else [ [ "1g" ]; [ "2h" ]; [ "1h" ]; [ "0g" ]; [ "0h" ]; [ "2g" ] ] + +let zero = String.make 10 '0' +let bindings steps = List.map (fun x -> ([ x ], zero)) steps + +let test_fold ?export_tree_to_store:(export_tree_to_store' = true) ~order + bindings expected = + let tree = Tree.empty () in + let* tree = + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree bindings + in + let* close = + match export_tree_to_store' with + | true -> + let+ ctxt = export_tree_to_store tree in + fun () -> close ctxt + | false -> Lwt.return Lwt.return + in + let* keys = + fold + ~force: + (if export_tree_to_store' then `True else `False (Fun.const Lwt.return)) + ~order tree ~init:[] + ~f:(fun k acc -> Lwt.return (k :: acc)) + in + let keys = List.rev keys in + let msg, equal_lists = + match order with + | `Sorted -> ("sorted", equal_ordered_slist) + | `Random _ -> ("random", equal_ordered_slist) + | `Undefined -> ("undefined", equal_slist) + in + equal_lists ~msg:(Fmt.str "Visit elements in %s order" msg) expected keys; + close () + +let test_fold_sorted () = + let bindings = bindings steps in + let expected = List.map fst bindings in + test_fold ~order:`Sorted bindings expected + +let test_fold_random () = + let bindings = bindings some_steps in + let state = Random.State.make [| 0 |] in + let* () = test_fold ~order:(`Random state) bindings some_random_steps in + let state = Random.State.make [| 1 |] in + let* () = test_fold ~order:(`Random state) bindings another_random_steps in + + (* Random fold order should still be respected if [~force:`False]. This is a + regression test for a bug in which the fold order of in-memory nodes during + a non-forcing traversal was always sorted. *) + let state = Random.State.make [| 1 |] in + let* () = + test_fold ~order:(`Random state) ~export_tree_to_store:false bindings + another_random_steps + in + + Lwt.return_unit + +let test_fold_undefined () = + let bindings = bindings steps in + let expected = List.map fst bindings in + test_fold ~order:`Undefined bindings expected + +let proof_of_bin s = + match proof_of_bin s with Ok s -> s | Error (`Msg e) -> Alcotest.fail e + +let check_equivalence tree proof op = + match op with + | Add (k, v) -> + let* tree = Tree.add tree k v in + let+ proof = Tree.add proof k v in + Alcotest.(check_repr Store.Hash.t) + (Fmt.str "same hash add %a" Fmt.(Dump.list string) k) + (Tree.hash tree) (Tree.hash proof); + (tree, proof) + | Del k -> + let* tree = Tree.remove tree k in + let+ proof = Tree.remove proof k in + Alcotest.(check_repr Store.Hash.t) + (Fmt.str "same hash del %a" Fmt.(Dump.list string) k) + (Tree.hash tree) (Tree.hash proof); + (tree, proof) + | Find k -> + let* v_tree = Tree.find tree k in + let+ v_proof = Tree.find proof k in + Alcotest.(check (option string)) + (Fmt.str "same value at %a" Fmt.(Dump.list string) k) + v_tree v_proof; + (tree, proof) + | Find_tree k -> + let* v_tree = Tree.find_tree tree k in + let+ v_proof = Tree.find_tree tree k in + Alcotest.(check_repr [%typ: Store.tree option]) + (Fmt.str "same tree at %a" Fmt.(Dump.list string) k) + v_tree v_proof; + (tree, proof) + +let test_proofs ctxt ops = + let tree = ctxt.tree in + let key = + match Tree.key tree with Some (`Node h) -> h | _ -> assert false + in + let hash = Tree.hash tree in + + (* Create a compressed parital Merle proof for ops *) + let* proof = proof_of_ops ctxt.repo (`Node key) ops in + + (* test encoding *) + let enc = bin_of_proof proof in + let dec = proof_of_bin enc in + Alcotest.(check_repr tree_proof_t) "same proof" proof dec; + + (* test equivalence *) + let tree_proof = Tree.Proof.to_tree proof in + + Alcotest.(check_repr Store.Hash.t) + "same initial hash" hash (Tree.hash tree_proof); + + let* _ = + Lwt_list.fold_left_s + (fun (tree, proof) op -> check_equivalence tree proof op) + (tree, tree_proof) + [ + Add ([ "00" ], "0"); + Add ([ "00" ], "1"); + Del [ "00" ]; + Find [ "00" ]; + Add ([ "00" ], "0"); + Add ([ "00" ], "1"); + Find [ "00" ]; + Find_tree [ "01" ]; + Find_tree [ "z"; "o"; "o" ]; + ] + in + Lwt.return_unit + +let test_large_inode () = + let bindings = bindings steps in + let* ctxt = init_tree bindings in + let ops = [ Add ([ "00" ], "3"); Del [ "01" ] ] in + test_proofs ctxt ops + +let fewer_steps = +["00"; "01"; "02"; "03"; "05"; "06"; "07"; "09"; "0a"; "0b"; "0c"; +"0e"; "0f"; "10"; "11"; "12"; "13"; "14"; "15"; "16"; "17"; "19"; +"1a"; "1b"; "1c"; "1d"; "1e"; "1f"; "20"; "22"; "23"; "25"; "26"; +"27"; "28"; "2a"; ][@@ocamlformat "disable"] + +let test_small_inode () = + let bindings = bindings fewer_steps in + let* ctxt = init_tree bindings in + let ops = [ Add ([ "00" ], ""); Del [ "01" ] ] in + test_proofs ctxt ops + +let test_deeper_proof () = + let* ctxt = + let tree = Tree.empty () in + let* level_one = + let bindings = bindings fewer_steps in + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree bindings + in + let* level_two = + let* tree = Tree.add_tree tree [ "0g" ] level_one in + let bindings = bindings steps in + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree bindings + in + let* level_three = + let* tree = Tree.add_tree tree [ "1g" ] level_two in + let bindings = bindings fewer_steps in + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree bindings + in + export_tree_to_store level_three + in + let ops = + [ + Find [ "1g"; "0g"; "00" ]; + Del [ "1g"; "0g"; "01" ]; + Find [ "02" ]; + Find_tree [ "1g"; "02" ]; + ] + in + test_proofs ctxt ops + +module Binary = Make (struct + let entries = 2 + let stable_hash = 2 + let inode_child_order = `Hash_bits + let contents_length_header = Some `Varint + let forbid_empty_dir_persistence = false +end) + +(* test large compressed proofs *) +let test_large_proofs () = + (* Build a proof on a large store (branching factor = 32) *) + let bindings = init_bindings 100_000 in + let ops n = + bindings + |> List.to_seq + |> Seq.take n + |> Seq.map (fun (s, _) -> Find_tree s) + |> List.of_seq + in + + let compare_proofs n = + let ops = ops n in + let* ctxt = init_tree bindings in + let key = + match Tree.key ctxt.tree with Some (`Node k) -> k | _ -> assert false + in + let* proof = proof_of_ops ctxt.repo (`Node key) ops in + let enc_32 = bin_of_proof proof in + let* () = close ctxt in + + (* Build a stream proof *) + let* ctxt = init_tree bindings in + let key = + match Tree.key ctxt.tree with Some (`Node k) -> k | _ -> assert false + in + let* proof = stream_of_ops ctxt.repo (`Node key) ops in + let s_enc_32 = bin_of_stream proof in + let* () = close ctxt in + + (* Build a proof on a large store (branching factor = 2) *) + let* ctxt = Binary.init_tree bindings in + let key = + match Binary.Store.Tree.key ctxt.tree with + | Some (`Node k) -> k + | _ -> assert false + in + let* proof = Binary.proof_of_ops ctxt.repo (`Node key) ops in + let enc_2 = Binary.bin_of_proof proof in + let* () = Binary.close ctxt in + + (* Build a stream proof *) + let* ctxt = Binary.init_tree bindings in + let key = + match Binary.Store.Tree.key ctxt.tree with + | Some (`Node k) -> k + | _ -> assert false + in + let* proof = Binary.stream_of_ops ctxt.repo (`Node key) ops in + let s_enc_2 = Binary.bin_of_stream proof in + let* () = Binary.close ctxt in + + Lwt.return + ( n, + String.length enc_32 / 1024, + String.length s_enc_32 / 1024, + String.length enc_2 / 1024, + String.length s_enc_2 / 1024 ) + in + let* a = compare_proofs 1 in + let* b = compare_proofs 100 in + let* c = compare_proofs 1_000 in + let+ d = compare_proofs 10_000 in + List.iter + (fun (n, k32, sk32, k2, sk2) -> + Fmt.pr "Size of Merkle proof for %d operations:\n" n; + Fmt.pr "- Merkle B-trees (32 children) : %dkB\n%!" k32; + Fmt.pr "- stream Merkle B-trees (32 children): %dkB\n%!" sk32; + Fmt.pr "- binary Merkle trees : %dkB\n%!" k2; + Fmt.pr "- stream binary Merkle trees : %dkB\n%!" sk2) + [ a; b; c; d ] + +module Custom = Make (struct + let entries = 2 + let stable_hash = 2 + + let index ~depth step = + let ascii_code = Bytes.get step depth |> Char.code in + ascii_code - 48 + + let inode_child_order = `Custom index + let contents_length_header = Some `Varint + let forbid_empty_dir_persistence = false +end) + +module P = Custom.Tree.Proof + +let pp_proof = Irmin.Type.pp (P.t P.tree_t) +let pp_stream = Irmin.Type.pp (P.t P.stream_t) + +let check_hash h s = + let s' = Irmin.Type.(to_string Hash.t) h in + Alcotest.(check string) "check hash" s s' + +let check_contents_hash h s = + match h with + | `Node _ -> Alcotest.failf "Expected kinded hash to be contents" + | `Contents (h, ()) -> + let s' = Irmin.Type.(to_string Hash.t) h in + Alcotest.(check string) "check hash" s s' + +let test_extenders () = + let bindings = + [ ([ "00000" ], "x"); ([ "00001" ], "y"); ([ "00010" ], "z") ] + in + let bindings2 = ([ "10000" ], "x1") :: bindings in + let bindings3 = ([ "10001" ], "y") :: bindings2 in + + let f t = + let+ v = Custom.Tree.get t [ "00000" ] in + Alcotest.(check string) "00000" "x" v; + (t, ()) + in + + let check_proof bindings = + let* ctxt = Custom.init_tree bindings in + let key = Custom.Tree.key ctxt.tree |> Option.get in + let* p, () = Custom.Tree.produce_proof ctxt.repo key f in + [%log.debug "Verifying proof %a" pp_proof p]; + let+ r = Custom.Tree.verify_proof p f in + match r with + | Ok (_, ()) -> () + | Error e -> + Alcotest.failf "check_proof: %a" + (Irmin.Type.pp Custom.Tree.verifier_error_t) + e + in + let* () = Lwt_list.iter_s check_proof [ bindings; bindings2; bindings3 ] in + + let check_stream bindings = + let* ctxt = Custom.init_tree bindings in + let key = Custom.Tree.key ctxt.tree |> Option.get in + let* p, () = Custom.Tree.produce_stream ctxt.repo key f in + [%log.debug "Verifying stream %a" pp_stream p]; + let+ r = Custom.Tree.verify_stream p f in + match r with + | Ok (_, ()) -> () + | Error e -> + Alcotest.failf "check_stream: %a" + (Irmin.Type.pp Custom.Tree.verifier_error_t) + e + in + Lwt_list.iter_s check_stream [ bindings; bindings2; bindings3 ] + +let test_hardcoded_stream () = + let bindings = + [ ([ "00100" ], "x"); ([ "00101" ], "y"); ([ "00110" ], "z") ] + in + let fail elt = + Alcotest.failf "Unexpected elt in stream %a" (Irmin.Type.pp P.elt_t) elt + in + let* ctxt = Custom.init_tree bindings in + let key = Custom.Tree.key ctxt.tree |> Option.get in + let f t = + let path = [ "00100" ] in + let+ v = Custom.Tree.get t path in + Alcotest.(check ~pos:__POS__ string) "" (List.assoc path bindings) v; + (t, ()) + in + let* p, () = Custom.Tree.produce_stream ctxt.repo key f in + let state = P.state p in + let counter = ref 0 in + Seq.iter + (fun elt -> + (match !counter with + | 0 -> ( + match elt with + | P.Inode_extender { length; segments = [ 0; 0; 1 ]; proof = h } + when length = 3 -> + check_hash h "25c1a3d3bb7e5124cf61954851d0c9ccf5113d4e" + | _ -> fail elt) + | 1 -> ( + match elt with + | P.Inode { length; proofs = [ (0, h1); (1, h0) ] } when length = 3 -> + check_hash h0 "8410f4d1be1d571f0d63638927d42c7c1c6f3df1"; + check_hash h1 "580c8955c438ca5b1f94d2f4eb712a85e2634b70" + | _ -> fail elt) + | 2 -> ( + match elt with + | P.Node [ ("00100", h0); ("00101", h1) ] -> + check_contents_hash h0 "11f6ad8ec52a2984abaafd7c3b516503785c2072"; + check_contents_hash h1 "95cb0bfd2977c761298d9624e4b4d4c72a39974a" + | _ -> fail elt) + | 3 -> ( match elt with P.Contents "x" -> () | _ -> fail elt) + | _ -> fail elt); + incr counter) + state; + if !counter <> 4 then Alcotest.fail "Not enough elements in the stream"; + Lwt.return_unit + +let test_hardcoded_proof () = + let bindings = + [ ([ "00000" ], "x"); ([ "00001" ], "y"); ([ "00010" ], "z") ] + in + let fail_with_tree elt = + Alcotest.failf "Unexpected elt in proof %a" (Irmin.Type.pp P.tree_t) elt + in + let fail_with_inode_tree elt = + Alcotest.failf "Unexpected elt in proof %a" + (Irmin.Type.pp P.inode_tree_t) + elt + in + let* ctxt = Custom.init_tree bindings in + let key = Custom.Tree.key ctxt.tree |> Option.get in + let f t = + let+ v = Custom.Tree.get t [ "00000" ] in + Alcotest.(check string) "00000" "x" v; + (t, ()) + in + let* p, () = Custom.Tree.produce_proof ctxt.repo key f in + let state = P.state p in + + let check_depth_2 = function + | P.Inode_values + [ ("00000", Contents ("x", ())); ("00001", Blinded_contents (h1, ())) ] + -> + check_hash h1 "95cb0bfd2977c761298d9624e4b4d4c72a39974a" + | t -> fail_with_inode_tree t + in + let check_depth_1 = function + | P.Inode_tree { length = 3; proofs = [ (0, t); (1, P.Blinded_inode h1) ] } + -> + check_hash h1 "4295267989ab4c4a036eb78f0610a57042e2b49f"; + check_depth_2 t + | t -> fail_with_inode_tree t + in + let () = + match (state : P.tree) with + | P.Extender { length = 3; segments = [ 0; 0; 0 ]; proof = t } -> + check_depth_1 t + | _ -> fail_with_tree state + in + Lwt.return_unit + +let tree_of_list ls = + let tree = Tree.empty () in + Lwt_list.fold_left_s (fun tree (k, v) -> Tree.add tree k v) tree ls + +let test_proof_exn _ = + let x = "x" in + let y = "y" in + let hx = Store.Contents.hash x in + let hy = Store.Contents.hash y in + let stream_elt1 : P.elt = Contents y in + let stream_elt2 : P.elt = Contents x in + let stream_elt3 : P.elt = + Node [ ("bx", `Contents (hx, ())); ("by", `Contents (hy, ())) ] + in + let* tree = tree_of_list [ ([ "bx" ], "x"); ([ "by" ], "y") ] in + let hash = Tree.hash tree in + + let stream_all = + P.v ~before:(`Node hash) ~after:(`Node hash) + (List.to_seq [ stream_elt3; stream_elt2; stream_elt1 ]) + in + let stream_short = + P.v ~before:(`Node hash) ~after:(`Node hash) + (List.to_seq [ stream_elt3; stream_elt2 ]) + in + let f_all t = + let* _ = Custom.Tree.find t [ "bx" ] in + let+ _ = Custom.Tree.find t [ "by" ] in + (t, ()) + in + let f_short t = + let+ _ = Custom.Tree.find t [ "bx" ] in + (t, ()) + in + (* Test the Stream_too_long error. *) + let* r = Custom.Tree.verify_stream stream_all f_short in + let* () = + match r with + | Error (`Stream_too_long _) -> Lwt.return_unit + | _ -> Alcotest.fail "expected Stream_too_long error" + in + (* Test the Stream_too_short error. *) + let* r = Custom.Tree.verify_stream stream_short f_all in + let* () = + match r with + | Error (`Stream_too_short _) -> Lwt.return_unit + | _ -> Alcotest.fail "expected Stream_too_short error" + in + (* Test the correct usecase. *) + let* r = Custom.Tree.verify_stream stream_all f_all in + let* () = + match r with + | Ok (_, ()) -> Lwt.return_unit + | Error e -> ( + match e with + | `Proof_mismatch str -> + Alcotest.failf "unexpected Proof_mismatch error: %s" str + | `Stream_too_long str -> + Alcotest.failf "unexpected Stream_too_long error: %s" str + | `Stream_too_short str -> + Alcotest.failf "unexpected Stream_too_short error: %s" str) + in + Lwt.return_unit + +let test_reexport_node () = + let* tree = Store.Tree.add (Store.Tree.empty ()) [ "foo"; "a" ] "a" in + let* repo1 = Store.Repo.v (config ~fresh:true root) in + let* _ = + Store.Backend.Repo.batch repo1 (fun c n _ -> Store.save_tree repo1 c n tree) + in + let* () = Store.Repo.close repo1 in + (* Re-export the same tree using a different repo. *) + let* repo2 = Store.Repo.v (config ~fresh:false root) in + let* _ = + Alcotest.check_raises_lwt "re-export tree from another repo" + (Failure "Can't export the node key from another repo") (fun () -> + Store.Backend.Repo.batch repo2 (fun c n _ -> + Store.save_tree repo2 c n tree)) + in + let* () = Store.Repo.close repo2 in + (* Re-export a fresh tree using a different repo. *) + let* repo2 = Store.Repo.v (config ~fresh:false root) in + let* tree = Store.Tree.add (Store.Tree.empty ()) [ "foo"; "a" ] "a" in + let _ = Store.Tree.hash tree in + let* c1 = Store.Tree.get_tree tree [ "foo" ] in + let* _ = + Store.Backend.Repo.batch repo2 (fun c n _ -> Store.save_tree repo2 c n c1) + in + let* () = + match Store.Tree.destruct c1 with + | `Contents _ -> Alcotest.fail "got `Contents, expected `Node" + | `Node node -> + let* _v = Store.to_backend_node node in + Lwt.return_unit + in + Store.Repo.close repo2 + +let tests = + [ + Alcotest_lwt.test_case "fold over keys in sorted order" `Quick + (fun _switch -> test_fold_sorted); + Alcotest_lwt.test_case "fold over keys in random order" `Quick + (fun _switch -> test_fold_random); + Alcotest_lwt.test_case "fold over keys in undefined order" `Quick + (fun _switch -> test_fold_undefined); + Alcotest_lwt.test_case "test Merkle proof for large inodes" `Quick + (fun _switch -> test_large_inode); + Alcotest_lwt.test_case "test Merkle proof for small inodes" `Quick + (fun _switch -> test_small_inode); + Alcotest_lwt.test_case "test deeper Merkle proof" `Quick (fun _switch -> + test_deeper_proof); + Alcotest_lwt.test_case "test large Merkle proof" `Slow (fun _switch -> + test_large_proofs); + Alcotest_lwt.test_case "test extenders in stream proof" `Quick + (fun _switch -> test_extenders); + Alcotest_lwt.test_case "test hardcoded stream proof" `Quick (fun _switch -> + test_hardcoded_stream); + Alcotest_lwt.test_case "test hardcoded proof" `Quick (fun _switch -> + test_hardcoded_proof); + Alcotest_lwt.test_case "test stream proof exn" `Quick (fun _switch -> + test_proof_exn); + Alcotest_lwt.test_case "test reexport node" `Quick (fun _switch -> + test_reexport_node); + ] diff --git a/vendors/irmin/test/irmin-pack/test_upgrade.ml b/vendors/irmin/test/irmin-pack/test_upgrade.ml new file mode 100644 index 000000000000..2dac4a04f0a8 --- /dev/null +++ b/vendors/irmin/test/irmin-pack/test_upgrade.ml @@ -0,0 +1,713 @@ +(* + * Copyright (c) 2022-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open! Import +open Common + +let ( / ) = Filename.concat +let archive_v2_minimal = "test" / "irmin-pack" / "data" / "version_2_minimal" +let archive_v2_always = "test" / "irmin-pack" / "data" / "version_2_always" +let archive_v3_minimal = "test" / "irmin-pack" / "data" / "version_3_minimal" +let archive_v3_always = "test" / "irmin-pack" / "data" / "version_3_always" + +let archive_v3_minimal_gced = + "test" / "irmin-pack" / "data" / "version_3_minimal_gced" + +let root_local_build = "_build" / "test-upgrade" + +type pack_entry = { + h : Schema.Hash.t; + o : Int63.t; + l : int; + k : [ `b | `n | `c ]; +} +(** [pack_entry]: hash / offset / length / kind *) + +let e h o l k = + let h = + match Irmin.Type.(of_string Schema.Hash.t) h with + | Error (`Msg s) -> Alcotest.failf "failed hash_of_string %s" s + | Ok h -> h + in + let o = Int63.of_int o in + { h; o; l; k } + +(* Objects inserted during preload + + borphan | b01 <- n01 <- n0 <- c0 *) +let borphan = e "c9bfadf2d211aa6da8e2d00732628a0880b7ee98" 0 29 `b +let b01 = e "5368d2c2f4fc5521fe8e8acd17cdd7349aa8f753" 29 25 `b +let n01 = e "9b120e5019dcc6cd90b4d9c9826c9ebbebdc0023" 54 34 `n +let n0 = e "fe0084f902d55464e9e6dbd82fb60fcf058bb6b1" 88 34 `n +let c0 = e "22e159de13b427226e5901defd17f0c14e744205" 122 42 `c + +(* Objects inserted during write1 + + to n01 <- to c0 <- + \ \ + b1 <- n1 <------- c1 | borphan' *) +let b1 = e "7e83ca2a65d6f90a809c8570c6c905a941b87732" 164 24 `b +let n1 = e "2cc1191a4cfbf869c62da4649961455df6e6b424" 188 44 `n +let c1 = e "09468f13334d3120d8798e27a28d23baba628710" 232 51 `c +let borphan' = e "945bcf284cb6f4735eb8eb74553637b43fde996b" 283 30 `b + +(* Objects inserted during write2 + + to c1 <- + \ + b2 <- n2 <- c2 *) +let b2 = e "32f28ea03b1b20126629d2ca63fc6665b0bbb604" 313 24 `b +let n2 = e "bbca871beaebb1b556e498a8e1ccae7817f5f4ff" 337 34 `n +let c2 = e "6d6c9fcf882f1473f5e2bd0cd4b475611c3a5b60" 371 51 `c + +let pack_entries = + [ n0; b1; borphan; c2; c1; b01; borphan'; n1; n2; n01; c0; b2 ] + +let dict_entries = + [ ("step-n01", 1); ("step-b01", 0); ("step-b1", 2); ("step-b2", 3) ] + +let dict_entries = List.to_seq dict_entries |> Hashtbl.of_seq + +let index_entries = + List.map (fun e -> (e.h, e.o)) pack_entries |> List.to_seq |> Hashtbl.of_seq + +let key_of_entry x = + Irmin_pack_unix.Pack_key.v_direct ~offset:x.o ~length:x.l x.h + +type start_mode = From_v2 | From_v3 | From_scratch | From_v3_c0_gced +[@@deriving irmin] + +type setup = { + indexing_strategy : [ `always | `minimal ]; + start_mode : start_mode; + lru_size : int; +} +[@@deriving irmin ~pp] + +type phase = + | S1_before_start + | S2_before_write + | S3_before_gc + | S4_before_write + | S5_before_close +[@@deriving irmin ~pp] + +(** A model is updated in conjunction with a store. Both should always reference + the same entries *) +module Model = struct + type t = { + setup : setup; + dict : (string, unit) Hashtbl.t; + suffix : (Int63.t, unit) Hashtbl.t; + index : (Schema.Hash.t, unit) Hashtbl.t; + } + + let v setup = + let dict = Hashtbl.create 5 in + let suffix = Hashtbl.create 5 in + let index = Hashtbl.create 5 in + { setup; dict; suffix; index } + + let preload_dict t = + Hashtbl.replace t.dict "step-b01" (); + Hashtbl.replace t.dict "step-n01" () + + let preload_suffix t = + if t.setup.start_mode <> From_v3_c0_gced then + Hashtbl.replace t.suffix borphan.o (); + Hashtbl.replace t.suffix b01.o (); + Hashtbl.replace t.suffix n01.o (); + Hashtbl.replace t.suffix n0.o (); + Hashtbl.replace t.suffix c0.o () + + let preload_index t = + if t.setup.indexing_strategy = `always then ( + Hashtbl.replace t.index borphan.h (); + Hashtbl.replace t.index b01.h (); + Hashtbl.replace t.index n01.h (); + Hashtbl.replace t.index n0.h ()); + Hashtbl.replace t.index c0.h () + + let preload t = + preload_suffix t; + preload_index t; + preload_dict t + + let write1_dict t = Hashtbl.replace t.dict "step-b1" () + + let write1_suffix t = + Hashtbl.replace t.suffix b1.o (); + Hashtbl.replace t.suffix n1.o (); + Hashtbl.replace t.suffix c1.o (); + Hashtbl.replace t.suffix borphan'.o () + + let write1_index t = + if t.setup.indexing_strategy = `always then ( + Hashtbl.replace t.index b1.h (); + Hashtbl.replace t.index n1.h (); + Hashtbl.replace t.index borphan'.h ()); + Hashtbl.replace t.index c1.h () + + let write1 t = + write1_suffix t; + write1_index t; + write1_dict t + + let gc t = + Hashtbl.remove t.suffix borphan.o; + Hashtbl.remove t.suffix n0.o; + Hashtbl.remove t.suffix c0.o + + let write2_dict t = Hashtbl.replace t.dict "step-b2" () + + let write2_suffix t = + Hashtbl.replace t.suffix b2.o (); + Hashtbl.replace t.suffix n2.o (); + Hashtbl.replace t.suffix c2.o () + + let write2_index t = + if t.setup.indexing_strategy = `always then ( + Hashtbl.replace t.index b2.h (); + Hashtbl.replace t.index n2.h ()); + Hashtbl.replace t.index c2.h () + + let write2 t = + write2_suffix t; + write2_index t; + write2_dict t + + (** The 5 different states in which a model may be *) + include struct + let create_empty setup = v setup + + let create_after_preload setup = + let m = v setup in + preload m; + m + + let create_after_write1 setup = + let m = v setup in + preload m; + write1 m; + m + + let create_after_gc setup = + let m = v setup in + preload m; + write1 m; + gc m; + m + + let create_after_write2 setup = + let m = v setup in + preload m; + write1 m; + gc m; + write2 m; + m + end +end + +(** A store is updated in conjunction with a model. Both should always reference + the same entries *) +module Store = struct + module S = struct + module Maker = Irmin_pack_unix.Maker (Conf) + include Maker.Make (Schema) + end + + type repo = S.repo + + let config setup ?(readonly = false) ?(fresh = true) root = + let module Index = Irmin_pack.Indexing_strategy in + let indexing_strategy = + if setup.indexing_strategy = `always then Index.always else Index.minimal + in + let lru_size = setup.lru_size in + Irmin_pack.config ~readonly ~indexing_strategy ~lru_size ~fresh root + + let v setup ~readonly ~fresh root = + S.Repo.v (config setup ~readonly ~fresh root) + + let close = S.Repo.close + let reload = S.reload + + let gc repo = + let k = key_of_entry c1 in + let* launched = S.Gc.start_exn ~unlink:true repo k in + assert launched; + let* result = S.Gc.finalise_exn ~wait:true repo in + match result with + | `Idle | `Running -> Alcotest.fail "expected finalised gc" + | `Finalised _ -> Lwt.return_unit + + let dict_find_opt (repo : S.repo) step = + S.Internal.(Dict.find (dict repo) step) + + let index_find_opt (repo : S.repo) hash = + S.Internal.(Index.find (File_manager.index (file_manager repo)) hash) + + let suffix_mem (repo : S.repo) e = + let k = key_of_entry e in + try + match e.k with + | `c -> S.Backend.Commit.mem (S.Backend.Repo.commit_t repo) k + | `n -> S.Backend.Node.mem (S.Backend.Repo.node_t repo) k + | `b -> S.Backend.Contents.mem (S.Backend.Repo.contents_t repo) k + with Irmin_pack_unix.Pack_store.Invalid_read _ -> + (* In RW mode, [mem] will raise an exception if the offset of the key is + out of the bounds of the pack file *) + Lwt.return_false + + let put_borphan bstore = + let+ k = S.Backend.Contents.add bstore "borphan" in + assert (k = key_of_entry borphan); + k + + let put_b01 bstore = + let+ k = S.Backend.Contents.add bstore "b01" in + assert (k = key_of_entry b01); + k + + let put_n01 bstore nstore = + let* k_b01 = put_b01 bstore in + let step = "step-b01" in + let childs = [ (step, `Contents (k_b01, ())) ] in + let n = S.Backend.Node.Val.of_list childs in + let+ k = S.Backend.Node.add nstore n in + assert (k = key_of_entry n01); + k + + let put_n0 bstore nstore = + let* k_n01 = put_n01 bstore nstore in + let step = "step-n01" in + let childs = [ (step, `Node k_n01) ] in + let n = S.Backend.Node.Val.of_list childs in + let+ k = S.Backend.Node.add nstore n in + assert (k = key_of_entry n0); + k + + let put_c0 bstore nstore cstore = + let* k_n0 = put_n0 bstore nstore in + let c = S.Backend.Commit.Val.v ~info:S.Info.empty ~node:k_n0 ~parents:[] in + let+ k = S.Backend.Commit.add cstore c in + assert (k = key_of_entry c0); + k + + let put_b1 bstore = + let+ k = S.Backend.Contents.add bstore "b1" in + k + + let put_n1 bstore nstore = + let* k_b1 = put_b1 bstore in + let k_n01 = key_of_entry n01 in + let step = "step-b1" in + let step' = "step-b01" in + let childs = [ (step, `Contents (k_b1, ())); (step', `Node k_n01) ] in + let n = S.Backend.Node.Val.of_list childs in + let+ k = S.Backend.Node.add nstore n in + assert (k = key_of_entry n1); + k + + let put_c1 bstore nstore cstore = + let* k_n1 = put_n1 bstore nstore in + let k_c0 = key_of_entry c0 in + let c = + S.Backend.Commit.Val.v ~info:S.Info.empty ~node:k_n1 ~parents:[ k_c0 ] + in + let+ k = S.Backend.Commit.add cstore c in + assert (k = key_of_entry c1); + k + + let put_borphan' bstore = + let+ k = S.Backend.Contents.add bstore "borphan'" in + assert (k = key_of_entry borphan'); + k + + let put_b2 bstore = + let+ k = S.Backend.Contents.add bstore "b2" in + assert (k = key_of_entry b2); + k + + let put_n2 bstore nstore = + let* k_b2 = put_b2 bstore in + let step = "step-b2" in + let childs = [ (step, `Contents (k_b2, ())) ] in + let n = S.Backend.Node.Val.of_list childs in + let+ k = S.Backend.Node.add nstore n in + assert (k = key_of_entry n2); + k + + let put_c2 bstore nstore cstore = + let* k_n2 = put_n2 bstore nstore in + let k_c1 = key_of_entry c1 in + let c = + S.Backend.Commit.Val.v ~info:S.Info.empty ~node:k_n2 ~parents:[ k_c1 ] + in + let+ k = S.Backend.Commit.add cstore c in + assert (k = key_of_entry c2); + k + + let preload repo = + S.Backend.Repo.batch repo (fun bstore nstore cstore -> + let* _ = put_borphan bstore in + let* _ = put_c0 bstore nstore cstore in + Lwt.return_unit) + + let write1 repo = + S.Backend.Repo.batch repo (fun bstore nstore cstore -> + let* _ = put_c1 bstore nstore cstore in + let* _ = put_borphan' bstore in + Lwt.return_unit) + + let write2 repo = + S.Backend.Repo.batch repo (fun bstore nstore cstore -> + let* _ = put_c2 bstore nstore cstore in + Lwt.return_unit) +end + +exception Skip_the_rest_of_that_test + +type hash = Store.S.hash [@@deriving irmin ~pp] + +type t = { + setup : setup; + mutable ro : (Model.t * Store.repo) option; + mutable rw : (Model.t * Store.repo) option; +} + +let check_dict repo model = + Hashtbl.iter + (fun step idx -> + let got = Store.dict_find_opt repo idx in + let exp = Hashtbl.mem model.Model.dict step in + match (got, exp) with + | None, false -> () + | Some step', true -> + let msg = Fmt.str "Dict entry with id:%d" idx in + Alcotest.(check string) msg step step' + | Some step', false -> + Alcotest.failf + "Dict entry with id:%d step:%s shouldn't be there (it's under step \ + %s)" + idx step step' + | None, true -> + Alcotest.failf "Dict entry with id:%d step:%s missing" idx step) + dict_entries + +let check_index repo model = + Hashtbl.iter + (fun hash off -> + let got = Store.index_find_opt repo hash in + let exp = Hashtbl.mem model.Model.index hash in + match (got, exp) with + | None, false -> () + | Some (off', _, _), true -> + let msg = Fmt.str "Index entry with hash:%a" pp_hash hash in + Alcotest.(check int) msg (Int63.to_int off) (Int63.to_int off') + | Some (off', _, _), false -> + Alcotest.failf + "Index entry with hash:%a offset:%d shouldn't be there (it \ + contains offset %d)" + pp_hash hash (Int63.to_int off) (Int63.to_int off') + | None, true -> + Alcotest.failf "Index entry with hash:%a off:%d is missing" pp_hash + hash (Int63.to_int off)) + index_entries + +let check_suffix repo model = + Lwt_list.iter_s + (fun e -> + let+ got = Store.suffix_mem repo e in + let exp = Hashtbl.mem model.Model.suffix e.o in + match (got, exp) with + | false, false -> () + | true, true -> () + | true, false -> + Alcotest.failf "Pack entry with hash:%a off:%d shouldn't be there" + pp_hash e.h (Int63.to_int e.o) + | false, true -> + Alcotest.failf "Pack entry with hash:%a off:%d is missing" pp_hash e.h + (Int63.to_int e.o)) + pack_entries + +let check t = + Lwt_list.iter_s + (fun (model, repo) -> + check_dict repo model; + check_index repo model; + check_suffix repo model) + (Option.to_list t.ro @ Option.to_list t.rw) + +let create_test_env setup = + rm_dir root_local_build; + let () = + match setup.start_mode with + | From_scratch -> () + | From_v2 -> + let root_archive = + if setup.indexing_strategy = `always then archive_v2_always + else archive_v2_minimal + in + setup_test_env ~root_archive ~root_local_build + | From_v3 -> + let root_archive = + if setup.indexing_strategy = `always then archive_v3_always + else archive_v3_minimal + in + setup_test_env ~root_archive ~root_local_build + | From_v3_c0_gced -> + let root_archive = + if setup.indexing_strategy = `minimal then archive_v3_minimal_gced + else assert false + in + setup_test_env ~root_archive ~root_local_build + in + + { setup; rw = None; ro = None } + +(** One of the 4 rw mutations *) +let start_rw t = + [%logs.app "*** start_rw %a" pp_setup t.setup]; + let+ rw = + match t.rw with + | Some _ -> assert false + | None -> + let model = + match t.setup.start_mode with + | From_v2 | From_v3 | From_v3_c0_gced -> + (* Model with pre-loaded data. *) + let m = Model.v t.setup in + Model.preload m; + m + | From_scratch -> Model.v t.setup + in + let+ repo = + Store.v t.setup ~readonly:false ~fresh:false root_local_build + in + (model, repo) + in + t.rw <- Some rw + +(** One of the 4 rw mutations *) +let write1_rw t = + [%logs.app "*** write1_rw %a" pp_setup t.setup]; + match t.rw with + | None -> assert false + | Some (_, repo) -> + t.rw <- Some (Model.create_after_write1 t.setup, repo); + let* () = + (* If the preload commit is not yet in the store, add it. Note that + adding the same commit twice is not idempotent in indexing strategy + minimal, therefore we need to make this distinction. *) + if t.setup.start_mode = From_scratch then + let* _ = Store.preload repo in + Lwt.return_unit + else Lwt.return_unit + in + let* _ = Store.write1 repo in + Lwt.return_unit + +(** One of the 4 rw mutations *) +let gc_rw t = + [%logs.app "*** gc_rw %a" pp_setup t.setup]; + match t.rw with + | None -> assert false + | Some (_, repo) -> + t.rw <- Some (Model.create_after_gc t.setup, repo); + let* () = + match (t.setup.start_mode, t.setup.indexing_strategy) with + | From_v2, _ | _, `always -> + let* () = + Alcotest.check_raises_lwt "GC on V2/always" + (Irmin_pack_unix.Errors.Pack_error + (`Gc_disallowed "Store does not support GC")) + (fun () -> Store.gc repo) + in + raise Skip_the_rest_of_that_test + | (From_v3 | From_scratch | From_v3_c0_gced), `minimal -> Store.gc repo + in + Lwt.return_unit + +(** One of the 4 rw mutations *) +let write2_rw t = + [%logs.app "*** write2_rw %a" pp_setup t.setup]; + match t.rw with + | None -> assert false + | Some (_, repo) -> + t.rw <- Some (Model.create_after_write2 t.setup, repo); + let* _ = Store.write2 repo in + Lwt.return_unit + +(** One of the 2 ro mutations *) +let open_ro t current_phase = + [%logs.app "*** open_ro %a, %a" pp_setup t.setup pp_phase current_phase]; + let+ ro = + match t.ro with + | Some _ -> assert false + | None -> + let model = + match (t.setup.start_mode, current_phase) with + | From_scratch, (S1_before_start | S2_before_write) -> + Model.create_empty t.setup + | ( (From_v2 | From_v3 | From_v3_c0_gced), + (S1_before_start | S2_before_write) ) -> + Model.create_after_preload t.setup + | (From_v2 | From_v3 | From_v3_c0_gced | From_scratch), S3_before_gc + -> + Model.create_after_write1 t.setup + | ( (From_v2 | From_v3 | From_v3_c0_gced | From_scratch), + S4_before_write ) -> + Model.create_after_gc t.setup + | ( (From_v2 | From_v3 | From_v3_c0_gced | From_scratch), + S5_before_close ) -> + Model.create_after_write2 t.setup + in + let fail_and_skip error = + let* () = + Alcotest.check_raises_lwt "open empty/V2 store in RO" + (Irmin_pack_unix.Errors.Pack_error error) (fun () -> + let* repo = + Store.v t.setup ~readonly:true ~fresh:false root_local_build + in + Store.close repo) + in + raise Skip_the_rest_of_that_test + in + let+ repo = + match (t.setup.start_mode, current_phase) with + | From_scratch, S1_before_start -> + let missing_path = + Irmin_pack.Layout.V1_and_v2.pack ~root:root_local_build + in + fail_and_skip (`No_such_file_or_directory missing_path) + | From_v2, S1_before_start -> fail_and_skip `Migration_needed + | (From_v2 | From_v3 | From_v3_c0_gced | From_scratch), _ -> + Store.v t.setup ~readonly:true ~fresh:false root_local_build + in + (model, repo) + in + t.ro <- Some ro + +(** One of the 2 ro mutations *) +let sync_ro t current_phase = + [%logs.app "*** sync_ro %a, %a" pp_setup t.setup pp_phase current_phase]; + match t.ro with + | None -> assert false + | Some (_, repo) -> + let () = + match current_phase with + | S1_before_start | S2_before_write -> () + | S3_before_gc -> t.ro <- Some (Model.create_after_write1 t.setup, repo) + | S4_before_write -> t.ro <- Some (Model.create_after_gc t.setup, repo) + | S5_before_close -> + t.ro <- Some (Model.create_after_write2 t.setup, repo) + in + Store.reload repo + +let close_everything t = + Lwt_list.iter_s + (fun (_, repo) -> Store.close repo) + (Option.to_list t.ro @ Option.to_list t.rw) + +let test_one t ~ro_open_at ~ro_sync_at = + let aux phase = + let* () = check t in + let* () = if ro_open_at = phase then open_ro t phase else Lwt.return_unit in + let* () = check t in + if ro_sync_at = phase then sync_ro t phase; + let* () = check t in + Lwt.return_unit + in + + let* () = aux S1_before_start in + let* () = start_rw t in + let* () = aux S2_before_write in + let* () = write1_rw t in + let* () = aux S3_before_gc in + let* () = gc_rw t in + let* () = aux S4_before_write in + let* () = write2_rw t in + let* () = aux S5_before_close in + Lwt.return_unit + +let test_one_guarded setup ~ro_open_at ~ro_sync_at = + let t = create_test_env setup in + Lwt.catch + (fun () -> + let* () = test_one t ~ro_open_at ~ro_sync_at in + close_everything t) + (function + | Skip_the_rest_of_that_test -> + [%logs.app "*** skip rest of %a" pp_setup setup]; + close_everything t + | exn -> Lwt.fail exn) + +(** All possible interleaving of the ro calls (open and sync) with the rw calls + (open, write1, gc and write2). *) +let test start_mode indexing_strategy lru_size = + let setup = { start_mode; indexing_strategy; lru_size } in + let t = test_one_guarded setup in + + let* () = t ~ro_open_at:S1_before_start ~ro_sync_at:S1_before_start in + let* () = t ~ro_open_at:S1_before_start ~ro_sync_at:S2_before_write in + let* () = t ~ro_open_at:S1_before_start ~ro_sync_at:S3_before_gc in + let* () = t ~ro_open_at:S1_before_start ~ro_sync_at:S4_before_write in + let* () = t ~ro_open_at:S1_before_start ~ro_sync_at:S5_before_close in + + let* () = t ~ro_open_at:S2_before_write ~ro_sync_at:S2_before_write in + let* () = t ~ro_open_at:S2_before_write ~ro_sync_at:S3_before_gc in + let* () = t ~ro_open_at:S2_before_write ~ro_sync_at:S4_before_write in + let* () = t ~ro_open_at:S2_before_write ~ro_sync_at:S5_before_close in + + let* () = t ~ro_open_at:S3_before_gc ~ro_sync_at:S3_before_gc in + let* () = t ~ro_open_at:S3_before_gc ~ro_sync_at:S4_before_write in + let* () = t ~ro_open_at:S3_before_gc ~ro_sync_at:S5_before_close in + + let* () = t ~ro_open_at:S4_before_write ~ro_sync_at:S4_before_write in + let* () = t ~ro_open_at:S4_before_write ~ro_sync_at:S5_before_close in + + let* () = t ~ro_open_at:S5_before_close ~ro_sync_at:S5_before_close in + Lwt.return_unit + +(** Product on lru_size *) +let test start_mode indexing_strategy = + let* () = test start_mode indexing_strategy 0 in + let* () = test start_mode indexing_strategy 100 in + Lwt.return_unit + +let test_gced_store () = + let* () = test From_v3_c0_gced `minimal in + Lwt.return_unit + +(** Product on indexing_strategy *) +let test start_mode () = + let* () = test start_mode `minimal in + let* () = test start_mode `always in + Lwt.return_unit + +(** Product on start_mode *) +let tests = + [ + Alcotest_lwt.test_case "upgrade From_v3" `Quick (fun _switch () -> + test From_v3 ()); + Alcotest_lwt.test_case "upgrade From_v2" `Quick (fun _switch () -> + test From_v2 ()); + Alcotest_lwt.test_case "upgrade From_scratch" `Quick (fun _switch () -> + test From_scratch ()); + Alcotest_lwt.test_case "upgrade From_v3 after Gc" `Quick (fun _switch () -> + test_gced_store ()); + ] diff --git a/vendors/irmin/test/irmin-tezos/dune b/vendors/irmin/test/irmin-tezos/dune new file mode 100644 index 000000000000..43186b51d431 --- /dev/null +++ b/vendors/irmin/test/irmin-tezos/dune @@ -0,0 +1,33 @@ +(executable + (name irmin_fsck) + (modules irmin_fsck) + (libraries irmin-pack irmin-pack.unix irmin-tezos)) + +(executable + (name generate) + (modules generate) + (libraries irmin-tezos irmin-pack irmin-pack.unix)) + +(rule + (alias generate-cli-test-data) + (targets data) + (action + (run %{exe:generate.exe}))) + +(cram + (package irmin-tezos) + (deps + (file irmin_fsck.exe) + (file data) + (alias generate-cli-test-data))) + +;FIXME: we should not depend on the version of cmdliner +;(rule +; (alias runtest) +; (package irmin-tezos) +; (action +; (progn +; (with-stdout-to +; irmin-fsck-help.txt.gen +; (run %{exe:irmin_fsck.exe} --help=plain)) +; (diff? irmin-fsck-help.txt irmin-fsck-help.txt.gen)))) diff --git a/vendors/irmin/test/irmin-tezos/generate.ml b/vendors/irmin/test/irmin-tezos/generate.ml new file mode 100644 index 000000000000..c47da5fad841 --- /dev/null +++ b/vendors/irmin/test/irmin-tezos/generate.ml @@ -0,0 +1,68 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Lwt.Syntax + +let rm_dir data_dir = + if Sys.file_exists data_dir then ( + let cmd = Printf.sprintf "rm -rf %s" data_dir in + Fmt.epr "exec: %s\n%!" cmd; + let _ = Sys.command cmd in + ()) + +module Simple = struct + let data_dir = "data/pack" + + module Conf = struct + include Irmin_tezos.Conf + + let entries = 2 + let stable_hash = 3 + end + + module Schema = Irmin.Schema.KV (Irmin.Contents.String) + + module Store = struct + open Irmin_pack_unix.Maker (Conf) + include Make (Schema) + end + + let config root = Irmin_pack.config ~readonly:false ~fresh:true root + let info = Store.Info.empty + + let create_store () = + rm_dir data_dir; + (* make sure the parent directory data/ exists; by default Store.Repo.v will not + create the containing directory *) + if not (Sys.file_exists "data") then Unix.mkdir "data" 0o755; + let* rw = Store.Repo.v (config data_dir) in + let tree = Store.Tree.singleton [ "a"; "b1"; "c1"; "d1"; "e1" ] "x1" in + let* tree = Store.Tree.add tree [ "a"; "b1"; "c1"; "d2"; "e2" ] "x2" in + let* tree = Store.Tree.add tree [ "a"; "b1"; "c1"; "d3"; "e3" ] "x2" in + let* tree = Store.Tree.add tree [ "a"; "b2"; "c2"; "e3" ] "x2" in + let* c1 = Store.Commit.v rw ~parents:[] ~info tree in + + let* tree = Store.Tree.add tree [ "a"; "b3" ] "x3" in + let* c2 = Store.Commit.v rw ~parents:[ Store.Commit.key c1 ] ~info tree in + + let* tree = Store.Tree.remove tree [ "a"; "b1"; "c1" ] in + let* _ = Store.Commit.v rw ~parents:[ Store.Commit.key c2 ] ~info tree in + + Store.Repo.close rw +end + +let generate () = Simple.create_store () +let () = Lwt_main.run (generate ()) diff --git a/vendors/irmin/test/irmin-tezos/generate.mli b/vendors/irmin/test/irmin-tezos/generate.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin-tezos/generate.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin-tezos/irmin-fsck-help.txt b/vendors/irmin/test/irmin-tezos/irmin-fsck-help.txt new file mode 100644 index 000000000000..6709f1443787 --- /dev/null +++ b/vendors/irmin/test/irmin-tezos/irmin-fsck-help.txt @@ -0,0 +1,33 @@ +NAME + irmin-fsck - Check Irmin data-stores. + +SYNOPSIS + irmin-fsck COMMAND ... + +COMMANDS + integrity-check + Check integrity of an existing store. + + integrity-check-index + Check index integrity. + + integrity-check-inodes + Check integrity of inodes in an existing store. + + reconstruct-index + Reconstruct index from an existing pack file. + + stat + Print high-level statistics about the store. + + stat-store + Traverse one commit, specified with the --commit argument, in the + store for stats. If no commit is specified the current head is + used. + +OPTIONS + --help[=FMT] (default=auto) + Show this help in format FMT. The value FMT must be one of `auto', + `pager', `groff' or `plain'. With `auto', the format is `pager` or + `plain' whenever the TERM env var is `dumb' or undefined. + diff --git a/vendors/irmin/test/irmin-tezos/irmin_fsck.ml b/vendors/irmin/test/irmin-tezos/irmin_fsck.ml new file mode 100644 index 000000000000..ac0be3236458 --- /dev/null +++ b/vendors/irmin/test/irmin-tezos/irmin_fsck.ml @@ -0,0 +1,38 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Schema = Irmin.Schema.KV (Irmin.Contents.String) + +module Maker = struct + module Maker = Irmin_pack_unix.Maker (Irmin_tezos.Conf) + include Maker.Make (Schema) +end + +module Store = Irmin_pack_unix.Checks.Make (Maker) + +module Maker_tz = struct + module Maker = Irmin_pack_unix.Maker (Irmin_tezos.Conf) + include Maker.Make (Irmin_tezos.Schema) +end + +module Store_tz = Irmin_pack_unix.Checks.Make (Maker_tz) + +let () = + try + let store_type = Sys.getenv "STORE" in + if store_type = "PACK" then match Store.cli () with _ -> . + else raise Not_found + with Not_found -> ( match Store_tz.cli () with _ -> .) diff --git a/vendors/irmin/test/irmin-tezos/stat.t/run.t b/vendors/irmin/test/irmin-tezos/stat.t/run.t new file mode 100644 index 000000000000..1a73d42a09c8 --- /dev/null +++ b/vendors/irmin/test/irmin-tezos/stat.t/run.t @@ -0,0 +1,25 @@ +Running stat on a v3 store + $ STORE=PACK ../irmin_fsck.exe stat ../data/pack 2>&1 | cat -e | tail -n 10 + "hash_size": {$ + "Bytes": 64$ + },$ + "log_size": 2500000,$ + "objects": {$ + "nb_commits": 3,$ + "nb_nodes": 16,$ + "nb_contents": 3$ + }$ + } + +Running index-integrity-check on a v3 store minimal + $ STORE=PACK ../irmin_fsck.exe integrity-check-index ../data/pack 2>&1 | cat -e | tail -n 10 + { "Commit_v1" = 0;$ + "Commit_v2" = 3;$ + "Contents" = 3;$ + "Inode_v1_unstable" = 0;$ + "Inode_v1_stable" = 0;$ + "Inode_v2_root" = 12;$ + "Inode_v2_nonroot" = 4;$ + "Dangling_parent_commit" = 0;$ + "Duplicated entries" = 0;$ + "Missing entries" = 0 }$ diff --git a/vendors/irmin/test/irmin/data/dune b/vendors/irmin/test/irmin/data/dune new file mode 100644 index 000000000000..415dd47b0005 --- /dev/null +++ b/vendors/irmin/test/irmin/data/dune @@ -0,0 +1,4 @@ +(test + (name test) + (package irmin) + (libraries irmin.data alcotest vector fmt)) diff --git a/vendors/irmin/test/irmin/data/import.ml b/vendors/irmin/test/irmin/data/import.ml new file mode 100644 index 000000000000..38df5ec8bab9 --- /dev/null +++ b/vendors/irmin/test/irmin/data/import.ml @@ -0,0 +1,22 @@ +let check typ pos ~expected actual = + Alcotest.(check ~pos typ) "" expected actual + +let check_bool = check Alcotest.bool + +let check_ok_or_duplicate = + let pp : [ `Ok | `Duplicate ] Fmt.t = + Fmt.of_to_string (function `Ok -> "`Ok" | `Duplicate -> "`Duplicate") + in + check (Alcotest.testable pp ( = )) + +let check_invalid_arg pos f = + let fail got = + Alcotest.failf ~pos + "Expected function to raise `Invalid_argument`, but raised: %a" + Fmt.(Dump.option exn) + got + in + match f () with + | _ -> fail None + | exception Invalid_argument _ -> () + | exception exn -> fail (Some exn) diff --git a/vendors/irmin/test/irmin/data/test.ml b/vendors/irmin/test/irmin/data/test.ml new file mode 100644 index 000000000000..291685956585 --- /dev/null +++ b/vendors/irmin/test/irmin/data/test.ml @@ -0,0 +1,6 @@ +open! Import + +let () = + Random.self_init (); + Alcotest.run __FILE__ + [ ("Fixed_size_string_set", Test_fixed_size_string_set.tests) ] diff --git a/vendors/irmin/test/irmin/data/test.mli b/vendors/irmin/test/irmin/data/test.mli new file mode 100644 index 000000000000..468d18d917ad --- /dev/null +++ b/vendors/irmin/test/irmin/data/test.mli @@ -0,0 +1 @@ +(* Intentionally empty *) diff --git a/vendors/irmin/test/irmin/data/test_fixed_size_string_set.ml b/vendors/irmin/test/irmin/data/test_fixed_size_string_set.ml new file mode 100644 index 000000000000..42d50d00ae07 --- /dev/null +++ b/vendors/irmin/test/irmin/data/test_fixed_size_string_set.ml @@ -0,0 +1,104 @@ +open! Import +module String_set = Irmin_data.Fixed_size_string_set + +let hash : string -> int = Hashtbl.hash + +let hash_substring : Bigstringaf.t -> off:int -> len:int -> int = + fun t ~off ~len -> hash (Bigstringaf.substring t ~off ~len) + +let test_add_and_mem () = + let set = + String_set.create ~elt_length:1 ~initial_slots:0 ~hash ~hash_substring () + in + String_set.mem set "a" |> check_bool __POS__ ~expected:false; + String_set.add_exn set "a"; + String_set.mem set "a" |> check_bool __POS__ ~expected:true; + String_set.add_exn set "b"; + String_set.add_exn set "c"; + + String_set.mem set "a" |> check_bool __POS__ ~expected:true; + String_set.mem set "b" |> check_bool __POS__ ~expected:true; + String_set.mem set "c" |> check_bool __POS__ ~expected:true; + + String_set.add set "a" |> check_ok_or_duplicate __POS__ ~expected:`Duplicate; + String_set.add set "b" |> check_ok_or_duplicate __POS__ ~expected:`Duplicate; + String_set.add set "c" |> check_ok_or_duplicate __POS__ ~expected:`Duplicate; + String_set.add set "d" |> check_ok_or_duplicate __POS__ ~expected:`Ok + +let test_random () = + let elt_length = 8 in + let set = + String_set.create ~elt_length ~initial_slots:31 ~hash ~hash_substring () + in + let reference_tbl = Stdlib.Hashtbl.create 0 in + let reference_vector = Vector.create ~dummy:"" in + let random_string () = + String.init elt_length (fun _ -> char_of_int (Random.int 256)) + in + for i = 0 to 10_000 do + (* Add a new element: *) + let new_elt = random_string () in + String_set.add_exn set new_elt; + Stdlib.Hashtbl.add reference_tbl new_elt (); + Vector.push reference_vector new_elt; + + (* Pick a random existing element and check [mem] is true: *) + let elt = Vector.get reference_vector (Random.int (i + 1)) in + assert (Stdlib.Hashtbl.mem reference_tbl elt); + String_set.mem set elt |> check_bool __POS__ ~expected:true; + + (* Pick a random non-existing element and check [mem] is false: *) + let non_elt = random_string () in + assert (not (Stdlib.Hashtbl.mem reference_tbl non_elt)); + String_set.mem set non_elt |> check_bool __POS__ ~expected:false; + + (* Check that the internal invariants hold, and that all internal elements + are also contained in the reference: *) + if i mod 1_000 = 0 then + String_set.invariant + (fun elt -> + check_bool __POS__ ~expected:true + (Stdlib.Hashtbl.mem reference_tbl elt)) + set + done + +let test_invalid_argument () = + (* [create] *) + let () = + (* Must have a positive [elt_length]: *) + check_invalid_arg __POS__ (fun () -> String_set.create ~elt_length:0 ()); + + (* Cannot pass [hash] without passing [hash_substring] (and vice versa): *) + check_invalid_arg __POS__ (fun () -> + String_set.create ~elt_length:1 ~hash:(fun _ -> assert false) ()); + check_invalid_arg __POS__ (fun () -> + String_set.create ~elt_length:1 + ~hash_substring:(fun _ -> assert false) + ()) + in + + (* [add] *) + let () = + let null = "0" in + let t = String_set.create ~elt_length:1 ~null () in + + (* Element must have the correct length: *) + check_invalid_arg __POS__ (fun () -> String_set.add_exn t ""); + + (* Cannot add the null element: *) + check_invalid_arg __POS__ (fun () -> String_set.add_exn t null); + + (* An exception is raised on adding a duplicate element: *) + String_set.add_exn t "a"; + check_invalid_arg __POS__ (fun () -> String_set.add_exn t "a") + in + + () + +let tests = + let test name fn = Alcotest.test_case name `Quick fn in + [ + test "add_and_mem" test_add_and_mem; + test "random" test_random; + test "invalid_argument" test_invalid_argument; + ] diff --git a/vendors/irmin/test/irmin/data/test_fixed_size_string_set.mli b/vendors/irmin/test/irmin/data/test_fixed_size_string_set.mli new file mode 100644 index 000000000000..d38ba9a90a2b --- /dev/null +++ b/vendors/irmin/test/irmin/data/test_fixed_size_string_set.mli @@ -0,0 +1 @@ +val tests : unit Alcotest.test_case list diff --git a/vendors/irmin/test/irmin/dune b/vendors/irmin/test/irmin/dune new file mode 100644 index 000000000000..4189f8292287 --- /dev/null +++ b/vendors/irmin/test/irmin/dune @@ -0,0 +1,18 @@ +(test + (name test) + ;; Attached to `irmin-test` to avoid a cyclic dependency with `irmin` + (package irmin-test) + (preprocess + (pps ppx_irmin.internal)) + (libraries + irmin + irmin.mem + irmin-test + alcotest + alcotest-lwt + lwt + lwt.unix + hex + logs + logs.fmt + qcheck-alcotest)) diff --git a/vendors/irmin/test/irmin/generic-key/dune b/vendors/irmin/test/irmin/generic-key/dune new file mode 100644 index 000000000000..96e1b41b0919 --- /dev/null +++ b/vendors/irmin/test/irmin/generic-key/dune @@ -0,0 +1,15 @@ +(test + (name test) + ;; Attached to `irmin-test` to avoid a cyclic dependency with `irmin` + (package irmin-test) + (preprocess + (pps ppx_irmin.internal)) + (libraries + irmin + irmin.mem + irmin-test + alcotest + alcotest-lwt + lwt + lwt.unix + vector)) diff --git a/vendors/irmin/test/irmin/generic-key/test.ml b/vendors/irmin/test/irmin/generic-key/test.ml new file mode 100644 index 000000000000..28f52b7cea79 --- /dev/null +++ b/vendors/irmin/test/irmin/generic-key/test.ml @@ -0,0 +1,22 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +let () = + Lwt_main.run + @@ Irmin_test.Store.run __FILE__ ~slow:true ~misc:[] ~sleep:Lwt_unix.sleep + [ + (`Quick, Test_store_offset.suite); (`Quick, Test_inlined_contents.suite); + ] diff --git a/vendors/irmin/test/irmin/generic-key/test_inlined_contents.ml b/vendors/irmin/test/irmin/generic-key/test_inlined_contents.ml new file mode 100644 index 000000000000..755689678dce --- /dev/null +++ b/vendors/irmin/test/irmin/generic-key/test_inlined_contents.ml @@ -0,0 +1,94 @@ +open Irmin + +(** A store in which all values are stored as immediates inside their respective + keys. The store itself keeps no information, except for the bookkeeping + needed to handle [clear]-ing the in-memory keys. *) +module Keyed_by_value = struct + type (_, 'v) key = { value : 'v } + + module Key (Hash : Hash.S) (Value : Type.S) = struct + type t = (Hash.t, Value.t) key + type hash = Hash.t [@@deriving irmin ~pre_hash] + type value = Value.t [@@deriving irmin ~pre_hash] + + let value_to_hash t = Hash.hash (fun f -> pre_hash_value t f) + let to_hash t = value_to_hash t.value + + let (t : t Type.t) = + let open Type in + map + ~pre_hash:(fun t f -> + let hash = value_to_hash t.value in + pre_hash_hash hash f) + Value.t + (fun _ -> + Alcotest.fail ~pos:__POS__ "Key implementation is non-serialisable") + (fun t -> t.value) + end + + module Make (Hash : Hash.S) (Value : Type.S) = struct + type _ t = { instance : unit option ref } + type hash = Hash.t + type value = Value.t + + module Key = Key (Hash) (Value) + + type key = Key.t + + let check_not_closed t = + match !(t.instance) with None -> raise Closed | Some t -> t + + let v _ = Lwt.return { instance = ref (Some ()) } + + let mem t _ = + let _ = check_not_closed t in + Lwt.return_true + + let unsafe_add t _ value = + let _ = check_not_closed t in + Lwt.return { value } + + let add t v = unsafe_add t () v + + let find t k = + let _ = check_not_closed t in + Lwt.return_some k.value + + let index _ _ = Lwt.return_none + let batch t f = f (t :> Perms.read_write t) + + let close t = + t.instance := None; + Lwt.return_unit + end +end + +module Plain = struct + type 'h key = 'h + + module Key = Key.Of_hash + + module Make (H : Hash.S) (V : Type.S) = struct + module CA = + Content_addressable.Check_closed (Irmin_mem.Content_addressable) (H) (V) + + include Indexable.Of_content_addressable (H) (CA) + + let v = CA.v + end +end + +module Store_maker = Generic_key.Maker (struct + module Contents_store = Keyed_by_value + module Node_store = Plain + module Commit_store = Plain + module Branch_store = Atomic_write.Check_closed (Irmin_mem.Atomic_write) +end) + +module Store = Store_maker.Make (Schema.KV (Contents.String)) + +let suite = + let store = (module Store : Irmin_test.Generic_key) in + let config = Irmin_mem.config () in + Irmin_test.Suite.create_generic_key ~name:"inlined_contents" ~store ~config + ~import_supported:false () diff --git a/vendors/irmin/test/irmin/generic-key/test_store_offset.ml b/vendors/irmin/test/irmin/generic-key/test_store_offset.ml new file mode 100644 index 000000000000..3f9d8bdd4cca --- /dev/null +++ b/vendors/irmin/test/irmin/generic-key/test_store_offset.ml @@ -0,0 +1,142 @@ +(* + * Copyright (c) 2018-2022 Tarides + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin + +(** A store abstraction over an append-only sequence of values. The key of a + value is the slot at which it's stored in this sequence. There is no index + for finding stored values by their hash, so any sharing must be achieved at + the level of keys. *) +module Slot_keyed_vector : Indexable.Maker_concrete_key1 = struct + type 'h key = { + slot : int; + hash : 'h; + (* Sanity check that keys are used only w/ the stores that created them: *) + store_id : < >; + } + + let key_t hash_t = + let open Type in + let hash_equal = unstage (equal hash_t) in + let hash_pre_hash = unstage (pre_hash hash_t) in + record "key" (fun _ _ -> + Alcotest.fail ~pos:__POS__ "Key implementation is non-serialisable") + |+ field "slot" int (fun t -> t.slot) + |+ field "hash" hash_t (fun t -> t.hash) + |> sealr + |> like (* TODO: write tests that expose the need for these directly *) + ~equal:(fun a b -> hash_equal a.hash b.hash) + ~pre_hash:(fun t f -> hash_pre_hash t.hash f) + + module Key (Hash : Hash.S) = struct + type t = Hash.t key [@@deriving irmin] + type hash = Hash.t + + let to_hash t = t.hash + end + + module Make (Hash : Hash.S) (Value : Type.S) = struct + type instance = { data : (Hash.t * Value.t) option Vector.t; id : < > } + type _ t = { instance : instance option ref } + + let v = + (* NOTE: at time of writing, [irmin-test] relies on the fact that the + store constructor is memoised (modulo [close] semantics, which must be + non-memoised), so we must use a singleton here. *) + let singleton = { data = Vector.create ~dummy:None; id = object end } in + fun _ -> Lwt.return { instance = ref (Some singleton) } + + type nonrec key = Hash.t key [@@deriving irmin] + type value = Value.t + type hash = Hash.t [@@deriving irmin ~equal] + + let index _ _ = Lwt.return_none + + module Key = struct + type t = key [@@deriving irmin] + type hash = Hash.t + + let to_hash t = t.hash + end + + module Hash = Irmin.Hash.Typed (Hash) (Value) + + let check_not_closed t = + match !(t.instance) with None -> raise Closed | Some t -> t + + let check_key_belongs_to_store pos (k : key) (t : instance) = + let key_store_id = k.store_id and expected_id = t.id in + let r = key_store_id == expected_id in + if not r then + Alcotest.(check ~pos int) + "Key ID matches the given store ID" (Oo.id expected_id) + (Oo.id key_store_id) + + let check_hash_is_consistent pos k recovered_hash = + let r = equal_hash k.hash recovered_hash in + if not r then + Alcotest.(check ~pos (Irmin_test.testable Hash.t)) + "Recovered hash is consistent with the key" k.hash recovered_hash + + let unsafe_add t hash v = + let t = check_not_closed t in + Vector.push t.data (Some (hash, v)); + let key = { slot = Vector.length t.data - 1; hash; store_id = t.id } in + Lwt.return key + + let add t v = unsafe_add t (Hash.hash v) v + + let find t k = + let t = check_not_closed t in + check_key_belongs_to_store __POS__ k t; + match Vector.get t.data k.slot with + | exception Not_found -> Lwt.return_none + | None -> + Alcotest.failf "Invalid key slot %d. No data contained here." k.slot + | Some (recovered_hash, data) -> + check_hash_is_consistent __POS__ k recovered_hash; + Lwt.return (Some data) + + let mem t k = + let t = check_not_closed t in + check_key_belongs_to_store __POS__ k t; + assert (k.slot < Vector.length t.data); + Lwt.return_true + + let batch t f = + let _ = check_not_closed t in + f (t :> Perms.read_write t) + + let close t = + t.instance := None; + Lwt.return_unit + end +end + +module Store_maker = Generic_key.Maker (struct + module Contents_store = Indexable.Maker_concrete_key2_of_1 (Slot_keyed_vector) + module Node_store = Slot_keyed_vector + module Commit_store = Slot_keyed_vector + module Branch_store = Atomic_write.Check_closed (Irmin_mem.Atomic_write) +end) + +module Store = Store_maker.Make (Schema.KV (Contents.String)) + +let suite = + let store = (module Store : Irmin_test.Generic_key) in + let config = Irmin_mem.config () in + Irmin_test.Suite.create_generic_key ~name:"store_offset" ~store ~config + ~import_supported:false () diff --git a/vendors/irmin/test/irmin/test.ml b/vendors/irmin/test/irmin/test.ml new file mode 100644 index 000000000000..1c3cf66d075d --- /dev/null +++ b/vendors/irmin/test/irmin/test.ml @@ -0,0 +1,36 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module Test_node = Irmin_test.Node.Make (Irmin.Node.Generic_key.Make) + +let lift_suite_to_lwt : + unit Alcotest.test_case list -> unit Alcotest_lwt.test_case list = + List.map (fun (n, s, f) -> (n, s, Fun.const (Lwt.wrap f))) + +let suite = + [ + ("lru", Test_lru.suite |> lift_suite_to_lwt); + ("tree", Test_tree.suite); + ("node", Test_node.suite |> lift_suite_to_lwt); + ("hash", Test_hash.suite); + ("conf", Test_conf.suite); + ] + +let () = + Logs.set_level (Some Debug); + Logs.set_reporter (Irmin_test.reporter ()); + Random.self_init (); + Lwt_main.run (Alcotest_lwt.run "irmin" suite) diff --git a/vendors/irmin/test/irmin/test.mli b/vendors/irmin/test/irmin/test.mli new file mode 100644 index 000000000000..e790aeb70f0d --- /dev/null +++ b/vendors/irmin/test/irmin/test.mli @@ -0,0 +1 @@ +(* empty *) diff --git a/vendors/irmin/test/irmin/test_conf.ml b/vendors/irmin/test/irmin/test_conf.ml new file mode 100644 index 000000000000..f8b34e7f4f41 --- /dev/null +++ b/vendors/irmin/test/irmin/test_conf.ml @@ -0,0 +1,46 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Backend.Conf + +let test_conf () = + let spec_a = Spec.v "a" in + let spec_b = Spec.v "b" in + let x = key ~spec:spec_a "x" Irmin.Type.int 0 in + let _y = key ~spec:spec_a "y" Irmin.Type.int 1 in + let conf_a = add (empty spec_a) x 1 in + let () = Alcotest.(check int) "x" 1 (get conf_a x) in + let () = + Alcotest.check_raises "Wrong spec" + (Invalid_argument "invalid config key: x") (fun () -> + ignore (add (empty spec_b) x 1)) + in + let specs = + Spec.list () |> Seq.map Spec.name |> List.of_seq |> List.sort String.compare + in + let () = + Alcotest.(check (list string)) "Spec list" [ "a"; "b"; "mem" ] specs + in + let keys = + Spec.keys spec_a + |> Seq.map (fun (K k) -> name k) + |> List.of_seq + |> List.sort String.compare + in + let () = Alcotest.(check (list string)) "Key list" [ "x"; "y" ] keys in + () + +let suite = [ Alcotest_lwt.test_case_sync "conf" `Quick test_conf ] diff --git a/vendors/irmin/test/irmin/test_conf.mli b/vendors/irmin/test/irmin/test_conf.mli new file mode 100644 index 000000000000..3258b5f81c75 --- /dev/null +++ b/vendors/irmin/test/irmin/test_conf.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val suite : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin/test_hash.ml b/vendors/irmin/test/irmin/test_hash.ml new file mode 100644 index 000000000000..ce653b0b3cf7 --- /dev/null +++ b/vendors/irmin/test/irmin/test_hash.ml @@ -0,0 +1,37 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin + +let test_short_hash () = + let h = Hash.BLAKE2B.hash (fun f -> f "") in + let () = + Hash.BLAKE2B.short_hash h + |> Alcotest.(check int) + "Specialised short hash" + (Int64.to_int 241225442164632184L) + in + let () = + Type.(unstage (short_hash Hash.BLAKE2B.t)) ~seed:0 h + |> Alcotest.(check int) "Generic seeded short hash" 674923654 + in + let () = + Type.(unstage (short_hash Hash.BLAKE2B.t)) ?seed:None h + |> Alcotest.(check int) "Generic unseeded short hash" 674923654 + in + () + +let suite = [ Alcotest_lwt.test_case_sync "short_hash" `Quick test_short_hash ] diff --git a/vendors/irmin/test/irmin/test_hash.mli b/vendors/irmin/test/irmin/test_hash.mli new file mode 100644 index 000000000000..3258b5f81c75 --- /dev/null +++ b/vendors/irmin/test/irmin/test_hash.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val suite : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/irmin/test_lru.ml b/vendors/irmin/test/irmin/test_lru.ml new file mode 100644 index 000000000000..95b1f9478c5a --- /dev/null +++ b/vendors/irmin/test/irmin/test_lru.ml @@ -0,0 +1,88 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +module S = struct + type t = int [@@deriving irmin ~equal ~short_hash] + + let hash t = short_hash t +end + +module M = struct + include Irmin.Backend.Lru.Make (S) + + let bindings t = + let all = ref [] in + iter t (fun k v -> all := (k, v) :: !all); + List.sort compare !all +end + +module M' = struct + include Hashtbl.Make (S) + + let bindings t = + let all = ref [] in + iter (fun k v -> all := (k, v) :: !all) t; + List.sort compare !all +end + +type key = int +type action = Add of key * int | Clear + +let add k v = Add (k, v) +let clear = Clear + +let gen_action = + QCheck.Gen.(frequency [ (5, map2 add small_int nat); (1, pure clear) ]) + +let print_action = function + | Add (k, v) -> Fmt.str "add %d %d" k v + | Clear -> Fmt.str "clear" + +let apply t = function Add (k, v) -> M.add t k v | Clear -> M.clear t +let apply' t = function Add (k, v) -> M'.replace t k v | Clear -> M'.clear t + +let run_aux create apply t = + let state = create () in + let rec aux = function + | [] -> () + | h :: rest -> + apply state h; + aux rest + in + aux t; + state + +let run = run_aux (fun () -> M.create 100) apply +let run' = run_aux (fun () -> M'.create 100) apply' +let eq m m' = M.bindings m = M'.bindings m' +let arbitrary_action = QCheck.make gen_action ~print:print_action + +let test_map = + QCheck.Test.make ~name:"Maps" ~count:10_000 + QCheck.(list arbitrary_action) + (fun t -> eq (run t) (run' t)) + +let test_weight = + QCheck.Test.make ~name:"Weights" ~count:10_000 + QCheck.(list arbitrary_action) + (fun t -> + let cap = 5 in + let tbl = run_aux (fun () -> M.create ~weight:(fun k -> k) cap) apply t in + let elts = M.bindings tbl in + let w = List.fold_left (fun acc (_, v) -> acc + v) 0 elts in + w <= cap) + +let suite = List.map QCheck_alcotest.to_alcotest [ test_map; test_weight ] diff --git a/vendors/irmin/test/irmin/test_tree.ml b/vendors/irmin/test/irmin/test_tree.ml new file mode 100644 index 000000000000..f11403a17d29 --- /dev/null +++ b/vendors/irmin/test/irmin/test_tree.ml @@ -0,0 +1,881 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +open Irmin.Export_for_backends +open Irmin + +module Metadata = struct + type t = Default | Left | Right [@@deriving irmin] + + let merge = + Merge.v t (fun ~old:_ _ _ -> Merge.conflict "Can't merge metadata") + + let default = Default +end + +module Schema = struct + module Metadata = Metadata + module Contents = Contents.String + module Path = Path.String_list + module Branch = Branch.String + module Hash = Hash.BLAKE2B + module Node = Node.Generic_key.Make (Hash) (Path) (Metadata) + module Commit = Commit.Make (Hash) + module Info = Info.Default +end + +module Store = Irmin_mem.Make (Schema) +module Tree = Store.Tree +open Schema + +type diffs = (string list * (Contents.t * Metadata.t) Diff.t) list +[@@deriving irmin] + +type kind = [ `Contents | `Node ] [@@deriving irmin] + +module Alcotest = struct + include Alcotest + + let gtestable typ = testable (Type.pp_dump typ) Type.(unstage (equal typ)) + let gcheck typ = check (gtestable typ) + let diffs = gtestable diffs_t + let assert_ msg b = check bool msg true b + + let check_tree_lwt = + let concrete_tree = gtestable Tree.concrete_t in + fun ?__POS__:pos msg ~expected b_lwt -> + b_lwt + >>= Tree.to_concrete + >|= Alcotest.check ?pos concrete_tree msg expected + + let inspect = + Alcotest.testable + (fun ppf -> function + | `Contents -> Fmt.string ppf "contents" + | `Node `Key -> Fmt.string ppf "key" + | `Node `Map -> Fmt.string ppf "map" + | `Node `Value -> Fmt.string ppf "value" + | `Node `Portable_dirty -> Fmt.string ppf "portable_dirty" + | `Node `Pruned -> Fmt.string ppf "pruned") + ( = ) +end + +let check_exn_lwt ~exn_type pos f = + Lwt.catch + (fun () -> + let* _ = f () in + Alcotest.failf ~pos + "Expected a `%s` exception, but no exception was raised." + (match exn_type with + | `Dangling_hash -> "Dangling_hash" + | `Pruned_hash -> "Pruned_hash")) + (fun exn -> + match (exn_type, exn) with + | `Dangling_hash, Tree.Dangling_hash _ -> Lwt.return_unit + | `Pruned_hash, Tree.Pruned_hash _ -> Lwt.return_unit + | _ -> Lwt.fail exn) + +(* Let-syntax for testing all possible combinations of a set of choices: *) +let ( let&* ) x f = Lwt_list.iter_s f x +and ( and&* ) l m = List.concat_map (fun a -> List.map (fun b -> (a, b)) m) l + +let ( >> ) f g x = g (f x) +let c ?(info = Metadata.default) blob = `Contents (blob, info) + +let invalid_tree () = + let+ repo = Store.Repo.v (Irmin_mem.config ()) in + let hash = Store.Hash.hash (fun f -> f "") in + Tree.shallow repo (`Node hash) + +let test_bindings _ () = + let tree = + Tree.of_concrete + (`Tree [ ("aa", c "0"); ("ab", c "1"); ("a", c "2"); ("b", c "3") ]) + in + let check_sorted = + Alcotest.(check (list string)) + "Bindings are reported in lexicographic order" [ "a"; "aa"; "ab"; "b" ] + in + (* [Tree.list] returns all keys in lexicographic order *) + Tree.list tree [] >|= (List.map fst >> check_sorted) + +let test_paginated_bindings _ () = + let tree = + Tree.of_concrete + (`Tree + [ + ("aa", c "0"); + ("a", c "1"); + ("bbb", c "3"); + ("b", c "3"); + ("aaa", c "2"); + ]) + in + let check_sorted expected = + Alcotest.(check (list string)) + "Bindings are reported in lexicographic order" expected + in + let* () = + Tree.list ~offset:0 ~length:2 tree [] + >|= (List.map fst >> check_sorted [ "a"; "aa" ]) + in + let* () = + Tree.list ~offset:2 ~length:3 tree [] + >|= (List.map fst >> check_sorted [ "aaa"; "b"; "bbb" ]) + in + let* () = + Tree.list ~offset:1 ~length:1 tree [] + >|= (List.map fst >> check_sorted [ "aa" ]) + in + let* () = + Tree.list ~offset:4 ~length:2 tree [] + >|= (List.map fst >> check_sorted [ "bbb" ]) + in + let* () = + Tree.list ~offset:5 ~length:2 tree [] >|= (List.map fst >> check_sorted []) + in + Lwt.return_unit + +let tree bs = Tree.of_concrete (`Tree bs) + +(** Basic tests of the [Tree.diff] operation. *) +let test_diff _ () = + let empty = tree [] in + let single = tree [ ("k", c "v") ] in + + (* Adding a single key *) + let* () = + Tree.diff empty single + >|= Alcotest.(check diffs) + "Added [k \226\134\146 v]" + [ ([ "k" ], `Added ("v", Default)) ] + in + (* Removing a single key *) + let* () = + Tree.diff single empty + >|= Alcotest.(check diffs) + "Removed [k \226\134\146 v]" + [ ([ "k" ], `Removed ("v", Default)) ] + in + (* Changing metadata *) + Tree.diff + (tree [ ("k", c ~info:Left "v") ]) + (tree [ ("k", c ~info:Right "v") ]) + >|= Alcotest.(check diffs) + "Changed metadata" + [ ([ "k" ], `Updated (("v", Left), ("v", Right))) ] + +let test_empty _ () = + let* () = + Alcotest.check_tree_lwt "The empty tree is empty" ~expected:(`Tree []) + (Lwt.return (Tree.empty ())) + in + + (* Ensure that different [empty] values have disjoint cache state. + + This is a regression test for a bug in which all [Tree.empty] values had + shared cache state and any keys obtained from [export] were discarded (to + avoid sharing keys from different repositories). *) + let* () = + let* repo = Store.Repo.v (Irmin_mem.config ()) in + let empty_exported = Tree.empty () and empty_not_exported = Tree.empty () in + let+ () = + Store.Backend.Repo.batch repo (fun c n _ -> + Store.save_tree repo c n empty_exported >|= ignore) + in + Alcotest.(check inspect) + "The exported empty tree is now in Key form" (`Node `Key) + (Tree.inspect empty_exported); + Alcotest.(check inspect) + "The non-exported empty tree should still be represented as a Map" + (`Node `Map) + (Tree.inspect empty_not_exported) + in + + Lwt.return_unit + +let test_add _ () = + let sample_tree ?(ab = "ab_v") ?ac () : Tree.concrete = + let ac = match ac with Some ac -> [ ("ac", ac) ] | None -> [] in + `Tree [ ("a", `Tree ([ ("aa", c "0"); ("ab", c ab) ] @ ac)); ("b", c "3") ] + in + + let* () = + Alcotest.check_tree_lwt "Adding a root value to an empty tree" + ~expected:(c "1") + (Tree.add (Tree.empty ()) [] "1") + in + + let* () = + let t = Tree.of_concrete (sample_tree ()) in + let expected = sample_tree ~ab:"new_value" () in + Alcotest.check_tree_lwt "Replacing an existing value in a tree" ~expected + (Tree.add t [ "a"; "ab" ] "new_value") + in + + let* () = + let t = Tree.of_concrete (sample_tree ()) in + let expected = sample_tree ~ac:(`Tree [ ("aca", c "new_value") ]) () in + Alcotest.check_tree_lwt + "Adding at a non-existent path in a tree creates necessary intermediate \ + nodes" + ~expected + (Tree.add t [ "a"; "ac"; "aca" ] "new_value") + in + + let* () = + let t = Tree.of_concrete (c "1") in + let+ t' = Tree.add t [] "1" in + Alcotest.assert_ "Re-adding a root value preserves physical equality" + (t == t') + in + + let* () = + let t = tree [ ("a", `Tree [ ("b", c "1") ]) ] in + let+ t' = Tree.add t [ "a"; "b" ] "1" in + Alcotest.assert_ "Re-adding a non-root value preserves physical equality" + (t == t') + in + + Lwt.return_unit + +let test_remove _ () = + let tree = + Tree.of_concrete + (`Tree [ ("a", `Tree [ ("aa", c "0"); ("ab", c "1") ]); ("b", c "3") ]) + in + + let* () = + let t = Tree.empty () in + let+ t' = Tree.remove t [] in + Alcotest.assert_ "Removing in an empty tree preserves physical equality" + (t == t') + in + + let* () = + let+ tree' = Tree.remove tree [ "a"; "non"; "existent"; "path" ] in + Alcotest.assert_ + "Removing at a non-existent path in a non-empty tree preserves physical \ + equality" + (tree == tree') + in + + let* () = + let tree = Tree.of_concrete (c "1") in + let+ tree' = Tree.remove tree [ "a"; "non"; "existent"; "path" ] in + Alcotest.assert_ + "Removing at a non-existent path in a root contents value preserves \ + physical equality" + (tree == tree') + in + + let* () = + Alcotest.check_tree_lwt + "Removing a root contents value results in an empty root node." + ~expected:(`Tree []) + (Tree.remove (Tree.of_concrete (c "1")) []) + in + + Lwt.return_unit + +(* Build a function that requires a given input, always returns a given output, + and can be called at most once. *) +let transform_once : type a b. a Type.t -> a -> b -> a -> b = + fun typ -> + let equal = Type.(unstage (equal typ)) in + let pp = Type.pp_dump typ in + fun source target -> + let called = ref false in + fun x -> + if !called then Alcotest.failf "Transformation called more than once"; + called := true; + if equal source x then target + else Alcotest.failf "Expected %a but got %a" pp source pp x + +let test_update _ () = + let unrelated_binding = ("a_unrelated", c "<>") in + let abc ?info v = + `Tree + [ ("a", `Tree [ ("b", `Tree [ ("c", c ?info v) ]) ]); unrelated_binding ] + in + let abc1 = Tree.of_concrete (abc "1") in + let ( --> ) = transform_once [%typ: string option] in + + let* () = + Alcotest.check_tree_lwt + "Changing the value of a root contents node results in a new contents \ + node." + ~expected:(c "2") + (Tree.update (Tree.of_concrete (c "1")) [] (Some "1" --> Some "2")) + in + + let* () = + Alcotest.check_tree_lwt + "Removing a root contents node results in an empty root node." + ~expected:(`Tree []) + (Tree.update (Tree.of_concrete (c "1")) [] (Some "1" --> None)) + in + + let* () = + Alcotest.check_tree_lwt + "Updating a root node to a contents value removes all bindings and sets \ + the correct metadata." + ~expected:(c ~info:Metadata.Right "2") + (Tree.update ~metadata:Metadata.Right abc1 [] (None --> Some "2")) + in + + let* () = + (* Replacing a root node with a dangling hash does not raise an + exception. *) + let* invalid_tree = invalid_tree () in + Tree.update_tree abc1 [] (function + | Some _ -> Some invalid_tree + | None -> assert false) + >|= ignore + in + + let* () = + Alcotest.check_tree_lwt + "Updating at an existing contents path changes the contents value \ + appropriately." + ~expected:(abc "2") + (Tree.update abc1 [ "a"; "b"; "c" ] (Some "1" --> Some "2")) + in + + let* () = + let s = "1" and s' = "1" ^ "" in + assert (s != s'); + let+ abc1' = Tree.update abc1 [ "a"; "b"; "c" ] (Some s --> Some s') in + Alcotest.assert_ + "Performing a no-op change to tree contents preserves physical equality" + (abc1 == abc1') + in + + let* () = + let+ abc1' = + Tree.update_tree abc1 [ "a"; "b" ] (function + | Some t -> Some t + | None -> assert false) + in + Alcotest.assert_ + "Replacing a subtree node with a physically-equal one preserves physical \ + equality" + (abc1 == abc1') + in + + let* () = + Alcotest.check_tree_lwt + "Changing the metadata of an existing contents value updates the tree." + ~expected:(abc ~info:Metadata.Left "1") + (Tree.update ~metadata:Metadata.Left abc1 [ "a"; "b"; "c" ] + (Some "1" --> Some "1")) + in + + let* () = + Alcotest.check_tree_lwt + "Removing a siblingless contents value causes newly-empty directories to \ + be pruned." + ~expected:(`Tree [ unrelated_binding ]) + (Tree.update abc1 [ "a"; "b"; "c" ] (Some "1" --> None)) + in + + let* () = + Alcotest.check_tree_lwt + "Removing a siblingless node causes newly-empty directories to be pruned" + ~expected:(`Tree [ unrelated_binding ]) + (Tree.update_tree abc1 [ "a"; "b" ] (function + | Some _ -> None + | None -> assert false)) + in + + let* () = + Alcotest.check_tree_lwt + "Updating at a non-existent contents path adds a new directory entry." + ~expected: + (`Tree + [ + ("a", `Tree [ ("b", `Tree [ ("c", c "1"); ("c'", c "new_value") ]) ]); + unrelated_binding; + ]) + (Tree.update abc1 [ "a"; "b"; "c'" ] (None --> Some "new_value")) + in + + let* () = + Alcotest.check_tree_lwt + "Updating at an existing node path replaces the subtree with the given \ + element." + ~expected: + (`Tree [ ("a", `Tree [ ("b", c "new_value") ]); unrelated_binding ]) + (Tree.update abc1 [ "a"; "b" ] (None --> Some "new_value")) + in + + let* () = + Alcotest.check_tree_lwt + "Updating at a path in an empty tree creates the necessary intermediate \ + nodes with the new contents." + ~expected:(`Tree [ ("a", `Tree [ ("b", `Tree [ ("c", c "1") ]) ]) ]) + (Tree.update (Tree.empty ()) [ "a"; "b"; "c" ] (None --> Some "1")) + in + + let* () = + let+ abc1' = Tree.update abc1 [ "a"; "b"; "c"; "d"; "e" ] (None --> None) in + Alcotest.assert_ + "Removing at a non-existent path in a non-empty tree preserves physical \ + equality." + (abc1 == abc1') + in + + let* () = + let t = Tree.empty () in + let+ t' = Tree.update t [] (None --> None) in + Alcotest.assert_ "Removing from an empty tree preserves physical equality" + (t == t') + in + + let* () = + let+ abc1' = + Tree.update_tree abc1 [ "a"; "b"; "d" ] (function + | None -> Some (Tree.empty ()) + | Some _ -> assert false) + in + Alcotest.assert_ + "Adding an empty tree at an empty location preserves physical equality" + (abc1 == abc1') + in + + Lwt.return_unit + +(* Correct stats for a completely lazy tree *) +let lazy_stats = Tree.{ nodes = 0; leafs = 0; skips = 1; depth = 0; width = 0 } + +(* Take a tree and persist it to some underlying store, making it lazy. *) +let persist_tree ?clear : Store.tree -> Store.tree Lwt.t = + fun tree -> + let* store = Store.Repo.v (Irmin_mem.config ()) >>= Store.empty in + let* () = Store.set_tree_exn ?clear ~info:Store.Info.none store [] tree in + Store.tree store + +type path = Store.Path.t [@@deriving irmin ~pp ~equal] + +let test_clear _ () = + (* 1. Build a tree *) + let size = 830829 in + let* t = + List.init size string_of_int + |> Lwt_list.fold_left_s (fun acc i -> Tree.add acc [ i ] i) (Tree.empty ()) + in + (* Check the state of the root and root/42 *) + Alcotest.(check inspect) "Before clear, root" (`Node `Map) (Tree.inspect t); + let* () = + Tree.stats ~force:false t + >|= Alcotest.(gcheck Tree.stats_t) + "Before clear, root node is eagerly evaluated" + { nodes = 1; leafs = size; skips = 0; depth = 1; width = size } + in + let* entry42 = Tree.find_tree t [ "42" ] >|= Option.get in + Alcotest.(check inspect) + "Before clear, root/42" `Contents (Tree.inspect entry42); + let* () = + let dont_skip k = Alcotest.failf "should not have skipped %a" pp_path k in + Tree.fold ~force:(`False dont_skip) entry42 () + in + (* 2. Clear on non-persisted *) + Tree.clear t; + (* The state of the tree shouldn't have changed after this clear *) + Alcotest.(check inspect) "Before persist" (`Node `Map) (Tree.inspect t); + let* () = + Tree.stats ~force:false t + >|= Alcotest.(gcheck Tree.stats_t) + "Before persist, root node is eagerly evaluated" + { nodes = 1; leafs = size; skips = 0; depth = 1; width = size } + in + let* entry42 = Tree.find_tree t [ "42" ] >|= Option.get in + Alcotest.(check inspect) "Before persist" `Contents (Tree.inspect entry42); + let* () = + let dont_skip k = Alcotest.failf "should not have skipped %a" pp_path k in + Tree.fold ~force:(`False dont_skip) entry42 () + in + (* 3. Persist (and implicitly clear) *) + let* _ = persist_tree t in + (* Check the state of the root *) + Alcotest.(check inspect) "After persist+clear" (`Node `Key) (Tree.inspect t); + let* () = + Tree.stats ~force:false t + >|= Alcotest.(gcheck Tree.stats_t) + "After persist+clear, root node is no longer cached" lazy_stats + in + Lwt.return_unit + +let test_minimal_reads _ () = + (* 1. Build a tree *) + let size = 10 in + let* t = + List.init size string_of_int + |> Lwt_list.fold_left_s (fun acc i -> Tree.add acc [ i ] i) (Tree.empty ()) + in + + (* Persist with no clear *) + Tree.reset_counters (); + let* _ = persist_tree ~clear:false t in + let* _ = Tree.find t [ "0" ] in + let cnt = Tree.counters () in + Alcotest.(check int) "no reads" 0 cnt.node_find; + + (* Persist with clear *) + Tree.reset_counters (); + let* _ = persist_tree ~clear:true t in + let* _ = Tree.find_tree t [ "0" ] in + let cnt = Tree.counters () in + Alcotest.(check int) "reads" 1 cnt.node_find; + Lwt.return_unit + +let with_binding k v t = Tree.add_tree t k v + +let clear_and_assert_lazy tree = + let* _ = persist_tree tree in + Tree.clear tree; + Tree.stats ~force:false tree + >|= Alcotest.(gcheck Tree.stats_t) + "Initially the tree is entirely lazy" lazy_stats + +let test_fold_force _ () = + let* invalid_tree = + let+ repo = Store.Repo.v (Irmin_mem.config ()) in + let hash = Store.Hash.hash (fun f -> f "") in + Tree.shallow repo (`Node hash) + in + + (* Ensure that [fold] doesn't force a lazy tree when [~force:(`False f)], + and that [f] is called the correct number of times. *) + let* () = + let* tree = + Tree.singleton [ "existing"; "subtree" ] "value" + |> with_binding [ "dangling"; "subtree"; "hash" ] invalid_tree + >>= with_binding [ "other"; "lazy"; "path" ] invalid_tree + in + let force = `False (Lwt.wrap2 List.cons) in + Tree.fold ~force tree [] + >|= Alcotest.(check (slist (list string) Stdlib.compare)) + "Unforced paths" + [ [ "dangling"; "subtree"; "hash" ]; [ "other"; "lazy"; "path" ] ] + in + let create_sample_tree () = + Tree.of_concrete + (`Tree + [ + ("a", `Tree [ ("aa", c "v-aa"); ("ab", c "v-ab"); ("ac", c "v-ac") ]); + ("b", c "v-b"); + ("c", c "v-c"); + ]) + in + let eager_stats = + Tree.{ nodes = 2; leafs = 5; skips = 0; depth = 2; width = 3 } + in + + (* Ensure that [fold ~force:`True ~cache:true] forces all lazy trees. *) + let* () = + let sample_tree = create_sample_tree () in + let* () = clear_and_assert_lazy sample_tree in + Tree.fold ~force:`True ~cache:true sample_tree () >>= fun () -> + Tree.stats ~force:false sample_tree + >|= Alcotest.(gcheck Tree.stats_t) + "After folding, the tree is eagerly evaluated" eager_stats + in + + (* Ensure that [fold ~force:`True ~cache:false] visits all children and does + not leave them cached. *) + let* () = + let sample_tree = create_sample_tree () in + clear_and_assert_lazy sample_tree >>= fun () -> + let* contents = + Tree.fold ~force:`True ~cache:false + ~contents:(fun _ -> Lwt.wrap2 List.cons) + sample_tree [] + in + let+ () = + Tree.stats ~force:false sample_tree + >|= Alcotest.(gcheck Tree.stats_t) + "After folding, the tree is cleared" lazy_stats + in + Alcotest.(check (slist string compare)) + "During forced fold, all contents were traversed" + [ "v-aa"; "v-ab"; "v-ac"; "v-b"; "v-c" ] + contents + in + + (* Ensure that [fold ~force:`True ~cache:false] visits newly added values and + updated values only once and does not visit removed values. *) + let* () = + let sample_tree = create_sample_tree () in + let* () = clear_and_assert_lazy sample_tree in + Tree.remove sample_tree [ "a"; "ab" ] >>= fun updated_tree -> + Tree.add updated_tree [ "a"; "ad" ] "v-ad" >>= fun updated_tree -> + Tree.add updated_tree [ "a"; "ac" ] "v-acc" >>= fun updated_tree -> + let visited = ref [] in + let contents k v () = + if equal_path k [ "a"; "ab" ] then + Alcotest.failf + "Removed contents at %a should not be visited during fold" pp_path k; + if equal_path k [ "a"; "ac" ] then + if not (String.equal v "v-acc") then + Alcotest.failf "Outdated contents at %a visited during fold" pp_path k; + if List.mem ~equal:equal_path k !visited then + Alcotest.failf "Visited node at %a twice during fold" pp_path k + else visited := k :: !visited; + Lwt.return_unit + in + Tree.fold ~force:`True ~cache:false ~contents updated_tree () >|= fun () -> + Alcotest.(check bool) + "Newly added contents visited" + (List.mem ~equal:equal_path [ "a"; "ad" ] !visited) + true + in + + Lwt.return_unit + +(* Tests of "broken" trees: trees that can't be dereferenced. Tree currently + supports two varieties of broken tree: + + - shallow trees containing [(repo, key)] pairs for which [repo] doesn't + contain [key]. Attempted dereferences should raise [Dangling_hash]. + + - pruned trees (hash-only tree nodes, with no underlying repository). + Attempted dereferences should raise [Pruned_hash]. *) +module Broken = struct + let shallow_of_ptr kinded_key = + let+ repo = Store.Repo.v (Irmin_mem.config ()) in + Tree.shallow repo kinded_key + + let pruned_of_ptr kinded_hash = Lwt.return (Tree.pruned kinded_hash) + let random_string32 = Irmin.Type.(unstage (random (string_of (`Fixed 32)))) + + let random_contents () = + let value = Tree.of_concrete (c (random_string32 ())) in + let value_ptr = `Contents (Tree.hash value, Metadata.default) in + (value, value_ptr) + + let random_node () = + let value = tree [ ("k", c (random_string32 ())) ] in + let value_ptr = `Node (Tree.hash value) in + (value, value_ptr) + + let test_hashes _ () = + let&* leaf_type, (leaf, leaf_ptr) = + [ ("contents", random_contents ()); ("node", random_node ()) ] + and&* operation_name, operation = + [ ("shallow", shallow_of_ptr); ("pruned", pruned_of_ptr) ] + and&* path = [ []; [ "k" ] ] in + let* leaf_broken = operation leaf_ptr in + let* hash_actual = Tree.(add_tree (empty ())) path leaf >|= Tree.hash in + let+ hash_expected = + Tree.(add_tree (empty ())) path leaf_broken >|= Tree.hash + in + Alcotest.(gcheck Store.Hash.t) + (Fmt.str + "Hashing a %s %s value at path %a is equivalent to hashing the \ + non-broken %s" + operation_name leaf_type + Fmt.Dump.(list string) + path leaf_type) + hash_expected hash_actual + + let test_trees _ () = + let run_tests ~exn_type ~broken_contents ~broken_node ~path = + [%logs.app + "Testing operations on a tree with a broken position at %a" pp_path path]; + let* broken_leaf = Tree.(add_tree (empty ())) path broken_contents in + let* broken_node = Tree.(add_tree (empty ())) path broken_node in + let beneath = path @ [ "a"; "b"; "c" ] in + let blob = "v" and node = tree [ ("k", c "v") ] in + let add_blob_or_node path = + [ + (fun tr -> Tree.(add tr path blob)); + (fun tr -> Tree.(add_tree tr path node)); + ] + in + + (* [add] on broken nodes/contents replaces the broken position. *) + let* () = + let&* broken = [ broken_leaf; broken_node ] + and&* add = add_blob_or_node path in + let* expected = add (Tree.empty ()) >>= Tree.to_concrete in + Alcotest.check_tree_lwt ~__POS__ "" ~expected (add broken) + in + + (* [add] _beneath_ a broken contents value also works fine, but on broken + nodes an exception is raised. (We can't know what the node's contents are, + so there's no valid return tree.) *) + let* () = + let&* add_beneath = add_blob_or_node beneath in + let* expected = add_beneath (Tree.empty ()) >>= Tree.to_concrete in + Alcotest.check_tree_lwt ~__POS__ "" ~expected (add_beneath broken_leaf) + in + let* () = + let&* add_beneath = add_blob_or_node beneath in + check_exn_lwt ~exn_type __POS__ (fun () -> add_beneath broken_node) + in + + (* [find] on broken contents raises an exception (can't recover contents), + but _beneath_ broken contents it returns [None] (mismatched type). (The + behaviour is reversed for broken nodes.) *) + let* () = + check_exn_lwt ~exn_type __POS__ (fun () -> Tree.find broken_leaf path) + in + let* () = + check_exn_lwt ~exn_type __POS__ (fun () -> + Tree.find broken_node beneath) + in + let* () = + Tree.find broken_leaf beneath + >|= Alcotest.(check ~pos:__POS__ (option reject)) "" None + in + let* () = + Store.Tree.find broken_node path + >|= Alcotest.(check ~pos:__POS__ (option reject)) "" None + in + + (* [list] on (or beneath) broken contents returns the empty list, but on + (or beneath) broken nodes an exception is raised. *) + let* () = + let&* path = [ path; beneath ] in + Tree.list broken_leaf path + >|= Alcotest.(check ~pos:__POS__ (list reject)) "" [] + in + let* () = + let&* path = [ path; beneath ] in + check_exn_lwt ~exn_type __POS__ (fun () -> Tree.list broken_node path) + in + Lwt.return_unit + in + let&* path = [ []; [ "k" ] ] + and&* exn_type, tree_of_ptr = + [ (`Dangling_hash, shallow_of_ptr); (`Pruned_hash, pruned_of_ptr) ] + in + let* broken_contents = tree_of_ptr (snd (random_contents ())) in + let* broken_node = tree_of_ptr (snd (random_node ())) in + run_tests ~exn_type ~broken_contents ~broken_node ~path + + let test_pruned_fold _ () = + let&* _, ptr = [ random_contents (); random_node () ] + and&* path = [ []; [ "k" ] ] in + let* tree = Tree.(add_tree (empty ())) path (Tree.pruned ptr) in + + (* Folding over a pruned tree with [force:`True] should fail: *) + let* () = + check_exn_lwt ~exn_type:`Pruned_hash __POS__ (fun () -> + Tree.fold ~force:`True tree ()) + in + + (* But folding with [force:`False] should not: *) + let* () = Tree.fold ~force:(`False (fun _ -> Lwt.return)) tree () in + + (* Similarly, attempting to export a pruned tree should fail: *) + let* repo = Store.Repo.v (Irmin_mem.config ()) in + check_exn_lwt ~exn_type:`Pruned_hash __POS__ (fun () -> + Store.Backend.Repo.batch repo (fun c n _ -> + Store.save_tree repo c n tree >|= ignore)) +end + +let test_kind_empty_path _ () = + let cont = c "c" |> Tree.of_concrete in + let tree = `Tree [ ("k", c "c") ] |> Tree.of_concrete in + let* k = Tree.kind cont [] in + Alcotest.(check (option (gtestable kind_t))) + "Kind of empty path in content" (Some `Contents) k; + let* k = Tree.kind tree [] in + Alcotest.(check (option (gtestable kind_t))) + "Kind of empty path in tree" (Some `Node) k; + Lwt.return_unit + +let test_generic_equality _ () = + (* Regression test for a bug in which the equality derived from [tree_t] did + not respect equivalences between in-memory trees and lazy trees. *) + let* tree = persist_tree (tree [ ("k", c "v") ]) in + let+ should_be_empty = Tree.remove tree [ "k" ] in + Alcotest.(gcheck Store.tree_t) + "Modified empty tree is equal to [(Tree.empty ())]" (Tree.empty ()) + should_be_empty + +let test_is_empty _ () = + (* Test for equivalence against an [is_equal] derived from generic equality, + for backwards compatibility. *) + let is_empty = + let equal = Type.unstage (Type.equal Store.tree_t) in + fun t -> + let reference = equal t (Tree.empty ()) in + let candidate = Tree.is_empty t in + Alcotest.(check bool) + "`equal (Tree.empty ())` agrees with `is_empty`" reference candidate; + candidate + in + let kv = tree [ ("k", c "v") ] in + let () = Alcotest.(check bool) "empty tree" true (is_empty (Tree.empty ())) in + let () = Alcotest.(check bool) "non-empty tree" false (is_empty kv) in + let* () = + let+ tree = Tree.remove kv [ "k" ] in + Alcotest.(check bool) "emptied tree" true (is_empty tree) + in + let* repo = Store.Repo.v (Irmin_mem.config ()) in + let () = + let shallow_empty = Tree.(shallow repo (`Node (hash (empty ())))) in + Alcotest.(check bool) "shallow empty tree" true (is_empty shallow_empty) + in + let () = + let shallow_empty = Tree.(shallow repo (`Node (hash kv))) in + Alcotest.(check bool) + "shallow non-empty tree" false (is_empty shallow_empty) + in + Lwt.return_unit + +let test_of_concrete _ () = + let* () = + let aa = ("aa", c "aa-v") in + let ac = ("ac", c "ac-v") in + let input = tree [ ("a", `Tree [ aa; ("ab", `Tree []); ac ]) ] in + let pruned = `Tree [ ("a", `Tree [ aa; ac ]) ] in + Alcotest.check_tree_lwt "Empty subtrees are pruned" ~expected:pruned + (Tree.to_concrete input >|= Tree.of_concrete) + in + + let () = + Alcotest.check_raises "Tree with duplicate bindings is rejected" + (Invalid_argument "of_concrete: duplicate bindings for step `k`") + (fun () -> + ignore (Tree.of_concrete (`Tree [ ("k", c "v1"); ("k", c "v2") ]))) + in + + Lwt.return_unit + +let suite = + [ + Alcotest_lwt.test_case "bindings" `Quick test_bindings; + Alcotest_lwt.test_case "paginated bindings" `Quick test_paginated_bindings; + Alcotest_lwt.test_case "diff" `Quick test_diff; + Alcotest_lwt.test_case "empty" `Quick test_empty; + Alcotest_lwt.test_case "add" `Quick test_add; + Alcotest_lwt.test_case "remove" `Quick test_remove; + Alcotest_lwt.test_case "update" `Quick test_update; + Alcotest_lwt.test_case "clear" `Quick test_clear; + Alcotest_lwt.test_case "minimal_reads" `Quick test_minimal_reads; + Alcotest_lwt.test_case "fold" `Quick test_fold_force; + Alcotest_lwt.test_case "Broken.hashes" `Quick Broken.test_hashes; + Alcotest_lwt.test_case "Broken.trees" `Quick Broken.test_trees; + Alcotest_lwt.test_case "Broken.pruned_fold" `Quick Broken.test_pruned_fold; + Alcotest_lwt.test_case "kind of empty path" `Quick test_kind_empty_path; + Alcotest_lwt.test_case "generic equality" `Quick test_generic_equality; + Alcotest_lwt.test_case "is_empty" `Quick test_is_empty; + Alcotest_lwt.test_case "of_concrete" `Quick test_of_concrete; + ] diff --git a/vendors/irmin/test/irmin/test_tree.mli b/vendors/irmin/test/irmin/test_tree.mli new file mode 100644 index 000000000000..3258b5f81c75 --- /dev/null +++ b/vendors/irmin/test/irmin/test_tree.mli @@ -0,0 +1,17 @@ +(* + * Copyright (c) 2013-2022 Thomas Gazagnaire + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +val suite : unit Alcotest_lwt.test_case list diff --git a/vendors/irmin/test/libirmin/dune b/vendors/irmin/test/libirmin/dune new file mode 100644 index 000000000000..d71a6fa7822b --- /dev/null +++ b/vendors/irmin/test/libirmin/dune @@ -0,0 +1,27 @@ +(rule + (alias runtest) + (package libirmin) + (action + (setenv + DYLD_FALLBACK_LIBRARY_PATH + ../../src/libirmin/lib + (setenv + LD_LIBRARY_PATH + ../../src/libirmin/lib + (run ./test.exe))))) + +(rule + (targets test.exe) + (deps + (file test.c) + (file greatest.h) + (package libirmin)) + (action + (run + %{cc} + -I../../src/libirmin/lib + -o + test.exe + test.c + -L../../src/libirmin/lib + -lirmin))) diff --git a/vendors/irmin/test/libirmin/greatest.h b/vendors/irmin/test/libirmin/greatest.h new file mode 100644 index 000000000000..4c2b3f2d93da --- /dev/null +++ b/vendors/irmin/test/libirmin/greatest.h @@ -0,0 +1,1290 @@ +/* + * Copyright (c) 2011-2021 Scott Vokes + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef GREATEST_H +#define GREATEST_H + +#if defined(__cplusplus) && !defined(GREATEST_NO_EXTERN_CPLUSPLUS) +extern "C" { +#endif + +/* 1.5.0 */ +#define GREATEST_VERSION_MAJOR 1 +#define GREATEST_VERSION_MINOR 5 +#define GREATEST_VERSION_PATCH 0 + +/* A unit testing system for C, contained in 1 file. + * It doesn't use dynamic allocation or depend on anything + * beyond ANSI C89. + * + * An up-to-date version can be found at: + * https://github.com/silentbicycle/greatest/ + */ + +/********************************************************************* + * Minimal test runner template + *********************************************************************/ +#if 0 + +#include "greatest.h" + +TEST foo_should_foo(void) { + PASS(); +} + +static void setup_cb(void *data) { + printf("setup callback for each test case\n"); +} + +static void teardown_cb(void *data) { + printf("teardown callback for each test case\n"); +} + +SUITE(suite) { + /* Optional setup/teardown callbacks which will be run before/after + * every test case. If using a test suite, they will be cleared when + * the suite finishes. */ + SET_SETUP(setup_cb, voidp_to_callback_data); + SET_TEARDOWN(teardown_cb, voidp_to_callback_data); + + RUN_TEST(foo_should_foo); +} + +/* Add definitions that need to be in the test runner's main file. */ +GREATEST_MAIN_DEFS(); + +/* Set up, run suite(s) of tests, report pass/fail/skip stats. */ +int run_tests(void) { + GREATEST_INIT(); /* init. greatest internals */ + /* List of suites to run (if any). */ + RUN_SUITE(suite); + + /* Tests can also be run directly, without using test suites. */ + RUN_TEST(foo_should_foo); + + GREATEST_PRINT_REPORT(); /* display results */ + return greatest_all_passed(); +} + +/* main(), for a standalone command-line test runner. + * This replaces run_tests above, and adds command line option + * handling and exiting with a pass/fail status. */ +int main(int argc, char **argv) { + GREATEST_MAIN_BEGIN(); /* init & parse command-line args */ + RUN_SUITE(suite); + GREATEST_MAIN_END(); /* display results */ +} + +#endif +/*********************************************************************/ + +#include +#include +#include +#include + +/*********** + * Options * + ***********/ + +/* Default column width for non-verbose output. */ +#ifndef GREATEST_DEFAULT_WIDTH +#define GREATEST_DEFAULT_WIDTH 72 +#endif + +/* FILE *, for test logging. */ +#ifndef GREATEST_STDOUT +#define GREATEST_STDOUT stdout +#endif + +/* Remove GREATEST_ prefix from most commonly used symbols? */ +#ifndef GREATEST_USE_ABBREVS +#define GREATEST_USE_ABBREVS 1 +#endif + +/* Set to 0 to disable all use of setjmp/longjmp. */ +#ifndef GREATEST_USE_LONGJMP +#define GREATEST_USE_LONGJMP 0 +#endif + +/* Make it possible to replace fprintf with another + * function with the same interface. */ +#ifndef GREATEST_FPRINTF +#define GREATEST_FPRINTF fprintf +#endif + +#if GREATEST_USE_LONGJMP +#include +#endif + +/* Set to 0 to disable all use of time.h / clock(). */ +#ifndef GREATEST_USE_TIME +#define GREATEST_USE_TIME 1 +#endif + +#if GREATEST_USE_TIME +#include +#endif + +/* Floating point type, for ASSERT_IN_RANGE. */ +#ifndef GREATEST_FLOAT +#define GREATEST_FLOAT double +#define GREATEST_FLOAT_FMT "%g" +#endif + +/* Size of buffer for test name + optional '_' separator and suffix */ +#ifndef GREATEST_TESTNAME_BUF_SIZE +#define GREATEST_TESTNAME_BUF_SIZE 128 +#endif + +/********* + * Types * + *********/ + +/* Info for the current running suite. */ +typedef struct greatest_suite_info { + unsigned int tests_run; + unsigned int passed; + unsigned int failed; + unsigned int skipped; + +#if GREATEST_USE_TIME + /* timers, pre/post running suite and individual tests */ + clock_t pre_suite; + clock_t post_suite; + clock_t pre_test; + clock_t post_test; +#endif +} greatest_suite_info; + +/* Type for a suite function. */ +typedef void greatest_suite_cb(void); + +/* Types for setup/teardown callbacks. If non-NULL, these will be run + * and passed the pointer to their additional data. */ +typedef void greatest_setup_cb(void *udata); +typedef void greatest_teardown_cb(void *udata); + +/* Type for an equality comparison between two pointers of the same type. + * Should return non-0 if equal, otherwise 0. + * UDATA is a closure value, passed through from ASSERT_EQUAL_T[m]. */ +typedef int greatest_equal_cb(const void *expd, const void *got, void *udata); + +/* Type for a callback that prints a value pointed to by T. + * Return value has the same meaning as printf's. + * UDATA is a closure value, passed through from ASSERT_EQUAL_T[m]. */ +typedef int greatest_printf_cb(const void *t, void *udata); + +/* Callbacks for an arbitrary type; needed for type-specific + * comparisons via GREATEST_ASSERT_EQUAL_T[m].*/ +typedef struct greatest_type_info { + greatest_equal_cb *equal; + greatest_printf_cb *print; +} greatest_type_info; + +typedef struct greatest_memory_cmp_env { + const unsigned char *exp; + const unsigned char *got; + size_t size; +} greatest_memory_cmp_env; + +/* Callbacks for string and raw memory types. */ +extern greatest_type_info greatest_type_info_string; +extern greatest_type_info greatest_type_info_memory; + +typedef enum { + GREATEST_FLAG_FIRST_FAIL = 0x01, + GREATEST_FLAG_LIST_ONLY = 0x02, + GREATEST_FLAG_ABORT_ON_FAIL = 0x04 +} greatest_flag_t; + +/* Internal state for a PRNG, used to shuffle test order. */ +struct greatest_prng { + unsigned char random_order; /* use random ordering? */ + unsigned char initialized; /* is random ordering initialized? */ + unsigned char pad_0[6]; + unsigned long state; /* PRNG state */ + unsigned long count; /* how many tests, this pass */ + unsigned long count_ceil; /* total number of tests */ + unsigned long count_run; /* total tests run */ + unsigned long a; /* LCG multiplier */ + unsigned long c; /* LCG increment */ + unsigned long m; /* LCG modulus, based on count_ceil */ +}; + +/* Struct containing all test runner state. */ +typedef struct greatest_run_info { + unsigned char flags; + unsigned char verbosity; + unsigned char running_test; /* guard for nested RUN_TEST calls */ + unsigned char exact_name_match; + + unsigned int tests_run; /* total test count */ + + /* currently running test suite */ + greatest_suite_info suite; + + /* overall pass/fail/skip counts */ + unsigned int passed; + unsigned int failed; + unsigned int skipped; + unsigned int assertions; + + /* info to print about the most recent failure */ + unsigned int fail_line; + unsigned int pad_1; + const char *fail_file; + const char *msg; + + /* current setup/teardown hooks and userdata */ + greatest_setup_cb *setup; + void *setup_udata; + greatest_teardown_cb *teardown; + void *teardown_udata; + + /* formatting info for ".....s...F"-style output */ + unsigned int col; + unsigned int width; + + /* only run a specific suite or test */ + const char *suite_filter; + const char *test_filter; + const char *test_exclude; + const char *name_suffix; /* print suffix with test name */ + char name_buf[GREATEST_TESTNAME_BUF_SIZE]; + + struct greatest_prng prng[2]; /* 0: suites, 1: tests */ + +#if GREATEST_USE_TIME + /* overall timers */ + clock_t begin; + clock_t end; +#endif + +#if GREATEST_USE_LONGJMP + int pad_jmp_buf; + unsigned char pad_2[4]; + jmp_buf jump_dest; +#endif +} greatest_run_info; + +struct greatest_report_t { + /* overall pass/fail/skip counts */ + unsigned int passed; + unsigned int failed; + unsigned int skipped; + unsigned int assertions; +}; + +/* Global var for the current testing context. + * Initialized by GREATEST_MAIN_DEFS(). */ +extern greatest_run_info greatest_info; + +/* Type for ASSERT_ENUM_EQ's ENUM_STR argument. */ +typedef const char *greatest_enum_str_fun(int value); + +/********************** + * Exported functions * + **********************/ + +/* These are used internally by greatest macros. */ +int greatest_test_pre(const char *name); +void greatest_test_post(int res); +int greatest_do_assert_equal_t(const void *expd, const void *got, + greatest_type_info *type_info, void *udata); +void greatest_prng_init_first_pass(int id); +int greatest_prng_init_second_pass(int id, unsigned long seed); +void greatest_prng_step(int id); + +/* These are part of the public greatest API. */ +void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata); +void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata); +void GREATEST_INIT(void); +void GREATEST_PRINT_REPORT(void); +int greatest_all_passed(void); +void greatest_set_suite_filter(const char *filter); +void greatest_set_test_filter(const char *filter); +void greatest_set_test_exclude(const char *filter); +void greatest_set_exact_name_match(void); +void greatest_stop_at_first_fail(void); +void greatest_abort_on_fail(void); +void greatest_list_only(void); +void greatest_get_report(struct greatest_report_t *report); +unsigned int greatest_get_verbosity(void); +void greatest_set_verbosity(unsigned int verbosity); +void greatest_set_flag(greatest_flag_t flag); +void greatest_set_test_suffix(const char *suffix); + +/******************** + * Language Support * + ********************/ + +/* If __VA_ARGS__ (C99) is supported, allow parametric testing + * without needing to manually manage the argument struct. */ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 19901L) || \ + (defined(_MSC_VER) && _MSC_VER >= 1800) +#define GREATEST_VA_ARGS +#endif + +/********** + * Macros * + **********/ + +/* Define a suite. (The duplication is intentional -- it eliminates + * a warning from -Wmissing-declarations.) */ +#define GREATEST_SUITE(NAME) \ + void NAME(void); \ + void NAME(void) + +/* Declare a suite, provided by another compilation unit. */ +#define GREATEST_SUITE_EXTERN(NAME) void NAME(void) + +/* Start defining a test function. + * The arguments are not included, to allow parametric testing. */ +#define GREATEST_TEST static enum greatest_test_res + +/* PASS/FAIL/SKIP result from a test. Used internally. */ +typedef enum greatest_test_res { + GREATEST_TEST_RES_PASS = 0, + GREATEST_TEST_RES_FAIL = -1, + GREATEST_TEST_RES_SKIP = 1 +} greatest_test_res; + +/* Run a suite. */ +#define GREATEST_RUN_SUITE(S_NAME) greatest_run_suite(S_NAME, #S_NAME) + +/* Run a test in the current suite. */ +#define GREATEST_RUN_TEST(TEST) \ + do { \ + if (greatest_test_pre(#TEST) == 1) { \ + enum greatest_test_res res = GREATEST_SAVE_CONTEXT(); \ + if (res == GREATEST_TEST_RES_PASS) { \ + res = TEST(); \ + } \ + greatest_test_post(res); \ + } \ + } while (0) + +/* Ignore a test, don't warn about it being unused. */ +#define GREATEST_IGNORE_TEST(TEST) (void)TEST + +/* Run a test in the current suite with one void * argument, + * which can be a pointer to a struct with multiple arguments. */ +#define GREATEST_RUN_TEST1(TEST, ENV) \ + do { \ + if (greatest_test_pre(#TEST) == 1) { \ + enum greatest_test_res res = GREATEST_SAVE_CONTEXT(); \ + if (res == GREATEST_TEST_RES_PASS) { \ + res = TEST(ENV); \ + } \ + greatest_test_post(res); \ + } \ + } while (0) + +#ifdef GREATEST_VA_ARGS +#define GREATEST_RUN_TESTp(TEST, ...) \ + do { \ + if (greatest_test_pre(#TEST) == 1) { \ + enum greatest_test_res res = GREATEST_SAVE_CONTEXT(); \ + if (res == GREATEST_TEST_RES_PASS) { \ + res = TEST(__VA_ARGS__); \ + } \ + greatest_test_post(res); \ + } \ + } while (0) +#endif + +/* Check if the test runner is in verbose mode. */ +#define GREATEST_IS_VERBOSE() ((greatest_info.verbosity) > 0) +#define GREATEST_LIST_ONLY() (greatest_info.flags & GREATEST_FLAG_LIST_ONLY) +#define GREATEST_FIRST_FAIL() (greatest_info.flags & GREATEST_FLAG_FIRST_FAIL) +#define GREATEST_ABORT_ON_FAIL() \ + (greatest_info.flags & GREATEST_FLAG_ABORT_ON_FAIL) +#define GREATEST_FAILURE_ABORT() \ + (GREATEST_FIRST_FAIL() && \ + (greatest_info.suite.failed > 0 || greatest_info.failed > 0)) + +/* Message-less forms of tests defined below. */ +#define GREATEST_PASS() GREATEST_PASSm(NULL) +#define GREATEST_FAIL() GREATEST_FAILm(NULL) +#define GREATEST_SKIP() GREATEST_SKIPm(NULL) +#define GREATEST_ASSERT(COND) GREATEST_ASSERTm(#COND, COND) +#define GREATEST_ASSERT_OR_LONGJMP(COND) \ + GREATEST_ASSERT_OR_LONGJMPm(#COND, COND) +#define GREATEST_ASSERT_FALSE(COND) GREATEST_ASSERT_FALSEm(#COND, COND) +#define GREATEST_ASSERT_EQ(EXP, GOT) \ + GREATEST_ASSERT_EQm(#EXP " != " #GOT, EXP, GOT) +#define GREATEST_ASSERT_NEQ(EXP, GOT) \ + GREATEST_ASSERT_NEQm(#EXP " == " #GOT, EXP, GOT) +#define GREATEST_ASSERT_GT(EXP, GOT) \ + GREATEST_ASSERT_GTm(#EXP " <= " #GOT, EXP, GOT) +#define GREATEST_ASSERT_GTE(EXP, GOT) \ + GREATEST_ASSERT_GTEm(#EXP " < " #GOT, EXP, GOT) +#define GREATEST_ASSERT_LT(EXP, GOT) \ + GREATEST_ASSERT_LTm(#EXP " >= " #GOT, EXP, GOT) +#define GREATEST_ASSERT_LTE(EXP, GOT) \ + GREATEST_ASSERT_LTEm(#EXP " > " #GOT, EXP, GOT) +#define GREATEST_ASSERT_EQ_FMT(EXP, GOT, FMT) \ + GREATEST_ASSERT_EQ_FMTm(#EXP " != " #GOT, EXP, GOT, FMT) +#define GREATEST_ASSERT_IN_RANGE(EXP, GOT, TOL) \ + GREATEST_ASSERT_IN_RANGEm(#EXP " != " #GOT " +/- " #TOL, EXP, GOT, TOL) +#define GREATEST_ASSERT_EQUAL_T(EXP, GOT, TYPE_INFO, UDATA) \ + GREATEST_ASSERT_EQUAL_Tm(#EXP " != " #GOT, EXP, GOT, TYPE_INFO, UDATA) +#define GREATEST_ASSERT_STR_EQ(EXP, GOT) \ + GREATEST_ASSERT_STR_EQm(#EXP " != " #GOT, EXP, GOT) +#define GREATEST_ASSERT_STRN_EQ(EXP, GOT, SIZE) \ + GREATEST_ASSERT_STRN_EQm(#EXP " != " #GOT, EXP, GOT, SIZE) +#define GREATEST_ASSERT_MEM_EQ(EXP, GOT, SIZE) \ + GREATEST_ASSERT_MEM_EQm(#EXP " != " #GOT, EXP, GOT, SIZE) +#define GREATEST_ASSERT_ENUM_EQ(EXP, GOT, ENUM_STR) \ + GREATEST_ASSERT_ENUM_EQm(#EXP " != " #GOT, EXP, GOT, ENUM_STR) + +/* The following forms take an additional message argument first, + * to be displayed by the test runner. */ + +/* Fail if a condition is not true, with message. */ +#define GREATEST_ASSERTm(MSG, COND) \ + do { \ + greatest_info.assertions++; \ + if (!(COND)) { \ + GREATEST_FAILm(MSG); \ + } \ + } while (0) + +/* Fail if a condition is not true, longjmping out of test. */ +#define GREATEST_ASSERT_OR_LONGJMPm(MSG, COND) \ + do { \ + greatest_info.assertions++; \ + if (!(COND)) { \ + GREATEST_FAIL_WITH_LONGJMPm(MSG); \ + } \ + } while (0) + +/* Fail if a condition is not false, with message. */ +#define GREATEST_ASSERT_FALSEm(MSG, COND) \ + do { \ + greatest_info.assertions++; \ + if ((COND)) { \ + GREATEST_FAILm(MSG); \ + } \ + } while (0) + +/* Internal macro for relational assertions */ +#define GREATEST__REL(REL, MSG, EXP, GOT) \ + do { \ + greatest_info.assertions++; \ + if (!((EXP)REL(GOT))) { \ + GREATEST_FAILm(MSG); \ + } \ + } while (0) + +/* Fail if EXP is not ==, !=, >, <, >=, or <= to GOT. */ +#define GREATEST_ASSERT_EQm(MSG, E, G) GREATEST__REL(==, MSG, E, G) +#define GREATEST_ASSERT_NEQm(MSG, E, G) GREATEST__REL(!=, MSG, E, G) +#define GREATEST_ASSERT_GTm(MSG, E, G) GREATEST__REL(>, MSG, E, G) +#define GREATEST_ASSERT_GTEm(MSG, E, G) GREATEST__REL(>=, MSG, E, G) +#define GREATEST_ASSERT_LTm(MSG, E, G) GREATEST__REL(<, MSG, E, G) +#define GREATEST_ASSERT_LTEm(MSG, E, G) GREATEST__REL(<=, MSG, E, G) + +/* Fail if EXP != GOT (equality comparison by ==). + * Warning: FMT, EXP, and GOT will be evaluated more + * than once on failure. */ +#define GREATEST_ASSERT_EQ_FMTm(MSG, EXP, GOT, FMT) \ + do { \ + greatest_info.assertions++; \ + if ((EXP) != (GOT)) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\nExpected: "); \ + GREATEST_FPRINTF(GREATEST_STDOUT, FMT, EXP); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n Got: "); \ + GREATEST_FPRINTF(GREATEST_STDOUT, FMT, GOT); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n"); \ + GREATEST_FAILm(MSG); \ + } \ + } while (0) + +/* Fail if EXP is not equal to GOT, printing enum IDs. */ +#define GREATEST_ASSERT_ENUM_EQm(MSG, EXP, GOT, ENUM_STR) \ + do { \ + int greatest_EXP = (int)(EXP); \ + int greatest_GOT = (int)(GOT); \ + greatest_enum_str_fun *greatest_ENUM_STR = ENUM_STR; \ + if (greatest_EXP != greatest_GOT) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\nExpected: %s", \ + greatest_ENUM_STR(greatest_EXP)); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n Got: %s\n", \ + greatest_ENUM_STR(greatest_GOT)); \ + GREATEST_FAILm(MSG); \ + } \ + } while (0) + +/* Fail if GOT not in range of EXP +|- TOL. */ +#define GREATEST_ASSERT_IN_RANGEm(MSG, EXP, GOT, TOL) \ + do { \ + GREATEST_FLOAT greatest_EXP = (EXP); \ + GREATEST_FLOAT greatest_GOT = (GOT); \ + GREATEST_FLOAT greatest_TOL = (TOL); \ + greatest_info.assertions++; \ + if ((greatest_EXP > greatest_GOT && \ + greatest_EXP - greatest_GOT > greatest_TOL) || \ + (greatest_EXP < greatest_GOT && \ + greatest_GOT - greatest_EXP > greatest_TOL)) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, \ + "\nExpected: " GREATEST_FLOAT_FMT \ + " +/- " GREATEST_FLOAT_FMT \ + "\n Got: " GREATEST_FLOAT_FMT "\n", \ + greatest_EXP, greatest_TOL, greatest_GOT); \ + GREATEST_FAILm(MSG); \ + } \ + } while (0) + +/* Fail if EXP is not equal to GOT, according to strcmp. */ +#define GREATEST_ASSERT_STR_EQm(MSG, EXP, GOT) \ + do { \ + GREATEST_ASSERT_EQUAL_Tm(MSG, EXP, GOT, &greatest_type_info_string, NULL); \ + } while (0) + +/* Fail if EXP is not equal to GOT, according to strncmp. */ +#define GREATEST_ASSERT_STRN_EQm(MSG, EXP, GOT, SIZE) \ + do { \ + size_t size = SIZE; \ + GREATEST_ASSERT_EQUAL_Tm(MSG, EXP, GOT, &greatest_type_info_string, \ + &size); \ + } while (0) + +/* Fail if EXP is not equal to GOT, according to memcmp. */ +#define GREATEST_ASSERT_MEM_EQm(MSG, EXP, GOT, SIZE) \ + do { \ + greatest_memory_cmp_env env; \ + env.exp = (const unsigned char *)EXP; \ + env.got = (const unsigned char *)GOT; \ + env.size = SIZE; \ + GREATEST_ASSERT_EQUAL_Tm(MSG, env.exp, env.got, \ + &greatest_type_info_memory, &env); \ + } while (0) + +/* Fail if EXP is not equal to GOT, according to a comparison + * callback in TYPE_INFO. If they are not equal, optionally use a + * print callback in TYPE_INFO to print them. */ +#define GREATEST_ASSERT_EQUAL_Tm(MSG, EXP, GOT, TYPE_INFO, UDATA) \ + do { \ + greatest_type_info *type_info = (TYPE_INFO); \ + greatest_info.assertions++; \ + if (!greatest_do_assert_equal_t(EXP, GOT, type_info, UDATA)) { \ + if (type_info == NULL || type_info->equal == NULL) { \ + GREATEST_FAILm("type_info->equal callback missing!"); \ + } else { \ + GREATEST_FAILm(MSG); \ + } \ + } \ + } while (0) + +/* Pass. */ +#define GREATEST_PASSm(MSG) \ + do { \ + greatest_info.msg = MSG; \ + return GREATEST_TEST_RES_PASS; \ + } while (0) + +/* Fail. */ +#define GREATEST_FAILm(MSG) \ + do { \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + greatest_info.msg = MSG; \ + if (GREATEST_ABORT_ON_FAIL()) { \ + abort(); \ + } \ + return GREATEST_TEST_RES_FAIL; \ + } while (0) + +/* Optional GREATEST_FAILm variant that longjmps. */ +#if GREATEST_USE_LONGJMP +#define GREATEST_FAIL_WITH_LONGJMP() GREATEST_FAIL_WITH_LONGJMPm(NULL) +#define GREATEST_FAIL_WITH_LONGJMPm(MSG) \ + do { \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + greatest_info.msg = MSG; \ + longjmp(greatest_info.jump_dest, GREATEST_TEST_RES_FAIL); \ + } while (0) +#endif + +/* Skip the current test. */ +#define GREATEST_SKIPm(MSG) \ + do { \ + greatest_info.msg = MSG; \ + return GREATEST_TEST_RES_SKIP; \ + } while (0) + +/* Check the result of a subfunction using ASSERT, etc. */ +#define GREATEST_CHECK_CALL(RES) \ + do { \ + enum greatest_test_res greatest_RES = RES; \ + if (greatest_RES != GREATEST_TEST_RES_PASS) { \ + return greatest_RES; \ + } \ + } while (0) + +#if GREATEST_USE_TIME +#define GREATEST_SET_TIME(NAME) \ + NAME = clock(); \ + if (NAME == (clock_t)-1) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "clock error: %s\n", #NAME); \ + exit(EXIT_FAILURE); \ + } + +#define GREATEST_CLOCK_DIFF(C1, C2) \ + GREATEST_FPRINTF(GREATEST_STDOUT, " (%lu ticks, %.3f sec)", \ + (long unsigned int)(C2) - (long unsigned int)(C1), \ + (double)((C2) - (C1)) / (1.0 * (double)CLOCKS_PER_SEC)) +#else +#define GREATEST_SET_TIME(UNUSED) +#define GREATEST_CLOCK_DIFF(UNUSED1, UNUSED2) +#endif + +#if GREATEST_USE_LONGJMP +#define GREATEST_SAVE_CONTEXT() \ + /* setjmp returns 0 (GREATEST_TEST_RES_PASS) on first call * \ + * so the test runs, then RES_FAIL from FAIL_WITH_LONGJMP. */ \ + ((enum greatest_test_res)(setjmp(greatest_info.jump_dest))) +#else +#define GREATEST_SAVE_CONTEXT() \ + /*a no-op, since setjmp/longjmp aren't being used */ \ + GREATEST_TEST_RES_PASS +#endif + +/* Run every suite / test function run within BODY in pseudo-random + * order, seeded by SEED. (The top 3 bits of the seed are ignored.) + * + * This should be called like: + * GREATEST_SHUFFLE_TESTS(seed, { + * GREATEST_RUN_TEST(some_test); + * GREATEST_RUN_TEST(some_other_test); + * GREATEST_RUN_TEST(yet_another_test); + * }); + * + * Note that the body of the second argument will be evaluated + * multiple times. */ +#define GREATEST_SHUFFLE_SUITES(SD, BODY) GREATEST_SHUFFLE(0, SD, BODY) +#define GREATEST_SHUFFLE_TESTS(SD, BODY) GREATEST_SHUFFLE(1, SD, BODY) +#define GREATEST_SHUFFLE(ID, SD, BODY) \ + do { \ + struct greatest_prng *prng = &greatest_info.prng[ID]; \ + greatest_prng_init_first_pass(ID); \ + do { \ + prng->count = 0; \ + if (prng->initialized) { \ + greatest_prng_step(ID); \ + } \ + BODY; \ + if (!prng->initialized) { \ + if (!greatest_prng_init_second_pass(ID, SD)) { \ + break; \ + } \ + } else if (prng->count_run == prng->count_ceil) { \ + break; \ + } \ + } while (!GREATEST_FAILURE_ABORT()); \ + prng->count_run = prng->random_order = prng->initialized = 0; \ + } while (0) + +/* Include several function definitions in the main test file. */ +#define GREATEST_MAIN_DEFS() \ + \ + /* Is FILTER a subset of NAME? */ \ + static int greatest_name_match(const char *name, const char *filter, \ + int res_if_none) { \ + size_t offset = 0; \ + size_t filter_len = filter ? strlen(filter) : 0; \ + if (filter_len == 0) { \ + return res_if_none; \ + } /* no filter */ \ + if (greatest_info.exact_name_match && strlen(name) != filter_len) { \ + return 0; /* ignore substring matches */ \ + } \ + while (name[offset] != '\0') { \ + if (name[offset] == filter[0]) { \ + if (0 == strncmp(&name[offset], filter, filter_len)) { \ + return 1; \ + } \ + } \ + offset++; \ + } \ + \ + return 0; \ + } \ + \ + static void greatest_buffer_test_name(const char *name) { \ + struct greatest_run_info *g = &greatest_info; \ + size_t len = strlen(name), size = sizeof(g->name_buf); \ + memset(g->name_buf, 0x00, size); \ + (void)strncat(g->name_buf, name, size - 1); \ + if (g->name_suffix && (len + 1 < size)) { \ + g->name_buf[len] = '_'; \ + strncat(&g->name_buf[len + 1], g->name_suffix, size - (len + 2)); \ + } \ + } \ + \ + /* Before running a test, check the name filtering and \ + * test shuffling state, if applicable, and then call setup hooks. */ \ + int greatest_test_pre(const char *name) { \ + struct greatest_run_info *g = &greatest_info; \ + int match; \ + greatest_buffer_test_name(name); \ + match = greatest_name_match(g->name_buf, g->test_filter, 1) && \ + !greatest_name_match(g->name_buf, g->test_exclude, 0); \ + if (GREATEST_LIST_ONLY()) { /* just listing test names */ \ + if (match) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, " %s\n", g->name_buf); \ + } \ + goto clear; \ + } \ + if (match && (!GREATEST_FIRST_FAIL() || g->suite.failed == 0)) { \ + struct greatest_prng *p = &g->prng[1]; \ + if (p->random_order) { \ + p->count++; \ + if (!p->initialized || ((p->count - 1) != p->state)) { \ + goto clear; /* don't run this test yet */ \ + } \ + } \ + if (g->running_test) { \ + fprintf(stderr, "Error: Test run inside another test.\n"); \ + return 0; \ + } \ + GREATEST_SET_TIME(g->suite.pre_test); \ + if (g->setup) { \ + g->setup(g->setup_udata); \ + } \ + p->count_run++; \ + g->running_test = 1; \ + return 1; /* test should be run */ \ + } else { \ + goto clear; /* skipped */ \ + } \ + clear: \ + g->name_suffix = NULL; \ + return 0; \ + } \ + \ + static void greatest_do_pass(void) { \ + struct greatest_run_info *g = &greatest_info; \ + if (GREATEST_IS_VERBOSE()) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "PASS %s: %s", g->name_buf, \ + g->msg ? g->msg : ""); \ + } else { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "."); \ + } \ + g->suite.passed++; \ + } \ + \ + static void greatest_do_fail(void) { \ + struct greatest_run_info *g = &greatest_info; \ + if (GREATEST_IS_VERBOSE()) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)", g->name_buf, \ + g->msg ? g->msg : "", g->fail_file, g->fail_line); \ + } else { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "F"); \ + g->col++; /* add linebreak if in line of '.'s */ \ + if (g->col != 0) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n"); \ + g->col = 0; \ + } \ + GREATEST_FPRINTF(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)\n", g->name_buf, \ + g->msg ? g->msg : "", g->fail_file, g->fail_line); \ + } \ + g->suite.failed++; \ + } \ + \ + static void greatest_do_skip(void) { \ + struct greatest_run_info *g = &greatest_info; \ + if (GREATEST_IS_VERBOSE()) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "SKIP %s: %s", g->name_buf, \ + g->msg ? g->msg : ""); \ + } else { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "s"); \ + } \ + g->suite.skipped++; \ + } \ + \ + void greatest_test_post(int res) { \ + GREATEST_SET_TIME(greatest_info.suite.post_test); \ + if (greatest_info.teardown) { \ + void *udata = greatest_info.teardown_udata; \ + greatest_info.teardown(udata); \ + } \ + \ + greatest_info.running_test = 0; \ + if (res <= GREATEST_TEST_RES_FAIL) { \ + greatest_do_fail(); \ + } else if (res >= GREATEST_TEST_RES_SKIP) { \ + greatest_do_skip(); \ + } else if (res == GREATEST_TEST_RES_PASS) { \ + greatest_do_pass(); \ + } \ + greatest_info.name_suffix = NULL; \ + greatest_info.suite.tests_run++; \ + greatest_info.col++; \ + if (GREATEST_IS_VERBOSE()) { \ + GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test, \ + greatest_info.suite.post_test); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n"); \ + } else if (greatest_info.col % greatest_info.width == 0) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n"); \ + greatest_info.col = 0; \ + } \ + fflush(GREATEST_STDOUT); \ + } \ + \ + static void report_suite(void) { \ + if (greatest_info.suite.tests_run > 0) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, \ + "\n%u test%s - %u passed, %u failed, %u skipped", \ + greatest_info.suite.tests_run, \ + greatest_info.suite.tests_run == 1 ? "" : "s", \ + greatest_info.suite.passed, greatest_info.suite.failed, \ + greatest_info.suite.skipped); \ + GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite, \ + greatest_info.suite.post_suite); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n"); \ + } \ + } \ + \ + static void update_counts_and_reset_suite(void) { \ + greatest_info.setup = NULL; \ + greatest_info.setup_udata = NULL; \ + greatest_info.teardown = NULL; \ + greatest_info.teardown_udata = NULL; \ + greatest_info.passed += greatest_info.suite.passed; \ + greatest_info.failed += greatest_info.suite.failed; \ + greatest_info.skipped += greatest_info.suite.skipped; \ + greatest_info.tests_run += greatest_info.suite.tests_run; \ + memset(&greatest_info.suite, 0, sizeof(greatest_info.suite)); \ + greatest_info.col = 0; \ + } \ + \ + static int greatest_suite_pre(const char *suite_name) { \ + struct greatest_prng *p = &greatest_info.prng[0]; \ + if (!greatest_name_match(suite_name, greatest_info.suite_filter, 1) || \ + (GREATEST_FAILURE_ABORT())) { \ + return 0; \ + } \ + if (p->random_order) { \ + p->count++; \ + if (!p->initialized || ((p->count - 1) != p->state)) { \ + return 0; /* don't run this suite yet */ \ + } \ + } \ + p->count_run++; \ + update_counts_and_reset_suite(); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name); \ + GREATEST_SET_TIME(greatest_info.suite.pre_suite); \ + return 1; \ + } \ + \ + static void greatest_suite_post(void) { \ + GREATEST_SET_TIME(greatest_info.suite.post_suite); \ + report_suite(); \ + } \ + \ + static void greatest_run_suite(greatest_suite_cb *suite_cb, \ + const char *suite_name) { \ + if (greatest_suite_pre(suite_name)) { \ + suite_cb(); \ + greatest_suite_post(); \ + } \ + } \ + \ + int greatest_do_assert_equal_t(const void *expd, const void *got, \ + greatest_type_info *type_info, void *udata) { \ + int eq = 0; \ + if (type_info == NULL || type_info->equal == NULL) { \ + return 0; \ + } \ + eq = type_info->equal(expd, got, udata); \ + if (!eq) { \ + if (type_info->print != NULL) { \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\nExpected: "); \ + (void)type_info->print(expd, udata); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n Got: "); \ + (void)type_info->print(got, udata); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\n"); \ + } \ + } \ + return eq; \ + } \ + \ + static void greatest_usage(const char *name) { \ + GREATEST_FPRINTF( \ + GREATEST_STDOUT, \ + "Usage: %s [-hlfavex] [-s SUITE] [-t TEST] [-x EXCLUDE]\n" \ + " -h, --help print this Help\n" \ + " -l List suites and tests, then exit (dry run)\n" \ + " -f Stop runner after first failure\n" \ + " -a Abort on first failure (implies -f)\n" \ + " -v Verbose output\n" \ + " -s SUITE only run suites containing substring SUITE\n" \ + " -t TEST only run tests containing substring TEST\n" \ + " -e only run exact name match for -s or -t\n" \ + " -x EXCLUDE exclude tests containing substring EXCLUDE\n", \ + name); \ + } \ + \ + static void greatest_parse_options(int argc, char **argv) { \ + int i = 0; \ + for (i = 1; i < argc; i++) { \ + if (argv[i][0] == '-') { \ + char f = argv[i][1]; \ + if ((f == 's' || f == 't' || f == 'x') && argc <= i + 1) { \ + greatest_usage(argv[0]); \ + exit(EXIT_FAILURE); \ + } \ + switch (f) { \ + case 's': /* suite name filter */ \ + greatest_set_suite_filter(argv[i + 1]); \ + i++; \ + break; \ + case 't': /* test name filter */ \ + greatest_set_test_filter(argv[i + 1]); \ + i++; \ + break; \ + case 'x': /* test name exclusion */ \ + greatest_set_test_exclude(argv[i + 1]); \ + i++; \ + break; \ + case 'e': /* exact name match */ \ + greatest_set_exact_name_match(); \ + break; \ + case 'f': /* first fail flag */ \ + greatest_stop_at_first_fail(); \ + break; \ + case 'a': /* abort() on fail flag */ \ + greatest_abort_on_fail(); \ + break; \ + case 'l': /* list only (dry run) */ \ + greatest_list_only(); \ + break; \ + case 'v': /* first fail flag */ \ + greatest_info.verbosity++; \ + break; \ + case 'h': /* help */ \ + greatest_usage(argv[0]); \ + exit(EXIT_SUCCESS); \ + default: \ + case '-': \ + if (0 == strncmp("--help", argv[i], 6)) { \ + greatest_usage(argv[0]); \ + exit(EXIT_SUCCESS); \ + } else if (0 == strcmp("--", argv[i])) { \ + return; /* ignore following arguments */ \ + } \ + GREATEST_FPRINTF(GREATEST_STDOUT, "Unknown argument '%s'\n", \ + argv[i]); \ + greatest_usage(argv[0]); \ + exit(EXIT_FAILURE); \ + } \ + } \ + } \ + } \ + \ + int greatest_all_passed(void) { return (greatest_info.failed == 0); } \ + \ + void greatest_set_test_filter(const char *filter) { \ + greatest_info.test_filter = filter; \ + } \ + \ + void greatest_set_test_exclude(const char *filter) { \ + greatest_info.test_exclude = filter; \ + } \ + \ + void greatest_set_suite_filter(const char *filter) { \ + greatest_info.suite_filter = filter; \ + } \ + \ + void greatest_set_exact_name_match(void) { \ + greatest_info.exact_name_match = 1; \ + } \ + \ + void greatest_stop_at_first_fail(void) { \ + greatest_set_flag(GREATEST_FLAG_FIRST_FAIL); \ + } \ + \ + void greatest_abort_on_fail(void) { \ + greatest_set_flag(GREATEST_FLAG_ABORT_ON_FAIL); \ + } \ + \ + void greatest_list_only(void) { \ + greatest_set_flag(GREATEST_FLAG_LIST_ONLY); \ + } \ + \ + void greatest_get_report(struct greatest_report_t *report) { \ + if (report) { \ + report->passed = greatest_info.passed; \ + report->failed = greatest_info.failed; \ + report->skipped = greatest_info.skipped; \ + report->assertions = greatest_info.assertions; \ + } \ + } \ + \ + unsigned int greatest_get_verbosity(void) { \ + return greatest_info.verbosity; \ + } \ + \ + void greatest_set_verbosity(unsigned int verbosity) { \ + greatest_info.verbosity = (unsigned char)verbosity; \ + } \ + \ + void greatest_set_flag(greatest_flag_t flag) { \ + greatest_info.flags = (unsigned char)(greatest_info.flags | flag); \ + } \ + \ + void greatest_set_test_suffix(const char *suffix) { \ + greatest_info.name_suffix = suffix; \ + } \ + \ + void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata) { \ + greatest_info.setup = cb; \ + greatest_info.setup_udata = udata; \ + } \ + \ + void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata) { \ + greatest_info.teardown = cb; \ + greatest_info.teardown_udata = udata; \ + } \ + \ + static int greatest_string_equal_cb(const void *expd, const void *got, \ + void *udata) { \ + size_t *size = (size_t *)udata; \ + return (size != NULL \ + ? (0 == strncmp((const char *)expd, (const char *)got, *size)) \ + : (0 == strcmp((const char *)expd, (const char *)got))); \ + } \ + \ + static int greatest_string_printf_cb(const void *t, void *udata) { \ + (void)udata; /* note: does not check \0 termination. */ \ + return GREATEST_FPRINTF(GREATEST_STDOUT, "%s", (const char *)t); \ + } \ + \ + greatest_type_info greatest_type_info_string = { \ + greatest_string_equal_cb, \ + greatest_string_printf_cb, \ + }; \ + \ + static int greatest_memory_equal_cb(const void *expd, const void *got, \ + void *udata) { \ + greatest_memory_cmp_env *env = (greatest_memory_cmp_env *)udata; \ + return (0 == memcmp(expd, got, env->size)); \ + } \ + \ + /* Hexdump raw memory, with differences highlighted */ \ + static int greatest_memory_printf_cb(const void *t, void *udata) { \ + greatest_memory_cmp_env *env = (greatest_memory_cmp_env *)udata; \ + const unsigned char *buf = (const unsigned char *)t; \ + unsigned char diff_mark = ' '; \ + FILE *out = GREATEST_STDOUT; \ + size_t i, line_i, line_len = 0; \ + int len = 0; /* format hexdump with differences highlighted */ \ + for (i = 0; i < env->size; i += line_len) { \ + diff_mark = ' '; \ + line_len = env->size - i; \ + if (line_len > 16) { \ + line_len = 16; \ + } \ + for (line_i = i; line_i < i + line_len; line_i++) { \ + if (env->exp[line_i] != env->got[line_i]) \ + diff_mark = 'X'; \ + } \ + len += GREATEST_FPRINTF(out, "\n%04x %c ", (unsigned int)i, diff_mark); \ + for (line_i = i; line_i < i + line_len; line_i++) { \ + int m = env->exp[line_i] == env->got[line_i]; /* match? */ \ + len += GREATEST_FPRINTF(out, "%02x%c", buf[line_i], m ? ' ' : '<'); \ + } \ + for (line_i = 0; line_i < 16 - line_len; line_i++) { \ + len += GREATEST_FPRINTF(out, " "); \ + } \ + GREATEST_FPRINTF(out, " "); \ + for (line_i = i; line_i < i + line_len; line_i++) { \ + unsigned char c = buf[line_i]; \ + len += GREATEST_FPRINTF(out, "%c", isprint(c) ? c : '.'); \ + } \ + } \ + len += GREATEST_FPRINTF(out, "\n"); \ + return len; \ + } \ + \ + void greatest_prng_init_first_pass(int id) { \ + greatest_info.prng[id].random_order = 1; \ + greatest_info.prng[id].count_run = 0; \ + } \ + \ + int greatest_prng_init_second_pass(int id, unsigned long seed) { \ + struct greatest_prng *p = &greatest_info.prng[id]; \ + if (p->count == 0) { \ + return 0; \ + } \ + p->count_ceil = p->count; \ + for (p->m = 1; p->m < p->count; p->m <<= 1) { \ + } \ + p->state = seed & 0x1fffffff; /* only use lower 29 bits */ \ + p->a = 4LU * p->state; /* to avoid overflow when */ \ + p->a = (p->a ? p->a : 4) | 1; /* multiplied by 4 */ \ + p->c = 2147483647; /* and so p->c ((2 ** 31) - 1) is */ \ + p->initialized = 1; /* always relatively prime to p->a. */ \ + fprintf(stderr, "init_second_pass: a %lu, c %lu, state %lu\n", p->a, p->c, \ + p->state); \ + return 1; \ + } \ + \ + /* Step the pseudorandom number generator until its state reaches \ + * another test ID between 0 and the test count. \ + * This use a linear congruential pseudorandom number generator, \ + * with the power-of-two ceiling of the test count as the modulus, the \ + * masked seed as the multiplier, and a prime as the increment. For \ + * each generated value < the test count, run the corresponding test. \ + * This will visit all IDs 0 <= X < mod once before repeating, \ + * with a starting position chosen based on the initial seed. \ + * For details, see: Knuth, The Art of Computer Programming \ + * Volume. 2, section 3.2.1. */ \ + void greatest_prng_step(int id) { \ + struct greatest_prng *p = &greatest_info.prng[id]; \ + do { \ + p->state = ((p->a * p->state) + p->c) & (p->m - 1); \ + } while (p->state >= p->count_ceil); \ + } \ + \ + void GREATEST_INIT(void) { \ + /* Suppress unused function warning if features aren't used */ \ + (void)greatest_run_suite; \ + (void)greatest_parse_options; \ + (void)greatest_prng_step; \ + (void)greatest_prng_init_first_pass; \ + (void)greatest_prng_init_second_pass; \ + (void)greatest_set_test_suffix; \ + \ + memset(&greatest_info, 0, sizeof(greatest_info)); \ + greatest_info.width = GREATEST_DEFAULT_WIDTH; \ + GREATEST_SET_TIME(greatest_info.begin); \ + } \ + \ + /* Report passes, failures, skipped tests, the number of \ + * assertions, and the overall run time. */ \ + void GREATEST_PRINT_REPORT(void) { \ + if (!GREATEST_LIST_ONLY()) { \ + update_counts_and_reset_suite(); \ + GREATEST_SET_TIME(greatest_info.end); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "\nTotal: %u test%s", \ + greatest_info.tests_run, \ + greatest_info.tests_run == 1 ? "" : "s"); \ + GREATEST_CLOCK_DIFF(greatest_info.begin, greatest_info.end); \ + GREATEST_FPRINTF(GREATEST_STDOUT, ", %u assertion%s\n", \ + greatest_info.assertions, \ + greatest_info.assertions == 1 ? "" : "s"); \ + GREATEST_FPRINTF(GREATEST_STDOUT, "Pass: %u, fail: %u, skip: %u.\n", \ + greatest_info.passed, greatest_info.failed, \ + greatest_info.skipped); \ + } \ + } \ + \ + greatest_type_info greatest_type_info_memory = { \ + greatest_memory_equal_cb, \ + greatest_memory_printf_cb, \ + }; \ + \ + greatest_run_info greatest_info + +/* Handle command-line arguments, etc. */ +#define GREATEST_MAIN_BEGIN() \ + do { \ + GREATEST_INIT(); \ + greatest_parse_options(argc, argv); \ + } while (0) + +/* Report results, exit with exit status based on results. */ +#define GREATEST_MAIN_END() \ + do { \ + GREATEST_PRINT_REPORT(); \ + return (greatest_all_passed() ? EXIT_SUCCESS : EXIT_FAILURE); \ + } while (0) + +/* Make abbreviations without the GREATEST_ prefix for the + * most commonly used symbols. */ +#if GREATEST_USE_ABBREVS +#define TEST GREATEST_TEST +#define SUITE GREATEST_SUITE +#define SUITE_EXTERN GREATEST_SUITE_EXTERN +#define RUN_TEST GREATEST_RUN_TEST +#define RUN_TEST1 GREATEST_RUN_TEST1 +#define RUN_SUITE GREATEST_RUN_SUITE +#define IGNORE_TEST GREATEST_IGNORE_TEST +#define ASSERT GREATEST_ASSERT +#define ASSERTm GREATEST_ASSERTm +#define ASSERT_FALSE GREATEST_ASSERT_FALSE +#define ASSERT_EQ GREATEST_ASSERT_EQ +#define ASSERT_NEQ GREATEST_ASSERT_NEQ +#define ASSERT_GT GREATEST_ASSERT_GT +#define ASSERT_GTE GREATEST_ASSERT_GTE +#define ASSERT_LT GREATEST_ASSERT_LT +#define ASSERT_LTE GREATEST_ASSERT_LTE +#define ASSERT_EQ_FMT GREATEST_ASSERT_EQ_FMT +#define ASSERT_IN_RANGE GREATEST_ASSERT_IN_RANGE +#define ASSERT_EQUAL_T GREATEST_ASSERT_EQUAL_T +#define ASSERT_STR_EQ GREATEST_ASSERT_STR_EQ +#define ASSERT_STRN_EQ GREATEST_ASSERT_STRN_EQ +#define ASSERT_MEM_EQ GREATEST_ASSERT_MEM_EQ +#define ASSERT_ENUM_EQ GREATEST_ASSERT_ENUM_EQ +#define ASSERT_FALSEm GREATEST_ASSERT_FALSEm +#define ASSERT_EQm GREATEST_ASSERT_EQm +#define ASSERT_NEQm GREATEST_ASSERT_NEQm +#define ASSERT_GTm GREATEST_ASSERT_GTm +#define ASSERT_GTEm GREATEST_ASSERT_GTEm +#define ASSERT_LTm GREATEST_ASSERT_LTm +#define ASSERT_LTEm GREATEST_ASSERT_LTEm +#define ASSERT_EQ_FMTm GREATEST_ASSERT_EQ_FMTm +#define ASSERT_IN_RANGEm GREATEST_ASSERT_IN_RANGEm +#define ASSERT_EQUAL_Tm GREATEST_ASSERT_EQUAL_Tm +#define ASSERT_STR_EQm GREATEST_ASSERT_STR_EQm +#define ASSERT_STRN_EQm GREATEST_ASSERT_STRN_EQm +#define ASSERT_MEM_EQm GREATEST_ASSERT_MEM_EQm +#define ASSERT_ENUM_EQm GREATEST_ASSERT_ENUM_EQm +#define PASS GREATEST_PASS +#define FAIL GREATEST_FAIL +#define SKIP GREATEST_SKIP +#define PASSm GREATEST_PASSm +#define FAILm GREATEST_FAILm +#define SKIPm GREATEST_SKIPm +#define SET_SETUP GREATEST_SET_SETUP_CB +#define SET_TEARDOWN GREATEST_SET_TEARDOWN_CB +#define CHECK_CALL GREATEST_CHECK_CALL +#define SHUFFLE_TESTS GREATEST_SHUFFLE_TESTS +#define SHUFFLE_SUITES GREATEST_SHUFFLE_SUITES + +#ifdef GREATEST_VA_ARGS +#define RUN_TESTp GREATEST_RUN_TESTp +#endif + +#if GREATEST_USE_LONGJMP +#define ASSERT_OR_LONGJMP GREATEST_ASSERT_OR_LONGJMP +#define ASSERT_OR_LONGJMPm GREATEST_ASSERT_OR_LONGJMPm +#define FAIL_WITH_LONGJMP GREATEST_FAIL_WITH_LONGJMP +#define FAIL_WITH_LONGJMPm GREATEST_FAIL_WITH_LONGJMPm +#endif + +#endif /* USE_ABBREVS */ + +#if defined(__cplusplus) && !defined(GREATEST_NO_EXTERN_CPLUSPLUS) +} +#endif + +#endif diff --git a/vendors/irmin/test/libirmin/test.c b/vendors/irmin/test/libirmin/test.c new file mode 100644 index 000000000000..571c19b0c75f --- /dev/null +++ b/vendors/irmin/test/libirmin/test.c @@ -0,0 +1,164 @@ +#include "irmin.h" +#include +#include +#include + +#include "greatest.h" + +TEST test_irmin_value_json(void) { + AUTO IrminType *json = irmin_type_json(); + IrminValue *j1 = irmin_value_of_string(json, "{\"a\": 1}", -1); + ASSERT_NEQ(j1, NULL); + irmin_value_free(j1); + + IrminValue *j2 = irmin_value_of_string(json, "{\"a\": 1", -1); + ASSERT_EQ(j2, NULL); + + PASS(); +} + +TEST test_irmin_store(void) { + // Setup config + AUTO IrminConfig *config = irmin_config_git_mem(NULL); + + // Initialize repo and store + AUTO IrminRepo *repo = irmin_repo_new(config); + AUTO Irmin *store = irmin_main(repo); + + // Create new string value + AUTO IrminString *a = irmin_string_new("123", 3); + + // Create path: a/b/c + char *k[] = {"a", "b", "c", NULL}; + AUTO IrminPath *path = irmin_path(repo, k); + + // Create commit info + AUTO IrminInfo *info = irmin_info_new(repo, "test", "set"); + + // Set a/b/c to "123" + ASSERT(irmin_set(store, path, (IrminContents *)a, info)); + ASSERT(irmin_mem(store, path)); + + // Get a/b/c from store + AUTO IrminString *v = (IrminString *)irmin_find(store, path); + ASSERT_NEQ(v, NULL); + + // Get string representation + uint64_t length = irmin_string_length(v); + ASSERT_EQ(strncmp(irmin_string_data(v), irmin_string_data(a), length), 0); + + // Check that tree exists at a/b + AUTO IrminPath *path1 = irmin_path_of_string(repo, "a/b", -1); + ASSERT(irmin_mem_tree(store, path1)); + + // Get tree at a/b + AUTO IrminTree *t = irmin_find_tree(store, path1); + + // Set d to "456" + AUTO IrminPath *path2 = irmin_path_of_string(repo, "d", 1); + AUTO IrminString *b = irmin_string_new("456", -1); + irmin_tree_add(repo, t, path2, (IrminContents *)b, NULL); + ASSERT(irmin_tree_mem(repo, t, path2)); + + // Commit updated tree + info = irmin_realloc(info, irmin_info_new(repo, "test", "tree")); + irmin_set_tree(store, path1, t, info); + + // Ensure the store contains a/b/d + AUTO IrminPath *path3 = irmin_path_of_string(repo, "a/b/d", -1); + ASSERT(irmin_mem(store, path3)); + + // Big string + size_t size = 1024 * 1024 * 64; + char *src = malloc(size); + memset(src, 'a', size); + AUTO IrminContents *big_string = + (IrminContents *)irmin_value_string(src, size); + AUTO IrminInfo *info2 = irmin_info_new(repo, "test", "big_string"); + ASSERT(irmin_set(store, path3, big_string, info2)); + AUTO IrminString *big_string_ = (IrminString *)irmin_find(store, path3); + ASSERT_EQ(irmin_string_length(big_string_), size); + ASSERT_EQ(strncmp(irmin_string_data(big_string_), src, size), 0); + free(src); + + // List + IrminPathArray *paths = irmin_list(store, path1); + ASSERT_EQ(irmin_path_array_length(repo, paths), 2); + + // Fetch + AUTO IrminRepo *repo1 = irmin_repo_new(config); + AUTO Irmin *store1 = irmin_main(repo1); + AUTO IrminRemote *remote = irmin_remote_store(store); + AUTO IrminCommit *c = irmin_fetch(store1, -1, remote); + ASSERT(c); + ASSERT(irmin_mem(store1, path3)); + + // Push + info = irmin_realloc(info, irmin_info_new(repo1, "test", "push")); + ASSERT(irmin_remove(store1, path3, info)); + c = irmin_realloc(c, irmin_push(store1, -1, remote)); + ASSERT(c); + + ASSERT_FALSE(irmin_mem(store1, path3)); + + PASS(); +} + +TEST test_irmin_tree(void) { + // Setup config + AUTO IrminConfig *config = irmin_config_mem(NULL, NULL); + + // Initialize repo and store + AUTO IrminRepo *repo = irmin_repo_new(config); + AUTO Irmin *store = irmin_main(repo); + + AUTO IrminTree *tree = irmin_tree_new(repo); + + AUTO IrminPath *p1 = irmin_path_of_string(repo, "a/b/c", -1); + AUTO IrminContents *v1 = irmin_contents_of_string(repo, "1", -1); + ASSERT(irmin_tree_add(repo, tree, p1, v1, NULL)); + + AUTO IrminPath *ab = irmin_path_parent(repo, p1); + ASSERT(irmin_tree_mem_tree(repo, tree, ab)); + AUTO IrminContents *v2 = irmin_tree_find(repo, tree, p1); + ASSERT_NEQ(v2, NULL); + + AUTO IrminType *ty = irmin_type_contents(repo); + ASSERT(irmin_value_equal(ty, (IrminValue *)v1, (IrminValue *)v2)); + + AUTO IrminPath *empty = irmin_path_empty(repo); + AUTO IrminInfo *info = irmin_info_new(repo, "test", "tree a/b/c"); + ASSERT(irmin_set_tree(store, empty, tree, info)); + ASSERT(irmin_tree_mem(repo, tree, p1)); + + AUTO IrminKindedKey *key = irmin_tree_key(repo, tree); + ASSERT_NEQ(key, NULL); + ASSERT(irmin_kinded_key_is_node(repo, key)); + + AUTO IrminHash *hash = irmin_tree_hash(repo, tree); + ASSERT_NEQ(hash, NULL); + + AUTO IrminTree *tree1 = irmin_tree_of_key(repo, key); + ASSERT_NEQ(tree1, NULL); + + AUTO IrminTree *tree2 = irmin_tree_of_key(repo, key); + ASSERT_NEQ(tree2, NULL); + + AUTO IrminType *ty1 = irmin_type_tree(repo); + ASSERT(irmin_value_equal(ty1, (IrminValue *)tree1, (IrminValue *)tree2)); + + ASSERT_FALSE(irmin_repo_has_error(repo)); + + PASS(); +} + +GREATEST_MAIN_DEFS(); + +int main(int argc, char *argv[]) { + GREATEST_MAIN_BEGIN(); + irmin_log_level("error"); + RUN_TEST(test_irmin_value_json); + RUN_TEST(test_irmin_store); + RUN_TEST(test_irmin_tree); + GREATEST_MAIN_END(); +} diff --git a/vendors/irmin/test/ppx_irmin/dune b/vendors/irmin/test/ppx_irmin/dune new file mode 100644 index 000000000000..c549f9af30ab --- /dev/null +++ b/vendors/irmin/test/ppx_irmin/dune @@ -0,0 +1,55 @@ +;; The PPX-dependent executable under test + +(executable + (name test_logs) + (modules test_logs) + (preprocess + (pps ppx_irmin.internal)) + (libraries fmt)) + +;; Run the PPX on the `.ml` file + +(rule + (targets pp.ml) + (action + (write-file %{targets} "let () = Ppxlib.Driver.standalone ()"))) + +(executable + (name pp) + (modules pp) + (libraries ppx_irmin.internal ppxlib)) + +(rule + (targets test_logs-processed.actual) + (deps + (:pp pp.exe) + (:input test_logs.ml)) + (action + (run ./%{pp} -deriving-keep-w32 both --impl %{input} -o %{targets}))) + +;; Compare the post-processed output to the .expected file + +(rule + (alias runtest) + (package ppx_irmin) + (action + (diff test_logs-processed.expected test_logs-processed.actual))) + +;; Ensure that the post-processed executable runs correctly + +(rule + (alias runtest) + (targets test_logs-output.actual) + (package ppx_irmin) + (action + (with-outputs-to + %{targets} + (run ./test_logs.exe)))) + +;; Compare the output logs of the executable run to the .expected file + +(rule + (alias runtest) + (package ppx_irmin) + (action + (diff test_logs-output.expected test_logs-output.actual))) diff --git a/vendors/irmin/test/ppx_irmin/test_logs-output.expected b/vendors/irmin/test/ppx_irmin/test_logs-output.expected new file mode 100644 index 000000000000..5430cdab83f8 --- /dev/null +++ b/vendors/irmin/test/ppx_irmin/test_logs-output.expected @@ -0,0 +1,5 @@ +[Line 2, characters 2-32] [App] Simple log entry +[Line 3, characters 2-45] [Error] Log entry on Line 3 +[Line 4, characters 2-49] [Warning] Infix @ operator: 3 +[Line 5, characters 2-76] [Info] Log entry in CPS form: Line 5, 3.140000 +[Line 12, characters 2-154] [Debug] Everything's OK on line 14 diff --git a/vendors/irmin/test/ppx_irmin/test_logs-processed.expected b/vendors/irmin/test/ppx_irmin/test_logs-processed.expected new file mode 100644 index 000000000000..a1beacece770 --- /dev/null +++ b/vendors/irmin/test/ppx_irmin/test_logs-processed.expected @@ -0,0 +1,62 @@ +let test () = + Logs.app + (fun f -> + f "Simple log entry" + ~tags:(Logs.Tag.add Ppx_irmin_internal_lib.Source_code_position.tag + __POS__ Logs.Tag.empty)); + Logs.err + (fun f -> + f "Log entry on Line %d" __LINE__ + ~tags:(Logs.Tag.add Ppx_irmin_internal_lib.Source_code_position.tag + __POS__ Logs.Tag.empty)); + Logs.warn + (fun f -> + f "Infix @@ operator: %d" (1 + 2) + ~tags:(Logs.Tag.add Ppx_irmin_internal_lib.Source_code_position.tag + __POS__ Logs.Tag.empty)); + Logs.info + (fun f -> + (fun f -> f "Log entry in CPS form: Line %d, %f" __LINE__ 3.14 : + (?header:string -> (_, _, _, _) format4 -> _) -> _) + (f + ~tags:(Logs.Tag.add + Ppx_irmin_internal_lib.Source_code_position.tag __POS__ + Logs.Tag.empty))); + Logs.debug + (fun f -> + (fun f -> + if true + then f "Everything's OK on line %d" __LINE__ + else f "Something's gone terribly wrong on line %d" __LINE__ : + (?header:string -> (_, _, _, _) format4 -> _) -> _) + (f + ~tags:(Logs.Tag.add + Ppx_irmin_internal_lib.Source_code_position.tag __POS__ + Logs.Tag.empty))); + () +let () = + let pp_source_pos ppf (_file, lnum, cnum, enum) = + Fmt.pf ppf "Line %d, characters %d-%d" lnum cnum enum in + let pp_level = + Fmt.of_to_string + (function + | Logs.App -> "App" + | Logs.Error -> "Error" + | Logs.Warning -> "Warning" + | Logs.Info -> "Info" + | Logs.Debug -> "Debug") in + let report _src level ~over k msgf = + let k _ = over (); k () in + msgf @@ + (fun ?header:_ -> + fun ?(tags= Logs.Tag.empty) -> + fun fmt -> + let source_pos = + Logs.Tag.find Ppx_irmin_internal_lib.Source_code_position.tag + tags in + (let open Fmt in kpf k stdout) + ("[%a] [%a] @[" ^^ (fmt ^^ "@]@.")) (Fmt.option pp_source_pos) + source_pos pp_level level) in + Logs.set_reporter { Logs.report = report }; + Logs.set_level (Some Debug); + test () diff --git a/vendors/irmin/test/ppx_irmin/test_logs.ml b/vendors/irmin/test/ppx_irmin/test_logs.ml new file mode 100644 index 000000000000..f1ad7d1a5632 --- /dev/null +++ b/vendors/irmin/test/ppx_irmin/test_logs.ml @@ -0,0 +1,46 @@ +let test () = + [%logs.app "Simple log entry"]; + [%logs.err "Log entry on Line %d" __LINE__]; + [%logs.warn "Infix @@ operator: %d" @@ (1 + 2)]; + [%logs.info fun f -> f "Log entry in CPS form: Line %d, %f" __LINE__ 3.14]; + + (* Test with a non-immediate application of [f] in the body. + + NOTE: The [Logs] API doesn't support polymorphic continuations: both + applications of [f] in the body must have the same number and type of + placeholders. *) + [%logs.debug + fun f -> + if true then f "Everything's OK on line %d" __LINE__ + else f "Something's gone terribly wrong on line %d" __LINE__]; + () + +(* Setup a reporter that can print tags added by the PPX, then run the tests. *) +let () = + let pp_source_pos ppf (_file, lnum, cnum, enum) = + Fmt.pf ppf "Line %d, characters %d-%d" lnum cnum enum + in + let pp_level = + Fmt.of_to_string (function + | Logs.App -> "App" + | Logs.Error -> "Error" + | Logs.Warning -> "Warning" + | Logs.Info -> "Info" + | Logs.Debug -> "Debug") + in + let report _src level ~over k msgf = + let k _ = + over (); + k () + in + msgf @@ fun ?header:_ ?(tags = Logs.Tag.empty) fmt -> + let source_pos = + Logs.Tag.find Ppx_irmin_internal_lib.Source_code_position.tag tags + in + Fmt.(kpf k stdout) + ("[%a] [%a] @[" ^^ fmt ^^ "@]@.") + (Fmt.option pp_source_pos) source_pos pp_level level + in + Logs.set_reporter { Logs.report }; + Logs.set_level (Some Debug); + test () -- GitLab From a4b2aac348c18b86afd140562e2f37b6c64d380b Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Mon, 13 Mar 2023 15:20:16 +0100 Subject: [PATCH 02/11] Node: conform to irmin.3.7 api --- src/bin_node/node_storage_command.ml | 1 + src/lib_store/unix/snapshots.ml | 2 ++ src/lib_tree_encoding/tezos_tree_encoding.ml | 3 +++ src/lib_tree_encoding/tezos_tree_encoding.mli | 3 +++ 4 files changed, 9 insertions(+) diff --git a/src/bin_node/node_storage_command.ml b/src/bin_node/node_storage_command.ml index 4c6fa73cb0f3..48977d6cd36d 100644 --- a/src/bin_node/node_storage_command.ml +++ b/src/bin_node/node_storage_command.ml @@ -129,6 +129,7 @@ module Term = struct ~auto_repair ~always:false ~heads:None + () in return_unit) diff --git a/src/lib_store/unix/snapshots.ml b/src/lib_store/unix/snapshots.ml index dcf3ba89e8c5..318ac9f7429e 100644 --- a/src/lib_store/unix/snapshots.ml +++ b/src/lib_store/unix/snapshots.ml @@ -4172,10 +4172,12 @@ module Make_snapshot_importer (Importer : IMPORTER) : Snapshot_importer = struct ~msg:"Checking context integrity" @@ fun () -> Context.Checks.Pack.Integrity_check.run + ?ppf:None ~root:dst_context_dir ~auto_repair:false ~always:false ~heads:(Some [Context_hash.to_b58check imported_context_hash]) + () else Lwt.return_unit in let* block_validation_result = diff --git a/src/lib_tree_encoding/tezos_tree_encoding.ml b/src/lib_tree_encoding/tezos_tree_encoding.ml index e9786c583930..87f0941a7a51 100644 --- a/src/lib_tree_encoding/tezos_tree_encoding.ml +++ b/src/lib_tree_encoding/tezos_tree_encoding.ml @@ -472,10 +472,13 @@ module Encodings_util = struct and type value := bytes and type tree := tree + type lower_policy + val init : ?patch_context:(t -> t tzresult Lwt.t) -> ?readonly:bool -> ?index_log_size:int -> + ?lower_policy:lower_policy -> string -> index Lwt.t diff --git a/src/lib_tree_encoding/tezos_tree_encoding.mli b/src/lib_tree_encoding/tezos_tree_encoding.mli index bc0f3d5873e6..9d29c1a512d4 100644 --- a/src/lib_tree_encoding/tezos_tree_encoding.mli +++ b/src/lib_tree_encoding/tezos_tree_encoding.mli @@ -305,10 +305,13 @@ module Encodings_util : sig and type value := bytes and type tree := tree + type lower_policy + val init : ?patch_context:(t -> t tzresult Lwt.t) -> ?readonly:bool -> ?index_log_size:int -> + ?lower_policy:lower_policy -> string -> index Lwt.t -- GitLab From 56e72a82b8d3a590dba952cd777552d26fce8ec5 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 14 Mar 2023 11:08:00 +0100 Subject: [PATCH 03/11] Node: remove obsolete data versions --- src/lib_node_config/data_version.ml | 31 ++--------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/lib_node_config/data_version.ml b/src/lib_node_config/data_version.ml index e92bf36212ce..0bea21ef3a7f 100644 --- a/src/lib_node_config/data_version.ml +++ b/src/lib_node_config/data_version.ml @@ -106,11 +106,6 @@ end (* FIXME https://gitlab.com/tezos/tezos/-/issues/2861 We should enable the semantic versioning instead of applying hardcoded rules.*) -let v_0_6 = Version.make ~major:0 ~minor:6 - -let v_0_7 = Version.make ~major:0 ~minor:7 - -let v_0_8 = Version.make ~major:0 ~minor:8 let v_1_0 = Version.make ~major:1 ~minor:0 @@ -133,31 +128,11 @@ let current_version = v_3_0 *) let upgradable_data_version = let open Lwt_result_syntax in - let v_1_0_upgrade ~data_dir = - let context_root = context_dir data_dir in - (* The upgrade function consist in letting irmin doing its own - file renaming. To do so, it must be done using a RW instance.*) - let*! ctxt = Context.init ~readonly:false context_root in - let*! () = Context.close ctxt in - return_unit - in let v_3_0_upgrade ~data_dir genesis = let store_dir = store_dir data_dir in Store.v_3_0_upgrade ~store_dir genesis in [ - ( v_0_6, - fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - let* () = v_1_0_upgrade ~data_dir in - v_3_0_upgrade ~data_dir genesis ); - ( v_0_7, - fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - let* () = v_1_0_upgrade ~data_dir in - v_3_0_upgrade ~data_dir genesis ); - ( v_0_8, - fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - let* () = v_1_0_upgrade ~data_dir in - v_3_0_upgrade ~data_dir genesis ); ( v_1_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> v_3_0_upgrade ~data_dir genesis ); @@ -454,10 +429,8 @@ let ensure_data_dir ?(mode = Is_compatible) genesis data_dir = | None -> return_unit (* Enable automatic upgrade to avoid users to manually upgrade. *) - | Some (version, _) - when Version.( - equal version v_2_0 || equal version v_1_0 || equal version v_0_6 - || equal version v_0_7 || equal version v_0_8) -> + | Some (version, _) when Version.(equal version v_2_0 || equal version v_1_0) + -> let* () = upgrade_data_dir ~data_dir genesis ~chain_name:() ~sandbox_parameters:() in -- GitLab From 1f23561bdc126b578368edaa2c706338bf9a3cd2 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Thu, 16 Mar 2023 15:17:59 +0100 Subject: [PATCH 04/11] Storage/context: introduce add_volume function --- src/lib_context/disk/context.ml | 14 ++++++++++++++ src/lib_context/memory/context.ml | 2 ++ src/lib_context/sigs/context.ml | 11 +++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/lib_context/disk/context.ml b/src/lib_context/disk/context.ml index c0c0429270a5..10f01af5421e 100644 --- a/src/lib_context/disk/context.ml +++ b/src/lib_context/disk/context.ml @@ -221,6 +221,14 @@ module Events = struct ~name:"gc_launch_failure" ~msg:"context garbage collection launch failed: {error}" ("error", Data_encoding.string) + + let add_volume = + declare_0 + ~section + ~level:Debug + ~name:"add_volume" + ~msg:"adding new volume to the context" + () end module Make (Encoding : module type of Tezos_context_encoding.Context) = struct @@ -435,6 +443,12 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct let h = Store.Commit.key commit in Store.create_one_commit_store index.repo h path + let add_volume index = + let open Lwt_syntax in + let* () = Events.(emit add_volume ()) in + Store.add_volume index.repo ; + Lwt.return_unit + (*-- Generic Store Primitives ------------------------------------------------*) let data_key = Tezos_context_sigs.Context.data_key diff --git a/src/lib_context/memory/context.ml b/src/lib_context/memory/context.ml index a04227182ae4..3482a7d0838a 100644 --- a/src/lib_context/memory/context.ml +++ b/src/lib_context/memory/context.ml @@ -202,6 +202,8 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct let export_snapshot _ _ ~path:_ = (* not implemented for in-memory context *) Lwt.return_unit + let add_volume _ = (* not implemented for in-memory context *) Lwt.return_unit + let sync _ = (* not implemented for in-memory context *) Lwt.return_unit (*-- Generic Store Primitives ------------------------------------------------*) diff --git a/src/lib_context/sigs/context.ml b/src/lib_context/sigs/context.ml index c5f957849367..d1954071aaf2 100644 --- a/src/lib_context/sigs/context.ml +++ b/src/lib_context/sigs/context.ml @@ -790,6 +790,17 @@ module type TEZOS_CONTEXT = sig import consist in copying the exported store. *) val export_snapshot : index -> Context_hash.t -> path:string -> unit Lwt.t + (** [add_volume index] closes the current volumes and opens a new + one. + In irmin's storage, a volume is a data chunk that aims to + receive the data collected during the next GC. This data is + collected only for Archive history modes (that uses an Archived + lower policy). In Full or Rolling history modes (that uses a + Deleted lower policy) the data is discarded. This function can + be called at anytime to complete a volume (and implicitly start + a new one). *) + val add_volume : index -> unit Lwt.t + val set_head : index -> Tezos_crypto.Hashed.Chain_id.t -> Context_hash.t -> unit Lwt.t -- GitLab From a4a1ec64bc5d5ae60046cd46fd960ab671cb4a1c Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Fri, 17 Mar 2023 10:52:44 +0100 Subject: [PATCH 05/11] Storage: introduce context volumes --- src/bin_node/node_replay_command.ml | 1 + src/lib_context/disk/context.ml | 90 ++++++++++++++++-- src/lib_context/memory/context.ml | 6 +- src/lib_context/sigs/context.ml | 45 +++++++-- src/lib_node_config/data_version.ml | 26 ++++-- src/lib_shell/block_validator_process.ml | 10 +- src/lib_shell/block_validator_process.mli | 1 + src/lib_shell/chain_validator.ml | 104 ++++++++++----------- src/lib_shell/node.ml | 1 + src/lib_store/unix/block_store.ml | 54 ++++++++--- src/lib_store/unix/store.ml | 42 +++++---- src/lib_validation/external_validation.ml | 8 +- src/lib_validation/external_validation.mli | 1 + src/lib_validation/external_validator.ml | 7 ++ 14 files changed, 283 insertions(+), 113 deletions(-) diff --git a/src/bin_node/node_replay_command.ml b/src/bin_node/node_replay_command.ml index c527fccab974..e93e7941c3e9 100644 --- a/src/bin_node/node_replay_command.ml +++ b/src/bin_node/node_replay_command.ml @@ -418,6 +418,7 @@ let replay ~internal_events ~singleprocess ~strict readonly; genesis; context_root; + history_mode = None; protocol_root; process_path = Sys.executable_name; sandbox_parameters = None; diff --git a/src/lib_context/disk/context.ml b/src/lib_context/disk/context.ml index 10f01af5421e..3cabb74ba05d 100644 --- a/src/lib_context/disk/context.ml +++ b/src/lib_context/disk/context.ml @@ -162,19 +162,25 @@ module Events = struct let section = ["node"; "context"; "disk"] let init_context = - declare_3 + declare_4 ~section ~level:Info ~name:"init_context" ~msg: "initializing context (readonly: {readonly}, index_log_size: \ - {index_log_size}, lru_size: {lru_size})" + {index_log_size}, lru_size: {lru_size}, lower_root: {lower_root})" ~pp1:Format.pp_print_bool ("readonly", Data_encoding.bool) ~pp2:Format.pp_print_int ("index_log_size", Data_encoding.int31) ~pp3:Format.pp_print_int ("lru_size", Data_encoding.int31) + ~pp4:(fun ppf v -> + Format.fprintf + ppf + "%s" + ((function Some path -> path | None -> "none") v)) + ("lower_root", Data_encoding.(option string)) let starting_gc = declare_1 @@ -800,11 +806,78 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct (*-- Initialisation ----------------------------------------------------------*) - let init ?patch_context ?(readonly = false) ?index_log_size:tbl_log_size root - = + type lower_policy = Archived | Deleted + + (* Subirectory name of the context directory where context volumes + will be stored, if any. *) + let lower_root_dir = "volumes" + + (* Additionally, this is a safe guard regarding unexpected policy switches. + TODO: introduce ~force option to allow history_mode switches *) + let check_lower_policy ~context_root lower_policy = + let open Lwt_syntax in + let* context_dir_exists, lower_root_exists = + let* context_exists = Lwt_unix.file_exists context_root in + if not context_exists then return (context_exists, false) + else + let* files = + Lwt_stream.to_list (Lwt_unix.files_of_directory context_root) + in + let files = List.filter (fun s -> s <> "." && s <> "..") files in + match files with + | [] -> return (context_exists, false) + | l when List.exists (fun s -> s = lower_root_dir) l -> + return (context_exists, true) + | _ -> return (context_exists, false) + in + let* lower_root = + match lower_policy with + | Some lower_policy -> ( + match (lower_policy, context_dir_exists, lower_root_exists) with + | Archived, true, true (* Valid archived configuration *) -> + let lower_root_path = + Filename.(concat context_root lower_root_dir) + in + return_some lower_root_path + | Archived, false, false (* Uninitialized context root *) -> + let lower_root_path = + Filename.(concat context_root lower_root_dir) + in + let* () = Lwt_unix.mkdir context_root 0o755 in + return_some lower_root_path + | Deleted, true, false | Deleted, false, false -> + (* Valid deleted configuration. Return none. *) return_none + | Archived, false, true -> + (* Invalid config, archived expects a lower root*) assert false + | Deleted, false, true -> + (* Invalid config, deleted expects no lower root *) assert false + | Archived, true, false -> assert false + | Deleted, true, true -> + (* Inconsistent cases*) + assert false) + | None -> ( + match (context_dir_exists, lower_root_exists) with + | true, true -> + (* Archived configuration *) + let lower_root_path = + Filename.(concat context_root lower_root_dir) + in + return_some lower_root_path + | false, false -> (* Assuming default policy: Deleted *) return_none + | true, false -> (* Deleted configuration *) return_none + | false, true -> (* Inconsistent case *) assert false) + in + return (lower_root, context_dir_exists) + + let init ?patch_context ?(readonly = false) ?index_log_size:tbl_log_size + ?lower_policy context_root = let open Lwt_syntax in (* Forces the context to use the minimal indexing strategy. *) let indexing_strategy = Irmin_pack.Indexing_strategy.minimal in + let* lower_root, context_root_exists = + check_lower_policy ~context_root lower_policy + in + let fresh = not context_root_exists in let+ repo = let env = Tezos_context_helpers.Env.v in let index_log_size = @@ -814,7 +887,8 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct in let lru_size = env.lru_size in let* () = - Events.(emit init_context (readonly, index_log_size, lru_size)) + Events.( + emit init_context (readonly, index_log_size, lru_size, lower_root)) in Store.Repo.v (Irmin_pack.config @@ -822,9 +896,11 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct ~indexing_strategy ~index_log_size ~lru_size - root) + ~lower_root + ~fresh + context_root) in - {path = root; repo; patch_context; readonly} + {path = context_root; repo; patch_context; readonly} let close index = let _interrupted_gc = Store.Gc.cancel index.repo in diff --git a/src/lib_context/memory/context.ml b/src/lib_context/memory/context.ml index 3482a7d0838a..2a59127c49a1 100644 --- a/src/lib_context/memory/context.ml +++ b/src/lib_context/memory/context.ml @@ -517,9 +517,13 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct let fork_test_chain v ~protocol ~expiration = add_test_chain v (Forking {protocol; expiration}) - let init ?patch_context ?(readonly = false) ?index_log_size path = + type lower_policy = Archived | Deleted + + let init ?patch_context ?(readonly = false) ?index_log_size ?lower_policy path + = let open Lwt_syntax in ignore index_log_size ; + ignore lower_policy ; let cfg = Irmin_pack.config ~readonly path in let* repo = Store.Repo.v cfg in Lwt.return {path; repo; patch_context} diff --git a/src/lib_context/sigs/context.ml b/src/lib_context/sigs/context.ml index d1954071aaf2..51de8753b7fb 100644 --- a/src/lib_context/sigs/context.ml +++ b/src/lib_context/sigs/context.ml @@ -657,15 +657,35 @@ module type TEZOS_CONTEXT = sig val index : context -> index + (** Defines the policy of the lower layer of the context store. + [Archived] aims to move all the commits, subject to a garbage + collection, to the lower layer. This policy must be used when + using the Archive history mode. + [Deleted] aims to drop all the commits subject to a garbage + collection. This policy must be used when using the Full or + Rolling history mode. + + Warning: the lower policy must be used with care as stores + initialized, successively, with different policies, may + introduce a discontinuity in the context history. + *) + type lower_policy = Archived | Deleted + (** Open or initialize a versioned store at a given path. The indexing_strategy, which determines whether newly-exported objects by this store handle should also be added to the store's - index, is set to [`Minimal] by default. *) + index, is set to [`Minimal] by default. + + The [?lower_policy] argument defines the lower policy of the + context. By default, the [Deleted] policy is used. However, + [init] will detect inconsistent configuration and fail if any. + *) val init : ?patch_context:(context -> context tzresult Lwt.t) -> ?readonly:bool -> ?index_log_size:int -> + ?lower_policy:lower_policy -> string -> index Lwt.t @@ -730,16 +750,23 @@ module type TEZOS_CONTEXT = sig val commit : time:Time.Protocol.t -> ?message:string -> context -> Context_hash.t Lwt.t - (** [gc index commit_hash] removes from disk all the data older than - the [commit_hash]. Operations needing to checkout commits - greater or equal to [commit_hash] will continue to work. Calling - [checkout h'] on GC-ed commits will return [None]. + (** [gc index commit_hash] moves the data older that the given + [commit_hash] from the upper layer to the lower layer. + + For Full and Rolling history modes ([Deleted] lower policy), + this is considered as a garbage collection -- operations needing + to checkout commits greater or equal to [commit_hash] will + continue to work. Calling [checkout h'] on GC-ed commits will + return [None]. + + For archive nodes ([Archived] lower policy), the data is simply + moved from the upper to the lower layer. From the irmin point of view, a successful gc call on a - [commit_hash] will result in a new prefix file containing that - [commit_hash] as a root commit. This prefix file is considered - as standalone as all the data referenced by that commit is - contained in that file. *) + [commit_hash] will result in a new prefix file, for the upper + store, containing that [commit_hash] as a root commit. This + prefix file is considered as standalone as all the data + referenced by that commit is contained in that file. *) val gc : index -> Context_hash.t -> unit Lwt.t (** [wait_gc_completion index] will return a blocking thread if an diff --git a/src/lib_node_config/data_version.ml b/src/lib_node_config/data_version.ml index 0bea21ef3a7f..c7d63957f436 100644 --- a/src/lib_node_config/data_version.ml +++ b/src/lib_node_config/data_version.ml @@ -101,7 +101,8 @@ end * - 1.0 : context upgrade (upgrade to irmin.3.3) -- v14.0 * - 2.0 : introduce context GC (upgrade to irmin.3.4) -- v15.0 * - 3.0 : change blocks' context hash semantics and introduce - context split (upgrade to irmin.3.5) -- v16.0 *) + context split (upgrade to irmin.3.5) -- v16.0 + * - 4.0 : introduce context volumes (upgrade to irmin.3.7) *) (* FIXME https://gitlab.com/tezos/tezos/-/issues/2861 We should enable the semantic versioning instead of applying @@ -113,7 +114,9 @@ let v_2_0 = Version.make ~major:2 ~minor:0 let v_3_0 = Version.make ~major:3 ~minor:0 -let current_version = v_3_0 +let v_4_0 = Version.make ~major:4 ~minor:0 + +let current_version = v_4_0 (* List of upgrade functions from each still supported previous version to the current [data_version] above. If this list grows too @@ -132,13 +135,23 @@ let upgradable_data_version = let store_dir = store_dir data_dir in Store.v_3_0_upgrade ~store_dir genesis in + let v_4_0_upgrade ~data_dir = + let _context_dir = context_dir data_dir in + (* TODO call Context.v_4_0_upgrade *) + return_unit + in [ ( v_1_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - v_3_0_upgrade ~data_dir genesis ); + let* _ = v_3_0_upgrade ~data_dir genesis in + v_4_0_upgrade ~data_dir ); ( v_2_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> - v_3_0_upgrade ~data_dir genesis ); + let* _ = v_3_0_upgrade ~data_dir genesis in + v_4_0_upgrade ~data_dir ); + ( v_3_0, + fun ~data_dir _ ~chain_name:_ ~sandbox_parameters:_ -> + v_4_0_upgrade ~data_dir ); ] type error += Invalid_data_dir_version of Version.t * Version.t @@ -429,8 +442,9 @@ let ensure_data_dir ?(mode = Is_compatible) genesis data_dir = | None -> return_unit (* Enable automatic upgrade to avoid users to manually upgrade. *) - | Some (version, _) when Version.(equal version v_2_0 || equal version v_1_0) - -> + | Some (version, _) + when Version.( + equal version v_3_0 || equal version v_2_0 || equal version v_1_0) -> let* () = upgrade_data_dir ~data_dir genesis ~chain_name:() ~sandbox_parameters:() in diff --git a/src/lib_shell/block_validator_process.ml b/src/lib_shell/block_validator_process.ml index 12e7533d3c9a..8a4c17710132 100644 --- a/src/lib_shell/block_validator_process.ml +++ b/src/lib_shell/block_validator_process.ml @@ -38,6 +38,7 @@ type validator_kind = readonly : bool; data_dir : string; context_root : string; + history_mode : History_mode.t option; protocol_root : string; process_path : string; sandbox_parameters : Data_encoding.json option; @@ -567,6 +568,7 @@ module External_validator_process = struct readonly : bool; data_dir : string; context_root : string; + history_mode : History_mode.t option; protocol_root : string; user_activated_upgrades : User_activated.upgrades; user_activated_protocol_overrides : User_activated.protocol_overrides; @@ -642,8 +644,9 @@ module External_validator_process = struct { External_validation.context_root = vp.context_root; protocol_root = vp.protocol_root; - sandbox_parameters = vp.sandbox_parameters; + history_mode = vp.history_mode; genesis = vp.genesis; + sandbox_parameters = vp.sandbox_parameters; user_activated_upgrades = vp.user_activated_upgrades; user_activated_protocol_overrides = vp.user_activated_protocol_overrides; operation_metadata_size_limit = vp.operation_metadata_size_limit; @@ -863,7 +866,7 @@ module External_validator_process = struct _; } : validator_environment) ~genesis ~data_dir ~readonly ~context_root - ~protocol_root ~process_path ~sandbox_parameters ~dal_config + ~history_mode ~protocol_root ~process_path ~sandbox_parameters ~dal_config ~internal_events = let open Lwt_result_syntax in let*! () = Events.(emit init ()) in @@ -873,6 +876,7 @@ module External_validator_process = struct readonly; genesis; context_root; + history_mode; protocol_root; user_activated_upgrades; user_activated_protocol_overrides; @@ -1068,6 +1072,7 @@ let init validator_environment validator_kind = readonly; data_dir; context_root; + history_mode; protocol_root; process_path; sandbox_parameters; @@ -1081,6 +1086,7 @@ let init validator_environment validator_kind = ~data_dir ~readonly ~context_root + ~history_mode ~protocol_root ~process_path ~sandbox_parameters diff --git a/src/lib_shell/block_validator_process.mli b/src/lib_shell/block_validator_process.mli index 1f2b0cb59fe5..b7b99f919d44 100644 --- a/src/lib_shell/block_validator_process.mli +++ b/src/lib_shell/block_validator_process.mli @@ -50,6 +50,7 @@ type validator_kind = readonly : bool; data_dir : string; context_root : string; + history_mode : History_mode.t option; protocol_root : string; process_path : string; sandbox_parameters : Data_encoding.json option; diff --git a/src/lib_shell/chain_validator.ml b/src/lib_shell/chain_validator.ml index a31df640ae36..19e9129d7d43 100644 --- a/src/lib_shell/chain_validator.ml +++ b/src/lib_shell/chain_validator.ml @@ -426,57 +426,54 @@ let register_garbage_collect_callback w = let gc_lockfile_path = Naming.(file_path (gc_lockfile (Store.Chain.chain_dir chain_store))) in - let is_gc_allowed = Context_ops.is_gc_allowed index in let gc_callback = - if is_gc_allowed then - let gc_synchronous_call block_hash = - let* block = Store.Block.read_block chain_store block_hash in - let* resulting_context_hash = - Store.Block.resulting_context_hash chain_store block - in - let* () = - Block_validator.context_garbage_collection - nv.parameters.block_validator - index - resulting_context_hash - ~gc_lockfile_path - in - let kind = - Block_validator_process.kind nv.parameters.block_validator_process - in - (* The callback call will block until the GC is completed: either - using the Irmin function directly in single-process or using - the lockfile through the validator process used to notify the - GC completion. *) - match kind with - | Single_process -> - (* If the GC is running in the same instance, we can directly - wait for its completion. *) - let*! () = Context_ops.wait_gc_completion index in - return_unit - | External_process -> - (* Otherwise, we wait for the lockfile, which is locked by the - external process when the GC starts and released when the - GC ends. *) - let* gc_lockfile = - protect (fun () -> - let*! fd = - Lwt_unix.openfile - gc_lockfile_path - [Unix.O_CREAT; O_RDWR; O_CLOEXEC; O_SYNC] - 0o644 - in - return fd) - in - Lwt.finalize - (fun () -> - let*! () = Lwt_unix.lockf gc_lockfile Unix.F_RLOCK 0 in - let*! () = Lwt_unix.lockf gc_lockfile Unix.F_ULOCK 0 in - return_unit) - (fun () -> Lwt_unix.close gc_lockfile) + let gc_synchronous_call block_hash = + let* block = Store.Block.read_block chain_store block_hash in + let* resulting_context_hash = + Store.Block.resulting_context_hash chain_store block + in + let* () = + Block_validator.context_garbage_collection + nv.parameters.block_validator + index + resulting_context_hash + ~gc_lockfile_path + in + let kind = + Block_validator_process.kind nv.parameters.block_validator_process in - Some gc_synchronous_call - else None + (* The callback call will block until the GC is completed: either + using the Irmin function directly in single-process or using + the lockfile through the validator process used to notify the + GC completion. *) + match kind with + | Single_process -> + (* If the GC is running in the same instance, we can directly + wait for its completion. *) + let*! () = Context_ops.wait_gc_completion index in + return_unit + | External_process -> + (* Otherwise, we wait for the lockfile, which is locked by the + external process when the GC starts and released when the + GC ends. *) + let* gc_lockfile = + protect (fun () -> + let*! fd = + Lwt_unix.openfile + gc_lockfile_path + [Unix.O_CREAT; O_RDWR; O_CLOEXEC; O_SYNC] + 0o644 + in + return fd) + in + Lwt.finalize + (fun () -> + let*! () = Lwt_unix.lockf gc_lockfile Unix.F_RLOCK 0 in + let*! () = Lwt_unix.lockf gc_lockfile Unix.F_ULOCK 0 in + return_unit) + (fun () -> Lwt_unix.close gc_lockfile) + in + Some gc_synchronous_call in Store.Chain.register_gc_callback nv.parameters.chain_store gc_callback @@ -484,13 +481,10 @@ let register_split_callback w = let nv = Worker.state w in let chain_store = nv.parameters.chain_store in let index = Store.(context_index (Chain.global_store chain_store)) in - let is_gc_allowed = Context_ops.is_gc_allowed index in let split = - if is_gc_allowed then - Some - (fun () -> - Block_validator.context_split nv.parameters.block_validator index) - else None + Some + (fun () -> + Block_validator.context_split nv.parameters.block_validator index) in Store.Chain.register_split_callback nv.parameters.chain_store split diff --git a/src/lib_shell/node.ml b/src/lib_shell/node.ml index 58846d4b9b3c..2fffb3af4b43 100644 --- a/src/lib_shell/node.ml +++ b/src/lib_shell/node.ml @@ -267,6 +267,7 @@ let create ?(sandboxed = false) ?sandbox_parameters ~singleprocess ~version readonly = false; genesis; context_root; + history_mode; protocol_root; process_path = Sys.executable_name; sandbox_parameters; diff --git a/src/lib_store/unix/block_store.ml b/src/lib_store/unix/block_store.ml index 108bf78642fb..ebc0ad991cc3 100644 --- a/src/lib_store/unix/block_store.ml +++ b/src/lib_store/unix/block_store.ml @@ -1306,19 +1306,47 @@ let create_merging_thread block_store ~history_mode ~old_ro_store ~old_rw_store in return (new_ro_store, new_savepoint, new_caboose) -let may_trigger_gc block_store history_mode ~previous_savepoint ~new_savepoint = +let may_trigger_gc block_store history_mode ~previous_savepoint ~new_savepoint + ~new_head ~new_head_lafl_level = let open Lwt_result_syntax in - let savepoint_hash = fst new_savepoint in - if - History_mode.(equal history_mode Archive) - || Block_hash.(savepoint_hash = fst previous_savepoint) - then (* No GC required *) return_unit - else - match block_store.gc_callback with - | None -> return_unit - | Some gc -> - let*! () = Store_events.(emit start_context_gc new_savepoint) in - gc savepoint_hash + match history_mode with + | History_mode.Archive -> + let* prev_head_metadata_o = + read_block_metadata block_store (Block (Block_repr.hash new_head, 1)) + in + let prev_head_metadata = + WithExceptions.Option.get ~loc:__LOC__ prev_head_metadata_o + in + let prev_head_lafl = + Block_repr.last_allowed_fork_level prev_head_metadata + in + if not (prev_head_lafl = new_head_lafl_level) then + match block_store.gc_callback with + | None -> return_unit + | Some gc -> + let* new_head_lafl_block = + read_predecessor_block_by_level + block_store + ~head:new_head + new_head_lafl_level + in + let new_head_lafl_hash = Block_repr.hash new_head_lafl_block in + let*! () = + Store_events.( + emit start_context_gc (new_head_lafl_hash, new_head_lafl_level)) + in + gc new_head_lafl_hash + else return_unit + | Full _ | Rolling _ -> ( + let savepoint_hash = fst new_savepoint in + if Block_hash.(savepoint_hash = fst previous_savepoint) then + (* No GC required *) return_unit + else + match block_store.gc_callback with + | None -> return_unit + | Some gc -> + let*! () = Store_events.(emit start_context_gc new_savepoint) in + gc savepoint_hash) let split_context block_store new_head_lafl = let open Lwt_result_syntax in @@ -1427,6 +1455,8 @@ let merge_stores block_store ~(on_error : tztrace -> unit tzresult Lwt.t) history_mode ~previous_savepoint ~new_savepoint + ~new_head + ~new_head_lafl_level:new_head_lafl in (* The merge operation succeeded, the store is now idle. *) block_store.merging_thread <- None ; diff --git a/src/lib_store/unix/store.ml b/src/lib_store/unix/store.ml index cdad83580804..4bdcce2012cf 100644 --- a/src/lib_store/unix/store.ml +++ b/src/lib_store/unix/store.ml @@ -1367,10 +1367,10 @@ module Chain = struct (* Calls a context split when reaching the dawn of a cycle. See {!Lib_context.Context.split} for details. - In the context of full and rolling nodes, the split function is - expected to be called just after committing the first block of a - cycle, i.e, a future savepoint. Thus, that commit will end a - chunk and will be an optimal candidate for a GC call. + The split function is expected to be called just after committing + the first block of a cycle, i.e, a future savepoint. Thus, that + commit will end a chunk and will be an optimal candidate for a GC + call. The call of split is triggered when the last allowed fork level of the new head changes. This is not ensuring that the created @@ -1380,21 +1380,18 @@ module Chain = struct short, this will lead to the optimal behaviour. *) let may_split_context chain_store new_head_lafl previous_head = let open Lwt_result_syntax in - match history_mode chain_store with - | Archive -> return_unit - | Full _ | Rolling _ -> - let* previous_head_metadata = - Block.get_block_metadata chain_store previous_head - in - if - not - (Int32.equal - new_head_lafl - (Block.last_allowed_fork_level previous_head_metadata)) - then - let block_store = chain_store.block_store in - Block_store.split_context block_store new_head_lafl - else return_unit + let* previous_head_metadata = + Block.get_block_metadata chain_store previous_head + in + if + not + (Int32.equal + new_head_lafl + (Block.last_allowed_fork_level previous_head_metadata)) + then + let block_store = chain_store.block_store in + Block_store.split_context block_store new_head_lafl + else return_unit let set_head chain_store new_head = let open Lwt_result_syntax in @@ -2534,8 +2531,13 @@ let init ?patch_context ?commit_genesis ?history_mode ?(readonly = false) in Lwt.return (context_index, commit_genesis) | None -> + let*! lower_policy = + match history_mode with + | Some History_mode.Archive -> Lwt.return_some Context.Archived + | _ -> Lwt.return_none + in let*! context_index = - Context.init ~readonly ?patch_context context_dir + Context.init ~readonly ?patch_context ?lower_policy context_dir in let commit_genesis ~chain_id = Context.commit_genesis diff --git a/src/lib_validation/external_validation.ml b/src/lib_validation/external_validation.ml index 8f929fd49808..1a0605f32f4f 100644 --- a/src/lib_validation/external_validation.ml +++ b/src/lib_validation/external_validation.ml @@ -27,6 +27,7 @@ type parameters = { context_root : string; protocol_root : string; + history_mode : History_mode.t option; genesis : Genesis.t; sandbox_parameters : Data_encoding.json option; user_activated_upgrades : User_activated.upgrades; @@ -139,6 +140,7 @@ let parameters_encoding = (fun { context_root; protocol_root; + history_mode; genesis; user_activated_upgrades; user_activated_protocol_overrides; @@ -149,6 +151,7 @@ let parameters_encoding = } -> ( context_root, protocol_root, + history_mode, genesis, user_activated_upgrades, user_activated_protocol_overrides, @@ -158,6 +161,7 @@ let parameters_encoding = internal_events )) (fun ( context_root, protocol_root, + history_mode, genesis, user_activated_upgrades, user_activated_protocol_overrides, @@ -168,6 +172,7 @@ let parameters_encoding = { context_root; protocol_root; + history_mode; genesis; user_activated_upgrades; user_activated_protocol_overrides; @@ -176,9 +181,10 @@ let parameters_encoding = dal_config; internal_events; }) - (obj9 + (obj10 (req "context_root" string) (req "protocol_root" string) + (req "history_mode" (option History_mode.encoding)) (req "genesis" Genesis.encoding) (req "user_activated_upgrades" User_activated.upgrades_encoding) (req diff --git a/src/lib_validation/external_validation.mli b/src/lib_validation/external_validation.mli index 8ea896660947..3eb94d2c56c8 100644 --- a/src/lib_validation/external_validation.mli +++ b/src/lib_validation/external_validation.mli @@ -27,6 +27,7 @@ type parameters = { context_root : string; protocol_root : string; + history_mode : History_mode.t option; genesis : Genesis.t; sandbox_parameters : Data_encoding.json option; user_activated_upgrades : User_activated.upgrades; diff --git a/src/lib_validation/external_validator.ml b/src/lib_validation/external_validator.ml index 66e034097802..96bbcd632616 100644 --- a/src/lib_validation/external_validator.ml +++ b/src/lib_validation/external_validator.ml @@ -191,6 +191,7 @@ let init ~readonly input output = let*! { context_root; protocol_root; + history_mode; genesis; sandbox_parameters; user_activated_upgrades; @@ -209,6 +210,11 @@ let init ~readonly input output = Option.map (fun p -> ("sandbox_parameter", p)) sandbox_parameters in let*! context_index = + let*! lower_policy = + match history_mode with + | Some Archive -> Lwt.return_some Context.Archived + | _ -> Lwt.return_none + in Context.init ~patch_context:(fun ctxt -> let open Lwt_result_syntax in @@ -218,6 +224,7 @@ let init ~readonly input output = in Shell_context.unwrap_disk_context ctxt) ~readonly + ?lower_policy context_root in (* It is necessary to send the ok result, as a blocking promise for -- GitLab From f0cc1ab7fd58daf584522f40ce26c6a35bc03c9f Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Thu, 6 Apr 2023 15:04:43 +0200 Subject: [PATCH 06/11] Lwt_utils_unix: improve remove_dir doc --- src/lib_stdlib_unix/lwt_utils_unix.mli | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib_stdlib_unix/lwt_utils_unix.mli b/src/lib_stdlib_unix/lwt_utils_unix.mli index 00a2be9a42bb..20eee66ac450 100644 --- a/src/lib_stdlib_unix/lwt_utils_unix.mli +++ b/src/lib_stdlib_unix/lwt_utils_unix.mli @@ -85,6 +85,8 @@ val is_directory : string -> bool Lwt.t directory. *) val dir_exists : string -> bool Lwt.t +(** [remove_dir path] removes the directory located at [path], and its + content, recursively. *) val remove_dir : string -> unit Lwt.t (** [create_dir ?perm dir] creates the directory at the path [dir] and -- GitLab From 01171ec06868efecd883b99ef41cf38cd4e79628 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Mon, 20 Mar 2023 12:47:45 +0100 Subject: [PATCH 07/11] Node: plug context add volumes --- src/lib_context/disk/context.ml | 48 +++---- src/lib_context/memory/context.ml | 3 + src/lib_context/sigs/context.ml | 4 + src/lib_node_config/data_version.ml | 16 +-- .../context_ops/context_ops.ml | 5 + src/lib_shell/block_validator.ml | 4 + src/lib_shell/block_validator.mli | 11 +- src/lib_shell/block_validator_process.ml | 15 ++ src/lib_shell/block_validator_process.mli | 4 + src/lib_shell/chain_validator.ml | 12 ++ src/lib_store/mocked/store.ml | 7 + src/lib_store/store.mli | 9 ++ src/lib_store/unix/block_store.ml | 26 +++- src/lib_store/unix/block_store.mli | 6 + src/lib_store/unix/store.ml | 132 +++++++++++------- src/lib_store/unix/store.mli | 13 ++ src/lib_validation/external_validation.ml | 12 ++ src/lib_validation/external_validation.mli | 1 + src/lib_validation/external_validator.ml | 18 +++ 19 files changed, 257 insertions(+), 89 deletions(-) diff --git a/src/lib_context/disk/context.ml b/src/lib_context/disk/context.ml index 3cabb74ba05d..25db49eb727b 100644 --- a/src/lib_context/disk/context.ml +++ b/src/lib_context/disk/context.ml @@ -812,8 +812,8 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct will be stored, if any. *) let lower_root_dir = "volumes" - (* Additionally, this is a safe guard regarding unexpected policy switches. - TODO: introduce ~force option to allow history_mode switches *) + (* Additionally, this is a safe guard regarding unexpected policy + switches. *) let check_lower_policy ~context_root lower_policy = let open Lwt_syntax in let* context_dir_exists, lower_root_exists = @@ -833,39 +833,23 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct let* lower_root = match lower_policy with | Some lower_policy -> ( - match (lower_policy, context_dir_exists, lower_root_exists) with - | Archived, true, true (* Valid archived configuration *) -> + match lower_policy with + | Archived -> let lower_root_path = Filename.(concat context_root lower_root_dir) in return_some lower_root_path - | Archived, false, false (* Uninitialized context root *) -> + | Deleted -> return_none) + | None -> + if context_dir_exists then + if lower_root_exists then + (* Assuming Archived *) let lower_root_path = Filename.(concat context_root lower_root_dir) in - let* () = Lwt_unix.mkdir context_root 0o755 in return_some lower_root_path - | Deleted, true, false | Deleted, false, false -> - (* Valid deleted configuration. Return none. *) return_none - | Archived, false, true -> - (* Invalid config, archived expects a lower root*) assert false - | Deleted, false, true -> - (* Invalid config, deleted expects no lower root *) assert false - | Archived, true, false -> assert false - | Deleted, true, true -> - (* Inconsistent cases*) - assert false) - | None -> ( - match (context_dir_exists, lower_root_exists) with - | true, true -> - (* Archived configuration *) - let lower_root_path = - Filename.(concat context_root lower_root_dir) - in - return_some lower_root_path - | false, false -> (* Assuming default policy: Deleted *) return_none - | true, false -> (* Deleted configuration *) return_none - | false, true -> (* Inconsistent case *) assert false) + else (* Assuming Deleted (default mode) *) return_none + else (* Assuming Deleted (default mode) *) return_none in return (lower_root, context_dir_exists) @@ -874,10 +858,10 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct let open Lwt_syntax in (* Forces the context to use the minimal indexing strategy. *) let indexing_strategy = Irmin_pack.Indexing_strategy.minimal in - let* lower_root, context_root_exists = + let* lower_root, context_dir_exists = check_lower_policy ~context_root lower_policy in - let fresh = not context_root_exists in + let fresh = not context_dir_exists in let+ repo = let env = Tezos_context_helpers.Env.v in let index_log_size = @@ -902,6 +886,12 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct in {path = context_root; repo; patch_context; readonly} + let remove_lower_root context_root = + let open Lwt_syntax in + let lower_root_path = Filename.(concat context_root lower_root_dir) in + let* exists = Lwt_unix.file_exists lower_root_path in + if exists then Lwt_utils_unix.remove_dir lower_root_path else return_unit + let close index = let _interrupted_gc = Store.Gc.cancel index.repo in Store.Repo.close index.repo diff --git a/src/lib_context/memory/context.ml b/src/lib_context/memory/context.ml index 2a59127c49a1..4d929554c39d 100644 --- a/src/lib_context/memory/context.ml +++ b/src/lib_context/memory/context.ml @@ -204,6 +204,9 @@ module Make (Encoding : module type of Tezos_context_encoding.Context) = struct let add_volume _ = (* not implemented for in-memory context *) Lwt.return_unit + let remove_lower_root _ = + (* not implemented for in-memory context *) Lwt.return_unit + let sync _ = (* not implemented for in-memory context *) Lwt.return_unit (*-- Generic Store Primitives ------------------------------------------------*) diff --git a/src/lib_context/sigs/context.ml b/src/lib_context/sigs/context.ml index 51de8753b7fb..3766fbd2c185 100644 --- a/src/lib_context/sigs/context.ml +++ b/src/lib_context/sigs/context.ml @@ -828,6 +828,10 @@ module type TEZOS_CONTEXT = sig a new one). *) val add_volume : index -> unit Lwt.t + (** [remove_lower_root path] removes the lower root contained in the + context directory located at [path]. *) + val remove_lower_root : string -> unit Lwt.t + val set_head : index -> Tezos_crypto.Hashed.Chain_id.t -> Context_hash.t -> unit Lwt.t diff --git a/src/lib_node_config/data_version.ml b/src/lib_node_config/data_version.ml index c7d63957f436..277d95351c96 100644 --- a/src/lib_node_config/data_version.ml +++ b/src/lib_node_config/data_version.ml @@ -135,23 +135,23 @@ let upgradable_data_version = let store_dir = store_dir data_dir in Store.v_3_0_upgrade ~store_dir genesis in - let v_4_0_upgrade ~data_dir = - let _context_dir = context_dir data_dir in - (* TODO call Context.v_4_0_upgrade *) - return_unit + let v_4_0_upgrade ~data_dir genesis = + let context_dir = context_dir data_dir in + let store_dir = store_dir data_dir in + Store.v_4_0_upgrade ~store_dir ~context_dir genesis in [ ( v_1_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> let* _ = v_3_0_upgrade ~data_dir genesis in - v_4_0_upgrade ~data_dir ); + v_4_0_upgrade ~data_dir genesis ); ( v_2_0, fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> let* _ = v_3_0_upgrade ~data_dir genesis in - v_4_0_upgrade ~data_dir ); + v_4_0_upgrade ~data_dir genesis ); ( v_3_0, - fun ~data_dir _ ~chain_name:_ ~sandbox_parameters:_ -> - v_4_0_upgrade ~data_dir ); + fun ~data_dir genesis ~chain_name:_ ~sandbox_parameters:_ -> + v_4_0_upgrade ~data_dir genesis ); ] type error += Invalid_data_dir_version of Version.t * Version.t diff --git a/src/lib_protocol_environment/context_ops/context_ops.ml b/src/lib_protocol_environment/context_ops/context_ops.ml index 3112bdaf1f01..a07fefa78e15 100644 --- a/src/lib_protocol_environment/context_ops/context_ops.ml +++ b/src/lib_protocol_environment/context_ops/context_ops.ml @@ -218,6 +218,11 @@ let split context_index = | Disk_index index -> Context.split index | Memory_index index -> Tezos_context_memory.Context.split index +let add_volume context_index = + match context_index with + | Disk_index index -> Context.add_volume index + | Memory_index index -> Tezos_context_memory.Context.add_volume index + let sync = function | Disk_index index -> Context.sync index | Memory_index index -> Tezos_context_memory.Context.sync index diff --git a/src/lib_shell/block_validator.ml b/src/lib_shell/block_validator.ml index c864df357487..132157c5eee4 100644 --- a/src/lib_shell/block_validator.ml +++ b/src/lib_shell/block_validator.ml @@ -579,6 +579,10 @@ let context_split w index = let bv = Worker.state w in Block_validator_process.context_split bv.validation_process index +let context_add_volume w index = + let bv = Worker.state w in + Block_validator_process.context_add_volume bv.validation_process index + let fetch_and_compile_protocol w = let bv = Worker.state w in Protocol_validator.fetch_and_compile_protocol bv.protocol_validator diff --git a/src/lib_shell/block_validator.mli b/src/lib_shell/block_validator.mli index b06cbcbcf5f8..2af80c756836 100644 --- a/src/lib_shell/block_validator.mli +++ b/src/lib_shell/block_validator.mli @@ -143,9 +143,9 @@ val fetch_and_compile_protocol : Registered_protocol.t tzresult Lwt.t (** [context_garbage_collection bv index chain_store context_hash - ~gc_lockfile_path] moves the contexts below the give - [context_hash] from the upper layer to the lower layer. For full - and rolling nodes, this is considered as a garbage + ~gc_lockfile_path] moves the contexts below the given + [context_hash] from the upper layer to the lower layer. For Full + and Rolling history modes, this is considered as a garbage collection. When a garbage collection occurs in another process, a lock, located at [gc_lockfile_path], is taken to ensure synchronous GC calls. *) @@ -162,6 +162,11 @@ val context_garbage_collection : collection. *) val context_split : t -> Context_ops.index -> unit tzresult Lwt.t +(** [context_add_volume bv index] closes the current irmin lower + volumes and opens a new one. This is expected to be called, + arbitrarily, when cutting the commit history. *) +val context_add_volume : t -> Context_ops.index -> unit tzresult Lwt.t + val shutdown : t -> unit Lwt.t val running_worker : unit -> t diff --git a/src/lib_shell/block_validator_process.ml b/src/lib_shell/block_validator_process.ml index 8a4c17710132..3f4473bda05d 100644 --- a/src/lib_shell/block_validator_process.ml +++ b/src/lib_shell/block_validator_process.ml @@ -102,6 +102,8 @@ module type S = sig val context_split : t -> Context_ops.index -> unit tzresult Lwt.t + val context_add_volume : t -> Context_ops.index -> unit tzresult Lwt.t + val commit_genesis : t -> chain_id:Chain_id.t -> Context_hash.t tzresult Lwt.t (** [init_test_chain] must only be called on a forking block. *) @@ -396,6 +398,11 @@ module Internal_validator_process = struct let*! () = Context_ops.split context_index in return_unit + let context_add_volume _validator context_index = + let open Lwt_result_syntax in + let*! () = Context_ops.add_volume context_index in + return_unit + let commit_genesis validator ~chain_id = let context_index = get_context_index validator.chain_store in let genesis = Store.Chain.genesis validator.chain_store in @@ -986,6 +993,10 @@ module External_validator_process = struct let request = External_validation.Context_split in send_request validator request Data_encoding.unit + let context_add_volume validator _index = + let request = External_validation.Context_add_volume in + send_request validator request Data_encoding.unit + let commit_genesis validator ~chain_id = let request = External_validation.Commit_genesis {chain_id} in send_request validator request Context_hash.encoding @@ -1160,6 +1171,10 @@ let context_split (E {validator_process = (module VP); validator}) context_index = VP.context_split validator context_index +let context_add_volume (E {validator_process = (module VP); validator}) + context_index = + VP.context_add_volume validator context_index + let commit_genesis (E {validator_process = (module VP); validator}) ~chain_id = VP.commit_genesis validator ~chain_id diff --git a/src/lib_shell/block_validator_process.mli b/src/lib_shell/block_validator_process.mli index b7b99f919d44..9ac4541d11e1 100644 --- a/src/lib_shell/block_validator_process.mli +++ b/src/lib_shell/block_validator_process.mli @@ -131,6 +131,10 @@ val context_garbage_collection : layout into a new chunk. *) val context_split : t -> Context_ops.index -> unit tzresult Lwt.t +(** [context_add_volume bv index] closes the current irmin lower + volumes and opens a new one. *) +val context_add_volume : t -> Context_ops.index -> unit tzresult Lwt.t + val commit_genesis : t -> chain_id:Chain_id.t -> Context_hash.t tzresult Lwt.t (** [init_test_chain] must only be called on a forking block. *) diff --git a/src/lib_shell/chain_validator.ml b/src/lib_shell/chain_validator.ml index 19e9129d7d43..7e8a83f95b3d 100644 --- a/src/lib_shell/chain_validator.ml +++ b/src/lib_shell/chain_validator.ml @@ -488,6 +488,17 @@ let register_split_callback w = in Store.Chain.register_split_callback nv.parameters.chain_store split +let register_add_volume_callback w = + let nv = Worker.state w in + let chain_store = nv.parameters.chain_store in + let index = Store.(context_index (Chain.global_store chain_store)) in + let add_volume = + Some + (fun () -> + Block_validator.context_add_volume nv.parameters.block_validator index) + in + Store.Chain.register_add_volume_callback nv.parameters.chain_store add_volume + let may_synchronise_context synchronisation_state chain_store = if not @@ -937,6 +948,7 @@ let rec create ~start_testchain ~active_chains ?parent ~block_validator_process Chain_id.Table.add active_chains (Store.Chain.chain_id chain_store) w ; register_garbage_collect_callback w ; register_split_callback w ; + register_add_volume_callback w ; Lwt_watcher.notify global_chains_input (Store.Chain.chain_id chain_store, true) ; return w diff --git a/src/lib_store/mocked/store.ml b/src/lib_store/mocked/store.ml index 89ab66d92104..2ae06962fb03 100644 --- a/src/lib_store/mocked/store.ml +++ b/src/lib_store/mocked/store.ml @@ -1723,6 +1723,10 @@ module Chain = struct (* Not implemented as both the store and context garbage collection are disabled in the mockup mode.*) let register_split_callback _ _ = () + + (* Not implemented as both the store and context garbage collection + are disabled in the mockup mode.*) + let register_add_volume_callback _ _ = () end module Protocol = struct @@ -2065,3 +2069,6 @@ module Unsafe = struct end let v_3_0_upgrade ~store_dir:_ _genesis = Lwt_result_syntax.return_unit + +let v_4_0_upgrade ~store_dir:_ ~context_dir:_ _genesis = + Lwt_result_syntax.return_unit diff --git a/src/lib_store/store.mli b/src/lib_store/store.mli index 430a310e6d85..e507e6bf0857 100644 --- a/src/lib_store/store.mli +++ b/src/lib_store/store.mli @@ -948,6 +948,12 @@ module Chain : sig split the context into a new chunk. *) val register_split_callback : chain_store -> (unit -> unit tzresult Lwt.t) option -> unit + + (** [register_add_volume_callback chain_store callback] installs a + [callback] that may be triggered during a [set_head] in order to + add a volume to the context. *) + val register_add_volume_callback : + chain_store -> (unit -> unit tzresult Lwt.t) option -> unit end (** [global_block_watcher global_store] instantiates a new block @@ -1023,6 +1029,9 @@ end val v_3_0_upgrade : store_dir:string -> Genesis.t -> unit tzresult Lwt.t +val v_4_0_upgrade : + store_dir:string -> context_dir:string -> Genesis.t -> unit tzresult Lwt.t + (**/**) (** Unsafe set of functions intended for internal store manipulation diff --git a/src/lib_store/unix/block_store.ml b/src/lib_store/unix/block_store.ml index ebc0ad991cc3..f7eb3252619a 100644 --- a/src/lib_store/unix/block_store.ml +++ b/src/lib_store/unix/block_store.ml @@ -46,6 +46,7 @@ type block_store = { block_cache : Block_repr.t Block_lru_cache.t; mutable gc_callback : (Block_hash.t -> unit tzresult Lwt.t) option; mutable split_callback : (unit -> unit tzresult Lwt.t) option; + mutable add_volume_callback : (unit -> unit tzresult Lwt.t) option; merge_mutex : Lwt_mutex.t; merge_scheduler : Lwt_idle_waiter.t; (* Target level x Merging thread *) @@ -1323,7 +1324,7 @@ let may_trigger_gc block_store history_mode ~previous_savepoint ~new_savepoint if not (prev_head_lafl = new_head_lafl_level) then match block_store.gc_callback with | None -> return_unit - | Some gc -> + | Some gc -> ( let* new_head_lafl_block = read_predecessor_block_by_level block_store @@ -1335,7 +1336,24 @@ let may_trigger_gc block_store history_mode ~previous_savepoint ~new_savepoint Store_events.( emit start_context_gc (new_head_lafl_hash, new_head_lafl_level)) in - gc new_head_lafl_hash + let* () = gc new_head_lafl_hash in + match block_store.add_volume_callback with + | Some add_volume -> + let cemented_blocks_dir = + Naming.cemented_blocks_dir block_store.chain_dir + in + let* cycles = + Cemented_block_store.load_table cemented_blocks_dir + in + let nb_cycles = + match cycles with + | None -> 0 + | Some cycles -> Array.length cycles + in + let cycles_per_volume = 50 in + if nb_cycles mod cycles_per_volume = 0 then add_volume () + else return_unit + | None -> return_unit) else return_unit | Full _ | Rolling _ -> ( let savepoint_hash = fst new_savepoint in @@ -1631,6 +1649,7 @@ let load ?block_cache_limit chain_dir ~genesis_block ~readonly = block_cache; gc_callback = None; split_callback = None; + add_volume_callback = None; merge_mutex; merge_scheduler; merging_thread = None; @@ -1662,6 +1681,9 @@ let register_gc_callback block_store gc_callback = let register_split_callback block_store split_callback = block_store.split_callback <- split_callback +let register_add_volume_callback block_store add_volume_callback = + block_store.add_volume_callback <- add_volume_callback + let pp_merge_status fmt status = match status with | Not_running -> Format.fprintf fmt "not running" diff --git a/src/lib_store/unix/block_store.mli b/src/lib_store/unix/block_store.mli index 034fe00320e9..81cf6ce45484 100644 --- a/src/lib_store/unix/block_store.mli +++ b/src/lib_store/unix/block_store.mli @@ -358,6 +358,12 @@ val register_gc_callback : val register_split_callback : block_store -> (unit -> unit tzresult Lwt.t) option -> unit +(** [register_add_volume_callback chain_store callback] installs a + [callback] that may be triggered during a [set_head] in order to + add a volume to the context. *) +val register_add_volume_callback : + block_store -> (unit -> unit tzresult Lwt.t) option -> unit + (** [split_context block_store new_head_lafl] calls the callback registered by [register_split_callback] if any. *) val split_context : t -> Int32.t -> unit tzresult Lwt.t diff --git a/src/lib_store/unix/store.ml b/src/lib_store/unix/store.ml index 4bdcce2012cf..afa623551713 100644 --- a/src/lib_store/unix/store.ml +++ b/src/lib_store/unix/store.ml @@ -2345,6 +2345,9 @@ module Chain = struct let register_split_callback chain_store callback = Block_store.register_split_callback chain_store.block_store callback + + let register_add_volume_callback chain_store callback = + Block_store.register_add_volume_callback chain_store.block_store callback end module Protocol = struct @@ -2629,53 +2632,63 @@ let may_switch_history_mode ~store_dir ~context_dir genesis ~new_history_mode = () in let chain_store = main_chain_store store in - Lwt.finalize - (fun () -> - let block_store = chain_store.block_store in - let*! current_head = Chain.current_head chain_store in - let previous_history_mode = Chain.history_mode chain_store in - if History_mode.equal previous_history_mode new_history_mode then - return_unit - else - let is_valid_switch = - match (previous_history_mode, new_history_mode) with - | (Full n, Full m | Rolling n, Rolling m) when n = m -> false - | Archive, Full _ - | Archive, Rolling _ - | Full _, Full _ - | Full _, Rolling _ - | Rolling _, Rolling _ -> - true - | _ -> - (* The remaining combinations are invalid switches *) - false - in - let* () = - fail_unless - is_valid_switch - (Cannot_switch_history_mode - { - previous_mode = previous_history_mode; - next_mode = new_history_mode; - }) - in - let*! () = lock_for_write chain_store.lockfile in - let* () = - Block_store.switch_history_mode - block_store - ~current_head - ~previous_history_mode - ~new_history_mode - in - let* () = Chain.set_history_mode chain_store new_history_mode in - let*! () = - Store_events.( - emit switch_history_mode (previous_history_mode, new_history_mode)) - in - return_unit) - (fun () -> - let*! () = unlock chain_store.lockfile in - close_store store) + let block_store = chain_store.block_store in + let*! current_head = Chain.current_head chain_store in + let previous_history_mode = Chain.history_mode chain_store in + let* () = + Lwt.finalize + (fun () -> + if History_mode.equal previous_history_mode new_history_mode then + return_unit + else + let is_valid_switch = + match (previous_history_mode, new_history_mode) with + | (Full n, Full m | Rolling n, Rolling m) when n = m -> false + | Archive, Full _ + | Archive, Rolling _ + | Full _, Full _ + | Full _, Rolling _ + | Rolling _, Rolling _ -> + true + | _ -> + (* The remaining combinations are invalid switches *) + false + in + let* () = + fail_unless + is_valid_switch + (Cannot_switch_history_mode + { + previous_mode = previous_history_mode; + next_mode = new_history_mode; + }) + in + let*! () = lock_for_write chain_store.lockfile in + let* () = + Block_store.switch_history_mode + block_store + ~current_head + ~previous_history_mode + ~new_history_mode + in + let* () = Chain.set_history_mode chain_store new_history_mode in + return_unit) + (fun () -> + let*! () = unlock chain_store.lockfile in + close_store store) + in + (* Removes, if necessary, the data stored by an archive node. *) + let*! () = + match (previous_history_mode, new_history_mode) with + | Archive, Full _ | Archive, Rolling _ -> + Context.remove_lower_root context_dir + | _ -> Lwt.return_unit + in + let*! () = + Store_events.( + emit switch_history_mode (previous_history_mode, new_history_mode)) + in + return_unit let get_chain_store store chain_id = let chain_store = main_chain_store store in @@ -3010,6 +3023,31 @@ let v_3_0_upgrade ~store_dir genesis = let*! () = List.iter_s (fun f -> f ()) !finalizers in return_unit) +let v_4_0_upgrade ~store_dir ~context_dir genesis = + let open Lwt_result_syntax in + let store_dir = Naming.store_dir ~dir_path:store_dir in + let chain_id = Chain_id.of_block_hash genesis.Genesis.block in + let chain_dir = Naming.chain_dir store_dir chain_id in + let chain_config_path = Naming.chain_config_file chain_dir in + let*! chain_config_path_exists = + Lwt_unix.file_exists (Naming.encoded_file_path chain_config_path) + in + let* lower_policy = + if chain_config_path_exists then + let* chain_config_data = Stored_data.load chain_config_path in + + let*! chain_config = Stored_data.get chain_config_data in + match chain_config.history_mode with + | Archive -> return_some Context.Archived + | Full _ | Rolling _ -> return_some Context.Deleted + else return_none + in + let*! context_index = + Context.init ~readonly:false ?lower_policy context_dir + in + let*! () = Context.close context_index in + return_unit + (************ For testing and internal purposes only **************) module Unsafe = struct let repr_of_block b = b diff --git a/src/lib_store/unix/store.mli b/src/lib_store/unix/store.mli index 96827bbf0e87..9d54622d959f 100644 --- a/src/lib_store/unix/store.mli +++ b/src/lib_store/unix/store.mli @@ -942,6 +942,12 @@ module Chain : sig split the context into a new chunk. *) val register_split_callback : chain_store -> (unit -> unit tzresult Lwt.t) option -> unit + + (** [register_add_volume_callback chain_store callback] installs a + [callback] that may be triggered during a [set_head] in order to + add a volume to the context. *) + val register_add_volume_callback : + chain_store -> (unit -> unit tzresult Lwt.t) option -> unit end (** [global_block_watcher global_store] instantiates a new block @@ -1021,6 +1027,13 @@ end {b Warning} Not backward-compatible. *) val v_3_0_upgrade : store_dir:string -> Genesis.t -> unit tzresult Lwt.t +(** Upgrade a v_3.0 to v_4.0 storage by calling the context upgrade + function. + + {b Warning} Not backward-compatible. *) +val v_4_0_upgrade : + store_dir:string -> context_dir:string -> Genesis.t -> unit tzresult Lwt.t + (**/**) (** Unsafe set of functions intended for internal store manipulation diff --git a/src/lib_validation/external_validation.ml b/src/lib_validation/external_validation.ml index 1a0605f32f4f..02ee6727811d 100644 --- a/src/lib_validation/external_validation.ml +++ b/src/lib_validation/external_validation.ml @@ -86,6 +86,7 @@ type request = gc_lockfile_path : string; } | Context_split + | Context_add_volume | Terminate | Reconfigure_event_logging of Tezos_base_unix.Internal_event_unix.Configuration.t @@ -129,6 +130,7 @@ let request_pp ppf = function Context_hash.pp context_hash | Context_split -> Format.fprintf ppf "splitting context" + | Context_add_volume -> Format.fprintf ppf "adding volume to context" | Reconfigure_event_logging _ -> Format.fprintf ppf "reconfigure event logging" @@ -416,6 +418,15 @@ let case_context_split tag = (function Context_split -> Some () | _ -> None) (fun () -> Context_split) +let case_context_add_volume tag = + let open Data_encoding in + case + tag + ~title:"context_add_volume" + unit + (function Context_add_volume -> Some () | _ -> None) + (fun () -> Context_add_volume) + let request_encoding = let open Data_encoding in union @@ -456,6 +467,7 @@ let request_encoding = case_precheck (Tag 6); case_context_gc (Tag 7); case_context_split (Tag 8); + case_context_add_volume (Tag 9); ] let send pin encoding data = diff --git a/src/lib_validation/external_validation.mli b/src/lib_validation/external_validation.mli index 3eb94d2c56c8..b1fa9a64424f 100644 --- a/src/lib_validation/external_validation.mli +++ b/src/lib_validation/external_validation.mli @@ -86,6 +86,7 @@ type request = gc_lockfile_path : string; } | Context_split + | Context_add_volume | Terminate | Reconfigure_event_logging of Tezos_base_unix.Internal_event_unix.Configuration.t diff --git a/src/lib_validation/external_validator.ml b/src/lib_validation/external_validator.ml index 96bbcd632616..e3290ce27b28 100644 --- a/src/lib_validation/external_validator.ml +++ b/src/lib_validation/external_validator.ml @@ -115,6 +115,14 @@ module Events = struct ~msg:"spliting context" () + let context_add_volume_request = + declare_0 + ~section + ~level:Info + ~name:"context_add_volume_request" + ~msg:"adding volume to context" + () + let termination_request = declare_0 ~section @@ -572,6 +580,16 @@ let run ~readonly ~using_std_channel input output = (Ok ()) in loop cache None + | External_validation.Context_add_volume -> + let*! () = Events.(emit context_add_volume_request) () in + let*! () = Context.add_volume context_index in + let*! () = + External_validation.send + output + (Error_monad.result_encoding Data_encoding.empty) + (Ok ()) + in + loop cache None | External_validation.Terminate -> let*! () = Lwt_io.flush_all () in Events.(emit termination_request ()) -- GitLab From e6712029622408619f8cdd2d2f85bd23aecd829d Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 25 Apr 2023 14:30:06 +0200 Subject: [PATCH 08/11] Store: store_known_protocols is now part of Store.Protocol --- src/lib_shell/node.ml | 47 +-------------------------- src/lib_shell/node_event.ml | 34 -------------------- src/lib_store/mocked/store.ml | 2 ++ src/lib_store/shared/store_events.ml | 34 ++++++++++++++++++++ src/lib_store/store.mli | 5 +++ src/lib_store/unix/store.ml | 48 ++++++++++++++++++++++++++++ src/lib_store/unix/store.mli | 5 +++ 7 files changed, 95 insertions(+), 80 deletions(-) diff --git a/src/lib_shell/node.ml b/src/lib_shell/node.ml index 2fffb3af4b43..a8b27fab9f1a 100644 --- a/src/lib_shell/node.ml +++ b/src/lib_shell/node.ml @@ -139,51 +139,6 @@ type config = { dal : Tezos_crypto_dal.Cryptobox.Config.t; } -(* These protocols are linked with the node and - do not have their actual hash on purpose. *) -let test_protocol_hashes = - List.map - (fun s -> Protocol_hash.of_b58check_exn s) - [ - "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK"; - "ProtoDemoCounterDemoCounterDemoCounterDemoCou4LSpdT"; - "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp"; - "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im"; - ] - -let store_known_protocols store = - let open Lwt_syntax in - let embedded_protocols = Registered_protocol.seq_embedded () in - Seq.S.iter - (fun protocol_hash -> - match Store.Protocol.mem store protocol_hash with - | true -> Node_event.(emit store_protocol_already_included) protocol_hash - | false -> ( - match Registered_protocol.get_embedded_sources protocol_hash with - | None -> Node_event.(emit store_protocol_missing_files) protocol_hash - | Some protocol -> ( - let hash = Protocol.hash protocol in - if not (Protocol_hash.equal hash protocol_hash) then - if - List.mem - ~equal:Protocol_hash.equal - protocol_hash - test_protocol_hashes - then Lwt.return_unit - (* noop. test protocol should not be stored *) - else - Node_event.(emit store_protocol_incorrect_hash) protocol_hash - else - let* o = Store.Protocol.store store hash protocol in - match o with - | Some hash' -> - assert (hash = hash') ; - Node_event.(emit store_protocol_success) protocol_hash - | None -> - Node_event.(emit store_protocol_already_included) - protocol_hash))) - embedded_protocols - let check_context_consistency store = let open Lwt_result_syntax in let main_chain_store = Store.main_chain_store store in @@ -299,7 +254,7 @@ let create ?(sandboxed = false) ?sandbox_parameters ~singleprocess ~version target in let distributed_db = Distributed_db.create store p2p in - let*! () = store_known_protocols store in + let*! () = Store.Protocol.persist_embedded_protocols store in let* validator = Validator.create store diff --git a/src/lib_shell/node_event.ml b/src/lib_shell/node_event.ml index beec2a93edf0..2be0ffa72538 100644 --- a/src/lib_shell/node_event.ml +++ b/src/lib_shell/node_event.ml @@ -39,40 +39,6 @@ let p2p_event = ~level:Notice ("status", Data_encoding.string) -let section = section_root @ ["protocol_store"] - -let store_protocol_already_included = - declare_1 - ~section - ~name:"store_protocol_already_included" - ~msg:"protocol {protocol} is already in store: nothing to do" - ~level:Debug - ("protocol", Protocol_hash.encoding) - -let store_protocol_missing_files = - declare_1 - ~section - ~name:"store_protocol_missing_files" - ~msg:"protocol {protocol} won't be stored: missing source files" - ~level:Warning - ("protocol", Protocol_hash.encoding) - -let store_protocol_incorrect_hash = - declare_1 - ~section - ~name:"store_protocol_incorrect_hash" - ~msg:"protocol {protocol} won't be stored: wrong hash" - ~level:Warning - ("protocol", Protocol_hash.encoding) - -let store_protocol_success = - declare_1 - ~section - ~name:"store_successful_store" - ~msg:"protocol {protocol} successfully stored" - ~level:Info - ("protocol", Protocol_hash.encoding) - let section = section_root @ ["storage_consistency"] let storage_corrupted_context_detected = diff --git a/src/lib_store/mocked/store.ml b/src/lib_store/mocked/store.ml index 2ae06962fb03..883aa5d506ae 100644 --- a/src/lib_store/mocked/store.ml +++ b/src/lib_store/mocked/store.ml @@ -1761,6 +1761,8 @@ module Protocol = struct let protocol_watcher {protocol_watcher; _} = Lwt_watcher.create_stream protocol_watcher + + let persist_embedded_protocols _ = Lwt.return_unit end let create_store ?block_cache_limit ~context_index ~chain_id ~genesis diff --git a/src/lib_store/shared/store_events.ml b/src/lib_store/shared/store_events.ml index 8df410289f85..c974db17ebfa 100644 --- a/src/lib_store/shared/store_events.ml +++ b/src/lib_store/shared/store_events.ml @@ -446,6 +446,40 @@ let restore_inferred_history_mode = ("history_mode", History_mode.encoding) ~pp1:History_mode.pp +(* Debug *) + +let store_protocol_already_included = + declare_1 + ~section + ~name:"store_protocol_already_included" + ~msg:"protocol {protocol} is already in store: nothing to do" + ~level:Debug + ("protocol", Protocol_hash.encoding) + +let store_protocol_missing_files = + declare_1 + ~section + ~name:"store_protocol_missing_files" + ~msg:"protocol {protocol} won't be stored: missing source files" + ~level:Warning + ("protocol", Protocol_hash.encoding) + +let store_protocol_incorrect_hash = + declare_1 + ~section + ~name:"store_protocol_incorrect_hash" + ~msg:"protocol {protocol} won't be stored: wrong hash" + ~level:Warning + ("protocol", Protocol_hash.encoding) + +let store_protocol_success = + declare_1 + ~section + ~name:"store_successful_store" + ~msg:"protocol {protocol} successfully stored" + ~level:Info + ("protocol", Protocol_hash.encoding) + (* Warning *) let warning_missing_metadata = declare_2 diff --git a/src/lib_store/store.mli b/src/lib_store/store.mli index e507e6bf0857..1b9a71f0fd5d 100644 --- a/src/lib_store/store.mli +++ b/src/lib_store/store.mli @@ -992,6 +992,11 @@ module Protocol : sig watcher in [global_store]. *) val protocol_watcher : store -> Protocol_hash.t Lwt_stream.t * Lwt_watcher.stopper + + (** [persist_embeded_protocols store] iterates over all the embedded + protocols and stores each of them if missing. Additionally, it + fails if a protocol have an unexpected hash. *) + val persist_embedded_protocols : store -> unit Lwt.t end (** The utility module used to traverse the chain. *) diff --git a/src/lib_store/unix/store.ml b/src/lib_store/unix/store.ml index afa623551713..53fe3904228e 100644 --- a/src/lib_store/unix/store.ml +++ b/src/lib_store/unix/store.ml @@ -2382,6 +2382,54 @@ module Protocol = struct let protocol_watcher {protocol_watcher; _} = Lwt_watcher.create_stream protocol_watcher + + (* These protocols are linked with the node and + do not have their actual hash on purpose. *) + let test_protocol_hashes = + List.map + (fun s -> Protocol_hash.of_b58check_exn s) + [ + "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK"; + "ProtoDemoCounterDemoCounterDemoCounterDemoCou4LSpdT"; + "ProtoDemoNoopsDemoNoopsDemoNoopsDemoNoopsDemo6XBoYp"; + "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im"; + ] + + let persist_embedded_protocols store_t = + let open Lwt_syntax in + let embedded_protocols = Registered_protocol.seq_embedded () in + Seq.S.iter + (fun protocol_hash -> + match mem store_t protocol_hash with + | true -> + Store_events.(emit store_protocol_already_included) protocol_hash + | false -> ( + match Registered_protocol.get_embedded_sources protocol_hash with + | None -> + Store_events.(emit store_protocol_missing_files) protocol_hash + | Some protocol -> ( + let hash = Protocol.hash protocol in + if not (Protocol_hash.equal hash protocol_hash) then + if + List.mem + ~equal:Protocol_hash.equal + protocol_hash + test_protocol_hashes + then Lwt.return_unit + (* noop. test protocol should not be stored *) + else + Store_events.(emit store_protocol_incorrect_hash) + protocol_hash + else + let* o = store store_t hash protocol in + match o with + | Some hash' -> + assert (hash = hash') ; + Store_events.(emit store_protocol_success) protocol_hash + | None -> + Store_events.(emit store_protocol_already_included) + protocol_hash))) + embedded_protocols end let create_store ?block_cache_limit ~context_index ~chain_id ~genesis diff --git a/src/lib_store/unix/store.mli b/src/lib_store/unix/store.mli index 9d54622d959f..359e0e962875 100644 --- a/src/lib_store/unix/store.mli +++ b/src/lib_store/unix/store.mli @@ -986,6 +986,11 @@ module Protocol : sig watcher in [global_store]. *) val protocol_watcher : store -> Protocol_hash.t Lwt_stream.t * Lwt_watcher.stopper + + (** [persist_embeded_protocols store] iterates over all the embedded + protocols and stores each of them if missing. Additionally, it + fails if a protocol have an unexpected hash. *) + val persist_embedded_protocols : store -> unit Lwt.t end (** The utility module used to traverse the chain. *) -- GitLab From 9afeb437ce63d310d9637d7d87089a891b3b3e14 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 25 Apr 2023 14:09:02 +0200 Subject: [PATCH 09/11] Store: reimplement reconstruction feature --- src/bin_node/node_reconstruct_command.ml | 1 + src/bin_node/node_snapshot_command.ml | 1 + src/lib_store/unix/reconstruction.ml | 1161 +++++++------------ src/lib_store/unix/reconstruction.mli | 1 + src/lib_store/unix/test/test_reconstruct.ml | 5 +- 5 files changed, 406 insertions(+), 763 deletions(-) diff --git a/src/bin_node/node_reconstruct_command.ml b/src/bin_node/node_reconstruct_command.ml index 0038d2eb726b..771edbbf7c36 100644 --- a/src/bin_node/node_reconstruct_command.ml +++ b/src/bin_node/node_reconstruct_command.ml @@ -79,6 +79,7 @@ module Term = struct in Reconstruction.reconstruct ~patch_context + ~data_dir ~store_dir ~context_dir genesis diff --git a/src/bin_node/node_snapshot_command.ml b/src/bin_node/node_snapshot_command.ml index 75ac467ab9fa..12a00e892694 100644 --- a/src/bin_node/node_snapshot_command.ml +++ b/src/bin_node/node_snapshot_command.ml @@ -256,6 +256,7 @@ module Term = struct in Reconstruction.reconstruct ~patch_context + ~data_dir ~store_dir:store_root ~context_dir:context_root genesis diff --git a/src/lib_store/unix/reconstruction.ml b/src/lib_store/unix/reconstruction.ml index 33a5aab85d03..4e5def6d702e 100644 --- a/src/lib_store/unix/reconstruction.ml +++ b/src/lib_store/unix/reconstruction.ml @@ -104,68 +104,6 @@ let () = open Reconstruction_events -(* The status of a metadata. It is: - - Complete: all the metadata of the corresponding cycle are stored - - Partial level: the metadata before level are missing - - Not_stored: no metadata are stored *) -type metadata_status = Complete | Partial of Int32.t | Not_stored - -(* We assume that : - - a cemented metadata cycle is partial if, at least, the first - metadata of the cycle (start_level) is missing. - - there only exists a contiguous set of empty metadata *) -let cemented_metadata_status cemented_store - {Cemented_block_store.start_level; end_level; _} = - let open Lwt_result_syntax in - let* o = Cemented_block_store.read_block_metadata cemented_store end_level in - match o with - | None -> return Not_stored - | Some _ -> ( - let* o = - Cemented_block_store.read_block_metadata cemented_store start_level - in - match o with - | Some _ -> return Complete - | None -> - let rec search inf sup = - if inf >= sup then return (Partial inf) - else - let level = Int32.(add inf (div (sub sup inf) 2l)) in - let* o = - Cemented_block_store.read_block_metadata cemented_store level - in - match o with - | None -> search (Int32.succ level) sup - | Some _ -> search inf (Int32.pred level) - in - search (Int32.succ start_level) (Int32.pred end_level)) - -(* We assume that the given list is not empty. *) -let compute_block_metadata_hash block_metadata = - Some (Block_metadata_hash.hash_bytes [block_metadata]) - -let split_operations_metadata = function - | Block_validation.No_metadata_hash metadata -> (metadata, None) - | Metadata_hash l -> - let metadata, hashes = - List.fold_left - (fun (metadata_acc, hashes_acc) l -> - let metadata, hashes = List.split l in - (metadata :: metadata_acc, hashes :: hashes_acc)) - ([], []) - l - in - (List.rev metadata, Some (List.rev hashes)) - -let compute_all_operations_metadata_hash block = - if Block_repr.validation_passes block = 0 then None - else - Option.map - (fun ll -> - Operation_metadata_list_list_hash.compute - (List.map Operation_metadata_list_hash.compute ll)) - (Block_repr.operations_metadata_hashes block) - let apply_context context_index chain_id ~user_activated_upgrades ~user_activated_protocol_overrides ~operation_metadata_size_limit ~predecessor_block_metadata_hash ~predecessor_ops_metadata_hash @@ -199,11 +137,7 @@ let apply_context context_index chain_id ~user_activated_upgrades operation_metadata_size_limit; } in - let* { - result = - {Block_validation.validation_store; block_metadata; ops_metadata; _}; - _; - } = + let* {result; _} = Block_validation.apply apply_environment block_header @@ -216,13 +150,8 @@ let apply_context context_index chain_id ~user_activated_upgrades block to the next one. *) in - return - ( validation_store.resulting_context_hash, - validation_store.message, - validation_store.max_operations_ttl, - validation_store.last_allowed_fork_level, - fst block_metadata, - ops_metadata ) + let _ = result.validation_store in + return result (** Returns the protocol environment version of a given protocol level. *) let protocol_of_protocol_level chain_store protocol_level block_hash = @@ -238,38 +167,7 @@ let protocol_of_protocol_level chain_store protocol_level block_hash = {block = block_hash; protocol = protocol_hash}) (Registered_protocol.get_result protocol_hash) -(* Restores the block and operations metadata hash of a given block, - if needed. *) -let restore_block_contents chain_store block_protocol_env ~block_metadata - ~operations_metadata message max_operations_ttl last_allowed_fork_level - block = - let operations_metadata, operations_metadata_hashes = - split_operations_metadata operations_metadata - in - let contents = - if - Store.Block.is_genesis chain_store (Block_repr.hash block) - || block_protocol_env = Protocol.V0 - then block.contents - else - { - block.contents with - block_metadata_hash = compute_block_metadata_hash block_metadata; - operations_metadata_hashes; - } - in - let metadata = - { - Block_repr.message; - max_operations_ttl; - last_allowed_fork_level; - block_metadata; - operations_metadata; - } - in - {block with contents; metadata = Some metadata} - -let reconstruct_genesis_operations_metadata chain_store = +let _reconstruct_genesis_operations_metadata chain_store = let open Lwt_result_syntax in let*! genesis_block = Store.Chain.genesis_block chain_store in let* { @@ -281,7 +179,8 @@ let reconstruct_genesis_operations_metadata chain_store = } = Store.Block.get_block_metadata chain_store genesis_block in - let operations_metadata = + let block_metadata_hash = Store.Block.block_metadata_hash genesis_block in + let ops_metadata = match Store.Block.operations_metadata_hashes genesis_block with | Some v -> let operations_metadata = @@ -297,564 +196,34 @@ let reconstruct_genesis_operations_metadata chain_store = let* resulting_context_hash = Store.Block.resulting_context_hash chain_store genesis_block in - return - ( resulting_context_hash, - message, - max_operations_ttl, - last_allowed_fork_level, - block_metadata, - operations_metadata ) - -let reconstruct_chunk chain_store context_index ~user_activated_upgrades - ~user_activated_protocol_overrides ~operation_metadata_size_limit - ~start_level ~end_level = - let open Lwt_result_syntax in - let chain_id = Store.Chain.chain_id chain_store in - let rec loop level acc = - if level > end_level then return List.(rev acc) - else - let* block = - let*! o = Store.Block.read_block_by_level_opt chain_store level in - match o with - | None -> - failwith - "Cannot read block in cemented store. The storage is corrupted." - | Some b -> return b - in - let* (module Proto) = - protocol_of_protocol_level - chain_store - (Store.Block.proto_level block) - (Store.Block.hash block) - in - let* ( _resulting_context_hash, - message, - max_operations_ttl, - last_allowed_fork_level, - block_metadata, - operations_metadata ) = - if Store.Block.is_genesis chain_store (Store.Block.hash block) then - reconstruct_genesis_operations_metadata chain_store - else - let* ( predecessor_block, - predecessor_block_metadata_hash, - predecessor_ops_metadata_hash ) = - match acc with - | [] -> - (* As the predecessor of the first block of the chunk was - already reconstructed and stored, we can read it as - usual. *) - let* predecessor_block = - Store.Block.read_predecessor chain_store block - in - return - ( predecessor_block, - Store.Block.block_metadata_hash predecessor_block, - Store.Block.all_operations_metadata_hash predecessor_block - ) - | (pred, _) :: _ -> - (* While the chunk is being recontsructed, we compute the - block and operations metadata hash using the predecessor - stored in chunk being accumulated instead of reading - it. *) - let predecessor_block = Store.Unsafe.block_of_repr pred in - return - ( predecessor_block, - Block_repr.block_metadata_hash pred, - compute_all_operations_metadata_hash pred ) - in - apply_context - context_index - chain_id - ~user_activated_upgrades - ~user_activated_protocol_overrides - ~operation_metadata_size_limit - ~predecessor_block_metadata_hash - ~predecessor_ops_metadata_hash - ~predecessor_block - ~expected_context_hash:Proto.expected_context_hash - block - in - let*! () = - Event.(emit reconstruct_block_success) (Store.Block.descriptor block) - in - let block_protocol_env = Proto.environment_version in - let reconstructed_block = - restore_block_contents - chain_store - block_protocol_env - ~block_metadata - ~operations_metadata - message - max_operations_ttl - last_allowed_fork_level - (Store.Unsafe.repr_of_block block) - in - loop (Int32.succ level) ((reconstructed_block, block_protocol_env) :: acc) - in - loop start_level [] - -let store_chunk cemented_store chunk = - let open Lwt_result_syntax in - let* lower_block, lower_env_version = - match List.hd chunk with - | None -> failwith "Cannot read chunk to cement." - | Some e -> return e - in - let* _, higher_env_version = - match List.last_opt chunk with - | None -> failwith "Cannot read chunk to cement." - | Some e -> return e - in - let block_chunk = List.map fst chunk in - if lower_env_version = Protocol.V0 && higher_env_version = Protocol.V0 then - (* No need to rewrite the cemented blocks as the block and - operation metadata hashes are not expected to be stored, only - store the metadata. *) - Cemented_block_store.cement_blocks_metadata cemented_store block_chunk - else - (* In case of blocks with expected block and operations metadata - hash, we check if they are missing to, potentially, restore - them. *) - let is_valid level = - let* o = - Cemented_block_store.get_cemented_block_by_level - ~read_metadata:false - cemented_store - level - in - match o with - | None -> tzfail (Reconstruction_failure (Cannot_read_block_level level)) - | Some b -> ( - match - ( Block_repr.block_metadata_hash b, - Block_repr.operations_metadata_hashes b ) - with - | Some _, Some _ -> return_true - | _ -> return_false) - in - let* valid_lower_block = is_valid (Block_repr.level lower_block) in - (* If the lower cycle bounds have the block and operations - metadata hash stored, as expected, we only store the - metadata. We check only the lower bound as the only case where - the upper bound may differ is after a snapshot import. In this - case, the lower bound is enough to determine the validity of - the cycle as the lower cannot be valid while the upper is - not. *) - if valid_lower_block then - Cemented_block_store.cement_blocks_metadata cemented_store block_chunk - else - (* Overwrite the existing cycle to restore the blocks and - operations metadata hash and store the associated - metadata. *) - Cemented_block_store.( - cement_blocks - ~check_consistency:false - cemented_store - ~write_metadata:true - (make_chunk_iterator block_chunk)) - -let gather_available_metadata chain_store ~start_level ~end_level = - let open Lwt_result_syntax in - let rec aux level acc = - if level > end_level then return acc - else - let* block = Store.Block.read_block_by_level chain_store level in - let* metadata = Store.Block.get_block_metadata chain_store block in - let block_with_metadata = - {(Store.Unsafe.repr_of_block block) with metadata = Some metadata} - in - aux (Int32.succ level) (block_with_metadata :: acc) - in - aux start_level [] - -(* Reconstruct the storage without checking if the context is already - populated. We assume that committing an existing context is a - nop. *) -let reconstruct_cemented chain_store context_index ~user_activated_upgrades - ~user_activated_protocol_overrides ~operation_metadata_size_limit - ~start_block_level ~progress_display_mode = - let open Lwt_result_syntax in - let block_store = Store.Unsafe.get_block_store chain_store in - let cemented_block_store = Block_store.cemented_block_store block_store in - let chain_dir = Store.Chain.chain_dir chain_store in - let cemented_blocks_dir = Naming.cemented_blocks_dir chain_dir in - let* cemented_cycles, start_cycle_index = - let* o = - Cemented_block_store.load_table cemented_blocks_dir - (* Filter the cemented cycles to get the ones to reconstruct *) - in - match o with - | None -> return ([], 0) - | Some cycles -> - let cycles_to_restore = - List.filter - (fun {Cemented_block_store.start_level; end_level; _} -> - start_level >= start_block_level - || start_block_level >= start_level - && start_block_level <= end_level) - (Array.to_list cycles) - in - let first_cycle_index = - Array.length cycles - List.length cycles_to_restore - in - return (cycles_to_restore, first_cycle_index) - in - Animation.display_progress - ~pp_print_step:(fun ppf i -> - Format.fprintf - ppf - "Reconstructing cemented blocks: %i/%d cycles rebuilt" - (i + start_cycle_index) - (List.length cemented_cycles + start_cycle_index)) - ~progress_display_mode - (fun notify -> - let rec aux = function - | [] -> - (* No cemented to reconstruct *) - return_unit - | ({Cemented_block_store.start_level; end_level; _} as file) :: tl -> ( - let* s = cemented_metadata_status cemented_block_store file in - match s with - | Complete -> - (* Should not happen: we should have stopped or not started *) - return_unit - | Partial limit -> - (* Reconstruct it partially and then stop *) - (* As the block at level = limit contains metadata the - sub chunk stops before. Then, we gather the stored - metadata at limit (incl.). *) - let* chunk = - reconstruct_chunk - chain_store - context_index - ~user_activated_upgrades - ~user_activated_protocol_overrides - ~operation_metadata_size_limit - ~start_level - ~end_level:Int32.(pred limit) - in - let* brs = - gather_available_metadata - chain_store - ~start_level:limit - ~end_level - in - let* available_metadata = - List.map_es - (fun br -> - let* (module Proto) = - protocol_of_protocol_level - chain_store - (Block_repr.proto_level br) - (Block_repr.hash br) - in - return (br, Proto.environment_version)) - brs - in - let* () = - store_chunk - cemented_block_store - (List.append chunk available_metadata) - in - let*! () = notify () in - return_unit - | Not_stored -> - (* Reconstruct it and continue *) - let* chunk = - reconstruct_chunk - chain_store - context_index - ~user_activated_upgrades - ~user_activated_protocol_overrides - ~operation_metadata_size_limit - ~start_level - ~end_level - in - let* () = store_chunk cemented_block_store chunk in - let*! () = notify () in - aux tl) - in - aux cemented_cycles) - -(* Tries to read the resulting context hash of a block in the cemented - block store first, then fallback in the floating. - This is necessary, while reconstructing the storage, as the blocks - are reconstructed from the genesis and as the max_op_ttl blocks - from the floating store are overlapping the cemented store. Thus, - these blocks will have their metadata freshly reconstructed but - their resulting context hashes might be wrong (as the context_hash - was set to Context.zero after a snapshot imported). *) -let local_resulting_context_hash chain_store block = - let open Lwt_result_syntax in - let block_store = Store.Unsafe.get_block_store chain_store in - let cemented_store = Block_store.cemented_block_store block_store in - let* expect_predecessor = - Store.Chain.expect_predecessor_context_hash - chain_store - ~protocol_level:(Block_repr.proto_level block) - in - let get_succ_from_floating block_store block = - let floating_block_stores = Block_store.floating_block_stores block_store in - let block_hash = Block_repr.hash block in - let exception Found of Block_hash.t in - let* succ_hash = - List.find_map_es - (fun fs -> - protect - (fun () -> - let* () = - Floating_block_store.raw_iterate - (fun (bytes, _offset) -> - let pred_hash = - Block_repr_unix.raw_get_block_predecessor bytes - in - if Block_hash.equal pred_hash block_hash then - raise (Found (Block_repr_unix.raw_get_block_hash bytes)) - else return_unit) - fs - in - return_none) - ~on_error:(function - | Exn (Found h) :: _ -> return_some h | exn -> fail exn)) - floating_block_stores - in - match succ_hash with Some h -> return_some h | None -> return_none - in - let ( let*? ) t k = - let* v_opt = t in - match v_opt with None -> return_none | Some v -> k v - in - let*? adjusted_hash = - Block_store.get_hash block_store (Block (Block_repr.hash block, 0)) - in - if expect_predecessor then - let*? block_level = - return - (Cemented_block_store.get_cemented_block_level - cemented_store - adjusted_hash) - in - let* succ_block = - Cemented_block_store.get_cemented_block_by_level - cemented_store - ~read_metadata:false - (Int32.succ block_level) - in - match succ_block with - | Some succ_block -> return_some (Block_repr.context succ_block) - | None -> - (* We have reached the last cemented block. Falling back to - the floating store. *) - let*? succ_block_hash = get_succ_from_floating block_store block in - let* succ_block = Store.Block.read_block chain_store succ_block_hash in - return_some (Store.Block.context_hash succ_block) - else - let*? block = - Cemented_block_store.get_cemented_block_by_hash - cemented_store - ~read_metadata:false - adjusted_hash - in - return_some (Block_repr.context block) - -let reconstruct_floating chain_store context_index ~user_activated_upgrades - ~user_activated_protocol_overrides ~operation_metadata_size_limit - ~progress_display_mode = - let open Lwt_result_syntax in - let chain_id = Store.Chain.chain_id chain_store in - let chain_dir = Store.Chain.chain_dir chain_store in - let block_store = Store.Unsafe.get_block_store chain_store in - let cemented_block_store = Block_store.cemented_block_store block_store in - let*! new_ro_store = - Floating_block_store.init chain_dir ~readonly:false RO_TMP + let validation_store = + Block_validation. + { + resulting_context_hash; + timestamp = Store.Block.timestamp genesis_block; + message; + max_operations_ttl; + last_allowed_fork_level; + } in - let floating_stores = Block_store.floating_block_stores block_store in - let* () = - Animation.display_progress - ~pp_print_step:(fun ppf i -> - Format.fprintf ppf "Reconstructing floating blocks: %i" i) - ~progress_display_mode - (fun notify -> - List.iter_es - (fun fs -> - let* () = - Floating_block_store.iter_with_info_s - (fun (block, info) -> - let level = Block_repr.level block in - let* (module Proto) = - protocol_of_protocol_level - chain_store - (Block_repr.proto_level block) - (Block_repr.hash block) - in - let* ( resulting_context_hash, - message, - max_operations_ttl, - last_allowed_fork_level, - block_metadata, - operations_metadata ) = - if - (* If the block is genesis then just retrieve - its metadata. *) - Store.Block.is_genesis chain_store (Block_repr.hash block) - then reconstruct_genesis_operations_metadata chain_store - else - (* It is needed to read the metadata using the - cemented_block_store to avoid the cache mechanism which - stores blocks without metadata *) - let* o = - Cemented_block_store.read_block_metadata - (Block_store.cemented_block_store block_store) - level - in - match o with - | None -> - (* When the metadata is not available in the - cemented_block_store, it means that the block (in - the floating store) was not cemented yet. It is - thus needed to recompute its metadata + context - *) - let block = Store.Unsafe.block_of_repr block in - let predecessor_hash = - Store.Block.predecessor block - in - (* We try to read the predecessor in the floating - store as a floating store invariant assumes - that the predecessor of a block is always - stored before. In that case, by the definition - of [iter], the predecessor will be available - in the [new_ro_store], as already processed. *) - let* predecessor_block = - let*! o = - Floating_block_store.read_block - new_ro_store - predecessor_hash - in - match o with - | Some pb -> return (Store.Unsafe.block_of_repr pb) - | None -> ( - (* If the predecessor was already cemented, - read it in the cemented store. It is - assumed to be valid as the cemented store - was restored previously.*) - let* o = - Cemented_block_store - .get_cemented_block_by_hash - ~read_metadata:true - cemented_block_store - predecessor_hash - in - match o with - | None -> - tzfail - (Reconstruction_failure - (Cannot_read_block_hash - predecessor_hash)) - | Some b -> - return (Store.Unsafe.block_of_repr b)) - in - let* res = - apply_context - context_index - chain_id - ~user_activated_upgrades - ~user_activated_protocol_overrides - ~operation_metadata_size_limit - ~predecessor_block_metadata_hash: - (Store.Block.block_metadata_hash - predecessor_block) - ~predecessor_ops_metadata_hash: - (Store.Block.all_operations_metadata_hash - predecessor_block) - ~predecessor_block - ~expected_context_hash:Proto.expected_context_hash - block - in - let*! () = - Event.(emit reconstruct_block_success) - (Store.Block.descriptor block) - in - return res - | Some - { - message; - max_operations_ttl; - last_allowed_fork_level; - block_metadata; - operations_metadata; - } -> - let operations_metadata = - match - Block_repr.operations_metadata_hashes block - with - | Some v -> - let operations_metadata = - WithExceptions.List.map2 - ~loc:__LOC__ - (WithExceptions.List.combine ~loc:__LOC__) - operations_metadata - v - in - Block_validation.Metadata_hash - operations_metadata - | None -> No_metadata_hash operations_metadata - in - let* resulting_context_hash = - let* opt = - local_resulting_context_hash chain_store block - in - match opt with - | None -> - tzfail - (Reconstruction_failure - (Cannot_read_block_level level)) - | Some v -> return v - in - return - ( resulting_context_hash, - message, - max_operations_ttl, - last_allowed_fork_level, - block_metadata, - operations_metadata ) - in - let reconstructed_block = - restore_block_contents - chain_store - Proto.environment_version - ~block_metadata - ~operations_metadata - message - max_operations_ttl - last_allowed_fork_level - block - in - let* () = - Floating_block_store.append_block - new_ro_store - {info with resulting_context_hash} - reconstructed_block - in - let*! () = notify () in - return_unit) - fs - in - return_unit) - floating_stores) + let shell_header_hash = + Block_validation.Shell_header_hash.hash_bytes + [ + Data_encoding.Binary.to_bytes_exn + Block_header.shell_header_encoding + (Store.Block.shell_header genesis_block); + ] in - let* () = - Block_store.move_floating_store - block_store - ~src:new_ro_store - ~dst_kind:Floating_block_store.RO + let result = + Block_validation. + { + shell_header_hash; + validation_store; + block_metadata = (block_metadata, block_metadata_hash); + ops_metadata; + } in - (* Reset the RW to an empty floating_block_store *) - let*! empty_rw = Floating_block_store.init chain_dir ~readonly:false RW_TMP in - Block_store.move_floating_store - block_store - ~src:empty_rw - ~dst_kind:Floating_block_store.RW + return result (* Only Full modes with any offset can be reconstructed *) let check_history_mode_compatibility chain_store savepoint genesis_block = @@ -866,8 +235,8 @@ let check_history_mode_compatibility chain_store savepoint genesis_block = (Reconstruction_failure Nothing_to_reconstruct) | _ as history_mode -> tzfail (Cannot_reconstruct history_mode) -let restore_constants chain_store genesis_block head_lafl_block - ~cementing_highwatermark = +let restore_constants ~former_chain_store ~new_chain_store ~genesis_block + ~current_head = let open Lwt_result_syntax in (* The checkpoint is updated to the last allowed fork level of the current head if higher than the cementing @@ -875,6 +244,28 @@ let restore_constants chain_store genesis_block head_lafl_block cementing highwatermark (this may occur after a snapshot import). Thus, we ensure that the store invariant `cementing_highwatermark <= checkpoint` is maintained. *) + let* head_metadata = + Store.Block.get_block_metadata former_chain_store current_head + in + let* head_lafl_block = + Store.Block.read_block_by_level + former_chain_store + (Store.Block.last_allowed_fork_level head_metadata) + in + let* cementing_highwatermark_data = + Stored_data.load + (Naming.cementing_highwatermark_file + (Store.Chain.chain_dir former_chain_store)) + in + let* cementing_highwatermark = + let*! o = Stored_data.get cementing_highwatermark_data in + match o with + | None -> return_none + | Some chw -> + let* b = Store.Block.read_block_by_level former_chain_store chw in + let d = Store.Block.descriptor b in + return_some d + in let head_lafl_descr = Store.Block.descriptor head_lafl_block in let checkpoint = match cementing_highwatermark with @@ -883,53 +274,13 @@ let restore_constants chain_store genesis_block head_lafl_block if snd chw > Store.Block.level head_lafl_block then chw else head_lafl_descr in - let* () = Store.Unsafe.set_checkpoint chain_store checkpoint in - let* () = Store.Unsafe.set_history_mode chain_store History_mode.Archive in + let* () = Store.Unsafe.set_checkpoint new_chain_store checkpoint in + let* () = + Store.Unsafe.set_history_mode new_chain_store History_mode.Archive + in let genesis = Store.Block.descriptor genesis_block in - let* () = Store.Unsafe.set_savepoint chain_store genesis in - Store.Unsafe.set_caboose chain_store genesis - -(* Computes at which level the reconstruction should start. If a - previous reconstruction is left unfinished, the procedure will restart - at the lowest non cemented cycle. Otherwise, the reconstruction starts - at the genesis. *) -let compute_start_level chain_store savepoint = - let open Lwt_result_syntax in - let chain_dir = Store.Chain.chain_dir chain_store in - let reconstruct_lockfile = Naming.reconstruction_lock_file chain_dir in - let reconstruct_lockfile_path = Naming.file_path reconstruct_lockfile in - if Sys.file_exists reconstruct_lockfile_path then - let cemented_blocks_dir = Naming.cemented_blocks_dir chain_dir in - let* o = Cemented_block_store.load_table cemented_blocks_dir in - match o with - | None -> return 0l - | Some l -> - let rec aux level = function - | [] -> return level - | {Cemented_block_store.start_level; file; _} :: tl -> - let metadata_file = - Naming.cemented_blocks_metadata_file - (Naming.cemented_blocks_metadata_dir cemented_blocks_dir) - file - in - if Sys.file_exists (Naming.file_path metadata_file) then - aux start_level tl - else return start_level - in - let* start_block_level = aux 0l (Array.to_list l) in - let* start_block = - Store.Block.read_block_by_level chain_store start_block_level - in - let*! () = - Event.( - emit - reconstruct_resuming - (Store.Block.descriptor start_block, savepoint)) - in - return start_block_level - else - let*! () = Event.(emit reconstruct_start_default savepoint) in - return 0l + let* () = Store.Unsafe.set_savepoint new_chain_store genesis in + Store.Unsafe.set_caboose new_chain_store genesis (* [locked chain_dir f] locks the [chain_dir] while [f] is executing. The aim of this lock is to: @@ -976,88 +327,374 @@ let may_commit_genesis chain_store context_index genesis = in return_unit -let reconstruct ?patch_context ~store_dir ~context_dir genesis - ~user_activated_upgrades ~user_activated_protocol_overrides - ~operation_metadata_size_limit ~progress_display_mode = +let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level + ~end_level ~genesis_block ~read_block ~user_activated_upgrades + ~user_activated_protocol_overrides ~operation_metadata_size_limit + ~pp_print_step ~progress_display_mode = + let open Lwt_result_syntax in + let context_index = Store.context_index new_store in + let chain_id = Store.Chain.chain_id chain_store in + (*FIXME*) + if start_level = end_level && end_level = 0l then return_unit + else + Animation.display_progress + ~pp_print_step + ~progress_display_mode + (fun notify -> + let rec loop ~current_block_level ~predecessor_block ~last_block_level + ~last_lafl ~expected_context_hash = + let* block = read_block current_block_level in + (*FIXME*) + let block = WithExceptions.Option.get ~loc:__LOC__ block in + let block = Store.Unsafe.block_of_repr block in + if Store.Block.is_genesis chain_store (Store.Block.hash block) then + (* FIXME: Auto magic, no need to store anything *) + let* (module Proto) = + protocol_of_protocol_level + chain_store + (Store.Block.proto_level block) + (Store.Block.hash block) + in + loop + ~current_block_level:Int32.(succ (Store.Block.level block)) + ~predecessor_block:genesis_block + ~last_block_level + ~last_lafl + ~expected_context_hash:Proto.expected_context_hash + else + let block_header = Store.Block.header block in + let operations = Store.Block.operations block in + let* result = + let predecessor_block_metadata_hash = + Store.Block.block_metadata_hash predecessor_block + in + let predecessor_ops_metadata_hash = + Store.Block.all_operations_metadata_hash predecessor_block + in + apply_context + context_index + chain_id + ~user_activated_upgrades + ~user_activated_protocol_overrides + ~operation_metadata_size_limit + ~predecessor_block_metadata_hash + ~predecessor_ops_metadata_hash + ~predecessor_block + ~expected_context_hash + block + in + let* resulting_context = + protect (fun () -> + let*! c = + Context_ops.checkout_exn + context_index + result.validation_store.resulting_context_hash + in + return c) + in + let*! new_proto_hash = Context_ops.get_protocol resulting_context in + let* (module NewProto) = + Registered_protocol.get_result new_proto_hash + in + let prev_proto_level = Store.Block.proto_level predecessor_block in + let new_proto_level = Store.Block.proto_level block in + let* () = + if Compare.Int.(prev_proto_level < new_proto_level) then + Store.Chain.may_update_protocol_level + chain_store + ~pred:predecessor_block + ~protocol_level:new_proto_level + ~expect_predecessor_context: + (expected_context_hash = Predecessor_resulting_context) + (block, new_proto_hash) + else return_unit + in + let* stored_block = + Store.Block.store_block + chain_store + ~block_header + ~operations + result + in + let* lafl = + match stored_block with + | None -> + (* Even after a reconstruction resume, a block + should not be applied nor stored twice.*) + assert false + | Some block -> + let* metadata = + Store.Block.get_block_metadata chain_store block + in + let current_lafl = + Store.Block.last_allowed_fork_level metadata + in + if last_lafl = current_lafl then return last_lafl + else + let* _ = Store.Chain.set_head chain_store block in + return current_lafl + in + let*! () = notify () in + if current_block_level = last_block_level then return_unit + else + loop + ~current_block_level:Int32.(succ current_block_level) + ~predecessor_block:block + ~last_block_level + ~last_lafl:lafl + ~expected_context_hash:NewProto.expected_context_hash + in + let*! start_block = + if start_level = 0l then Lwt.return genesis_block + else Store.Chain.current_head former_chain_store + in + let* predecessor_block = + if start_level = 0l then return genesis_block + else + Store.Block.read_block + former_chain_store + ~distance: + Int32.( + to_int (Store.Block.level start_block) + - to_int start_level + 1) + (Store.Block.hash start_block) + in + let* (module Proto) = + protocol_of_protocol_level + chain_store + (Store.Block.proto_level start_block) + (Store.Block.hash start_block) + in + loop + ~current_block_level:start_level + ~predecessor_block + ~last_block_level:end_level + ~last_lafl:0l + ~expected_context_hash:Proto.expected_context_hash) + +let reconstruct_cemented ~former_chain_store ~former_cemented_store + ~new_chain_store ~new_store ~user_activated_upgrades + ~user_activated_protocol_overrides ~operation_metadata_size_limit + ~progress_display_mode ~cemented_start_level ~cemented_end_level = + let open Lwt_result_syntax in + let*! genesis_block = Store.Chain.genesis_block former_chain_store in + let read_cemented_block cemented_store i = + Cemented_block_store.get_cemented_block_by_level + cemented_store + ~read_metadata:false + i + in + Format.printf + "Reconstructing cemented store [%ld; …; %ld]@." + cemented_start_level + cemented_end_level ; + reconstruct_blocks + ~former_chain_store + ~new_store + ~chain_store:new_chain_store + ~read_block:(read_cemented_block former_cemented_store) + ~start_level:cemented_start_level + ~end_level:cemented_end_level + ~genesis_block + ~user_activated_upgrades + ~user_activated_protocol_overrides + ~operation_metadata_size_limit + ~pp_print_step:(fun ppf i -> + Format.fprintf + ppf + "Reconstructing cemented blocks: %i/%ld rebuilt" + (i + Int32.to_int cemented_start_level) + cemented_end_level) + ~progress_display_mode + +let reconstruct_floating ~former_chain_store ~former_block_store + ~new_chain_store ~new_store ~user_activated_upgrades + ~user_activated_protocol_overrides ~operation_metadata_size_limit + ~progress_display_mode ~current_head ~floating_start_level + ~floating_end_level = let open Lwt_result_syntax in - (* We need to inhibit the cache to avoid hitting the cache with - already loaded blocks with missing metadata. *) - let* store = + let*! genesis_block = Store.Chain.genesis_block former_chain_store in + let read_floating_block block_store head_hash head_level i = + Block_store.read_block + block_store + ~read_metadata:false + (Block (head_hash, Int32.(to_int (sub head_level i)))) + in + Format.printf + "Reconstructing floating store [%ld; …; %ld]@." + floating_start_level + floating_end_level ; + reconstruct_blocks + ~former_chain_store + ~new_store + ~chain_store:new_chain_store + ~read_block: + (read_floating_block + former_block_store + (Store.Block.hash current_head) + (Store.Block.level current_head)) + ~start_level:floating_start_level + ~end_level:floating_end_level + ~genesis_block + ~user_activated_upgrades + ~user_activated_protocol_overrides + ~operation_metadata_size_limit + ~pp_print_step:(fun ppf i -> + Format.fprintf ppf "Reconstructing floating blocks: %i" i) + ~progress_display_mode + +let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir + ~context_dir:former_context_dir genesis ~user_activated_upgrades + ~user_activated_protocol_overrides ~operation_metadata_size_limit + ~progress_display_mode = + let open Lwt_result_syntax in + let* former_store = Store.init - ~block_cache_limit:1 ?patch_context - ~store_dir - ~context_dir + ~store_dir:former_store_dir + ~context_dir:former_context_dir ~allow_testchains:false + ~readonly:true genesis in + let former_chain_store = Store.main_chain_store former_store in + let*! former_current_head = Store.Chain.current_head former_chain_store in + (* FIXME *) + let new_store_dir = Filename.concat data_dir "new_store" in + let new_context_dir = Filename.concat data_dir "new_context" in + (* Initializing a new empty archive store that will be + reconstructed. *) + let* new_store = + Store.init + ~history_mode:Archive + ?patch_context + ~store_dir:new_store_dir + ~context_dir:new_context_dir + ~allow_testchains:false + genesis + in + let context_index = Store.context_index new_store in + let new_chain_store = Store.main_chain_store new_store in + let new_chain_dir = Store.Chain.chain_dir new_chain_store in + let reconstruct_lockfile = Naming.reconstruction_lock_file new_chain_dir in + let reconstruct_lockfile_path = Naming.file_path reconstruct_lockfile in + let* highest_known_block = + if Sys.file_exists reconstruct_lockfile_path then + (* Resuming a Reconstruction. *) + let*! last_known_head = Store.Chain.current_head new_chain_store in + let former_current_head_hash = Store.Block.hash former_current_head in + let former_current_head_level = + Int32.to_int @@ Store.Block.level former_current_head + in + (* FIXME: bad perf *) + let rec loop level = + let* actual_block = + Store.Block.read_block + former_chain_store + ~distance:(former_current_head_level - level) + former_current_head_hash + in + let h = Store.Block.hash actual_block in + let*! known = Store.Block.is_known new_chain_store h in + if known then loop (succ level) else return level + in + let* hkb = loop Int32.(to_int (Store.Block.level last_known_head)) in + let* hkb = + Store.Block.read_block_by_level former_chain_store Int32.(of_int hkb) + in + let*! () = + Event.( + emit + reconstruct_resuming + ( Store.Block.descriptor hkb, + Store.Block.descriptor former_current_head )) + in + return @@ Store.Block.level hkb + else return 0l + in + let* () = may_commit_genesis new_chain_store context_index genesis in protect ~on_error:(fun err -> - let*! () = Store.close_store store in + let*! () = Store.close_store former_store in + let*! () = Store.close_store new_store in Lwt.return (Error err)) (fun () -> - let context_index = Store.context_index store in - let chain_store = Store.main_chain_store store in - let* () = may_commit_genesis chain_store context_index genesis in - let*! genesis_block = Store.Chain.genesis_block chain_store in - let*! savepoint = Store.Chain.savepoint chain_store in + let*! genesis_block = Store.Chain.genesis_block former_chain_store in + let*! savepoint = Store.Chain.savepoint former_chain_store in let* () = - check_history_mode_compatibility chain_store savepoint genesis_block + check_history_mode_compatibility + former_chain_store + savepoint + genesis_block in - let* start_block_level = compute_start_level chain_store savepoint in + (* FIXME: enable reconstruction resume *) let*! () = Event.(emit reconstruct_enum ()) in - let*! current_head = Store.Chain.current_head chain_store in - let* head_metadata = - Store.Block.get_block_metadata chain_store current_head + let former_block_store = + Store.Unsafe.get_block_store former_chain_store in - let* head_lafl_block = - Store.Block.read_block_by_level - chain_store - (Store.Block.last_allowed_fork_level head_metadata) - in - let* cementing_highwatermark_data = - Stored_data.load - (Naming.cementing_highwatermark_file - (Store.Chain.chain_dir chain_store)) - in - let* cementing_highwatermark = - let*! o = Stored_data.get cementing_highwatermark_data in - match o with - | None -> return_none - | Some chw -> - let* b = Store.Block.read_block_by_level chain_store chw in - let d = Store.Block.descriptor b in - return_some d - in - let chain_dir = Store.Chain.chain_dir chain_store in let* () = - locked chain_dir (fun () -> + locked new_chain_dir (fun () -> + (* Persist all embedded protocol first. *) + let*! () = Store.Protocol.persist_embedded_protocols new_store in + let former_cemented_store = + Block_store.cemented_block_store former_block_store + in + let highest_cemented_block = + match + Cemented_block_store.get_highest_cemented_level + former_cemented_store + with + | Some level -> level + | None -> 0l + in + let cemented_start_level = highest_known_block in + let cemented_end_level = highest_cemented_block in let* () = reconstruct_cemented - chain_store - context_index + ~former_chain_store + ~former_cemented_store + ~new_chain_store + ~new_store ~user_activated_upgrades ~user_activated_protocol_overrides ~operation_metadata_size_limit - ~start_block_level ~progress_display_mode + ~cemented_start_level + ~cemented_end_level + in + let floating_start_level = + let candidate = Int32.(succ highest_cemented_block) in + if highest_known_block <= candidate then candidate + else highest_known_block in + let floating_end_level = Store.Block.level former_current_head in let* () = reconstruct_floating - chain_store - context_index + ~former_chain_store + ~former_block_store + ~new_chain_store + ~new_store ~user_activated_upgrades ~user_activated_protocol_overrides ~operation_metadata_size_limit ~progress_display_mode + ~current_head:former_current_head + ~floating_start_level + ~floating_end_level in restore_constants - chain_store - genesis_block - head_lafl_block - ~cementing_highwatermark) + ~former_chain_store + ~new_chain_store + ~genesis_block + ~current_head:former_current_head) in - (* TODO? add a global check *) + Format.printf "await merging@." ; + let*! () = Block_store.await_merging former_block_store in + let*! () = Store.close_store former_store in + let*! () = Store.close_store new_store in + let*! () = Lwt_utils_unix.remove_dir former_store_dir in + let*! () = Lwt_utils_unix.remove_dir former_context_dir in + let*! () = Lwt_unix.rename new_store_dir former_store_dir in + let*! () = Lwt_unix.rename new_context_dir former_context_dir in let*! () = Event.(emit reconstruct_success ()) in - let*! () = Store.close_store store in return_unit) diff --git a/src/lib_store/unix/reconstruction.mli b/src/lib_store/unix/reconstruction.mli index ee4d382fbc29..bcd17a9fb37c 100644 --- a/src/lib_store/unix/reconstruction.mli +++ b/src/lib_store/unix/reconstruction.mli @@ -69,6 +69,7 @@ val reconstruct : ?patch_context: (Tezos_protocol_environment.Context.t -> Tezos_protocol_environment.Context.t tzresult Lwt.t) -> + data_dir:string -> store_dir:string -> context_dir:string -> Genesis.t -> diff --git a/src/lib_store/unix/test/test_reconstruct.ml b/src/lib_store/unix/test/test_reconstruct.ml index fff158336a36..3f2ad0c1933c 100644 --- a/src/lib_store/unix/test/test_reconstruct.ml +++ b/src/lib_store/unix/test/test_reconstruct.ml @@ -28,7 +28,8 @@ _______ Component: Store - Invocation: dune exec src/lib_store/unix/test/main.exe -- --match construct + Invocation: dune exec src/lib_store/unix/test/main.exe -- + --match reconstruct Subject: Store tests ( reconstruct ) *) @@ -90,6 +91,7 @@ let test_from_bootstrapped ~descr (store_dir, context_dir) store let* () = Reconstruction.reconstruct ~patch_context + ~data_dir:(Filename.dirname store_dir) ~store_dir ~context_dir genesis @@ -245,6 +247,7 @@ let test_from_snapshot ~descr:_ (store_dir, context_dir) store let* () = Reconstruction.reconstruct ~patch_context + ~data_dir:(Filename.dirname dst_store_dir) ~store_dir:dst_store_dir ~context_dir:dst_context_dir genesis -- GitLab From f4ce350eef10472ad0a29264c7e8ad5dca3c1b94 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 16 May 2023 17:34:28 +0200 Subject: [PATCH 10/11] fixup reconstruct --- src/lib_store/unix/reconstruction.ml | 189 +++++++++++--------- src/lib_store/unix/reconstruction_events.ml | 16 +- 2 files changed, 113 insertions(+), 92 deletions(-) diff --git a/src/lib_store/unix/reconstruction.ml b/src/lib_store/unix/reconstruction.ml index 4e5def6d702e..a940ab2f8c20 100644 --- a/src/lib_store/unix/reconstruction.ml +++ b/src/lib_store/unix/reconstruction.ml @@ -334,21 +334,20 @@ let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level let open Lwt_result_syntax in let context_index = Store.context_index new_store in let chain_id = Store.Chain.chain_id chain_store in - (*FIXME*) if start_level = end_level && end_level = 0l then return_unit else Animation.display_progress ~pp_print_step ~progress_display_mode (fun notify -> - let rec loop ~current_block_level ~predecessor_block ~last_block_level + let rec loop ~current_block_level ~predecessor_block ~end_block_level ~last_lafl ~expected_context_hash = let* block = read_block current_block_level in (*FIXME*) let block = WithExceptions.Option.get ~loc:__LOC__ block in let block = Store.Unsafe.block_of_repr block in if Store.Block.is_genesis chain_store (Store.Block.hash block) then - (* FIXME: Auto magic, no need to store anything *) + (* Nothing particular to do with the genesis. *) let* (module Proto) = protocol_of_protocol_level chain_store @@ -358,7 +357,7 @@ let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level loop ~current_block_level:Int32.(succ (Store.Block.level block)) ~predecessor_block:genesis_block - ~last_block_level + ~end_block_level ~last_lafl ~expected_context_hash:Proto.expected_context_hash else @@ -384,13 +383,12 @@ let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level block in let* resulting_context = - protect (fun () -> - let*! c = - Context_ops.checkout_exn - context_index - result.validation_store.resulting_context_hash - in - return c) + let*! c = + Context_ops.checkout_exn + context_index + result.validation_store.resulting_context_hash + in + return c in let*! new_proto_hash = Context_ops.get_protocol resulting_context in let* (module NewProto) = @@ -400,6 +398,8 @@ let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level let new_proto_level = Store.Block.proto_level block in let* () = if Compare.Int.(prev_proto_level < new_proto_level) then + (* At protocol change, we need to update the store's + protocol table. *) Store.Chain.may_update_protocol_level chain_store ~pred:predecessor_block @@ -420,7 +420,7 @@ let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level match stored_block with | None -> (* Even after a reconstruction resume, a block - should not be applied nor stored twice.*) + should not be applied nor stored twice. *) assert false | Some block -> let* metadata = @@ -429,47 +429,64 @@ let reconstruct_blocks ~former_chain_store ~new_store ~chain_store ~start_level let current_lafl = Store.Block.last_allowed_fork_level metadata in - if last_lafl = current_lafl then return last_lafl - else - let* _ = Store.Chain.set_head chain_store block in - return current_lafl + let* () = + (* If there is a LAFL change, we set the store's + head to trigger internals maintenance + procedures. No need to set the head on every + block. *) + if not (Int32.equal last_lafl current_lafl) then + let* (_ : Store.Block.t) = + Store.Chain.set_head chain_store block + in + return_unit + else return_unit + in + return current_lafl in let*! () = notify () in - if current_block_level = last_block_level then return_unit + if current_block_level = end_block_level then return_unit else loop ~current_block_level:Int32.(succ current_block_level) ~predecessor_block:block - ~last_block_level + ~end_block_level ~last_lafl:lafl ~expected_context_hash:NewProto.expected_context_hash in - let*! start_block = - if start_level = 0l then Lwt.return genesis_block - else Store.Chain.current_head former_chain_store - in - let* predecessor_block = + let* start_block = if start_level = 0l then return genesis_block else + let*! former_head = Store.Chain.current_head former_chain_store in Store.Block.read_block former_chain_store ~distance: - Int32.( - to_int (Store.Block.level start_block) - - to_int start_level + 1) - (Store.Block.hash start_block) + Int32.(to_int (sub (Store.Block.level former_head) start_level)) + (Store.Block.hash former_head) + in + let* predecessor_block = + if start_level = 0l then return genesis_block + else Store.Block.read_predecessor former_chain_store start_block in let* (module Proto) = protocol_of_protocol_level - chain_store + former_chain_store (Store.Block.proto_level start_block) (Store.Block.hash start_block) in + let* start_block_lafl = + (* The predecessor_block metadata are always present in the + store being reconstructed (it is genesis or a block + reconstructed prior to the resumed reconstruction). *) + let* m = + Store.Block.get_block_metadata chain_store predecessor_block + in + return (Store.Block.last_allowed_fork_level m) + in loop ~current_block_level:start_level ~predecessor_block - ~last_block_level:end_level - ~last_lafl:0l + ~end_block_level:end_level + ~last_lafl:start_block_lafl ~expected_context_hash:Proto.expected_context_hash) let reconstruct_cemented ~former_chain_store ~former_cemented_store @@ -478,16 +495,11 @@ let reconstruct_cemented ~former_chain_store ~former_cemented_store ~progress_display_mode ~cemented_start_level ~cemented_end_level = let open Lwt_result_syntax in let*! genesis_block = Store.Chain.genesis_block former_chain_store in - let read_cemented_block cemented_store i = + let read_cemented_block cemented_store = Cemented_block_store.get_cemented_block_by_level cemented_store ~read_metadata:false - i in - Format.printf - "Reconstructing cemented store [%ld; …; %ld]@." - cemented_start_level - cemented_end_level ; reconstruct_blocks ~former_chain_store ~new_store @@ -520,10 +532,6 @@ let reconstruct_floating ~former_chain_store ~former_block_store ~read_metadata:false (Block (head_hash, Int32.(to_int (sub head_level i)))) in - Format.printf - "Reconstructing floating store [%ld; …; %ld]@." - floating_start_level - floating_end_level ; reconstruct_blocks ~former_chain_store ~new_store @@ -543,6 +551,51 @@ let reconstruct_floating ~former_chain_store ~former_block_store Format.fprintf ppf "Reconstructing floating blocks: %i" i) ~progress_display_mode +(* Returns the highest block stored in the new chain store that is + being reconstructed. *) +let get_highest_know_block ~new_chain_store ~former_chain_store + ~former_current_head = + let open Lwt_result_syntax in + let new_chain_dir = Store.Chain.chain_dir new_chain_store in + let reconstruct_lockfile = Naming.reconstruction_lock_file new_chain_dir in + let reconstruct_lockfile_path = Naming.file_path reconstruct_lockfile in + if Sys.file_exists reconstruct_lockfile_path then + (* When a reconstruction lockfile is present, it means that a + previous reconstruction was interupted. We need to resume + it from where it was stopped. *) + let*! () = Event.(emit reconstruct_needs_resuming) () in + let*! last_known_head = Store.Chain.current_head new_chain_store in + let former_current_head_hash = Store.Block.hash former_current_head in + let former_current_head_level = + Int32.to_int (Store.Block.level former_current_head) + in + (* FIXME: bad perf. Do a dico search or something smart *) + let rec loop level = + let* actual_block = + Store.Block.read_block + former_chain_store + ~distance:(former_current_head_level - level) + former_current_head_hash + in + let h = Store.Block.hash actual_block in + let*! known = Store.Block.is_known new_chain_store h in + if known then loop (succ level) else return level + in + let* hkb = loop Int32.(to_int (Store.Block.level last_known_head)) in + let* hkb = + Store.Block.read_block_by_level former_chain_store Int32.(of_int hkb) + in + let*! () = + Event.( + emit + reconstruct_resuming + ( Store.Block.descriptor hkb, + Store.Block.descriptor former_current_head )) + in + return (Store.Block.level hkb) + else (* By default, we start from the genesis *) + return 0l + let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir ~context_dir:former_context_dir genesis ~user_activated_upgrades ~user_activated_protocol_overrides ~operation_metadata_size_limit @@ -559,11 +612,10 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir in let former_chain_store = Store.main_chain_store former_store in let*! former_current_head = Store.Chain.current_head former_chain_store in - (* FIXME *) - let new_store_dir = Filename.concat data_dir "new_store" in - let new_context_dir = Filename.concat data_dir "new_context" in (* Initializing a new empty archive store that will be reconstructed. *) + let new_store_dir = Filename.concat data_dir "new_store" in + let new_context_dir = Filename.concat data_dir "new_context" in let* new_store = Store.init ~history_mode:Archive @@ -575,42 +627,11 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir in let context_index = Store.context_index new_store in let new_chain_store = Store.main_chain_store new_store in - let new_chain_dir = Store.Chain.chain_dir new_chain_store in - let reconstruct_lockfile = Naming.reconstruction_lock_file new_chain_dir in - let reconstruct_lockfile_path = Naming.file_path reconstruct_lockfile in let* highest_known_block = - if Sys.file_exists reconstruct_lockfile_path then - (* Resuming a Reconstruction. *) - let*! last_known_head = Store.Chain.current_head new_chain_store in - let former_current_head_hash = Store.Block.hash former_current_head in - let former_current_head_level = - Int32.to_int @@ Store.Block.level former_current_head - in - (* FIXME: bad perf *) - let rec loop level = - let* actual_block = - Store.Block.read_block - former_chain_store - ~distance:(former_current_head_level - level) - former_current_head_hash - in - let h = Store.Block.hash actual_block in - let*! known = Store.Block.is_known new_chain_store h in - if known then loop (succ level) else return level - in - let* hkb = loop Int32.(to_int (Store.Block.level last_known_head)) in - let* hkb = - Store.Block.read_block_by_level former_chain_store Int32.(of_int hkb) - in - let*! () = - Event.( - emit - reconstruct_resuming - ( Store.Block.descriptor hkb, - Store.Block.descriptor former_current_head )) - in - return @@ Store.Block.level hkb - else return 0l + get_highest_know_block + ~new_chain_store + ~former_chain_store + ~former_current_head in let* () = may_commit_genesis new_chain_store context_index genesis in protect @@ -627,11 +648,10 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir savepoint genesis_block in - (* FIXME: enable reconstruction resume *) - let*! () = Event.(emit reconstruct_enum ()) in let former_block_store = Store.Unsafe.get_block_store former_chain_store in + let new_chain_dir = Store.Chain.chain_dir new_chain_store in let* () = locked new_chain_dir (fun () -> (* Persist all embedded protocol first. *) @@ -639,7 +659,7 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir let former_cemented_store = Block_store.cemented_block_store former_block_store in - let highest_cemented_block = + let highest_former_cemented_block = match Cemented_block_store.get_highest_cemented_level former_cemented_store @@ -648,7 +668,7 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir | None -> 0l in let cemented_start_level = highest_known_block in - let cemented_end_level = highest_cemented_block in + let cemented_end_level = highest_former_cemented_block in let* () = reconstruct_cemented ~former_chain_store @@ -663,7 +683,9 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir ~cemented_end_level in let floating_start_level = - let candidate = Int32.(succ highest_cemented_block) in + (* FIXME: is that true? succ of + highest_former_cemented_block should be enough.*) + let candidate = Int32.(succ highest_former_cemented_block) in if highest_known_block <= candidate then candidate else highest_known_block in @@ -688,7 +710,6 @@ let reconstruct ?patch_context ~data_dir ~store_dir:former_store_dir ~genesis_block ~current_head:former_current_head) in - Format.printf "await merging@." ; let*! () = Block_store.await_merging former_block_store in let*! () = Store.close_store former_store in let*! () = Store.close_store new_store in diff --git a/src/lib_store/unix/reconstruction_events.ml b/src/lib_store/unix/reconstruction_events.ml index 835151154b0e..b14148198eeb 100644 --- a/src/lib_store/unix/reconstruction_events.ml +++ b/src/lib_store/unix/reconstruction_events.ml @@ -40,6 +40,14 @@ module Event = struct ~pp1:pp_block_descriptor ("block", block_descriptor_encoding) + let reconstruct_needs_resuming = + declare_0 + ~section + ~level:Notice + ~name:"reconstruct_need_resuming" + ~msg:"resuming reconstruction" + () + let reconstruct_resuming = declare_2 ~section @@ -53,14 +61,6 @@ module Event = struct ~pp2:pp_block_descriptor ("end_block", block_descriptor_encoding) - let reconstruct_enum = - declare_0 - ~section - ~level:Notice - ~name:"reconstruct_enum" - ~msg:"enumerating all blocks to reconstruct" - () - let reconstruct_success = declare_0 ~section -- GitLab From 7663912828b2b6fba2183678c31b21abb2e10556 Mon Sep 17 00:00:00 2001 From: Victor Allombert Date: Tue, 16 May 2023 13:58:27 +0200 Subject: [PATCH 11/11] Store: improve snapshot import display --- src/lib_store/unix/snapshots.ml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib_store/unix/snapshots.ml b/src/lib_store/unix/snapshots.ml index 318ac9f7429e..52f8b34dc0be 100644 --- a/src/lib_store/unix/snapshots.ml +++ b/src/lib_store/unix/snapshots.ml @@ -4171,13 +4171,19 @@ module Make_snapshot_importer (Importer : IMPORTER) : Snapshot_importer = struct ~progress_display_mode:Auto ~msg:"Checking context integrity" @@ fun () -> - Context.Checks.Pack.Integrity_check.run - ?ppf:None - ~root:dst_context_dir - ~auto_repair:false - ~always:false - ~heads:(Some [Context_hash.to_b58check imported_context_hash]) - () + (* Dirty hack to get allow the animation to be displayed + as the Integrity_check.run function is non-lwt. *) + let*! _ = + Lwt_preemptive.detach + (Context.Checks.Pack.Integrity_check.run + ~root:dst_context_dir + ~auto_repair:false + ~always:false + ~heads: + (Some [Context_hash.to_b58check imported_context_hash])) + () + in + Lwt.return_unit else Lwt.return_unit in let* block_validation_result = -- GitLab

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Ν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 literal 0 HcmV?d00001 diff --git a/vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/gYQPmLU.png b/vendors/irmin/doc/irmin-pack/design/imgs/lower_layer/gYQPmLU.png new file mode 100644 index 0000000000000000000000000000000000000000..7323cb14ff3d2a6303453a4a098062f344169e23 GIT binary patch literal 80943 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