pigeonhole-db 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +899 -0
- data/Cargo.toml +45 -0
- data/LICENSE +21 -0
- data/README.md +22 -0
- data/extconf.rb +12 -0
- data/lib/pigeonhole/api.rb +615 -0
- data/lib/pigeonhole/index.rb +208 -0
- data/lib/pigeonhole/memory.rb +507 -0
- data/lib/pigeonhole/version.rb +6 -0
- data/lib/pigeonhole-db.rb +6 -0
- data/lib/pigeonhole.rb +47 -0
- data/sig/pigeonhole.rbs +1484 -0
- data/src/budget.rs +205 -0
- data/src/classes.rs +279 -0
- data/src/convert.rs +192 -0
- data/src/db.rs +685 -0
- data/src/error.rs +151 -0
- data/src/feed.rs +316 -0
- data/src/fork.rs +64 -0
- data/src/gvl.rs +112 -0
- data/src/index.rs +1157 -0
- data/src/lib.rs +534 -0
- data/src/memory.rs +2178 -0
- data/src/read.rs +312 -0
- data/src/table.rs +1161 -0
- data/src/vector.rs +262 -0
- data/src/walk.rs +406 -0
- data/vendor/bundle/ruby/3.4.0/bin/minitest +29 -0
- data/vendor/bundle/ruby/3.4.0/bin/rake +29 -0
- data/vendor/bundle/ruby/3.4.0/bin/rake-compiler +29 -0
- data/vendor/bundle/ruby/3.4.0/bin/rake-compiler-dock +29 -0
- data/vendor/bundle/ruby/3.4.0/bin/rb-sys-dock +29 -0
- data/vendor/bundle/ruby/3.4.0/bin/rbs +29 -0
- data/vendor/bundle/ruby/3.4.0/cache/drb-2.2.3.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/logger-1.7.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/minitest-6.0.6.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/prism-1.9.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rake-13.4.2.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rake-compiler-1.3.2.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rake-compiler-dock-1.12.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rb_sys-0.9.130.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rbs-4.2.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/toml-rb-6.0.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/tsort-0.2.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/prism-1.9.0/gem.build_complete +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/prism-1.9.0/gem_make.out +44 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/prism-1.9.0/mkmf.log +74 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/prism-1.9.0/prism/prism.so +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/rbs-4.2.0/gem.build_complete +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/rbs-4.2.0/gem_make.out +41 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/rbs-4.2.0/mkmf.log +102 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/rbs-4.2.0/rbs_extension.so +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/drb.gemspec +42 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/acl.rb +239 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/drb.rb +1993 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/eq.rb +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/extserv.rb +44 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/extservm.rb +94 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/gw.rb +161 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/observer.rb +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/ssl.rb +354 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/timeridconv.rb +97 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/unix.rb +118 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/version.rb +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb/weakidconv.rb +31 -0
- data/vendor/bundle/ruby/3.4.0/gems/drb-2.2.3/lib/drb.rb +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/BSDL +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/COPYING +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/README.md +104 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/errors.rb +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/formatter.rb +36 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/log_device.rb +265 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/period.rb +47 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/severity.rb +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/version.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger.rb +789 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/History.rdoc +1860 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/Manifest.txt +41 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/README.rdoc +763 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/Rakefile +89 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/bin/minitest +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/design_rationale.rb +54 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/hoe/minitest.rb +30 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/assertions.rb +821 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/autorun.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/benchmark.rb +452 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/bisect.rb +304 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/complete.rb +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/compress.rb +94 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/error_on_warning.rb +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/expectations.rb +321 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/find_minimal_combination.rb +127 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/hell.rb +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/manual_plugins.rb +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/parallel.rb +72 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/path_expander.rb +432 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/pride.rb +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/pride_plugin.rb +135 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/server.rb +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/server_plugin.rb +88 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/spec.rb +324 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/sprint.rb +105 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/sprint_plugin.rb +39 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/test.rb +232 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest/test_task.rb +331 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/lib/minitest.rb +1232 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/metametameta.rb +150 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_bisect.rb +249 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_find_minimal_combination.rb +138 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_minitest_assertions.rb +1729 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_minitest_benchmark.rb +151 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_minitest_reporter.rb +437 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_minitest_spec.rb +1095 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_minitest_test.rb +1295 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_minitest_test_task.rb +57 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_path_expander.rb +229 -0
- data/vendor/bundle/ruby/3.4.0/gems/minitest-6.0.6/test/minitest/test_server.rb +146 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/BSDmakefile +58 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/CHANGELOG.md +786 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/CODE_OF_CONDUCT.md +76 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/CONTRIBUTING.md +58 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/LICENSE.md +7 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/Makefile +116 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/README.md +143 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/config.yml +4739 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/build_system.md +119 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/configuration.md +68 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/cruby_compilation.md +27 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/design.md +53 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/encoding.md +121 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/fuzzing.md +88 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/heredocs.md +36 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/javascript.md +118 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/local_variable_depth.md +229 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/mapping.md +117 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/parser_translation.md +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/parsing_rules.md +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/releasing.md +75 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/relocation.md +34 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/ripper_translation.md +63 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/ruby_api.md +45 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/ruby_parser_translation.md +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/serialization.md +233 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/docs/testing.md +55 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/ext/prism/Makefile +273 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/ext/prism/api_node.c +6945 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/ext/prism/api_pack.c +276 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/ext/prism/extconf.rb +127 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/ext/prism/extension.c +1427 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/ext/prism/extension.h +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/ast.h +8254 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/defines.h +260 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/diagnostic.h +458 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/encoding.h +283 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/node.h +129 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/options.h +488 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/pack.h +163 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/parser.h +936 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/prettyprint.h +34 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/regexp.h +43 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/static_literals.h +121 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_buffer.h +236 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_char.h +204 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_constant_pool.h +218 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_integer.h +130 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_list.h +103 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_memchr.h +29 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_newline_list.h +113 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_string.h +200 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_strncasecmp.h +32 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/util/pm_strpbrk.h +46 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism/version.h +29 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/include/prism.h +408 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/compiler.rb +801 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/desugar_compiler.rb +392 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/dispatcher.rb +2210 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/dot_visitor.rb +4767 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/dsl.rb +1003 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/ffi.rb +578 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/inspect_visitor.rb +2393 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/lex_compat.rb +911 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/mutation_compiler.rb +772 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/node.rb +19966 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/node_ext.rb +511 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/pack.rb +230 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/parse_result/comments.rb +188 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/parse_result/errors.rb +66 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/parse_result/newlines.rb +155 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/parse_result.rb +907 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/pattern.rb +269 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/polyfill/append_as_bytes.rb +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/polyfill/byteindex.rb +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/polyfill/scan_byte.rb +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/polyfill/unpack1.rb +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/polyfill/warn.rb +36 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/prism.so +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/reflection.rb +416 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/relocation.rb +505 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/serialize.rb +2400 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/string_query.rb +31 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/parser/builder.rb +62 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/parser/compiler.rb +2234 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/parser/lexer.rb +820 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/parser.rb +376 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/parser_current.rb +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/parser_versions.rb +36 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/ripper/filter.rb +53 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/ripper/lexer.rb +135 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/ripper/sexp.rb +126 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/ripper/shim.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/ripper.rb +3520 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation/ruby_parser.rb +1964 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/translation.rb +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism/visitor.rb +813 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/lib/prism.rb +98 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/prism.gemspec +172 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/compiler.rbi +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/dsl.rbi +524 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/inspect_visitor.rbi +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/node.rbi +8750 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/node_ext.rbi +107 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/parse_result.rbi +404 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/reflection.rbi +58 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/string_query.rbi +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/translation/parser.rbi +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/translation/parser_versions.rbi +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/translation/ripper.rbi +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism/visitor.rbi +473 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/rbi/prism.rbi +63 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/compiler.rbs +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/dispatcher.rbs +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/dot_visitor.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/dsl.rbs +351 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/inspect_visitor.rbs +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/lex_compat.rbs +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/mutation_compiler.rbs +159 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/node.rbs +4042 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/node_ext.rbs +149 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/pack.rbs +43 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/parse_result/comments.rbs +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/parse_result.rbs +197 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/pattern.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/reflection.rbs +50 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/relocation.rbs +185 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/serialize.rbs +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/string_query.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism/visitor.rbs +169 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/sig/prism.rbs +272 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/diagnostic.c +854 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/encoding.c +5340 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/node.c +8685 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/options.c +338 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/pack.c +509 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/prettyprint.c +8957 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/prism.c +22679 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/regexp.c +790 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/serialize.c +2274 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/static_literals.c +617 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/token_type.c +703 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_buffer.c +357 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_char.c +318 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_constant_pool.c +342 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_integer.c +670 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_list.c +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_memchr.c +35 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_newline_list.c +125 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_string.c +381 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_strncasecmp.c +36 -0
- data/vendor/bundle/ruby/3.4.0/gems/prism-1.9.0/src/util/pm_strpbrk.c +206 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/History.rdoc +2454 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/MIT-LICENSE +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/README.rdoc +155 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/command_line_usage.rdoc +171 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/Rakefile1 +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/Rakefile2 +35 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/a.c +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/b.c +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/main.c +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/glossary.rdoc +42 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/jamis.rb +592 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/proto_rake.rdoc +127 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rake.1 +156 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rakefile.rdoc +635 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rational.rdoc +151 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/exe/rake +27 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/application.rb +847 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/backtrace.rb +25 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/clean.rb +78 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/cloneable.rb +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/cpu_counter.rb +122 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/default_loader.rb +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/dsl_definition.rb +196 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/early_time.rb +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/ext/core.rb +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/ext/string.rb +176 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_creation_task.rb +25 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_list.rb +435 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_task.rb +58 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_utils.rb +137 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_utils_ext.rb +135 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/invocation_chain.rb +57 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/invocation_exception_mixin.rb +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/late_time.rb +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/linked_list.rb +112 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/loaders/makefile.rb +54 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/multi_task.rb +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/name_space.rb +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/options.rb +31 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/packagetask.rb +222 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/phony.rb +16 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/private_reader.rb +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/promise.rb +100 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/pseudo_status.rb +30 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rake_module.rb +67 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rake_test_loader.rb +27 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rule_recursion_overflow_error.rb +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/scope.rb +43 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task.rb +434 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_argument_error.rb +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_arguments.rb +113 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_manager.rb +333 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/tasklib.rb +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/testtask.rb +192 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/thread_history_display.rb +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/thread_pool.rb +157 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/trace_output.rb +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/version.rb +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/win32.rb +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake.rb +69 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/rake.gemspec +102 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/Gemfile +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/History.md +708 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/LICENSE.txt +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/README.md +505 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/Rakefile +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/appveyor.yml +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/bin/rake-compiler +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/cucumber.yml +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/compile.feature +79 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/cross-compile.feature +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/cross-package-multi.feature +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/cross-package.feature +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/java-compile.feature +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/java-no-native-compile.feature +33 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/java-package.feature +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/package.feature +40 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/step_definitions/compilation.rb +70 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/step_definitions/cross_compilation.rb +27 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/step_definitions/execution.rb +52 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/step_definitions/folders.rb +32 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/step_definitions/gem.rb +46 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/step_definitions/java_compilation.rb +7 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/support/env.rb +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/support/file_template_helpers.rb +137 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/support/generator_helpers.rb +123 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/features/support/platform_extension_helpers.rb +27 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/lib/rake/baseextensiontask.rb +90 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/lib/rake/compiler_config.rb +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/lib/rake/extensioncompiler.rb +51 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/lib/rake/extensiontask.rb +621 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/lib/rake/javaextensiontask.rb +321 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/tasks/bin/cross-ruby.rake +189 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/tasks/bootstrap.rake +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/tasks/common.rake +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/tasks/cucumber.rake +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/tasks/gem.rake +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-1.3.2/tasks/rspec.rake +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/CHANGELOG.md +446 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/CONTRIBUTING.md +109 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/Dockerfile.jruby +79 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/Dockerfile.mri.erb +282 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/Gemfile +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/README.md +447 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/Rakefile +246 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/bin/rake-compiler-dock +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/buildkitd.toml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/gem_helper.rb +54 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/mk_i686.rb +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/mk_musl_cross.sh +37 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/mk_osxcross.sh +45 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/mk_pkg_config.sh +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/parallel_docker_build.rb +169 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/patches/rake-compiler-1.3.1/0004-Enable-build-of-static-libruby.patch +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/patches/rake-compiler-1.3.1/0005-build-miniruby-first.patch +16 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/patches/rake-compiler-1.3.1/0006-ruby-4-rubyspec-capiext.patch +16 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/rcd-env.sh +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/runas +7 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/sigfw.c +45 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/strip_wrapper_codesign +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/strip_wrapper_vbox +30 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/build/sudoers +1 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/colors.rb +43 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/docker_check.rb +356 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/predefined_user_group.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/starter.rb +206 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock/version.rb +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/lib/rake_compiler_dock.rb +151 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/Dockerfile +66 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/README.md +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/binutils-mingw-w64-ignore-check-errors.patch +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/gcc-mingw-w64-only-c-c++.patch +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/mingw64-ucrt/mingw-w64-enable-ucrt.patch +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/rake-compiler-dock.gemspec +34 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/env/Dockerfile.alpine +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/env/Dockerfile.debian +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/fixtures/mig_test_rpc.defs +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/Gemfile +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/Rakefile +97 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/java/RcdTestExtService.java +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/java/RubyRcdTest.java +16 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/mri/extconf.rb +111 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/mri/rcd_test_ext.c +65 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/ext/mri/rcd_test_ext.h +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/lib/rcd_test.rb +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/rcd_test.gemspec +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/rcd_test/test/test_basic.rb +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/test_environment_variables.rb +108 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/test_mig.rb +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/test_parallel_docker_build.rb +95 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/test_rubygems_plugins.rb +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/test_starter.rb +158 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.12.0/test/test_versions.rb +82 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/LICENSE-APACHE +190 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/LICENSE-MIT +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/README.md +42 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/certs/ianks.pem +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/exe/rb-sys-dock +495 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/cargo/config.rb +72 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/cargo/metadata.rb +158 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/cargo.rb +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/cargo_builder/link_flag_converter.rb +37 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/cargo_builder.rb +370 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/error.rb +43 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/extensiontask.rb +188 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/mkmf/config.rb +75 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/mkmf.rb +413 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/toolchain_info/data.rb +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/toolchain_info.rb +82 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/util/logger.rb +73 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys/version.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rb_sys-0.9.130/lib/rb_sys.rb +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/BSDL +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/CHANGELOG.md +2463 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/COPYING +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/Dockerfile.jruby +53 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/README.md +240 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/Rakefile +1213 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/Steepfile +55 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/config.yml +920 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/array.rbs +4205 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/basic_object.rbs +376 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/binding.rbs +148 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/builtin.rbs +278 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/class.rbs +223 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/comparable.rbs +192 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/complex.rbs +812 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/constants.rbs +96 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/data.rbs +415 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/dir.rbs +993 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/encoding.rbs +1368 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/enumerable.rbs +2506 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/enumerator/arithmetic_sequence.rbs +70 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/enumerator/product.rbs +92 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/enumerator.rbs +705 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/env.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/errno.rbs +682 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/errors.rbs +789 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/exception.rbs +485 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/false_class.rbs +82 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/fiber.rbs +570 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/fiber_error.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/file.rbs +2045 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/file_constants.rbs +463 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/file_stat.rbs +534 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/file_test.rbs +331 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/float.rbs +1292 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/gc.rbs +788 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/global_variables.rbs +184 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/hash.rbs +2183 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/integer.rbs +1374 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/io/buffer.rbs +995 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/io/wait.rbs +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/io.rbs +3473 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/kernel.rbs +3172 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/marshal.rbs +207 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/match_data.rbs +637 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/math.rbs +770 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/method.rbs +422 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/module.rbs +1856 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/nil_class.rbs +210 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/numeric.rbs +832 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/object.rbs +108 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/object_space/weak_key_map.rbs +166 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/object_space.rbs +197 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/pathname.rbs +1312 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/proc.rbs +905 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/process.rbs +2316 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/ractor.rbs +914 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/random.rbs +255 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/range.rbs +1209 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rational.rbs +502 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rb_config.rbs +88 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rbs/ops.rbs +154 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rbs/unnamed/argf.rbs +1236 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rbs/unnamed/env_class.rbs +1214 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rbs/unnamed/main_class.rbs +123 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rbs/unnamed/random.rbs +186 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/refinement.rbs +59 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/regexp.rbs +1974 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/ruby.rbs +53 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/ruby_vm.rbs +809 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/basic_specification.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/config_file.rbs +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/dependency_installer.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/errors.rbs +112 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/installer.rbs +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/path_support.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/platform.rbs +7 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/request_set.rbs +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/requirement.rbs +138 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/rubygems.rbs +1108 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/source_list.rbs +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/specification.rbs +31 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/stream_ui.rbs +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/uninstaller.rbs +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/rubygems/version.rbs +133 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/set.rbs +751 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/signal.rbs +110 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/string.rbs +5532 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/struct.rbs +668 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/symbol.rbs +482 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/thread.rbs +1821 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/thread_group.rbs +79 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/time.rbs +1793 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/trace_point.rbs +483 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/true_class.rbs +98 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/unbound_method.rbs +337 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/core/warning.rbs +87 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/CONTRIBUTING.md +107 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/aliases.md +79 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/architecture.md +110 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/collection.md +192 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/config.md +171 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/data_and_struct.md +86 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/encoding.md +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/gem.md +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/inline.md +634 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/rbs_by_example.md +309 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/release.md +303 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/repo.md +125 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/rust.md +96 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/sigs.md +167 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/stdlib.md +155 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/syntax.md +952 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/tools.md +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/type_fingerprint.md +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/docs/wasm_serialization.md +80 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/exe/rbs +7 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/Makefile +273 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/ast_translation.c +1870 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/ast_translation.h +41 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/class_constants.c +189 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/class_constants.h +105 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/compat.h +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/extconf.rb +40 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/legacy_location.c +299 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/legacy_location.h +82 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/main.c +649 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/rbs_extension.h +16 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/rbs_string_bridging.c +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/ext/rbs_extension/rbs_string_bridging.h +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/goodcheck.yml +91 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/ast.h +1055 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/defines.h +104 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/lexer.h +208 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/location.h +40 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/parser.h +187 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/serialize.h +39 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/string.h +47 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/util/rbs_allocator.h +59 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/util/rbs_assert.h +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/util/rbs_buffer.h +83 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/util/rbs_constant_pool.h +155 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/util/rbs_encoding.h +282 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs/util/rbs_unescape.h +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/include/rbs.h +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ancestor_graph.rb +92 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/annotate/annotations.rb +199 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/annotate/formatter.rb +82 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/annotate/rdoc_annotator.rb +398 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/annotate/rdoc_source.rb +131 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/annotate.rb +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/annotation.rb +29 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/comment.rb +29 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/declarations.rb +472 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/directives.rb +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/members.rb +451 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/ruby/annotations.rb +451 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/ruby/comment_block.rb +247 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/ruby/declarations.rb +291 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/ruby/helpers/constant_helper.rb +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/ruby/helpers/location_helper.rb +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/ruby/members.rb +762 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/type_param.rb +235 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/ast/visitor.rb +137 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/buffer.rb +189 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/builtin_names.rb +58 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/cli/colored_io.rb +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/cli/diff.rb +84 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/cli/validate.rb +294 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/cli.rb +1253 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/cleaner.rb +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/config/lockfile.rb +92 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/config/lockfile_generator.rb +269 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/config.rb +81 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/installer.rb +32 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/sources/base.rb +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/sources/git.rb +265 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/sources/local.rb +81 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/sources/rubygems.rb +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/sources/stdlib.rb +50 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection/sources.rb +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/collection.rb +16 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/constant.rb +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/definition.rb +415 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/definition_builder/ancestor_builder.rb +681 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/definition_builder/method_builder.rb +295 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/definition_builder.rb +1057 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/diff.rb +131 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/environment/class_entry.rb +81 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/environment/module_entry.rb +91 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/environment/use_map.rb +77 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/environment.rb +1028 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/environment_loader.rb +167 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/environment_walker.rb +155 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/errors.rb +634 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/factory.rb +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/file_finder.rb +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/inline_parser/comment_association.rb +117 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/inline_parser.rb +568 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/location_aux.rb +170 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/locator.rb +247 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/method_type.rb +145 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/namespace.rb +154 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/parser/lex_result.rb +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/parser/token.rb +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/parser_aux.rb +144 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/helpers.rb +164 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/node_usage.rb +99 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/rb.rb +816 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/rbi.rb +793 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/runtime/helpers.rb +59 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/runtime/reflection.rb +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/runtime/value_object_generator.rb +278 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/prototype/runtime.rb +680 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/repository.rb +127 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/resolver/constant_resolver.rb +219 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/resolver/type_name_resolver.rb +167 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/rewriter.rb +70 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/sorter.rb +198 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/source.rb +99 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/substitution.rb +83 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/subtractor.rb +204 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/errors.rb +80 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/guaranteed.rb +30 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/hook.rb +212 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/observer.rb +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/setup.rb +84 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/setup_helper.rb +50 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/tester.rb +167 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test/type_check.rb +457 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/test.rb +112 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/type_alias_dependency.rb +100 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/type_alias_regularity.rb +126 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/type_name.rb +122 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/types.rb +1646 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/unit_test/convertibles.rb +177 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/unit_test/spy.rb +138 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/unit_test/type_assertions.rb +383 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/unit_test/with_aliases.rb +145 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/unit_test.rb +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/validator.rb +186 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/variance_calculator.rb +189 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/vendorer.rb +71 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/version.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/wasm/deserializer.rb +213 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/wasm/location.rb +61 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/wasm/parser.rb +174 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/wasm/runtime.rb +211 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/wasm/serialization_schema.rb +111 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs/writer.rb +424 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs.rb +117 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs_extension.so +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rbs_jars.rb +39 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rdoc/discover.rb +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/lib/rdoc_plugin/parser.rb +168 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/rbs.gemspec +77 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/annotation.json +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/comment.json +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/decls.json +326 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/function.json +98 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/location.json +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/members.json +266 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/methodType.json +50 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/typeParam.json +52 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/schema/types.json +317 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ancestor_builder.rbs +163 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ancestor_graph.rbs +60 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/annotate/annotations.rbs +102 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/annotate/formatter.rbs +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/annotate/rdoc_annotater.rbs +85 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/annotate/rdoc_source.rbs +32 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/annotation.rbs +27 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ast/ruby/annotations.rbs +470 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ast/ruby/comment_block.rbs +127 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ast/ruby/declarations.rbs +158 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ast/ruby/helpers/constant_helper.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ast/ruby/helpers/location_helper.rbs +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/ast/ruby/members.rbs +198 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/buffer.rbs +108 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/builtin_names.rbs +44 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/cli/colored_io.rbs +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/cli/diff.rbs +15 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/cli/validate.rbs +47 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/cli.rbs +89 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection/cleaner.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection/config/lockfile.rbs +74 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection/config/lockfile_generator.rbs +68 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection/config.rbs +46 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection/installer.rbs +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection/sources.rbs +214 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/collection.rbs +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/comment.rbs +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/constant.rbs +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/declarations.rbs +274 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/definition.rbs +232 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/definition_builder.rbs +181 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/diff.rbs +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/directives.rbs +77 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/environment/class_entry.rbs +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/environment/module_entry.rbs +65 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/environment.rbs +286 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/environment_loader.rbs +111 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/environment_walker.rbs +65 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/errors.rbs +408 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/factory.rbs +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/file_finder.rbs +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/inline_parser/comment_association.rbs +71 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/inline_parser.rbs +126 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/location.rbs +135 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/locator.rbs +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/manifest.yaml +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/members.rbs +258 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/method_builder.rbs +89 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/method_types.rbs +58 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/namespace.rbs +161 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/parser.rbs +164 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/prototype/helpers.rbs +29 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/prototype/node_usage.rbs +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/prototype/rb.rbs +96 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/prototype/rbi.rbs +104 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/prototype/runtime.rbs +182 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/rbs.rbs +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/rdoc/rbs.rbs +67 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/repository.rbs +85 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/resolver/constant_resolver.rbs +92 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/resolver/context.rbs +34 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/resolver/type_name_resolver.rbs +61 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/rewriter.rbs +45 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/shims/bundler.rbs +38 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/shims/enumerable.rbs +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/shims/rubygems.rbs +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/sorter.rbs +41 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/source.rbs +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/substitution.rbs +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/subtractor.rbs +37 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/test/errors.rbs +52 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/test/guranteed.rbs +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/test/type_check.rbs +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/test.rbs +82 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/type_alias_dependency.rbs +53 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/type_alias_regularity.rbs +98 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/type_param.rbs +115 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/typename.rbs +89 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/types.rbs +588 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/unit_test/convertibles.rbs +154 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/unit_test/spy.rbs +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/unit_test/type_assertions.rbs +211 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/unit_test/with_aliases.rbs +136 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/use_map.rbs +35 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/util.rbs +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/validator.rbs +63 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/variance_calculator.rbs +87 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/vendorer.rbs +51 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/version.rbs +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/visitor.rbs +47 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/wasm/deserializer.rbs +66 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/wasm/serialization_schema.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/sig/writer.rbs +127 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/ast.c +1644 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/lexer.c +3223 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/lexer.re +187 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/lexstate.c +222 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/location.c +31 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/parser.c +4318 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/serialize.c +965 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/string.c +41 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/util/rbs_allocator.c +171 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/util/rbs_assert.c +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/util/rbs_buffer.c +54 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/util/rbs_constant_pool.c +268 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/util/rbs_encoding.c +21454 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/src/util/rbs_unescape.c +167 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/abbrev/0/abbrev.rbs +66 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/abbrev/0/array.rbs +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/base64/0/base64.rbs +355 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/benchmark/0/benchmark.rbs +452 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/bigdecimal/0/big_decimal.rbs +1647 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/bigdecimal-math/0/big_math.rbs +280 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/bigdecimal-math/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/cgi/0/core.rbs +911 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/cgi/0/manifest.yaml +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/cgi-escape/0/escape.rbs +171 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/coverage/0/coverage.rbs +266 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/csv/0/csv.rbs +3776 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/csv/0/manifest.yaml +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/date/0/date.rbs +1598 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/date/0/date_time.rbs +617 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/date/0/time.rbs +26 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/dbm/0/dbm.rbs +421 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/delegate/0/delegator.rbs +188 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/delegate/0/kernel.rbs +47 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/delegate/0/simple_delegator.rbs +96 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/did_you_mean/0/did_you_mean.rbs +344 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/digest/0/digest.rbs +693 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/erb/0/erb.rbs +933 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/etc/0/etc.rbs +884 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/fileutils/0/fileutils.rbs +1753 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/find/0/find.rbs +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/forwardable/0/forwardable.rbs +271 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/io-console/0/io-console.rbs +414 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/ipaddr/0/ipaddr.rbs +431 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/json/0/json.rbs +1963 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/kconv/0/kconv.rbs +166 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/logger/0/formatter.rbs +45 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/logger/0/log_device.rbs +100 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/logger/0/logger.rbs +796 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/logger/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/logger/0/period.rbs +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/logger/0/severity.rbs +34 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/kernel.rbs +42 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/abstract_reporter.rbs +52 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/assertion.rbs +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/assertions.rbs +590 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/backtrace_filter.rbs +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/bench_spec.rbs +102 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/benchmark.rbs +259 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/composite_reporter.rbs +25 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/compress.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/error_on_warning.rbs +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/expectation.rbs +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/expectations.rbs +21 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/guard.rbs +64 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/mock.rbs +64 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/parallel/executor.rbs +46 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/parallel/test/class_methods.rbs +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/parallel/test.rbs +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/parallel.rbs +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/pride_io.rbs +62 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/pride_lol.rbs +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/progress_reporter.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/reportable.rbs +53 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/reporter.rbs +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/result.rbs +28 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/runnable.rbs +163 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/skip.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/spec/dsl/instance_methods.rbs +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/spec/dsl.rbs +129 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/spec.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/statistics_reporter.rbs +81 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/summary_reporter.rbs +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/test/lifecycle_hooks.rbs +92 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/test.rbs +69 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/unexpected_error.rbs +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/unexpected_warning.rbs +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/unit/test_case.rbs +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest/unit.rbs +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/minitest/0/minitest.rbs +115 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/monitor/0/monitor.rbs +363 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/mutex_m/0/mutex_m.rbs +104 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/net-http/0/manifest.yaml +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/net-http/0/net-http.rbs +5580 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/net-protocol/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/net-protocol/0/net-protocol.rbs +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/net-smtp/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/net-smtp/0/net-smtp.rbs +55 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/nkf/0/nkf.rbs +402 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/objspace/0/objspace.rbs +470 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/observable/0/observable.rbs +217 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/open-uri/0/manifest.yaml +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/open-uri/0/open-uri.rbs +433 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/open3/0/open3.rbs +606 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/openssl/0/manifest.yaml +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/openssl/0/openssl.rbs +12237 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/optparse/0/optparse.rbs +1734 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/pathname/0/pathname.rbs +36 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/pp/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/pp/0/pp.rbs +301 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/prettyprint/0/prettyprint.rbs +383 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/pstore/0/pstore.rbs +608 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/psych/0/core_ext.rbs +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/psych/0/dbm.rbs +237 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/psych/0/manifest.yaml +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/psych/0/psych.rbs +455 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/psych/0/store.rbs +57 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/pty/0/pty.rbs +240 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/random-formatter/0/random-formatter.rbs +277 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/code_object.rbs +52 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/comment.rbs +61 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/context.rbs +153 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/markup.rbs +117 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/options.rbs +76 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/parser.rbs +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/rdoc.rbs +393 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/ri.rbs +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/store.rbs +48 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/rdoc/0/top_level.rbs +97 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/resolv/0/manifest.yaml +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/resolv/0/resolv.rbs +1787 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/ripper/0/ripper.rbs +1654 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/securerandom/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/securerandom/0/securerandom.rbs +49 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/shellwords/0/shellwords.rbs +229 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/singleton/0/singleton.rbs +137 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/addrinfo.rbs +666 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/basic_socket.rbs +590 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/constants.rbs +2295 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/ip_socket.rbs +94 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/socket.rbs +4170 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/socket_error.rbs +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/tcp_server.rbs +192 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/tcp_socket.rbs +87 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/udp_socket.rbs +133 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/unix_server.rbs +169 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/socket/0/unix_socket.rbs +172 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/stringio/0/stringio.rbs +1682 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/strscan/0/string_scanner.rbs +1648 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/tempfile/0/manifest.yaml +3 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/tempfile/0/tempfile.rbs +483 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/time/0/time.rbs +434 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/timeout/0/timeout.rbs +132 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/tmpdir/0/tmpdir.rbs +69 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/tsort/0/cyclic.rbs +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/tsort/0/interfaces.rbs +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/tsort/0/tsort.rbs +410 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/common.rbs +621 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/file.rbs +118 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/ftp.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/generic.rbs +1111 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/http.rbs +104 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/https.rbs +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/ldap.rbs +230 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/ldaps.rbs +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/mailto.rbs +92 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/rfc2396_parser.rbs +189 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/rfc3986_parser.rbs +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/ws.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/uri/0/wss.rbs +9 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/yaml/0/manifest.yaml +2 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/yaml/0/yaml.rbs +1 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/buf_error.rbs +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/data_error.rbs +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/deflate.rbs +211 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/error.rbs +20 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_file/crc_error.rbs +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_file/error.rbs +23 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_file/length_error.rbs +12 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_file/no_footer.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_file.rbs +156 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_reader.rbs +293 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/gzip_writer.rbs +169 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/inflate.rbs +180 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/mem_error.rbs +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/need_dict.rbs +13 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/stream_end.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/stream_error.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/version_error.rbs +11 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/zlib.rbs +449 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/stdlib/zlib/0/zstream.rbs +200 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/wasm/README.md +109 -0
- data/vendor/bundle/ruby/3.4.0/gems/rbs-4.2.0/wasm/rbs_wasm.c +479 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/LICENSE +19 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/README.md +135 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/datetime.rb +54 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/dumper.rb +182 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/errors.rb +17 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/inline_table.rb +18 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/keyvalue.rb +45 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/parser.rb +296 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/string.rb +41 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/table.rb +34 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/table_array.rb +43 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb/version.rb +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/toml-rb-6.0.0/lib/toml-rb.rb +90 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/Gemfile +4 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/README.md +72 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/Rakefile +10 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/bin/console +14 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/bin/setup +8 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/lib/tsort.rb +455 -0
- data/vendor/bundle/ruby/3.4.0/gems/tsort-0.2.0/tsort.gemspec +29 -0
- data/vendor/bundle/ruby/3.4.0/specifications/drb-2.2.3.gemspec +22 -0
- data/vendor/bundle/ruby/3.4.0/specifications/logger-1.7.0.gemspec +22 -0
- data/vendor/bundle/ruby/3.4.0/specifications/minitest-6.0.6.gemspec +35 -0
- data/vendor/bundle/ruby/3.4.0/specifications/prism-1.9.0.gemspec +24 -0
- data/vendor/bundle/ruby/3.4.0/specifications/rake-13.4.2.gemspec +26 -0
- data/vendor/bundle/ruby/3.4.0/specifications/rake-compiler-1.3.2.gemspec +33 -0
- data/vendor/bundle/ruby/3.4.0/specifications/rake-compiler-dock-1.12.0.gemspec +28 -0
- data/vendor/bundle/ruby/3.4.0/specifications/rb_sys-0.9.130.gemspec +29 -0
- data/vendor/bundle/ruby/3.4.0/specifications/rbs-4.2.0.gemspec +33 -0
- data/vendor/bundle/ruby/3.4.0/specifications/toml-rb-6.0.0.gemspec +27 -0
- data/vendor/bundle/ruby/3.4.0/specifications/tsort-0.2.0.gemspec +23 -0
- data/vendor/cache/Cargo.toml +21 -0
- data/vendor/cache/LICENSE +21 -0
- data/vendor/cache/README.md +5 -0
- data/vendor/cache/src/hash.rs +85 -0
- data/vendor/cache/src/lib.rs +751 -0
- data/vendor/cache/src/loom_tests.rs +340 -0
- data/vendor/cache/src/s3fifo.rs +648 -0
- data/vendor/cache/src/sync.rs +25 -0
- data/vendor/cache/src/tests.rs +260 -0
- data/vendor/compaction/Cargo.toml +32 -0
- data/vendor/compaction/LICENSE +21 -0
- data/vendor/compaction/README.md +5 -0
- data/vendor/compaction/src/blob.rs +478 -0
- data/vendor/compaction/src/cursor.rs +700 -0
- data/vendor/compaction/src/gc.rs +802 -0
- data/vendor/compaction/src/job.rs +861 -0
- data/vendor/compaction/src/lib.rs +102 -0
- data/vendor/compaction/src/merge.rs +995 -0
- data/vendor/compaction/src/picker.rs +681 -0
- data/vendor/compaction/src/resolver.rs +1346 -0
- data/vendor/engine/Cargo.toml +56 -0
- data/vendor/engine/LICENSE +21 -0
- data/vendor/engine/README.md +5 -0
- data/vendor/engine/src/admission.rs +421 -0
- data/vendor/engine/src/catalog.rs +1233 -0
- data/vendor/engine/src/check.rs +1386 -0
- data/vendor/engine/src/clock.rs +244 -0
- data/vendor/engine/src/clock_loom.rs +482 -0
- data/vendor/engine/src/close_gate.rs +325 -0
- data/vendor/engine/src/compact.rs +1509 -0
- data/vendor/engine/src/engine/hooks.rs +1654 -0
- data/vendor/engine/src/engine/info.rs +229 -0
- data/vendor/engine/src/engine.rs +6114 -0
- data/vendor/engine/src/error.rs +490 -0
- data/vendor/engine/src/feed.rs +960 -0
- data/vendor/engine/src/feed_reader.rs +1600 -0
- data/vendor/engine/src/flush.rs +839 -0
- data/vendor/engine/src/flushed_roots.rs +158 -0
- data/vendor/engine/src/flushed_through_loom.rs +77 -0
- data/vendor/engine/src/health.rs +201 -0
- data/vendor/engine/src/large.rs +372 -0
- data/vendor/engine/src/large_settle.rs +201 -0
- data/vendor/engine/src/lib.rs +112 -0
- data/vendor/engine/src/load_slot.rs +324 -0
- data/vendor/engine/src/maintenance.rs +935 -0
- data/vendor/engine/src/manifest/flight.rs +563 -0
- data/vendor/engine/src/manifest.rs +1516 -0
- data/vendor/engine/src/nonblocking.rs +603 -0
- data/vendor/engine/src/options.rs +334 -0
- data/vendor/engine/src/position.rs +125 -0
- data/vendor/engine/src/purge_guard.rs +220 -0
- data/vendor/engine/src/read/keys.rs +1049 -0
- data/vendor/engine/src/read/knn.rs +423 -0
- data/vendor/engine/src/read/reduce.rs +2057 -0
- data/vendor/engine/src/read/traverse.rs +1013 -0
- data/vendor/engine/src/read.rs +2429 -0
- data/vendor/engine/src/row_cache.rs +1101 -0
- data/vendor/engine/src/shard/tablets.rs +3582 -0
- data/vendor/engine/src/shard.rs +12215 -0
- data/vendor/engine/src/snapshot.rs +1429 -0
- data/vendor/engine/src/source.rs +1379 -0
- data/vendor/engine/src/timer_state.rs +226 -0
- data/vendor/engine/src/waker.rs +124 -0
- data/vendor/engine/src/watermark_waiters.rs +674 -0
- data/vendor/engine/src/write.rs +1321 -0
- data/vendor/format/Cargo.toml +40 -0
- data/vendor/format/LICENSE +21 -0
- data/vendor/format/README.md +5 -0
- data/vendor/format/src/blob.rs +101 -0
- data/vendor/format/src/block.rs +1120 -0
- data/vendor/format/src/bloom.rs +456 -0
- data/vendor/format/src/buckets.rs +552 -0
- data/vendor/format/src/bytes.rs +101 -0
- data/vendor/format/src/checksum.rs +132 -0
- data/vendor/format/src/compress.rs +196 -0
- data/vendor/format/src/cursor.rs +110 -0
- data/vendor/format/src/distance.rs +598 -0
- data/vendor/format/src/error.rs +93 -0
- data/vendor/format/src/exact.rs +602 -0
- data/vendor/format/src/feed.rs +285 -0
- data/vendor/format/src/filter.rs +157 -0
- data/vendor/format/src/half.rs +182 -0
- data/vendor/format/src/hash.rs +127 -0
- data/vendor/format/src/hll.rs +500 -0
- data/vendor/format/src/ids.rs +95 -0
- data/vendor/format/src/key.rs +620 -0
- data/vendor/format/src/kind_params.rs +101 -0
- data/vendor/format/src/lib.rs +54 -0
- data/vendor/format/src/manifest.rs +1287 -0
- data/vendor/format/src/roaring.rs +865 -0
- data/vendor/format/src/scan.rs +297 -0
- data/vendor/format/src/shm.rs +805 -0
- data/vendor/format/src/sst.rs +233 -0
- data/vendor/format/src/superblock.rs +345 -0
- data/vendor/format/src/value.rs +163 -0
- data/vendor/format/src/varint.rs +87 -0
- data/vendor/format/src/vector.rs +936 -0
- data/vendor/format/src/version.rs +92 -0
- data/vendor/format/src/wal.rs +999 -0
- data/vendor/io/Cargo.toml +29 -0
- data/vendor/io/LICENSE +21 -0
- data/vendor/io/README.md +5 -0
- data/vendor/io/src/async_poll.rs +44 -0
- data/vendor/io/src/buf.rs +694 -0
- data/vendor/io/src/completion.rs +444 -0
- data/vendor/io/src/error.rs +110 -0
- data/vendor/io/src/file.rs +206 -0
- data/vendor/io/src/lib.rs +53 -0
- data/vendor/io/src/nowait.rs +256 -0
- data/vendor/io/src/os/mod.rs +149 -0
- data/vendor/io/src/os/unix.rs +897 -0
- data/vendor/io/src/os/windows.rs +552 -0
- data/vendor/io/src/own.rs +257 -0
- data/vendor/io/src/pread.rs +854 -0
- data/vendor/io/src/ring_wake.rs +113 -0
- data/vendor/io/src/shared.rs +410 -0
- data/vendor/io/src/sim.rs +1545 -0
- data/vendor/io/src/sys.rs +214 -0
- data/vendor/io/src/uring.rs +1839 -0
- data/vendor/io/src/vfs.rs +154 -0
- data/vendor/memory/Cargo.toml +34 -0
- data/vendor/memory/LICENSE +21 -0
- data/vendor/memory/README.md +11 -0
- data/vendor/memory/src/consolidate.rs +640 -0
- data/vendor/memory/src/dedup.rs +231 -0
- data/vendor/memory/src/error.rs +131 -0
- data/vendor/memory/src/feed_loop.rs +572 -0
- data/vendor/memory/src/forget.rs +724 -0
- data/vendor/memory/src/hooks.rs +109 -0
- data/vendor/memory/src/ivf.rs +204 -0
- data/vendor/memory/src/layout.rs +340 -0
- data/vendor/memory/src/lib.rs +61 -0
- data/vendor/memory/src/recall.rs +1182 -0
- data/vendor/memory/src/store.rs +1785 -0
- data/vendor/memory/src/watch.rs +339 -0
- data/vendor/memtable/Cargo.toml +24 -0
- data/vendor/memtable/LICENSE +21 -0
- data/vendor/memtable/README.md +5 -0
- data/vendor/memtable/src/lib.rs +1658 -0
- data/vendor/memtable/src/loom_tests.rs +274 -0
- data/vendor/memtable/src/mem.rs +344 -0
- data/vendor/memtable/src/tests.rs +1061 -0
- data/vendor/pager/Cargo.toml +23 -0
- data/vendor/pager/LICENSE +21 -0
- data/vendor/pager/README.md +5 -0
- data/vendor/pager/src/alloc.rs +1008 -0
- data/vendor/pager/src/lib.rs +1710 -0
- data/vendor/pigeonhole/Cargo.toml +42 -0
- data/vendor/pigeonhole/LICENSE +21 -0
- data/vendor/pigeonhole/README.md +99 -0
- data/vendor/pigeonhole/src/cell.rs +829 -0
- data/vendor/pigeonhole/src/check.rs +368 -0
- data/vendor/pigeonhole/src/db.rs +2324 -0
- data/vendor/pigeonhole/src/doc_support.rs +89 -0
- data/vendor/pigeonhole/src/error.rs +257 -0
- data/vendor/pigeonhole/src/feed.rs +696 -0
- data/vendor/pigeonhole/src/info.rs +425 -0
- data/vendor/pigeonhole/src/lib.rs +202 -0
- data/vendor/pigeonhole/src/merge.rs +135 -0
- data/vendor/pigeonhole/src/metrics.rs +476 -0
- data/vendor/pigeonhole/src/nonblocking.rs +666 -0
- data/vendor/pigeonhole/src/options.rs +2075 -0
- data/vendor/pigeonhole/src/read/budget.rs +584 -0
- data/vendor/pigeonhole/src/read.rs +2463 -0
- data/vendor/pigeonhole/src/recovery.rs +876 -0
- data/vendor/pigeonhole/src/retry.rs +358 -0
- data/vendor/pigeonhole/src/set.rs +103 -0
- data/vendor/pigeonhole/src/table.rs +861 -0
- data/vendor/pigeonhole/src/vector.rs +351 -0
- data/vendor/pigeonhole/src/write.rs +2815 -0
- data/vendor/runtime/Cargo.toml +21 -0
- data/vendor/runtime/LICENSE +21 -0
- data/vendor/runtime/README.md +5 -0
- data/vendor/runtime/src/completion.rs +629 -0
- data/vendor/runtime/src/drivers.rs +1175 -0
- data/vendor/runtime/src/lib.rs +1546 -0
- data/vendor/runtime/src/pool.rs +992 -0
- data/vendor/runtime/src/sched.rs +809 -0
- data/vendor/runtime/src/signal.rs +532 -0
- data/vendor/runtime/src/submit_gate.rs +144 -0
- data/vendor/shm/Cargo.toml +24 -0
- data/vendor/shm/LICENSE +21 -0
- data/vendor/shm/README.md +5 -0
- data/vendor/shm/src/lib.rs +427 -0
- data/vendor/shm/src/lock.rs +153 -0
- data/vendor/shm/src/region.rs +1609 -0
- data/vendor/sst/Cargo.toml +26 -0
- data/vendor/sst/LICENSE +21 -0
- data/vendor/sst/README.md +5 -0
- data/vendor/sst/src/blob.rs +380 -0
- data/vendor/sst/src/iter.rs +803 -0
- data/vendor/sst/src/lib.rs +695 -0
- data/vendor/sst/src/reader.rs +814 -0
- data/vendor/sst/src/writer.rs +596 -0
- data/vendor/text/Cargo.toml +26 -0
- data/vendor/text/LICENSE +21 -0
- data/vendor/text/README.md +9 -0
- data/vendor/text/src/error.rs +108 -0
- data/vendor/text/src/fuzzy.rs +265 -0
- data/vendor/text/src/highlight.rs +236 -0
- data/vendor/text/src/index.rs +1152 -0
- data/vendor/text/src/layout.rs +424 -0
- data/vendor/text/src/lib.rs +75 -0
- data/vendor/text/src/maxscore.rs +658 -0
- data/vendor/text/src/query.rs +450 -0
- data/vendor/text/src/search.rs +569 -0
- data/vendor/text/src/sloppy.rs +460 -0
- data/vendor/text/src/tokenizer.rs +163 -0
- data/vendor/vector/Cargo.toml +28 -0
- data/vendor/vector/LICENSE +21 -0
- data/vendor/vector/README.md +9 -0
- data/vendor/vector/src/error.rs +63 -0
- data/vendor/vector/src/half.rs +167 -0
- data/vendor/vector/src/hooks.rs +135 -0
- data/vendor/vector/src/index.rs +2690 -0
- data/vendor/vector/src/layout.rs +102 -0
- data/vendor/vector/src/lib.rs +52 -0
- data/vendor/vector/src/point.rs +500 -0
- data/vendor/vector/src/rebalancer.rs +200 -0
- data/vendor/vector/src/registry.rs +81 -0
- data/vendor/wal/Cargo.toml +25 -0
- data/vendor/wal/LICENSE +21 -0
- data/vendor/wal/README.md +5 -0
- data/vendor/wal/src/feed.rs +610 -0
- data/vendor/wal/src/foreground.rs +122 -0
- data/vendor/wal/src/lib.rs +458 -0
- data/vendor/wal/src/mem.rs +166 -0
- data/vendor/wal/src/recovery.rs +426 -0
- data/vendor/wal/src/stream.rs +2382 -0
- metadata +1310 -0
|
@@ -0,0 +1,2324 @@
|
|
|
1
|
+
use std::path::{Path, PathBuf};
|
|
2
|
+
use std::sync::atomic::{AtomicU64, Ordering};
|
|
3
|
+
use std::sync::{Arc, Weak};
|
|
4
|
+
use std::time::Duration;
|
|
5
|
+
|
|
6
|
+
use arc_swap::ArcSwap;
|
|
7
|
+
use pigeonhole_engine::{Engine, EngineShard};
|
|
8
|
+
|
|
9
|
+
use crate::Durability;
|
|
10
|
+
use crate::Failure;
|
|
11
|
+
use pigeonhole_io::VfsRef;
|
|
12
|
+
|
|
13
|
+
use crate::table::TableCore;
|
|
14
|
+
use crate::{
|
|
15
|
+
Error, ErrorCode, IoRings, Options, ReadTable, ReaderOptions, Recovery, RecoveryStats, Result,
|
|
16
|
+
TableBuilder, Transaction, WriteBatch,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/// What every handle derived from one open database shares: the engine, whether
|
|
20
|
+
/// [`Pigeonhole::close`] ran, and the largest value a commit may carry.
|
|
21
|
+
///
|
|
22
|
+
/// The engine can be replaced (D265: automatic recovery reopens the file and swaps the new
|
|
23
|
+
/// engine in behind the handles). Every operation loads the current one through
|
|
24
|
+
/// [`Db::engine`]; what was taken from an earlier engine (a snapshot, a transaction, an
|
|
25
|
+
/// iterator) carries the [`generation`](Db::generation) it was taken in and expires with
|
|
26
|
+
/// `SnapshotExpired` once the generation moved on.
|
|
27
|
+
#[derive(Debug)]
|
|
28
|
+
pub(crate) struct Db {
|
|
29
|
+
engine: ArcSwap<Engine>,
|
|
30
|
+
/// Opens of the engine behind this handle: 1 at open, +1 per swap, with [`CLOSED`] set
|
|
31
|
+
/// once the database was closed through any handle. One word, so a scan step checks
|
|
32
|
+
/// both with one load ([`Db::check_generation`]): #827's per-row `Closed` check and
|
|
33
|
+
/// D265's generation check together cost what either does alone.
|
|
34
|
+
generation: AtomicU64,
|
|
35
|
+
/// The I/O backend the engine runs on (for [`Pigeonhole::io_rings`]).
|
|
36
|
+
vfs: VfsRef,
|
|
37
|
+
/// Largest value accepted at commit (decision D16), for error messages; 0 for readers.
|
|
38
|
+
pub(crate) max_value: usize,
|
|
39
|
+
/// Automatic recovery (D265): the supervisor's state and thread, with
|
|
40
|
+
/// `Options::auto_recover` on; `None` otherwise, and for readers.
|
|
41
|
+
supervision: Option<crate::recovery::Supervision>,
|
|
42
|
+
/// What a reopen needs: the options and the path (writers with the option on).
|
|
43
|
+
reopen: Option<(Options, PathBuf)>,
|
|
44
|
+
/// `Options::write_stall_timeout`: how long an operation waits for a recovery's swap.
|
|
45
|
+
stall_timeout: Duration,
|
|
46
|
+
/// Transaction outcomes since open (ICR 0061).
|
|
47
|
+
pub(crate) txn_counts: crate::retry::TxnCounts,
|
|
48
|
+
/// With the option on, this database's entry in the watch registry ([`watched`]; 0
|
|
49
|
+
/// otherwise): how a commit that resolves later finds it again on its error path only
|
|
50
|
+
/// (#966).
|
|
51
|
+
watch_id: u64,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// The supervised databases of one process, by watch id: a commit that resolves after its
|
|
55
|
+
/// call returned (an async commit, a ticket) keeps only the id and looks its database up
|
|
56
|
+
/// here if the failed engine refused it, so its success path takes no reference (perf287's
|
|
57
|
+
/// P1 on #968).
|
|
58
|
+
struct Watched {
|
|
59
|
+
/// The process it belongs to ([`pigeonhole_io::sys::process_id`]).
|
|
60
|
+
pid: u32,
|
|
61
|
+
list: std::sync::Mutex<Vec<(u64, std::sync::Weak<Db>)>>,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static WATCHED: arc_swap::ArcSwapOption<Watched> = arc_swap::ArcSwapOption::const_empty();
|
|
65
|
+
static NEXT_WATCH_ID: AtomicU64 = AtomicU64::new(1);
|
|
66
|
+
|
|
67
|
+
/// This process's watch registry. A forked child gets a fresh one: the parent's lock may
|
|
68
|
+
/// have been copied held into it (perf287's S3 on #968; ICR 0067's forked-child rule), and
|
|
69
|
+
/// none of the parent's databases is the child's to watch. Taken only at a supervised open,
|
|
70
|
+
/// a supervised database's drop, and a refusal's error path.
|
|
71
|
+
fn watched() -> Arc<Watched> {
|
|
72
|
+
let pid = pigeonhole_io::sys::process_id();
|
|
73
|
+
WATCHED.rcu(|cur| match cur {
|
|
74
|
+
Some(w) if w.pid == pid => Some(Arc::clone(w)),
|
|
75
|
+
_ => Some(Arc::new(Watched {
|
|
76
|
+
pid,
|
|
77
|
+
list: std::sync::Mutex::new(Vec::new()),
|
|
78
|
+
})),
|
|
79
|
+
});
|
|
80
|
+
WATCHED.load_full().expect("installed just now")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/// Runs `f` while another thread holds this process's watch registry locked (the fork test's
|
|
84
|
+
/// seam: a fork inside `f` copies the lock held, by a thread the child does not have, into
|
|
85
|
+
/// the child; perf287's S3 on #968).
|
|
86
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
87
|
+
pub(crate) fn with_watch_registry_locked_elsewhere<R>(f: impl FnOnce() -> R) -> R {
|
|
88
|
+
let (locked_tx, locked_rx) = std::sync::mpsc::channel();
|
|
89
|
+
let (done_tx, done_rx) = std::sync::mpsc::channel::<()>();
|
|
90
|
+
let holder = std::thread::spawn(move || {
|
|
91
|
+
let registry = watched();
|
|
92
|
+
let _held = registry
|
|
93
|
+
.list
|
|
94
|
+
.lock()
|
|
95
|
+
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
96
|
+
let _ = locked_tx.send(());
|
|
97
|
+
let _ = done_rx.recv();
|
|
98
|
+
});
|
|
99
|
+
let _ = locked_rx.recv();
|
|
100
|
+
let pid = pigeonhole_io::sys::process_id();
|
|
101
|
+
let r = f();
|
|
102
|
+
if pigeonhole_io::sys::process_id() != pid {
|
|
103
|
+
// A forked child: the holder is not in this process.
|
|
104
|
+
std::mem::forget((holder, done_tx));
|
|
105
|
+
return r;
|
|
106
|
+
}
|
|
107
|
+
let _ = done_tx.send(());
|
|
108
|
+
let _ = holder.join();
|
|
109
|
+
r
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
impl Drop for Db {
|
|
113
|
+
/// Leaves the watch registry (perf287's N1 on #968).
|
|
114
|
+
fn drop(&mut self) {
|
|
115
|
+
if self.watch_id == 0 {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
let registry = watched();
|
|
119
|
+
registry
|
|
120
|
+
.list
|
|
121
|
+
.lock()
|
|
122
|
+
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
|
123
|
+
.retain(|(id, d)| *id != self.watch_id && d.strong_count() > 0);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/// What a commit that resolves later needs to map a refusal by the failed engine
|
|
128
|
+
/// ([`Db::refused_later`]): its database's watch id (0 without the option) and the
|
|
129
|
+
/// generation it was submitted under. Copied, never counted.
|
|
130
|
+
#[derive(Debug, Clone, Copy, Default)]
|
|
131
|
+
pub(crate) struct Watch {
|
|
132
|
+
id: u64,
|
|
133
|
+
generation: u64,
|
|
134
|
+
transaction: bool,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
impl Watch {
|
|
138
|
+
/// For a transaction's commit: `SnapshotExpired` once the swap is in, as its sync
|
|
139
|
+
/// commit gets.
|
|
140
|
+
pub(crate) fn transaction(mut self) -> Self {
|
|
141
|
+
self.transaction = true;
|
|
142
|
+
self
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// `e`, or what the sync path reports for a refusal by the failed engine of the watched
|
|
146
|
+
/// database (#966). Only a refusal looks the database up: one the failed shard made
|
|
147
|
+
/// before logging, or a `Closed` from the failed engine's close (a slow commit meets it),
|
|
148
|
+
/// as the sync path's `after_commit_closed` takes both.
|
|
149
|
+
pub(crate) fn refused(self, e: Error) -> Error {
|
|
150
|
+
if self.id == 0 || (e.code() != ErrorCode::Closed && !e.refused_unlogged()) {
|
|
151
|
+
return e;
|
|
152
|
+
}
|
|
153
|
+
let db = watched()
|
|
154
|
+
.list
|
|
155
|
+
.lock()
|
|
156
|
+
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
|
157
|
+
.iter()
|
|
158
|
+
.find(|(id, _)| *id == self.id)
|
|
159
|
+
.and_then(|(_, w)| w.upgrade());
|
|
160
|
+
match db {
|
|
161
|
+
Some(db) => db.refused_later(e, self),
|
|
162
|
+
None => e,
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// The engine an operation runs on, held for the operation: the handle's cached `Arc`
|
|
168
|
+
/// (one generation load to validate it), or, after a swap left the handle stale, the
|
|
169
|
+
/// current engine loaded from the `ArcSwap` (the slow path).
|
|
170
|
+
pub(crate) enum EngineRef<'a> {
|
|
171
|
+
Cached(&'a Arc<Engine>),
|
|
172
|
+
/// The slow path's own strong reference (an `Arc` clone, not an `arc_swap` guard, so
|
|
173
|
+
/// the fast path's drop glue is a discriminant check and nothing else).
|
|
174
|
+
Loaded(Arc<Engine>),
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
impl std::ops::Deref for EngineRef<'_> {
|
|
178
|
+
type Target = Engine;
|
|
179
|
+
#[inline(always)]
|
|
180
|
+
fn deref(&self) -> &Engine {
|
|
181
|
+
match self {
|
|
182
|
+
EngineRef::Cached(e) => e,
|
|
183
|
+
EngineRef::Loaded(e) => e,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
impl EngineRef<'_> {
|
|
189
|
+
#[cfg_attr(not(test), allow(dead_code))]
|
|
190
|
+
pub(crate) fn to_arc(&self) -> Arc<Engine> {
|
|
191
|
+
match self {
|
|
192
|
+
EngineRef::Cached(e) => Arc::clone(e),
|
|
193
|
+
EngineRef::Loaded(e) => Arc::clone(e),
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// A handle's cached engine and the generation it was taken in (D265). Valid while the
|
|
199
|
+
/// database's generation is still that one: the check is one atomic load. A handle made
|
|
200
|
+
/// before a swap keeps the old engine alive (a light shell once its close released its
|
|
201
|
+
/// memory) and takes the slow path on every operation until a new handle is opened.
|
|
202
|
+
#[derive(Debug, Clone)]
|
|
203
|
+
pub(crate) struct Cached {
|
|
204
|
+
engine: Arc<Engine>,
|
|
205
|
+
generation: u64,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
impl Cached {
|
|
209
|
+
pub(crate) fn new(db: &Db) -> Self {
|
|
210
|
+
// The generation first: a swap in between leaves a cache that fails its check.
|
|
211
|
+
let generation = db.generation();
|
|
212
|
+
let engine = Arc::clone(&db.engine.load());
|
|
213
|
+
Self { engine, generation }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// The engine for one operation.
|
|
217
|
+
#[inline(always)]
|
|
218
|
+
pub(crate) fn get<'a>(&'a self, db: &'a Db) -> EngineRef<'a> {
|
|
219
|
+
if db.generation() == self.generation {
|
|
220
|
+
EngineRef::Cached(&self.engine)
|
|
221
|
+
} else {
|
|
222
|
+
Self::stale(db)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// The slow path, out of line and cold: inlined into every operation it made the fast
|
|
227
|
+
/// function large enough to spoil the codegen of the engine calls inlined after it
|
|
228
|
+
/// (about 30 instructions on a get, measured).
|
|
229
|
+
#[cold]
|
|
230
|
+
#[inline(never)]
|
|
231
|
+
fn stale(db: &Db) -> EngineRef<'_> {
|
|
232
|
+
db.engine()
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/// Runs `f` on the engine for one operation without materializing a guard: the fast
|
|
236
|
+
/// path is two loads, a compare and the call (a materialized `EngineRef`, constructed,
|
|
237
|
+
/// dereferenced and drop-checked, measured about 25 instructions more per operation).
|
|
238
|
+
#[inline(always)]
|
|
239
|
+
pub(crate) fn with<R>(&self, db: &Db, f: impl FnOnce(&Engine) -> R) -> R {
|
|
240
|
+
if db.generation() == self.generation {
|
|
241
|
+
f(&self.engine)
|
|
242
|
+
} else {
|
|
243
|
+
Self::stale_with(db, f)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#[cold]
|
|
248
|
+
#[inline(never)]
|
|
249
|
+
fn stale_with<R>(db: &Db, f: impl FnOnce(&Engine) -> R) -> R {
|
|
250
|
+
f(&db.engine())
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// A cache for a handle derived from this one: this one while it is current.
|
|
254
|
+
pub(crate) fn fresh(&self, db: &Db) -> Self {
|
|
255
|
+
if db.generation() == self.generation {
|
|
256
|
+
self.clone()
|
|
257
|
+
} else {
|
|
258
|
+
Self::new(db)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/// The bit of [`Db::generation`] that says the database was closed (`Pigeonhole::close`).
|
|
264
|
+
const CLOSED: u64 = 1 << 63;
|
|
265
|
+
|
|
266
|
+
impl Db {
|
|
267
|
+
fn new(engine: Arc<Engine>, vfs: VfsRef, max_value: usize) -> Arc<Self> {
|
|
268
|
+
Self::with_recovery(engine, vfs, max_value, None, Duration::from_secs(30))
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// `new`, supervised when `reopen` names the options and path to recover with and the
|
|
272
|
+
/// options ask for it.
|
|
273
|
+
fn with_recovery(
|
|
274
|
+
engine: Arc<Engine>,
|
|
275
|
+
vfs: VfsRef,
|
|
276
|
+
max_value: usize,
|
|
277
|
+
reopen: Option<(Options, PathBuf)>,
|
|
278
|
+
stall_timeout: Duration,
|
|
279
|
+
) -> Arc<Self> {
|
|
280
|
+
let supervision = reopen
|
|
281
|
+
.as_ref()
|
|
282
|
+
.map(|(o, _)| o.recovery())
|
|
283
|
+
.filter(|r| *r != Recovery::Off)
|
|
284
|
+
.map(crate::recovery::Supervision::new);
|
|
285
|
+
let watch_id = if supervision.is_some() {
|
|
286
|
+
NEXT_WATCH_ID.fetch_add(1, Ordering::Relaxed)
|
|
287
|
+
} else {
|
|
288
|
+
0
|
|
289
|
+
};
|
|
290
|
+
let db = Arc::new(Self {
|
|
291
|
+
engine: ArcSwap::from(engine),
|
|
292
|
+
generation: AtomicU64::new(1),
|
|
293
|
+
vfs,
|
|
294
|
+
max_value,
|
|
295
|
+
supervision,
|
|
296
|
+
reopen,
|
|
297
|
+
stall_timeout,
|
|
298
|
+
txn_counts: Default::default(),
|
|
299
|
+
watch_id,
|
|
300
|
+
});
|
|
301
|
+
if watch_id != 0 {
|
|
302
|
+
let registry = watched();
|
|
303
|
+
let mut w = registry
|
|
304
|
+
.list
|
|
305
|
+
.lock()
|
|
306
|
+
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
307
|
+
w.retain(|(_, d)| d.strong_count() > 0);
|
|
308
|
+
w.push((watch_id, Arc::downgrade(&db)));
|
|
309
|
+
}
|
|
310
|
+
db
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/// What a commit submitted now needs to map a refusal by the failed engine when it
|
|
314
|
+
/// resolves later (#966): nothing without the option.
|
|
315
|
+
///
|
|
316
|
+
/// Take it before choosing the engine the commit runs on (perf287's S2 on #968): taken
|
|
317
|
+
/// after, a swap in between records the new generation, and a refusal by the failed
|
|
318
|
+
/// engine then looks as if nothing swapped (`Closed` instead of `Busy`).
|
|
319
|
+
#[inline]
|
|
320
|
+
pub(crate) fn watch(&self) -> Watch {
|
|
321
|
+
self.watch_at(self.generation())
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/// [`Db::watch`] for a commit submitted under `generation` (a transaction's).
|
|
325
|
+
#[inline]
|
|
326
|
+
pub(crate) fn watch_at(&self, generation: u64) -> Watch {
|
|
327
|
+
if self.watch_id == 0 {
|
|
328
|
+
return Watch::default();
|
|
329
|
+
}
|
|
330
|
+
Watch {
|
|
331
|
+
id: self.watch_id,
|
|
332
|
+
generation,
|
|
333
|
+
transaction: false,
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/// The supervisor's state, with the option on.
|
|
338
|
+
pub(crate) fn supervision(&self) -> Option<&crate::recovery::Supervision> {
|
|
339
|
+
self.supervision.as_ref()
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/// The current engine, as an `Arc` (the supervisor's wait holds it).
|
|
343
|
+
pub(crate) fn engine_arc(&self) -> Arc<Engine> {
|
|
344
|
+
Arc::clone(&self.engine.load())
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
pub(crate) fn is_closed(&self) -> bool {
|
|
348
|
+
self.generation.load(Ordering::Acquire) & CLOSED != 0
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
pub(crate) fn stall_timeout(&self) -> Duration {
|
|
352
|
+
self.stall_timeout
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/// The engine options a recovery reopens with (the handle's own, re-resolved).
|
|
356
|
+
pub(crate) fn reopen_options(&self) -> Result<pigeonhole_engine::EngineOptions> {
|
|
357
|
+
let (options, _) = self.reopen.as_ref().expect("a supervised writer");
|
|
358
|
+
Ok(options.to_engine()?)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
pub(crate) fn path(&self) -> &Path {
|
|
362
|
+
let (_, path) = self.reopen.as_ref().expect("a supervised writer");
|
|
363
|
+
path
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/// Runs `op`, and once more on the current engine if it got `Closed` from an engine a
|
|
367
|
+
/// recovery was replacing (D265): the wait for the swap is bounded by
|
|
368
|
+
/// `Options::write_stall_timeout` (`Busy` past it; `Closed` once recovery gave up or
|
|
369
|
+
/// the handle is closed). Costs nothing on the success path.
|
|
370
|
+
/// Whether a recovery supervisor runs for this database (`Options::auto_recover`): the
|
|
371
|
+
/// hot read paths take `retry_closed` only then, and the engine call as before the
|
|
372
|
+
/// option otherwise. A closure handing the engine's result back costs a move of it
|
|
373
|
+
/// (`CellData` carries up to 128 inline bytes: about 60 instructions per point get on
|
|
374
|
+
/// callgrind, #836 round 6), which the option-off path must not pay.
|
|
375
|
+
#[inline(always)]
|
|
376
|
+
pub(crate) fn supervised(&self) -> bool {
|
|
377
|
+
self.supervision.is_some()
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
#[inline(always)]
|
|
381
|
+
pub(crate) fn retry_closed<T>(&self, mut op: impl FnMut() -> Result<T>) -> Result<T> {
|
|
382
|
+
// Option off: the operation as it was, nothing around it (the instructions run on
|
|
383
|
+
// #836 measured the version below with a load and a match around every get at
|
|
384
|
+
// about 120 instructions more per point get).
|
|
385
|
+
if self.supervision.is_none() {
|
|
386
|
+
return op();
|
|
387
|
+
}
|
|
388
|
+
// The generation before the operation (one load): a `Closed` is then judged against
|
|
389
|
+
// the engine the operation ran on, not against whatever is current once the thread
|
|
390
|
+
// runs again (perf287's R3 on #836).
|
|
391
|
+
let generation = self.generation();
|
|
392
|
+
match op() {
|
|
393
|
+
Err(e) if e.code() == ErrorCode::Closed => self.retry_after_closed(generation, op),
|
|
394
|
+
r => r,
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/// The retry, out of line: after the wait, the operation again on the current engine.
|
|
399
|
+
#[cold]
|
|
400
|
+
#[inline(never)]
|
|
401
|
+
fn retry_after_closed<T>(
|
|
402
|
+
&self,
|
|
403
|
+
generation: u64,
|
|
404
|
+
mut op: impl FnMut() -> Result<T>,
|
|
405
|
+
) -> Result<T> {
|
|
406
|
+
self.after_closed(generation)?;
|
|
407
|
+
op()
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/// An operation got `Closed`: whether to run it again (`Ok`), after waiting for a running
|
|
411
|
+
/// recovery's swap, or to fail (`Closed`, or `Busy` past the wait's bound).
|
|
412
|
+
#[cold]
|
|
413
|
+
#[inline(never)]
|
|
414
|
+
pub(crate) fn after_closed(&self, generation: u64) -> Result<()> {
|
|
415
|
+
let closed = || Err(pigeonhole_engine::Error::Closed.into());
|
|
416
|
+
if self.is_closed() {
|
|
417
|
+
return closed();
|
|
418
|
+
}
|
|
419
|
+
let Some(sup) = &self.supervision else {
|
|
420
|
+
return closed();
|
|
421
|
+
};
|
|
422
|
+
// A recovery either runs (wait for it) or completed since the operation loaded its
|
|
423
|
+
// engine (the failed one, closed meanwhile: run again on the new one). With neither,
|
|
424
|
+
// the `Closed` is the instance's own (a failure the option does not cover, or one
|
|
425
|
+
// the supervisor gave up on).
|
|
426
|
+
match sup.wait_settled(self.stall_timeout, || self.engine_arc().is_failed()) {
|
|
427
|
+
crate::recovery::Settled::Swapped if self.generation() != generation => Ok(()),
|
|
428
|
+
crate::recovery::Settled::Swapped => closed(),
|
|
429
|
+
crate::recovery::Settled::Failed => closed(),
|
|
430
|
+
crate::recovery::Settled::TimedOut => Err(Error::new(
|
|
431
|
+
ErrorCode::Busy,
|
|
432
|
+
"recovering after a shard failure (Options::auto_recover): the reopen did not \
|
|
433
|
+
finish within Options::write_stall_timeout; not committed, retry",
|
|
434
|
+
)),
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/// Before a commit is submitted: with a recovery running, waits for its swap (bounded),
|
|
439
|
+
/// so the commit runs on the new engine rather than being refused by the closing one.
|
|
440
|
+
/// Returns the generation the commit submits under, for `after_commit_closed`.
|
|
441
|
+
#[inline(always)]
|
|
442
|
+
pub(crate) fn before_commit(&self) -> Result<u64> {
|
|
443
|
+
match &self.supervision {
|
|
444
|
+
// Option off: no load at all (`after_commit_closed` returns early without it).
|
|
445
|
+
None => Ok(0),
|
|
446
|
+
Some(sup) if sup.recovering() => {
|
|
447
|
+
self.wait_for_swap()?;
|
|
448
|
+
Ok(self.generation())
|
|
449
|
+
}
|
|
450
|
+
Some(_) => Ok(self.generation()),
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
#[cold]
|
|
455
|
+
#[inline(never)]
|
|
456
|
+
fn wait_for_swap(&self) -> Result<()> {
|
|
457
|
+
let sup = self.supervision.as_ref().expect("checked");
|
|
458
|
+
match sup.wait_settled(self.stall_timeout, || self.engine_arc().is_failed()) {
|
|
459
|
+
crate::recovery::Settled::Swapped => Ok(()),
|
|
460
|
+
crate::recovery::Settled::Failed => Err(pigeonhole_engine::Error::Closed.into()),
|
|
461
|
+
crate::recovery::Settled::TimedOut => Err(Error::new(
|
|
462
|
+
ErrorCode::Busy,
|
|
463
|
+
"recovering after a shard failure (Options::auto_recover): the reopen did not \
|
|
464
|
+
finish within Options::write_stall_timeout; not committed, retry",
|
|
465
|
+
)),
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/// A commit got `Closed` from the engine, or a failed shard's refusal of a commit it never
|
|
470
|
+
/// logged (`Io`, before the supervisor began closing that engine: #921): with a recovery
|
|
471
|
+
/// running or just completed, the commit was refused by the failing engine before
|
|
472
|
+
/// anything was written, and the batch is gone with it: `Busy` (not committed, retry)
|
|
473
|
+
/// once the swap is in, or the error as it is if the recovery gave up. Without a
|
|
474
|
+
/// recovery, the error as it is.
|
|
475
|
+
#[cold]
|
|
476
|
+
#[inline(never)]
|
|
477
|
+
pub(crate) fn after_commit_closed(&self, generation: u64, e: Error) -> Error {
|
|
478
|
+
self.after_commit_closed_as(generation, e, false)
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/// [`after_commit_closed`](Self::after_commit_closed) for a transaction's commit: refused
|
|
482
|
+
/// by the failed engine before the swap, it gets `SnapshotExpired` rather than `Busy`
|
|
483
|
+
/// (perf287's S1 on #877, ICR 0060): its snapshot expired with the swap, as its reads
|
|
484
|
+
/// would have, and `SnapshotExpired` is what `Pigeonhole::transact` retries by default.
|
|
485
|
+
/// A recovery that times out is still `Busy`.
|
|
486
|
+
#[cold]
|
|
487
|
+
#[inline(never)]
|
|
488
|
+
pub(crate) fn after_transaction_commit_closed(&self, generation: u64, e: Error) -> Error {
|
|
489
|
+
self.after_commit_closed_as(generation, e, true)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
#[cold]
|
|
493
|
+
#[inline(never)]
|
|
494
|
+
fn after_commit_closed_as(&self, generation: u64, e: Error, transaction: bool) -> Error {
|
|
495
|
+
if e.code() != ErrorCode::Closed && !e.refused_unlogged() {
|
|
496
|
+
return e;
|
|
497
|
+
}
|
|
498
|
+
let Some(sup) = &self.supervision else {
|
|
499
|
+
return e;
|
|
500
|
+
};
|
|
501
|
+
// Closed through any handle: `Closed`, also for a refusal the failed shard made
|
|
502
|
+
// unlogged, as an async commit or a ticket gets it (`refused_later`; #970, N1).
|
|
503
|
+
if self.is_closed() {
|
|
504
|
+
return pigeonhole_engine::Error::Closed.into();
|
|
505
|
+
}
|
|
506
|
+
match sup.wait_settled(self.stall_timeout, || self.engine_arc().is_failed()) {
|
|
507
|
+
crate::recovery::Settled::Swapped if self.generation() != generation => {
|
|
508
|
+
if transaction {
|
|
509
|
+
Error::new(
|
|
510
|
+
ErrorCode::SnapshotExpired,
|
|
511
|
+
"refused by the failed engine while the database recovered \
|
|
512
|
+
(Options::auto_recover): not committed; the transaction's snapshot \
|
|
513
|
+
expired with the swap, so begin it again",
|
|
514
|
+
)
|
|
515
|
+
} else {
|
|
516
|
+
Error::new(
|
|
517
|
+
ErrorCode::Busy,
|
|
518
|
+
"refused by the failed engine while the database recovered \
|
|
519
|
+
(Options::auto_recover): not committed, retry on the recovered one",
|
|
520
|
+
)
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
crate::recovery::Settled::TimedOut => Error::new(
|
|
524
|
+
ErrorCode::Busy,
|
|
525
|
+
"recovering after a shard failure (Options::auto_recover): the reopen did not \
|
|
526
|
+
finish within Options::write_stall_timeout; not committed, retry",
|
|
527
|
+
),
|
|
528
|
+
// The supervisor gave up on a failure it covers: the handle stays failed and
|
|
529
|
+
// refuses commits with `Closed` (ICR 0060's rule for a covered failure), also one
|
|
530
|
+
// the failed shard refused before logging it, which can meet it before the engine
|
|
531
|
+
// is marked dead (#966). A failure it does not cover is as without the option.
|
|
532
|
+
crate::recovery::Settled::Failed if e.refused_unlogged() && sup.gave_up() => {
|
|
533
|
+
pigeonhole_engine::Error::Closed.into()
|
|
534
|
+
}
|
|
535
|
+
_ => e,
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/// A commit resolved after its call returned (an async commit, a ticket), refused by the
|
|
540
|
+
/// failed engine before it logged anything (the engine's `ShardFailed`, code `Io`, or a
|
|
541
|
+
/// `Closed` from its close), reported as the sync path reports it once it has waited, but
|
|
542
|
+
/// without waiting (#966):
|
|
543
|
+
/// `Busy` (`SnapshotExpired` for a transaction) once the swap is in, `Closed` while the
|
|
544
|
+
/// recovery runs or after a give-up. Not committed either way. A failure the option
|
|
545
|
+
/// does not cover is as without it.
|
|
546
|
+
#[cold]
|
|
547
|
+
#[inline(never)]
|
|
548
|
+
fn refused_later(&self, e: Error, watch: Watch) -> Error {
|
|
549
|
+
let Some(sup) = &self.supervision else {
|
|
550
|
+
return e;
|
|
551
|
+
};
|
|
552
|
+
if self.is_closed() {
|
|
553
|
+
return pigeonhole_engine::Error::Closed.into();
|
|
554
|
+
}
|
|
555
|
+
let failure = self
|
|
556
|
+
.engine_arc()
|
|
557
|
+
.failure()
|
|
558
|
+
.map(crate::recovery::Failure::from_engine);
|
|
559
|
+
if !sup.covers_refusal(failure) {
|
|
560
|
+
return e;
|
|
561
|
+
}
|
|
562
|
+
if self.generation() != watch.generation {
|
|
563
|
+
return if watch.transaction {
|
|
564
|
+
Error::new(
|
|
565
|
+
ErrorCode::SnapshotExpired,
|
|
566
|
+
"refused by the failed engine while the database recovered \
|
|
567
|
+
(Options::auto_recover): not committed; the transaction's snapshot \
|
|
568
|
+
expired with the swap, so begin it again",
|
|
569
|
+
)
|
|
570
|
+
} else {
|
|
571
|
+
Error::new(
|
|
572
|
+
ErrorCode::Busy,
|
|
573
|
+
"refused by the failed engine while the database recovered \
|
|
574
|
+
(Options::auto_recover): not committed, retry on the recovered one",
|
|
575
|
+
)
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
if sup.gave_up() {
|
|
579
|
+
return Error::new(
|
|
580
|
+
ErrorCode::Closed,
|
|
581
|
+
"refused by the failed engine, and automatic recovery gave up \
|
|
582
|
+
(recovery_stats().gave_up): not committed; reopen the database",
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
Error::new(
|
|
586
|
+
ErrorCode::Closed,
|
|
587
|
+
"refused by the failed engine while the database recovers \
|
|
588
|
+
(Options::auto_recover): not committed; retry once it recovered",
|
|
589
|
+
)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/// The current engine, loaded from the `ArcSwap` (the slow path; handles use their
|
|
593
|
+
/// `Cached`). Hold the guard only for the operation.
|
|
594
|
+
#[inline]
|
|
595
|
+
pub(crate) fn engine(&self) -> EngineRef<'_> {
|
|
596
|
+
EngineRef::Loaded(Arc::clone(&self.engine.load()))
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/// The generation the current engine was opened in (see [`Db::swap_engine`]).
|
|
600
|
+
#[inline]
|
|
601
|
+
pub(crate) fn generation(&self) -> u64 {
|
|
602
|
+
self.generation.load(Ordering::Acquire) & !CLOSED
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/// Fails unless `generation` is the current one and the database is open: with
|
|
606
|
+
/// `SnapshotExpired` when a snapshot, a transaction or an iterator from an earlier
|
|
607
|
+
/// engine would read through its old view (the reopen freed the extents it names:
|
|
608
|
+
/// D148's reasoning, D265), with `Closed` after `close()` (#826). One load.
|
|
609
|
+
#[inline]
|
|
610
|
+
pub(crate) fn check_generation(&self, generation: u64) -> Result<()> {
|
|
611
|
+
let current = self.generation.load(Ordering::Acquire);
|
|
612
|
+
if current == generation {
|
|
613
|
+
Ok(())
|
|
614
|
+
} else if current & CLOSED != 0 {
|
|
615
|
+
Err(pigeonhole_engine::Error::Closed.into())
|
|
616
|
+
} else {
|
|
617
|
+
Err(pigeonhole_engine::Error::SnapshotExpired.into())
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/// Replaces the engine (D265): later operations run on `engine`, the generation moves
|
|
622
|
+
/// on, and the previous engine is returned for the caller to drop. The order matters: the
|
|
623
|
+
/// new engine is in place before the generation moves, so an operation that passed its
|
|
624
|
+
/// generation check loads either the old engine (still open, or closing: it then fails
|
|
625
|
+
/// with `Closed`) or the new one, never a mix.
|
|
626
|
+
pub(crate) fn swap_engine(&self, engine: Arc<Engine>) -> Arc<Engine> {
|
|
627
|
+
let previous = self.engine.swap(engine);
|
|
628
|
+
self.generation.fetch_add(1, Ordering::AcqRel);
|
|
629
|
+
previous
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
fn io_rings(&self) -> Option<IoRings> {
|
|
633
|
+
self.vfs.ring_stats().map(|s| IoRings {
|
|
634
|
+
rings: s.rings,
|
|
635
|
+
attach_failures: s.attach_failures,
|
|
636
|
+
inline: s.inline,
|
|
637
|
+
})
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/// Fails with `Closed` once the database was closed through any handle.
|
|
641
|
+
#[inline]
|
|
642
|
+
pub(crate) fn check_open(&self) -> Result<()> {
|
|
643
|
+
if self.generation.load(Ordering::Acquire) & CLOSED != 0 {
|
|
644
|
+
Err(pigeonhole_engine::Error::Closed.into())
|
|
645
|
+
} else {
|
|
646
|
+
Ok(())
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
pub(crate) fn snapshot(self: &Arc<Self>, cached: &Cached) -> Result<Snapshot> {
|
|
651
|
+
self.check_open()?;
|
|
652
|
+
// The generation before the engine, inside the retry (perf287's R2 on #836): a swap
|
|
653
|
+
// in between leaves a snapshot that fails its check rather than one that passes it
|
|
654
|
+
// with an old view, and a snapshot retried on the new engine carries that one's.
|
|
655
|
+
let (inner, generation) = self.retry_closed(|| {
|
|
656
|
+
let generation = self.generation();
|
|
657
|
+
let inner = cached.with(self, Engine::snapshot)?;
|
|
658
|
+
Ok((inner, generation))
|
|
659
|
+
})?;
|
|
660
|
+
Ok(Snapshot {
|
|
661
|
+
inner,
|
|
662
|
+
db: Arc::downgrade(self),
|
|
663
|
+
generation,
|
|
664
|
+
})
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
pub(crate) fn durable_snapshot(self: &Arc<Self>, cached: &Cached) -> Result<Snapshot> {
|
|
668
|
+
self.check_open()?;
|
|
669
|
+
let (inner, generation) = self.retry_closed(|| {
|
|
670
|
+
let generation = self.generation();
|
|
671
|
+
let inner = cached.with(self, Engine::durable_snapshot)?;
|
|
672
|
+
Ok((inner, generation))
|
|
673
|
+
})?;
|
|
674
|
+
Ok(Snapshot {
|
|
675
|
+
inner,
|
|
676
|
+
db: Arc::downgrade(self),
|
|
677
|
+
generation,
|
|
678
|
+
})
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/// Refuses a snapshot taken from another database, or from an earlier engine of this one
|
|
682
|
+
/// (`SnapshotExpired`, D265).
|
|
683
|
+
#[inline]
|
|
684
|
+
pub(crate) fn check_snapshot(self: &Arc<Self>, snapshot: &Snapshot) -> Result<()> {
|
|
685
|
+
if !std::ptr::eq(Weak::as_ptr(&snapshot.db), Arc::as_ptr(self)) {
|
|
686
|
+
return Err(Error::new(
|
|
687
|
+
ErrorCode::InvalidArgument,
|
|
688
|
+
"the snapshot belongs to another database",
|
|
689
|
+
));
|
|
690
|
+
}
|
|
691
|
+
self.check_generation(snapshot.generation)
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/// An open database: the one writer process's handle. Cheap to clone; every clone shares the
|
|
696
|
+
/// same engine and shard threads.
|
|
697
|
+
///
|
|
698
|
+
/// ```
|
|
699
|
+
/// use pigeonhole::{Family, Options, Pigeonhole};
|
|
700
|
+
///
|
|
701
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
702
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
703
|
+
/// let db = Pigeonhole::open(dir.join("app.phdb"), Options::default().shards(1))?;
|
|
704
|
+
/// let users = db
|
|
705
|
+
/// .table("users")?
|
|
706
|
+
/// .family("profile", Family::default().max_versions(1))
|
|
707
|
+
/// .create_if_missing()?;
|
|
708
|
+
/// users.mutate(b"user:42").put("profile", b"name", b"Ada").commit()?;
|
|
709
|
+
/// assert_eq!(db.tables(), ["users"]);
|
|
710
|
+
/// db.close()?;
|
|
711
|
+
/// # Ok(())
|
|
712
|
+
/// # }
|
|
713
|
+
/// ```
|
|
714
|
+
#[derive(Debug, Clone)]
|
|
715
|
+
pub struct Pigeonhole {
|
|
716
|
+
pub(crate) db: Arc<Db>,
|
|
717
|
+
pub(crate) cached: Cached,
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
impl Pigeonhole {
|
|
721
|
+
/// The engine for one operation (the cached one while this handle is current).
|
|
722
|
+
#[inline]
|
|
723
|
+
pub(crate) fn engine(&self) -> EngineRef<'_> {
|
|
724
|
+
self.cached.get(&self.db)
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
impl Pigeonhole {
|
|
729
|
+
/// Opens (or creates) a database as the writer. A second writer, in this or another
|
|
730
|
+
/// process, fails with [`ErrorCode::WriterLocked`](crate::ErrorCode::WriterLocked).
|
|
731
|
+
/// Opening replays the WAL sidecars; there is no full-file recovery scan.
|
|
732
|
+
pub fn open(path: impl AsRef<Path>, options: Options) -> Result<Pigeonhole> {
|
|
733
|
+
let engine_options = options.to_engine()?;
|
|
734
|
+
let vfs = Arc::clone(&engine_options.vfs);
|
|
735
|
+
let max_value = max_value(&engine_options);
|
|
736
|
+
let shm = ShmFootprint::of(&engine_options);
|
|
737
|
+
let engine = Engine::open(path.as_ref(), engine_options).map_err(|e| shm.explain(e))?;
|
|
738
|
+
let stall_timeout = options.stall_timeout();
|
|
739
|
+
let supervised = options.recovery() != Recovery::Off;
|
|
740
|
+
let db = Db::with_recovery(
|
|
741
|
+
engine,
|
|
742
|
+
vfs,
|
|
743
|
+
max_value,
|
|
744
|
+
Some((options, path.as_ref().to_path_buf())),
|
|
745
|
+
stall_timeout,
|
|
746
|
+
);
|
|
747
|
+
if supervised {
|
|
748
|
+
crate::recovery::Supervision::start(&db)?;
|
|
749
|
+
}
|
|
750
|
+
let cached = Cached::new(&db);
|
|
751
|
+
Ok(Pigeonhole { db, cached })
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/// Opens a read-only handle (Phase 4). Any number of reader processes may open the same
|
|
755
|
+
/// file while a writer runs; they see each commit as soon as the writer publishes it.
|
|
756
|
+
///
|
|
757
|
+
/// **Readers need write access to the file.** The handle never writes, but the process
|
|
758
|
+
/// opens the `.phdb` file read-write, because the coordination locks it takes are
|
|
759
|
+
/// exclusive byte-range locks, which POSIX grants only on a writable descriptor (the same
|
|
760
|
+
/// requirement as SQLite in WAL mode). A file on read-only media, or one the reader's
|
|
761
|
+
/// user cannot write, cannot be opened this way (decision D36).
|
|
762
|
+
pub fn open_reader(path: impl AsRef<Path>, options: ReaderOptions) -> Result<PigeonholeReader> {
|
|
763
|
+
let engine_options = options.to_engine()?;
|
|
764
|
+
let vfs = Arc::clone(&engine_options.vfs);
|
|
765
|
+
let engine = Engine::open_reader(path.as_ref(), engine_options)?;
|
|
766
|
+
let db = Db::new(engine, vfs, 0);
|
|
767
|
+
let cached = Cached::new(&db);
|
|
768
|
+
Ok(PigeonholeReader { db, cached })
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/// Opens as the writer in application-owned mode (ICR 0088): no shard or compaction
|
|
772
|
+
/// threads are started; drive each [`Shard`] in the returned [`AppOwned`] from one of your
|
|
773
|
+
/// own (typically pinned) threads. The default I/O backend still runs a pool of 2-16 I/O threads for WAL syncs
|
|
774
|
+
/// and reads; a threadless mode is planned for Phase 3. Because no compaction thread
|
|
775
|
+
/// is started, [`Options::compaction_cores`] with `k > 0` is refused with
|
|
776
|
+
/// [`ErrorCode::InvalidArgument`](crate::ErrorCode::InvalidArgument) (decision D40).
|
|
777
|
+
///
|
|
778
|
+
/// Every blocking call (`commit`, `flush`, `close`) waits for the shards to run, so make
|
|
779
|
+
/// sure each shard is being driven before calling one. A thread that drives a shard (it
|
|
780
|
+
/// last called [`Shard::run_once`]) must not block on shard work: there `commit`,
|
|
781
|
+
/// `check_and_mutate`, transaction commits, `flush` and `compact` fail with
|
|
782
|
+
/// [`ErrorCode::InvalidArgument`](crate::ErrorCode::InvalidArgument) before doing
|
|
783
|
+
/// anything, instead of deadlocking. A thread holding a shard it has never run is not
|
|
784
|
+
/// detected, so run each shard before committing from its thread. Table creation, other
|
|
785
|
+
/// catalog changes and `shrink` may be called from any thread.
|
|
786
|
+
///
|
|
787
|
+
/// The loop for each shard: call [`Shard::run_once`] until it returns `false`, then sleep
|
|
788
|
+
/// until the [`Shard::set_wakeup`] callback fires (work arrived or I/O completed) or
|
|
789
|
+
/// [`Shard::next_wakeup`] passes (background work is due), whichever comes first. An idle
|
|
790
|
+
/// shard then uses no CPU, even while a write stall or a failed compaction's retry is
|
|
791
|
+
/// pending, beyond a short tablet-balancer pass: every 100 ms after writes, backing off to
|
|
792
|
+
/// one every 10 s while idle.
|
|
793
|
+
///
|
|
794
|
+
/// To close, call [`Pigeonhole::close`] and keep driving each shard the same way until
|
|
795
|
+
/// [`Shard::closed`] returns `Some`, then drop it: the close's flush and syncs run on
|
|
796
|
+
/// the shards, and `run_once` returns `false` while their I/O is in flight. Called on a
|
|
797
|
+
/// thread that drives no shard (once every shard has been run), `close` waits for this
|
|
798
|
+
/// and returns the close's result. Called on a thread that drives a shard, or before
|
|
799
|
+
/// every shard has been run, it cannot wait: it returns `Ok(())` once the shards are
|
|
800
|
+
/// told to close, and the close's result (a failed or unclean close) is then reported
|
|
801
|
+
/// only by [`Shard::closed`].
|
|
802
|
+
///
|
|
803
|
+
/// ```
|
|
804
|
+
/// use std::thread;
|
|
805
|
+
/// use std::time::Duration;
|
|
806
|
+
/// use pigeonhole::{AppOwned, Family, Options, Pigeonhole};
|
|
807
|
+
///
|
|
808
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
809
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
810
|
+
/// let AppOwned { db, shards, .. } =
|
|
811
|
+
/// Pigeonhole::open_application_owned(dir.join("app.phdb"), Options::default().shards(2))?;
|
|
812
|
+
/// let threads: Vec<_> = shards
|
|
813
|
+
/// .into_iter()
|
|
814
|
+
/// .map(|mut shard| {
|
|
815
|
+
/// thread::spawn(move || -> pigeonhole::Result<()> {
|
|
816
|
+
/// let me = thread::current();
|
|
817
|
+
/// shard.set_wakeup(Box::new(move || me.unpark()));
|
|
818
|
+
/// loop {
|
|
819
|
+
/// // Your event loop: run the shard until it is idle, do your own work...
|
|
820
|
+
/// while shard.run_once(Duration::from_micros(200)) {}
|
|
821
|
+
/// // ...and stop once the database's close has finished on every shard.
|
|
822
|
+
/// if let Some(closed) = shard.closed() {
|
|
823
|
+
/// return closed;
|
|
824
|
+
/// }
|
|
825
|
+
/// // ...then sleep until work arrives or background work is due.
|
|
826
|
+
/// match shard.next_wakeup() {
|
|
827
|
+
/// Some(due) => thread::park_timeout(due),
|
|
828
|
+
/// None => thread::park(),
|
|
829
|
+
/// }
|
|
830
|
+
/// }
|
|
831
|
+
/// })
|
|
832
|
+
/// })
|
|
833
|
+
/// .collect();
|
|
834
|
+
///
|
|
835
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
836
|
+
/// t.mutate(b"row").put("f", b"q", b"v").commit()?;
|
|
837
|
+
/// assert_eq!(t.get(b"row", "f", b"q")?.unwrap().value(), b"v");
|
|
838
|
+
///
|
|
839
|
+
/// drop(t);
|
|
840
|
+
/// // Waits for the shard threads to finish the close, and returns its result.
|
|
841
|
+
/// db.close()?;
|
|
842
|
+
/// for thread in threads {
|
|
843
|
+
/// thread.join().unwrap()?;
|
|
844
|
+
/// }
|
|
845
|
+
/// # Ok(())
|
|
846
|
+
/// # }
|
|
847
|
+
/// ```
|
|
848
|
+
///
|
|
849
|
+
/// # Background workers
|
|
850
|
+
/// With [`Options::background_workers`] above 0 (the default is 0), [`AppOwned::workers`]
|
|
851
|
+
/// holds that many background workers (D284) for flush and compaction, which then run on
|
|
852
|
+
/// threads you choose rather than in slices on the shards.
|
|
853
|
+
///
|
|
854
|
+
/// - **Why:** a flush or compaction slice on a shard holds up every commit queued
|
|
855
|
+
/// behind it for up to half a millisecond. With workers, the shards only commit.
|
|
856
|
+
/// - **Driving:** a worker runs as a shard does: [`BackgroundWorker::run_once`] until it
|
|
857
|
+
/// returns `false`, then sleep until its [`set_wakeup`](BackgroundWorker::set_wakeup)
|
|
858
|
+
/// callback fires or [`next_wakeup`](BackgroundWorker::next_wakeup) passes. Any thread
|
|
859
|
+
/// may drive one, including a thread that drives shards, and a worker may move between
|
|
860
|
+
/// threads: its I/O completes inside `run_once`. Or call
|
|
861
|
+
/// [`AppOwned::spawn_background_threads`] to give each a thread of its own.
|
|
862
|
+
/// - **Close:** [`Pigeonhole::close`] never waits for you to drive a worker. It takes
|
|
863
|
+
/// back what the workers hold (a flush finishes on its shard; a compaction is dropped
|
|
864
|
+
/// and runs again after the next open), waiting only for a slice a worker is running at
|
|
865
|
+
/// that moment. Then [`BackgroundWorker::closed`] is `true` and the worker can be
|
|
866
|
+
/// dropped.
|
|
867
|
+
/// - **A worker you stop driving** delays its tasks until the shards take them back: a
|
|
868
|
+
/// queued task no worker took, once no worker has looked for 10 ms; the tasks a worker
|
|
869
|
+
/// holds that could run, once it has made no pass for 100 ms (never inside a slice);
|
|
870
|
+
/// and a flush a worker holds but isn't running, 2 ms into a commit's wait for memtable
|
|
871
|
+
/// room.
|
|
872
|
+
/// [`EngineMetrics::background_fallback_take_backs`](crate::EngineMetrics::background_fallback_take_backs)
|
|
873
|
+
/// counts the first two, so a loop that forgot its workers shows up.
|
|
874
|
+
///
|
|
875
|
+
/// ```
|
|
876
|
+
/// use std::thread;
|
|
877
|
+
/// use std::time::Duration;
|
|
878
|
+
/// use pigeonhole::{Family, Options, Pigeonhole};
|
|
879
|
+
///
|
|
880
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
881
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
882
|
+
/// let options = Options::default().shards(2).background_workers(1);
|
|
883
|
+
/// let mut owned = Pigeonhole::open_application_owned(dir.join("app.phdb"), options)?;
|
|
884
|
+
/// // Flush and compaction get a thread each; the shards run on yours, as above.
|
|
885
|
+
/// let workers = owned.spawn_background_threads()?;
|
|
886
|
+
/// let shards: Vec<_> = owned
|
|
887
|
+
/// .shards
|
|
888
|
+
/// .drain(..)
|
|
889
|
+
/// .map(|mut shard| {
|
|
890
|
+
/// thread::spawn(move || -> pigeonhole::Result<()> {
|
|
891
|
+
/// let me = thread::current();
|
|
892
|
+
/// shard.set_wakeup(Box::new(move || me.unpark()));
|
|
893
|
+
/// loop {
|
|
894
|
+
/// while shard.run_once(Duration::from_micros(200)) {}
|
|
895
|
+
/// if let Some(closed) = shard.closed() {
|
|
896
|
+
/// return closed;
|
|
897
|
+
/// }
|
|
898
|
+
/// match shard.next_wakeup() {
|
|
899
|
+
/// Some(due) => thread::park_timeout(due),
|
|
900
|
+
/// None => thread::park(),
|
|
901
|
+
/// }
|
|
902
|
+
/// }
|
|
903
|
+
/// })
|
|
904
|
+
/// })
|
|
905
|
+
/// .collect();
|
|
906
|
+
///
|
|
907
|
+
/// let db = owned.db;
|
|
908
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
909
|
+
/// t.mutate(b"row").put("f", b"q", b"v").commit()?;
|
|
910
|
+
/// db.flush()?; // runs on the worker
|
|
911
|
+
/// assert_eq!(t.get(b"row", "f", b"q")?.unwrap().value(), b"v");
|
|
912
|
+
///
|
|
913
|
+
/// drop(t);
|
|
914
|
+
/// db.close()?;
|
|
915
|
+
/// for thread in shards {
|
|
916
|
+
/// thread.join().unwrap()?;
|
|
917
|
+
/// }
|
|
918
|
+
/// for thread in workers {
|
|
919
|
+
/// thread.join().unwrap();
|
|
920
|
+
/// }
|
|
921
|
+
/// # Ok(())
|
|
922
|
+
/// # }
|
|
923
|
+
/// ```
|
|
924
|
+
pub fn open_application_owned(path: impl AsRef<Path>, options: Options) -> Result<AppOwned> {
|
|
925
|
+
Self::open_app(path.as_ref(), options)
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/// The application-owned open: the shards and any background workers are handed out.
|
|
929
|
+
fn open_app(path: &Path, options: Options) -> Result<AppOwned> {
|
|
930
|
+
if options.recovery() != Recovery::Off {
|
|
931
|
+
return Err(Error::new(
|
|
932
|
+
ErrorCode::InvalidArgument,
|
|
933
|
+
"Options::auto_recover needs engine-owned shards: an application-owned engine's \
|
|
934
|
+
shards are driven by the application, which closes and reopens it itself",
|
|
935
|
+
));
|
|
936
|
+
}
|
|
937
|
+
let engine_options = options.to_engine_for(true)?;
|
|
938
|
+
let vfs = Arc::clone(&engine_options.vfs);
|
|
939
|
+
let max_value = max_value(&engine_options);
|
|
940
|
+
let shm = ShmFootprint::of(&engine_options);
|
|
941
|
+
let owned = Engine::open_application_owned_with(path, engine_options)
|
|
942
|
+
.map_err(|e| shm.explain(e))?;
|
|
943
|
+
let (engine, shards, workers) = (owned.engine, owned.shards, owned.workers);
|
|
944
|
+
let workers = workers
|
|
945
|
+
.into_iter()
|
|
946
|
+
.map(|inner| BackgroundWorker {
|
|
947
|
+
inner,
|
|
948
|
+
vfs: Arc::clone(&vfs),
|
|
949
|
+
})
|
|
950
|
+
.collect();
|
|
951
|
+
let shards = shards
|
|
952
|
+
.into_iter()
|
|
953
|
+
.map(|inner| Shard {
|
|
954
|
+
inner,
|
|
955
|
+
vfs: Arc::clone(&vfs),
|
|
956
|
+
io_fd_used: std::sync::atomic::AtomicBool::new(false),
|
|
957
|
+
})
|
|
958
|
+
.collect();
|
|
959
|
+
let db = Db::new(engine, Arc::clone(&vfs), max_value);
|
|
960
|
+
let cached = Cached::new(&db);
|
|
961
|
+
Ok(AppOwned {
|
|
962
|
+
db: Pigeonhole { db, cached },
|
|
963
|
+
shards,
|
|
964
|
+
workers,
|
|
965
|
+
})
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/// Starts defining or opening a table: chain `.family(..)` and finish with
|
|
969
|
+
/// `.create_if_missing()`, `.create()` or `.open()`.
|
|
970
|
+
pub fn table(&self, name: &str) -> Result<TableBuilder<'_>> {
|
|
971
|
+
Ok(TableBuilder::new(self, name))
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/// Names of every table.
|
|
975
|
+
pub fn tables(&self) -> Vec<String> {
|
|
976
|
+
self.db
|
|
977
|
+
.engine()
|
|
978
|
+
.tables()
|
|
979
|
+
.iter()
|
|
980
|
+
.map(|t| t.name.clone())
|
|
981
|
+
.collect()
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/// Drops a table and all its data.
|
|
985
|
+
pub fn drop_table(&self, name: &str) -> Result<()> {
|
|
986
|
+
let info = self
|
|
987
|
+
.db
|
|
988
|
+
.engine()
|
|
989
|
+
.table(name)
|
|
990
|
+
.ok_or_else(|| pigeonhole_engine::Error::TableNotFound(name.to_owned()))?;
|
|
991
|
+
self.db
|
|
992
|
+
.retry_closed(|| self.engine().drop_table(info.id).map_err(Error::from))
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/// A batch of writes across any rows and tables, committed with one durability point.
|
|
996
|
+
pub fn write_batch(&self) -> WriteBatch {
|
|
997
|
+
WriteBatch::new(Arc::clone(&self.db), self.cached.fresh(&self.db))
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/// Starts an optimistic multi-row transaction (Phase 4).
|
|
1001
|
+
pub fn transaction(&self) -> Result<Transaction> {
|
|
1002
|
+
self.db.check_open()?;
|
|
1003
|
+
let generation = self.db.generation();
|
|
1004
|
+
Ok(Transaction::new(
|
|
1005
|
+
Arc::clone(&self.db),
|
|
1006
|
+
self.engine().begin()?,
|
|
1007
|
+
generation,
|
|
1008
|
+
))
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
/// Whether `other` is a handle to the same open database as this one: a clone of it, or
|
|
1012
|
+
/// of a handle from the same [`open`](Self::open) (ICR 0110). Two opens of one file are
|
|
1013
|
+
/// different databases, even after the first is closed, and so are two copies of one
|
|
1014
|
+
/// file (a file copied while closed keeps its [`DatabaseInfo::db_id`](crate::DatabaseInfo)).
|
|
1015
|
+
/// An automatic recovery ([`Options::auto_recover`](crate::Options::auto_recover)) keeps
|
|
1016
|
+
/// the open, so it keeps the answer. Cheap (a pointer comparison): a library that keeps
|
|
1017
|
+
/// per-database state, such as a registry of open handles, can key on it.
|
|
1018
|
+
pub fn same_database(&self, other: &Pigeonhole) -> bool {
|
|
1019
|
+
Arc::ptr_eq(&self.db, &other.db)
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/// Whether this instance has failed (ICR 0040): a shard's thread panicked, an
|
|
1023
|
+
/// application-owned shard's driver was dropped before the close finished, a shard
|
|
1024
|
+
/// stopped after a WAL write or sync failed (or its in-memory state could not be
|
|
1025
|
+
/// updated), or a manifest commit to the main file failed. A failed instance refuses
|
|
1026
|
+
/// some or all commits until it is closed and reopened: see the user guide's
|
|
1027
|
+
/// "Recovering from a failed shard". [`failure`](Self::failure) says which shard and
|
|
1028
|
+
/// why. Cheap (one atomic load), so it can back a health endpoint.
|
|
1029
|
+
pub fn is_failed(&self) -> bool {
|
|
1030
|
+
self.engine().is_failed() || self.db.supervision().is_some_and(|s| s.stood_down())
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/// What automatic recovery ([`Options::auto_recover`](crate::Options::auto_recover))
|
|
1034
|
+
/// did since this handle opened: the engine's generation (1 at open, +1 per recovery),
|
|
1035
|
+
/// how many recoveries completed, whether the supervisor gave up, the last failure it
|
|
1036
|
+
/// handled and the last recovery's duration. All zero and `false` with the option off.
|
|
1037
|
+
/// Cheap (one lock, no I/O). Engine metrics restart from zero at each recovery;
|
|
1038
|
+
/// `generation` shows the reset.
|
|
1039
|
+
pub fn recovery_stats(&self) -> RecoveryStats {
|
|
1040
|
+
match self.db.supervision() {
|
|
1041
|
+
Some(s) => s.stats(self.db.generation()),
|
|
1042
|
+
None => RecoveryStats {
|
|
1043
|
+
generation: self.db.generation(),
|
|
1044
|
+
..RecoveryStats::default()
|
|
1045
|
+
},
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/// The instance's first failure, if any (see [`is_failed`](Self::is_failed)): the shard
|
|
1050
|
+
/// ([`Failure::MAIN_FILE`] for the main file) and the
|
|
1051
|
+
/// [`FailureCause`](crate::FailureCause). Later failures do not replace it.
|
|
1052
|
+
pub fn failure(&self) -> Option<Failure> {
|
|
1053
|
+
self.engine()
|
|
1054
|
+
.failure()
|
|
1055
|
+
.map(Failure::from_engine)
|
|
1056
|
+
.or_else(|| {
|
|
1057
|
+
self.db
|
|
1058
|
+
.supervision()
|
|
1059
|
+
.filter(|s| s.gave_up())
|
|
1060
|
+
.and_then(|s| s.last_failure())
|
|
1061
|
+
})
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
/// A consistent snapshot of everything committed so far. It sees a commit once the commit
|
|
1065
|
+
/// is applied, possibly before its fsync (D227): a power loss can remove what it read.
|
|
1066
|
+
pub fn snapshot(&self) -> Result<Snapshot> {
|
|
1067
|
+
self.db.snapshot(&self.cached)
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/// A consistent snapshot that sees a commit only once it is durable at its commit's level
|
|
1071
|
+
/// (D227, ICR 0037): of what it reads, `GroupSync` and `Sync` commits survive a power
|
|
1072
|
+
/// loss, `Buffered` ones a process crash, and `None` ones nothing. It may lag
|
|
1073
|
+
/// [`snapshot`](Self::snapshot) by the fsyncs in flight (typically well under a
|
|
1074
|
+
/// millisecond). Use it when what you read must never be undone: deriving a write on
|
|
1075
|
+
/// another shard from it, or a cursor you persist.
|
|
1076
|
+
///
|
|
1077
|
+
/// ```
|
|
1078
|
+
/// use pigeonhole::{Family, Options, Pigeonhole};
|
|
1079
|
+
///
|
|
1080
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1081
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1082
|
+
/// let db = Pigeonhole::open(dir.join("app.phdb"), Options::default().shards(1))?;
|
|
1083
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
1084
|
+
/// t.mutate(b"row").put("f", b"q", b"v").commit()?; // durable once it returns
|
|
1085
|
+
/// let durable = db.durable_snapshot()?;
|
|
1086
|
+
/// assert_eq!(t.get_at(&durable, b"row", "f", b"q")?.unwrap().value(), b"v");
|
|
1087
|
+
/// # drop(t);
|
|
1088
|
+
/// # db.close()?;
|
|
1089
|
+
/// # Ok(())
|
|
1090
|
+
/// # }
|
|
1091
|
+
/// ```
|
|
1092
|
+
pub fn durable_snapshot(&self) -> Result<Snapshot> {
|
|
1093
|
+
self.db.durable_snapshot(&self.cached)
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/// Per-shard commits, tablets and tablet changes since open, indexed by shard: a bench
|
|
1097
|
+
/// hook (ICR 0010) that shows whether one table's writes spread over the shards.
|
|
1098
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1099
|
+
#[doc(hidden)]
|
|
1100
|
+
pub fn shard_stats(&self) -> Vec<crate::ShardStats> {
|
|
1101
|
+
self.engine()
|
|
1102
|
+
.shard_stats()
|
|
1103
|
+
.into_iter()
|
|
1104
|
+
.map(crate::ShardStats::from_engine)
|
|
1105
|
+
.collect()
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
/// The active shard count the balancer published and the count it is heading for (the
|
|
1109
|
+
/// same unless a growth or the first pack from all shards is pending), `None` before its
|
|
1110
|
+
/// first decision: a bench hook (D242's amendment, #983) so a warm-up does not end inside
|
|
1111
|
+
/// a regrow or before the first pack.
|
|
1112
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1113
|
+
#[doc(hidden)]
|
|
1114
|
+
pub fn pack_target(&self) -> Option<(usize, usize)> {
|
|
1115
|
+
self.engine().pack_target()
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
/// The driver threads the shards run on now and whether every shard is on its driver
|
|
1119
|
+
/// (D289 PR 2), `None` in application-owned mode: a bench hook, so a warm-up does not end
|
|
1120
|
+
/// while the load controller resizes.
|
|
1121
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1122
|
+
#[doc(hidden)]
|
|
1123
|
+
pub fn driver_target(&self) -> Option<(usize, bool)> {
|
|
1124
|
+
self.engine().driver_target()
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
/// Fixes the driver target at `k`, or with `None` gives it back to the controller (D289
|
|
1128
|
+
/// PR 2): for tests that move shards between drivers under load.
|
|
1129
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1130
|
+
#[doc(hidden)]
|
|
1131
|
+
pub fn force_driver_target(&self, k: Option<usize>) {
|
|
1132
|
+
self.engine().force_driver_target(k);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/// The load controller's windows since the last call, one JSON object each (D289,
|
|
1136
|
+
/// #1015): every driver's busy, passes, slow passes, ops and sibling wait, the producer
|
|
1137
|
+
/// wakes, and what the controller decided. Empty in application-owned mode. The first
|
|
1138
|
+
/// call starts the log; with
|
|
1139
|
+
/// [`Options::adaptive_shard_threads`](crate::Options::adaptive_shard_threads) off it starts
|
|
1140
|
+
/// an observe-only controller that logs what it would decide but never resizes. A bench
|
|
1141
|
+
/// hook.
|
|
1142
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1143
|
+
#[doc(hidden)]
|
|
1144
|
+
pub fn driver_trace(&self) -> Vec<String> {
|
|
1145
|
+
self.engine().driver_trace()
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/// What the row cache did since open: hits, misses and fills (D201). All zero when
|
|
1149
|
+
/// [`Options::row_cache`](crate::Options::row_cache) is 0.
|
|
1150
|
+
pub fn row_cache_stats(&self) -> crate::RowCacheStats {
|
|
1151
|
+
crate::RowCacheStats::from_engine(&self.engine())
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
/// The CPUs the engine pinned its shard threads to (D235, ICR 0101): one per pinned
|
|
1155
|
+
/// shard thread, in thread order. A thread the OS places on a shard's CPU preempts the
|
|
1156
|
+
/// shard and delays the commits it serves (#1206). Where the machine has physical cores
|
|
1157
|
+
/// the shards don't use (fewer shards than cores), running busy application threads on
|
|
1158
|
+
/// those cores avoids that. Don't confine threads to the shards' SMT siblings instead:
|
|
1159
|
+
/// with one shard per core (the default) that only leaves the siblings, and a thread
|
|
1160
|
+
/// spinning there slows the shard on the same core (#1244 measured `Buffered` put p99
|
|
1161
|
+
/// about doubling).
|
|
1162
|
+
/// Empty when no shard thread is pinned: [`Options::pin_threads`](crate::Options::pin_threads)
|
|
1163
|
+
/// off, application-owned mode, a platform without hard thread affinity (macOS), a CPU
|
|
1164
|
+
/// quota or too few free CPUs, or every pin refused.
|
|
1165
|
+
/// An in-place recovery ([`Options::auto_recover`](crate::Options::auto_recover)) starts
|
|
1166
|
+
/// new shard threads, which may pin to other CPUs: read this again after one.
|
|
1167
|
+
///
|
|
1168
|
+
/// ```
|
|
1169
|
+
/// use pigeonhole::{Options, Pigeonhole};
|
|
1170
|
+
///
|
|
1171
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1172
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1173
|
+
/// let db = Pigeonhole::open(dir.join("app.phdb"), Options::default().shards(1))?;
|
|
1174
|
+
/// // Each one is a pinned shard thread's own CPU; none on macOS.
|
|
1175
|
+
/// let shard_cpus = db.pinned_shard_cpus();
|
|
1176
|
+
/// assert!(shard_cpus.len() as u64 <= db.engine_metrics().threads_pinned);
|
|
1177
|
+
/// # db.close()?;
|
|
1178
|
+
/// # Ok(())
|
|
1179
|
+
/// # }
|
|
1180
|
+
/// ```
|
|
1181
|
+
pub fn pinned_shard_cpus(&self) -> Vec<usize> {
|
|
1182
|
+
self.engine().pinned_shard_cpus()
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/// The writer's counters since this instance opened: commits and their latency,
|
|
1186
|
+
/// flushes, compactions, write stalls, the block cache, file growth, the shard threads,
|
|
1187
|
+
/// reader slots, transactions, and cross-shard commits' rounds and fast failures
|
|
1188
|
+
/// (ICR 0044, ICR 0087). Most are cumulative
|
|
1189
|
+
/// from 0 at open, so take two readings and subtract for an interval; see
|
|
1190
|
+
/// [`EngineMetrics`](crate::EngineMetrics) for each field. Cheap and non-blocking.
|
|
1191
|
+
pub fn engine_metrics(&self) -> crate::EngineMetrics {
|
|
1192
|
+
let mut m = crate::EngineMetrics::from_engine(self.engine().metrics());
|
|
1193
|
+
self.db.txn_counts.fill(&mut m);
|
|
1194
|
+
let engine = self.engine();
|
|
1195
|
+
m.group_syncs = engine.group_syncs();
|
|
1196
|
+
m.feed_background_syncs = engine.feed_background_syncs();
|
|
1197
|
+
m.feed_sidecar_syncs = engine.feed_sidecar_syncs();
|
|
1198
|
+
m
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/// Commit latency histograms per durability level since open, summed over shards: a
|
|
1202
|
+
/// bench hook (D213). Bucket `b` starts at
|
|
1203
|
+
/// [`commit_latency_floor(b)`](Self::commit_latency_floor) nanoseconds; subtract two readings for a phase.
|
|
1204
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1205
|
+
#[doc(hidden)]
|
|
1206
|
+
pub fn commit_latency_buckets(&self) -> [[u64; 64]; 4] {
|
|
1207
|
+
self.engine().commit_latency_buckets()
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/// The lower bound in nanoseconds of [`commit_latency_buckets`](Self::commit_latency_buckets)'
|
|
1211
|
+
/// bucket `b`.
|
|
1212
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1213
|
+
#[doc(hidden)]
|
|
1214
|
+
pub fn commit_latency_floor(b: usize) -> u64 {
|
|
1215
|
+
pigeonhole_engine::Engine::commit_latency_floor(b)
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/// Tablet changes refused for lack of room since open, as `(slot budget, view size)`:
|
|
1219
|
+
/// see the engine's `tablet_refusals`. A bench hook (#123).
|
|
1220
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1221
|
+
#[doc(hidden)]
|
|
1222
|
+
pub fn tablet_refusals(&self) -> (u64, u64) {
|
|
1223
|
+
self.engine().tablet_refusals()
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/// Bytes of async commits each shard holds submitted and not yet resolved (D210): a
|
|
1227
|
+
/// test hook. At most half `memtable_budget` a shard, or one commit larger than that
|
|
1228
|
+
/// alone.
|
|
1229
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1230
|
+
#[doc(hidden)]
|
|
1231
|
+
pub fn async_commit_inflight(&self) -> Vec<u64> {
|
|
1232
|
+
(0..self.engine().shard_stats().len())
|
|
1233
|
+
.map(|s| self.engine().admission_inflight(s))
|
|
1234
|
+
.collect()
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/// With io_uring (#402; the default on Linux, D218): how many io_uring rings the
|
|
1238
|
+
/// database has now (a shared one, plus one per shard thread that got its own), how
|
|
1239
|
+
/// often a thread could not get one, and how much I/O ran inline on the calling thread
|
|
1240
|
+
/// instead. `None` on other backends.
|
|
1241
|
+
///
|
|
1242
|
+
/// A ring registers a buffer pool on its first read that can use one. Pools are pinned
|
|
1243
|
+
/// memory, charged to the user's locked-memory limit (`RLIMIT_MEMLOCK`, often 8 MiB)
|
|
1244
|
+
/// unless the process has `CAP_IPC_LOCK`; a process registers them up to half that
|
|
1245
|
+
/// limit, 1 MiB a ring. Rings past it use plain buffers: correct, but each read pins its
|
|
1246
|
+
/// pages.
|
|
1247
|
+
pub fn io_rings(&self) -> Option<IoRings> {
|
|
1248
|
+
self.db.io_rings()
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/// D292's inline page-cache reads on this database's I/O backend so far (hits, misses
|
|
1252
|
+
/// and their times, refusals, breaker trips), or `None` on a backend without them. For
|
|
1253
|
+
/// benchmarks (ICR 0083); not part of the API.
|
|
1254
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1255
|
+
#[doc(hidden)]
|
|
1256
|
+
pub fn nowait_reads(&self) -> Option<pigeonhole_io::NowaitReads> {
|
|
1257
|
+
self.db.vfs.nowait_reads()
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/// The counters [`engine_metrics`](Self::engine_metrics) leaves out, by name (ICR 0087):
|
|
1261
|
+
/// the engine's mechanisms (shard parks and wakes, the WAL's unpin passes, visibility
|
|
1262
|
+
/// waits, cross-shard refusals and share waits, io_uring buffer pools, D292's inline
|
|
1263
|
+
/// page-cache reads, and the like), for benchmarks and tests. Not part of the API: names,
|
|
1264
|
+
/// and whether a name is present at all, may change in any release, so treat a missing
|
|
1265
|
+
/// name as absent.
|
|
1266
|
+
#[cfg(feature = "__unstable-hooks")]
|
|
1267
|
+
#[doc(hidden)]
|
|
1268
|
+
pub fn internal_metrics(&self) -> Vec<(&'static str, u64)> {
|
|
1269
|
+
crate::metrics::internal(
|
|
1270
|
+
&self.engine().metrics(),
|
|
1271
|
+
self.db.vfs.ring_stats().map(|s| s.pooled),
|
|
1272
|
+
self.db.vfs.nowait_reads(),
|
|
1273
|
+
)
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/// What the database holds and how it is stored: format version, file and free bytes,
|
|
1277
|
+
/// and per table its tablets, its families' stored options and their SSTs per level and
|
|
1278
|
+
/// blob files (ICR 0047). Reads the current catalog; cheap, no data I/O.
|
|
1279
|
+
pub fn info(&self) -> Result<crate::DatabaseInfo> {
|
|
1280
|
+
Ok(crate::DatabaseInfo::from_engine(self.engine().info()?))
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/// The writer default durability.
|
|
1284
|
+
pub fn default_durability(&self) -> Durability {
|
|
1285
|
+
Durability::from_engine(self.engine().default_durability())
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/// Changes the writer default; applies to commits that start afterwards.
|
|
1289
|
+
pub fn set_default_durability(&self, durability: Durability) {
|
|
1290
|
+
self.engine().set_default_durability(durability.engine());
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/// Writes every memtable into the file and returns once the data is there (the SSTs are
|
|
1294
|
+
/// in the manifest). Afterwards even [`Durability::None`] commits survive a crash, and
|
|
1295
|
+
/// the WAL behind the flushed data is checkpointed. Background flushes run on their own
|
|
1296
|
+
/// as memtables fill; call this to make everything so far durable in the file.
|
|
1297
|
+
///
|
|
1298
|
+
/// Each flushed memtable needs a fresh one from the memtable arena. When snapshots pin
|
|
1299
|
+
/// the arena's memory, the flush waits as a stalled write does, and fails with
|
|
1300
|
+
/// [`ErrorCode::Busy`](crate::ErrorCode::Busy) if no room frees up within the
|
|
1301
|
+
/// write-stall timeout. Nothing is lost: drop old snapshots and retry.
|
|
1302
|
+
///
|
|
1303
|
+
/// ```
|
|
1304
|
+
/// use pigeonhole::{Durability, Family, Options, Pigeonhole};
|
|
1305
|
+
///
|
|
1306
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1307
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1308
|
+
/// let path = dir.join("app.phdb");
|
|
1309
|
+
/// let db = Pigeonhole::open(&path, Options::default().shards(1))?;
|
|
1310
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
1311
|
+
/// t.mutate(b"row").put("f", b"q", b"v").durability(Durability::None).commit()?;
|
|
1312
|
+
/// db.flush()?; // now in the file, whatever the commit's durability level was
|
|
1313
|
+
/// # drop(t);
|
|
1314
|
+
/// db.close()?;
|
|
1315
|
+
///
|
|
1316
|
+
/// let db = Pigeonhole::open(&path, Options::default().shards(1))?;
|
|
1317
|
+
/// let t = db.table("t")?.open()?;
|
|
1318
|
+
/// assert_eq!(t.get(b"row", "f", b"q")?.unwrap().value(), b"v");
|
|
1319
|
+
/// # drop(t);
|
|
1320
|
+
/// # db.close()?;
|
|
1321
|
+
/// # Ok(())
|
|
1322
|
+
/// # }
|
|
1323
|
+
/// ```
|
|
1324
|
+
pub fn flush(&self) -> Result<()> {
|
|
1325
|
+
self.db
|
|
1326
|
+
.retry_closed(|| self.engine().flush().map_err(Error::from))
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
/// Compacts every table fully: flushes, then merges every level into the last one.
|
|
1330
|
+
/// Versions beyond a family's `max_versions`, expired cells and tombstones that no
|
|
1331
|
+
/// snapshot can still need are dropped. Compaction otherwise runs in the background;
|
|
1332
|
+
/// call this after a bulk load or delete to reclaim space and speed up reads. Its flush
|
|
1333
|
+
/// can fail with [`ErrorCode::Busy`](crate::ErrorCode::Busy) as
|
|
1334
|
+
/// [`flush`](Self::flush) does.
|
|
1335
|
+
///
|
|
1336
|
+
/// ```
|
|
1337
|
+
/// use pigeonhole::{Family, Options, Pigeonhole};
|
|
1338
|
+
///
|
|
1339
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1340
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1341
|
+
/// let db = Pigeonhole::open(dir.join("app.phdb"), Options::default().shards(1))?;
|
|
1342
|
+
/// let t = db
|
|
1343
|
+
/// .table("t")?
|
|
1344
|
+
/// .family("f", Family::default().max_versions(1))
|
|
1345
|
+
/// .create_if_missing()?;
|
|
1346
|
+
/// t.mutate(b"row").put("f", b"q", b"old").commit()?;
|
|
1347
|
+
/// t.mutate(b"row").put("f", b"q", b"new").commit()?;
|
|
1348
|
+
/// db.compact()?;
|
|
1349
|
+
/// assert_eq!(t.get(b"row", "f", b"q")?.unwrap().value(), b"new");
|
|
1350
|
+
/// # drop(t);
|
|
1351
|
+
/// # db.close()?;
|
|
1352
|
+
/// # Ok(())
|
|
1353
|
+
/// # }
|
|
1354
|
+
/// ```
|
|
1355
|
+
pub fn compact(&self) -> Result<()> {
|
|
1356
|
+
self.db
|
|
1357
|
+
.retry_closed(|| self.engine().compact(None).map_err(Error::from))
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
/// Writes a consistent single-file copy to `dest`, which must not exist, while writes
|
|
1361
|
+
/// continue. The copy holds exactly the commits visible when this is called and opens
|
|
1362
|
+
/// on its own, without WAL replay or sidecar files. Visible is not durable: the copy can
|
|
1363
|
+
/// hold commits whose fsync had not finished, which a power loss then removes from this
|
|
1364
|
+
/// database (see the durability guide). The snapshot's memtables are written into the
|
|
1365
|
+
/// copy, and its SST and blob files are copied byte for byte: the copy is about the size
|
|
1366
|
+
/// of the live data, keeps the source's level shape, and holds a blob file only if the
|
|
1367
|
+
/// snapshot references a value in it.
|
|
1368
|
+
///
|
|
1369
|
+
/// ```
|
|
1370
|
+
/// use pigeonhole::{Family, Options, Pigeonhole};
|
|
1371
|
+
///
|
|
1372
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1373
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1374
|
+
/// let db = Pigeonhole::open(dir.join("app.phdb"), Options::default().shards(1))?;
|
|
1375
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
1376
|
+
/// t.mutate(b"row").put("f", b"q", b"v").commit()?;
|
|
1377
|
+
///
|
|
1378
|
+
/// let copy_path = dir.join("backup.phdb");
|
|
1379
|
+
/// db.backup(©_path)?;
|
|
1380
|
+
/// t.mutate(b"row").put("f", b"q", b"later").commit()?; // not in the backup
|
|
1381
|
+
///
|
|
1382
|
+
/// let copy = Pigeonhole::open(©_path, Options::default().shards(1).create_if_missing(false))?;
|
|
1383
|
+
/// let ct = copy.table("t")?.open()?;
|
|
1384
|
+
/// assert_eq!(ct.get(b"row", "f", b"q")?.unwrap().value(), b"v");
|
|
1385
|
+
/// # drop(ct);
|
|
1386
|
+
/// # copy.close()?;
|
|
1387
|
+
/// # drop(t);
|
|
1388
|
+
/// # db.close()?;
|
|
1389
|
+
/// # Ok(())
|
|
1390
|
+
/// # }
|
|
1391
|
+
/// ```
|
|
1392
|
+
pub fn backup(&self, dest: impl AsRef<Path>) -> Result<()> {
|
|
1393
|
+
self.db
|
|
1394
|
+
.retry_closed(|| self.engine().backup(dest.as_ref()).map_err(Error::from))
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
/// As [`backup`](Self::backup), at a durable snapshot (D227, ICR 0037): the copy holds
|
|
1398
|
+
/// only commits durable here at their level. A `GroupSync` or `Sync` commit it holds
|
|
1399
|
+
/// survives a power loss here; a `Buffered` or `None` one may not.
|
|
1400
|
+
pub fn backup_durable(&self, dest: impl AsRef<Path>) -> Result<()> {
|
|
1401
|
+
self.db.retry_closed(|| {
|
|
1402
|
+
self.engine()
|
|
1403
|
+
.backup_durable(dest.as_ref())
|
|
1404
|
+
.map_err(Error::from)
|
|
1405
|
+
})
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
/// Returns free space at the end of the file to the filesystem and reports the bytes
|
|
1409
|
+
/// released. The file never shrinks by itself: space freed by compaction or by deleting
|
|
1410
|
+
/// rows is reused by later writes, but the file keeps its length. Call this after a
|
|
1411
|
+
/// large delete followed by [`compact`](Self::compact) when you need
|
|
1412
|
+
/// the disk space back (for example before copying the file, or on a small device).
|
|
1413
|
+
///
|
|
1414
|
+
/// It cuts off the free space at the end of the file, moves the live data that sits past
|
|
1415
|
+
/// the point where the file could end into free space nearer the start, and truncates
|
|
1416
|
+
/// again. The cost is reading and rewriting that data (at most the live bytes in the
|
|
1417
|
+
/// file's tail) and a manifest commit per round, so run it rarely. It runs online: reads,
|
|
1418
|
+
/// writes, flushes and compactions continue on other threads, and in-flight flush or
|
|
1419
|
+
/// compaction output is never moved. It returns `0` when there is nothing to release,
|
|
1420
|
+
/// for example before `compact` has freed anything. Space still held by an open
|
|
1421
|
+
/// snapshot or scan, a backup in progress or a reader process's snapshot is not released
|
|
1422
|
+
/// until that handle is dropped. While one is held, `shrink` never grows the file, even
|
|
1423
|
+
/// for a while, and so may give back less; call it again afterwards for the rest.
|
|
1424
|
+
///
|
|
1425
|
+
/// The file can end no earlier than its live data packed toward the start. Data lives in
|
|
1426
|
+
/// extents of a power of two from 64 KiB to 64 MiB, each aligned to its size, and the
|
|
1427
|
+
/// first 64 KiB of the file is the header: a file holding one 64 MiB extent (a large
|
|
1428
|
+
/// SST) is at least 128 MiB, however little else it holds. Data with no free extent of
|
|
1429
|
+
/// its size below it stays where it is; that is not an error.
|
|
1430
|
+
///
|
|
1431
|
+
/// Errors: [`ErrorCode::Closed`](crate::ErrorCode::Closed) after `close`;
|
|
1432
|
+
/// [`ErrorCode::ReadOnly`](crate::ErrorCode::ReadOnly) if this handle cannot write;
|
|
1433
|
+
/// [`ErrorCode::NoSpace`](crate::ErrorCode::NoSpace) when the disk is full and moving
|
|
1434
|
+
/// the manifest needs the file to grow by its few KiB first (free space and retry);
|
|
1435
|
+
/// [`ErrorCode::Io`](crate::ErrorCode::Io) on a disk failure. A failed shrink loses no
|
|
1436
|
+
/// data; if it fails while committing the manifest, reopen the database.
|
|
1437
|
+
///
|
|
1438
|
+
/// ```
|
|
1439
|
+
/// use pigeonhole::{Durability, Family, Options, Pigeonhole};
|
|
1440
|
+
///
|
|
1441
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1442
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1443
|
+
/// let path = dir.join("app.phdb");
|
|
1444
|
+
/// let db = Pigeonhole::open(&path, Options::default().shards(1))?;
|
|
1445
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
1446
|
+
/// t.mutate(b"keep").put("f", b"q", b"v").commit()?;
|
|
1447
|
+
/// let junk = db.table("junk")?.family("f", Family::default()).create_if_missing()?;
|
|
1448
|
+
/// for i in 0..2_000u32 {
|
|
1449
|
+
/// junk.mutate(&i.to_be_bytes()).put("f", b"q", &[7u8; 512]).durability(Durability::None).commit()?;
|
|
1450
|
+
/// }
|
|
1451
|
+
/// db.flush()?;
|
|
1452
|
+
/// for i in 0..2_000u32 {
|
|
1453
|
+
/// junk.mutate(&i.to_be_bytes()).delete_row().durability(Durability::None).commit()?;
|
|
1454
|
+
/// }
|
|
1455
|
+
/// # drop(junk);
|
|
1456
|
+
/// db.compact()?;
|
|
1457
|
+
///
|
|
1458
|
+
/// let before = std::fs::metadata(&path).unwrap().len();
|
|
1459
|
+
/// let released = db.shrink()?;
|
|
1460
|
+
/// let after = std::fs::metadata(&path).unwrap().len();
|
|
1461
|
+
/// assert_eq!(before - after, released);
|
|
1462
|
+
/// assert_eq!(t.get(b"keep", "f", b"q")?.unwrap().value(), b"v");
|
|
1463
|
+
/// # drop(t);
|
|
1464
|
+
/// # db.close()?;
|
|
1465
|
+
/// # Ok(())
|
|
1466
|
+
/// # }
|
|
1467
|
+
/// ```
|
|
1468
|
+
pub fn shrink(&self) -> Result<u64> {
|
|
1469
|
+
self.db
|
|
1470
|
+
.retry_closed(|| self.engine().shrink().map_err(Error::from))
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/// Closes this handle's database. Flushes every memtable and checkpoints the WAL; if
|
|
1474
|
+
/// this is the last process with the database open, also removes the sidecar files and
|
|
1475
|
+
/// shared-memory region, leaving one file. Dropping the last clone does the same,
|
|
1476
|
+
/// ignoring errors.
|
|
1477
|
+
///
|
|
1478
|
+
/// A crash instead of a clean close leaves the sidecars; the next open replays them.
|
|
1479
|
+
/// Every handle derived from this database (tables, batches) fails with
|
|
1480
|
+
/// [`ErrorCode::Closed`](crate::ErrorCode::Closed) afterwards.
|
|
1481
|
+
pub fn close(self) -> Result<()> {
|
|
1482
|
+
self.db.generation.fetch_or(CLOSED, Ordering::Release);
|
|
1483
|
+
// A running recovery settles first (its swap, or its give-up; bounded by its own
|
|
1484
|
+
// deadline), so the engine closed is the one every handle ends on. A failure the
|
|
1485
|
+
// supervisor has not marked yet is not waited for (perf287's R5 on #836): the
|
|
1486
|
+
// supervisor, once it wakes, finds the handle closed and ends, so there is no
|
|
1487
|
+
// recovery to wait for, and this closes the failed engine as a close without the
|
|
1488
|
+
// option would (unclean; the next open replays the log).
|
|
1489
|
+
if let Some(sup) = self.db.supervision() {
|
|
1490
|
+
sup.wait_settled(self.db.stall_timeout().saturating_mul(5), || false);
|
|
1491
|
+
}
|
|
1492
|
+
let result = self.db.engine().close();
|
|
1493
|
+
if let Some(sup) = self.db.supervision() {
|
|
1494
|
+
sup.join();
|
|
1495
|
+
}
|
|
1496
|
+
Ok(result?)
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/// A read-only handle, typically in another process. Has no write methods, so misuse does
|
|
1501
|
+
/// not compile. Reads run on the caller's thread.
|
|
1502
|
+
///
|
|
1503
|
+
/// ```
|
|
1504
|
+
/// use pigeonhole::{Family, Options, Pigeonhole, ReaderOptions};
|
|
1505
|
+
///
|
|
1506
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1507
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1508
|
+
/// let path = dir.join("shared.phdb");
|
|
1509
|
+
/// let db = Pigeonhole::open(&path, Options::default().shards(1))?;
|
|
1510
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
1511
|
+
/// t.mutate(b"row").put("f", b"q", b"v").commit()?;
|
|
1512
|
+
///
|
|
1513
|
+
/// // Normally in another process.
|
|
1514
|
+
/// let reader = Pigeonhole::open_reader(&path, ReaderOptions::default())?;
|
|
1515
|
+
/// let rt = reader.table("t")?;
|
|
1516
|
+
/// assert_eq!(rt.get(b"row", "f", b"q")?.unwrap().value(), b"v");
|
|
1517
|
+
/// # drop(rt);
|
|
1518
|
+
/// # drop(reader);
|
|
1519
|
+
/// # drop(t);
|
|
1520
|
+
/// # db.close()?;
|
|
1521
|
+
/// # Ok(())
|
|
1522
|
+
/// # }
|
|
1523
|
+
/// ```
|
|
1524
|
+
#[derive(Debug, Clone)]
|
|
1525
|
+
pub struct PigeonholeReader {
|
|
1526
|
+
db: Arc<Db>,
|
|
1527
|
+
cached: Cached,
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
impl PigeonholeReader {
|
|
1531
|
+
#[inline]
|
|
1532
|
+
pub(crate) fn engine(&self) -> EngineRef<'_> {
|
|
1533
|
+
self.cached.get(&self.db)
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
impl PigeonholeReader {
|
|
1538
|
+
/// File reads made synchronously inside async reads since open (D196, #398): a
|
|
1539
|
+
/// separated value too large to cache, or a block the cache could not keep. Zero means
|
|
1540
|
+
/// no async read blocked its executor thread on the file.
|
|
1541
|
+
#[cfg(feature = "async")]
|
|
1542
|
+
pub fn async_sync_reads(&self) -> u64 {
|
|
1543
|
+
self.engine().metrics().async_sync_reads
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/// As [`Pigeonhole::io_rings`].
|
|
1547
|
+
pub fn io_rings(&self) -> Option<IoRings> {
|
|
1548
|
+
self.db.io_rings()
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
/// As [`Pigeonhole::info`], from the catalog the writer last published.
|
|
1552
|
+
/// [`DatabaseInfo::free_bytes`](crate::DatabaseInfo::free_bytes) is `None`: a reader
|
|
1553
|
+
/// does not track allocations.
|
|
1554
|
+
pub fn info(&self) -> Result<crate::DatabaseInfo> {
|
|
1555
|
+
Ok(crate::DatabaseInfo::from_engine(self.engine().info()?))
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
/// What this reader's row cache did since it last attached to a writer: hits, misses
|
|
1559
|
+
/// and fills (D281). All zero when
|
|
1560
|
+
/// [`ReaderOptions::row_cache`](crate::ReaderOptions::row_cache) is 0. A re-attach (the
|
|
1561
|
+
/// writer restarted or recovered) empties the cache and starts the counts again.
|
|
1562
|
+
pub fn row_cache_stats(&self) -> crate::RowCacheStats {
|
|
1563
|
+
crate::RowCacheStats::from_engine(&self.engine())
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
/// Opens an existing table for reading.
|
|
1567
|
+
pub fn table(&self, name: &str) -> Result<ReadTable> {
|
|
1568
|
+
let info = self
|
|
1569
|
+
.db
|
|
1570
|
+
.engine()
|
|
1571
|
+
.table(name)
|
|
1572
|
+
.ok_or_else(|| pigeonhole_engine::Error::TableNotFound(name.to_owned()))?;
|
|
1573
|
+
Ok(ReadTable {
|
|
1574
|
+
core: Arc::new(TableCore::new(
|
|
1575
|
+
Arc::clone(&self.db),
|
|
1576
|
+
info,
|
|
1577
|
+
self.cached.fresh(&self.db),
|
|
1578
|
+
)),
|
|
1579
|
+
})
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
/// Names of every table.
|
|
1583
|
+
pub fn tables(&self) -> Vec<String> {
|
|
1584
|
+
self.db
|
|
1585
|
+
.engine()
|
|
1586
|
+
.tables()
|
|
1587
|
+
.iter()
|
|
1588
|
+
.map(|t| t.name.clone())
|
|
1589
|
+
.collect()
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/// A consistent snapshot of what the writer has published. May do I/O: re-attach after
|
|
1593
|
+
/// a writer restart and reload the manifest if it changed. It sees commits once applied,
|
|
1594
|
+
/// possibly before their fsync (D227).
|
|
1595
|
+
pub fn snapshot(&self) -> Result<Snapshot> {
|
|
1596
|
+
self.db.snapshot(&self.cached)
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
/// A snapshot that sees only commits durable at their level (D227, ICR 0037), as
|
|
1600
|
+
/// [`Pigeonhole::durable_snapshot`]. May do I/O, as [`snapshot`](Self::snapshot).
|
|
1601
|
+
pub fn durable_snapshot(&self) -> Result<Snapshot> {
|
|
1602
|
+
self.db.durable_snapshot(&self.cached)
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
/// As [`Pigeonhole::backup`], from this reader process while the writer runs (ICR 0049):
|
|
1606
|
+
/// a consistent single-file copy of everything visible at a snapshot taken now. `dest`
|
|
1607
|
+
/// must not exist.
|
|
1608
|
+
///
|
|
1609
|
+
/// The snapshot's pin in shared memory covers the whole view, memtables included, so
|
|
1610
|
+
/// the writer frees none of that view's memtables until the copy is done (its own
|
|
1611
|
+
/// backup releases them after copying them): a long backup of a write-heavy database
|
|
1612
|
+
/// can fill the writer's memtable arenas, and its commits then wait, up to
|
|
1613
|
+
/// [`Options::write_stall_timeout`](crate::Options::write_stall_timeout). A writer
|
|
1614
|
+
/// restart while the copy runs fails it with
|
|
1615
|
+
/// [`ErrorCode::SnapshotExpired`](crate::ErrorCode::SnapshotExpired), removing the
|
|
1616
|
+
/// partial copy, even one during the copy's own final commit, when the data was
|
|
1617
|
+
/// complete.
|
|
1618
|
+
pub fn backup(&self, dest: impl AsRef<Path>) -> Result<()> {
|
|
1619
|
+
Ok(self.engine().backup(dest.as_ref())?)
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/// As [`PigeonholeReader::backup`], at a durable snapshot (as
|
|
1623
|
+
/// [`Pigeonhole::backup_durable`]): the copy holds only commits durable at their level.
|
|
1624
|
+
pub fn backup_durable(&self, dest: impl AsRef<Path>) -> Result<()> {
|
|
1625
|
+
Ok(self.engine().backup_durable(dest.as_ref())?)
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
/// A point-in-time view for reads. Holding it pins the data it can see; drop it promptly.
|
|
1630
|
+
///
|
|
1631
|
+
/// ```
|
|
1632
|
+
/// use pigeonhole::{Family, Options, Pigeonhole};
|
|
1633
|
+
///
|
|
1634
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1635
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1636
|
+
/// let db = Pigeonhole::open(dir.join("app.phdb"), Options::default().shards(1))?;
|
|
1637
|
+
/// let t = db.table("t")?.family("f", Family::default()).create_if_missing()?;
|
|
1638
|
+
/// t.mutate(b"row").put("f", b"q", b"old").commit()?;
|
|
1639
|
+
///
|
|
1640
|
+
/// let snap = db.snapshot()?;
|
|
1641
|
+
/// t.mutate(b"row").put("f", b"q", b"new").commit()?;
|
|
1642
|
+
///
|
|
1643
|
+
/// assert_eq!(t.get_at(&snap, b"row", "f", b"q")?.unwrap().value(), b"old");
|
|
1644
|
+
/// assert_eq!(t.get(b"row", "f", b"q")?.unwrap().value(), b"new");
|
|
1645
|
+
/// drop(snap);
|
|
1646
|
+
/// # drop(t);
|
|
1647
|
+
/// # db.close()?;
|
|
1648
|
+
/// # Ok(())
|
|
1649
|
+
/// # }
|
|
1650
|
+
/// ```
|
|
1651
|
+
#[derive(Debug, Clone)]
|
|
1652
|
+
pub struct Snapshot {
|
|
1653
|
+
pub(crate) inner: pigeonhole_engine::Snapshot,
|
|
1654
|
+
/// The database it was taken from (weak: a snapshot does not keep the database open).
|
|
1655
|
+
db: Weak<Db>,
|
|
1656
|
+
/// The engine generation it was taken in (D265): reads through it fail with
|
|
1657
|
+
/// `SnapshotExpired` once the database recovered onto a newer engine.
|
|
1658
|
+
generation: u64,
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
impl Snapshot {
|
|
1662
|
+
/// The snapshot's sequence number.
|
|
1663
|
+
pub fn seqno(&self) -> u64 {
|
|
1664
|
+
self.inner.seqno()
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
/// What [`Pigeonhole::open_application_owned`] hands you: the database, its shards and its
|
|
1669
|
+
/// background workers (D284; none unless [`Options::background_workers`] asks for them). Move the shards and workers out to the threads that
|
|
1670
|
+
/// drive them.
|
|
1671
|
+
#[derive(Debug)]
|
|
1672
|
+
#[non_exhaustive]
|
|
1673
|
+
pub struct AppOwned {
|
|
1674
|
+
/// The database.
|
|
1675
|
+
pub db: Pigeonhole,
|
|
1676
|
+
/// One per shard, to drive as [`Pigeonhole::open_application_owned`] describes.
|
|
1677
|
+
pub shards: Vec<Shard>,
|
|
1678
|
+
/// [`Options::background_workers`] of them, for flush and compaction.
|
|
1679
|
+
pub workers: Vec<BackgroundWorker>,
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
impl AppOwned {
|
|
1683
|
+
/// Gives each background worker a thread of its own (named `pigeonhole-worker-<i>`),
|
|
1684
|
+
/// which drives it until the database's close finishes and then ends. Takes the workers
|
|
1685
|
+
/// out of [`workers`](Self::workers); join the handles after [`Pigeonhole::close`].
|
|
1686
|
+
///
|
|
1687
|
+
/// For an application that wants its shards on its own threads but has no use for the
|
|
1688
|
+
/// background work's: the workers' threads sleep while there is no flush or compaction.
|
|
1689
|
+
///
|
|
1690
|
+
/// # Errors
|
|
1691
|
+
/// [`ErrorCode::Io`](crate::ErrorCode::Io) when the operating system refuses a thread
|
|
1692
|
+
/// (a thread limit, a container's pids cap). The workers that got no thread are back in
|
|
1693
|
+
/// [`workers`](Self::workers), to drive yourself or drop; those already started keep
|
|
1694
|
+
/// running, and their handles are lost with the error, so join nothing: they end at the
|
|
1695
|
+
/// close.
|
|
1696
|
+
pub fn spawn_background_threads(&mut self) -> Result<Vec<std::thread::JoinHandle<()>>> {
|
|
1697
|
+
let mut handles = Vec::with_capacity(self.workers.len());
|
|
1698
|
+
let mut workers = std::mem::take(&mut self.workers).into_iter().enumerate();
|
|
1699
|
+
while let Some((i, worker)) = workers.next() {
|
|
1700
|
+
// The worker reaches its thread only once the thread exists: a refused spawn
|
|
1701
|
+
// leaves it here to hand back.
|
|
1702
|
+
let (tx, rx) = std::sync::mpsc::channel::<BackgroundWorker>();
|
|
1703
|
+
let spawned = std::thread::Builder::new()
|
|
1704
|
+
.name(format!("pigeonhole-worker-{i}"))
|
|
1705
|
+
.spawn(move || {
|
|
1706
|
+
let Ok(mut worker) = rx.recv() else {
|
|
1707
|
+
return;
|
|
1708
|
+
};
|
|
1709
|
+
while !worker.closed() {
|
|
1710
|
+
while worker.run_once(Duration::from_millis(1)) {}
|
|
1711
|
+
// Wakes for new work, the next deadline, or the close.
|
|
1712
|
+
worker.wait(Duration::from_secs(1));
|
|
1713
|
+
}
|
|
1714
|
+
});
|
|
1715
|
+
match spawned {
|
|
1716
|
+
Ok(handle) => {
|
|
1717
|
+
// The thread holds `rx` until it receives.
|
|
1718
|
+
let _ = tx.send(worker);
|
|
1719
|
+
handles.push(handle);
|
|
1720
|
+
}
|
|
1721
|
+
Err(e) => {
|
|
1722
|
+
self.workers.push(worker);
|
|
1723
|
+
self.workers.extend(workers.map(|(_, w)| w));
|
|
1724
|
+
return Err(Error::new(
|
|
1725
|
+
crate::ErrorCode::Io,
|
|
1726
|
+
format!("could not start background worker thread {i}: {e}"),
|
|
1727
|
+
));
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
Ok(handles)
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
/// A background worker in application-owned mode (D284): it runs flushes and compactions
|
|
1736
|
+
/// for every shard. Drive it from any thread with [`run_once`](Self::run_once), as you drive
|
|
1737
|
+
/// a [`Shard`]. See [`Pigeonhole::open_application_owned`].
|
|
1738
|
+
///
|
|
1739
|
+
/// Dropping it before the close hands what it holds back to the shards, which run it.
|
|
1740
|
+
#[derive(Debug)]
|
|
1741
|
+
pub struct BackgroundWorker {
|
|
1742
|
+
inner: pigeonhole_engine::BackgroundWorker,
|
|
1743
|
+
vfs: VfsRef,
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
impl BackgroundWorker {
|
|
1747
|
+
/// Runs flush and compaction slices for up to `budget`. Returns whether work remains.
|
|
1748
|
+
///
|
|
1749
|
+
/// A worker takes flushes ahead of compactions, and at most two tasks at a time; the
|
|
1750
|
+
/// others stay queued for the other workers. Its I/O completes inside the call, so the
|
|
1751
|
+
/// worker holds none in flight between calls and may move to another thread at any time.
|
|
1752
|
+
/// After the close it does nothing and returns `false`.
|
|
1753
|
+
pub fn run_once(&mut self, budget: Duration) -> bool {
|
|
1754
|
+
let budget = u64::try_from(budget.as_nanos()).unwrap_or(u64::MAX);
|
|
1755
|
+
let deadline = self.vfs.monotonic_nanos().saturating_add(budget);
|
|
1756
|
+
self.inner.run_once(deadline)
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
/// How long until a task this worker holds is due (one sleeping until a time), or
|
|
1760
|
+
/// `None` when none is. After [`run_once`](Self::run_once) returns `false`, sleep until
|
|
1761
|
+
/// the [`set_wakeup`](Self::set_wakeup) callback fires or this much time passes.
|
|
1762
|
+
pub fn next_wakeup(&self) -> Option<Duration> {
|
|
1763
|
+
let deadline = self.inner.next_deadline()?;
|
|
1764
|
+
let now = self.vfs.monotonic_nanos();
|
|
1765
|
+
Some(Duration::from_nanos(deadline.saturating_sub(now)))
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
/// Waits until this worker has work again, a task it holds falls due, the database
|
|
1769
|
+
/// closes, or `timeout` passes. It may return early: loop on [`run_once`](Self::run_once).
|
|
1770
|
+
pub fn wait(&mut self, timeout: Duration) {
|
|
1771
|
+
self.inner.wait(timeout);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
/// A waker that ends this worker's [`wait`](Self::wait) from any thread.
|
|
1775
|
+
pub fn waker(&self) -> std::task::Waker {
|
|
1776
|
+
self.inner.waker()
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
/// Registers a callback run (on another thread) when work arrives for this worker or the
|
|
1780
|
+
/// database closes: wake the thread that drives it. Called once right away. Keep it short
|
|
1781
|
+
/// and non-blocking.
|
|
1782
|
+
pub fn set_wakeup(&mut self, wake: Box<dyn Fn() + Send + Sync>) {
|
|
1783
|
+
self.inner.set_wakeup(wake);
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
/// Whether the database's close has taken this worker's tasks back: from then on it has
|
|
1787
|
+
/// nothing to do, and can be dropped.
|
|
1788
|
+
pub fn closed(&self) -> bool {
|
|
1789
|
+
self.inner.closed()
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
/// One shard in application-owned mode. Move it to the thread that should run it and call
|
|
1794
|
+
/// [`Shard::run_once`] from that thread's event loop.
|
|
1795
|
+
///
|
|
1796
|
+
/// See [`Pigeonhole::open_application_owned`] for an example.
|
|
1797
|
+
#[derive(Debug)]
|
|
1798
|
+
pub struct Shard {
|
|
1799
|
+
inner: EngineShard,
|
|
1800
|
+
vfs: VfsRef,
|
|
1801
|
+
/// The application asked for [`Shard::io_fd`] and got one, so it waits on it: then
|
|
1802
|
+
/// `next_wakeup` need not report in-flight I/O as due now (#408).
|
|
1803
|
+
io_fd_used: std::sync::atomic::AtomicBool,
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
impl Shard {
|
|
1807
|
+
/// Shard index.
|
|
1808
|
+
pub fn index(&self) -> usize {
|
|
1809
|
+
usize::from(self.inner.index())
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
/// Call before handing this shard to another thread: drives it until the calling
|
|
1813
|
+
/// thread has none of its I/O in flight (#492, ICR 0029).
|
|
1814
|
+
///
|
|
1815
|
+
/// With io_uring (the default on Linux, D218) in application-owned mode each
|
|
1816
|
+
/// driving thread has its own I/O ring, and only that thread can complete what was
|
|
1817
|
+
/// submitted to it. A shard moved with I/O still on the old thread's ring would wait on
|
|
1818
|
+
/// it for ever once that thread stops running turns. So: `release()` on the old thread,
|
|
1819
|
+
/// then move the shard, and take [`io_fd`](Shard::io_fd) again on the new thread (the
|
|
1820
|
+
/// descriptor belongs to the thread's ring).
|
|
1821
|
+
///
|
|
1822
|
+
/// A no-op on the pread backend (completions arrive on its pool threads) and in
|
|
1823
|
+
/// engine-owned mode (shards never move). Debug builds panic when a shard turns up on
|
|
1824
|
+
/// another thread with I/O left on the old one unreleased.
|
|
1825
|
+
///
|
|
1826
|
+
/// ```
|
|
1827
|
+
/// use pigeonhole::{Options, Pigeonhole};
|
|
1828
|
+
///
|
|
1829
|
+
/// let dir = std::env::temp_dir().join(format!("phdb-release-{}", std::process::id()));
|
|
1830
|
+
/// std::fs::create_dir_all(&dir).unwrap();
|
|
1831
|
+
/// let pigeonhole::AppOwned { db, mut shards, .. } =
|
|
1832
|
+
/// Pigeonhole::open_application_owned(dir.join("db.phdb"), Options::default().shards(1))?;
|
|
1833
|
+
/// let mut shard = shards.pop().unwrap();
|
|
1834
|
+
/// shard.run_once(std::time::Duration::from_millis(1));
|
|
1835
|
+
/// // Hand the shard to another thread.
|
|
1836
|
+
/// shard.release();
|
|
1837
|
+
/// let driver = std::thread::spawn(move || {
|
|
1838
|
+
/// while shard.closed().is_none() {
|
|
1839
|
+
/// shard.run_once(std::time::Duration::from_millis(1));
|
|
1840
|
+
/// }
|
|
1841
|
+
/// });
|
|
1842
|
+
/// db.close()?;
|
|
1843
|
+
/// driver.join().unwrap();
|
|
1844
|
+
/// # let _ = std::fs::remove_dir_all(&dir);
|
|
1845
|
+
/// # Ok::<(), pigeonhole::Error>(())
|
|
1846
|
+
/// ```
|
|
1847
|
+
pub fn release(&mut self) {
|
|
1848
|
+
self.inner.release();
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
/// Runs queued writes, group commit and background work for up to `budget`. Returns
|
|
1852
|
+
/// whether work remains.
|
|
1853
|
+
///
|
|
1854
|
+
/// A call first handles the queued messages (up to 1,024) and commits them as one group,
|
|
1855
|
+
/// whatever `budget` says. Then it runs background work (flush, compaction, the tablet
|
|
1856
|
+
/// balancer) in slices of at most 500 µs until `budget` is spent, handling newly queued
|
|
1857
|
+
/// messages between slices.
|
|
1858
|
+
///
|
|
1859
|
+
/// Background work waiting for a time (a write stall's pacing, a wait for memtable room,
|
|
1860
|
+
/// a failed compaction's retry, the tablet balancer's next pass) is not work that
|
|
1861
|
+
/// remains: with only that left it returns `false`, and
|
|
1862
|
+
/// [`next_wakeup`](Shard::next_wakeup) says when to call it again. The callback
|
|
1863
|
+
/// registered with [`set_wakeup`](Shard::set_wakeup) does not fire for it.
|
|
1864
|
+
///
|
|
1865
|
+
/// A call that completed a future woken through [`waker`](Shard::waker) (a commit this
|
|
1866
|
+
/// thread awaits) returns `true` before its background work, so the loop can poll that
|
|
1867
|
+
/// future sooner; the background work runs on the next call, and at the latest every
|
|
1868
|
+
/// ninth (D237).
|
|
1869
|
+
pub fn run_once(&mut self, budget: std::time::Duration) -> bool {
|
|
1870
|
+
let budget = u64::try_from(budget.as_nanos()).unwrap_or(u64::MAX);
|
|
1871
|
+
let deadline = self.vfs.monotonic_nanos().saturating_add(budget);
|
|
1872
|
+
self.inner.run_once(deadline)
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
/// How long until background work on this shard is due (a write stall's pacing, a wait
|
|
1876
|
+
/// for memtable room, a failed compaction's retry, the tablet balancer's next pass), or
|
|
1877
|
+
/// `None` when none is waiting for a time. `Some(Duration::ZERO)` means it is due now.
|
|
1878
|
+
/// The tablet balancer's next pass is always pending, so this is never `None`; it is
|
|
1879
|
+
/// bounded by the balancer's current interval:
|
|
1880
|
+
/// 100 ms after a write or a tablet change, doubling with each idle pass up to 10 s.
|
|
1881
|
+
///
|
|
1882
|
+
/// With io_uring (the default on Linux, D218), I/O the shard submitted goes to
|
|
1883
|
+
/// a ring of the thread that drives it and completes only when that thread runs a shard
|
|
1884
|
+
/// again, so this is `Some(Duration::ZERO)` while any is in flight (#402), unless the
|
|
1885
|
+
/// application waits on [`io_fd`](Shard::io_fd), which turns readable when some has
|
|
1886
|
+
/// finished: once `io_fd` has returned a descriptor, in-flight I/O no longer counts as due
|
|
1887
|
+
/// (#408).
|
|
1888
|
+
///
|
|
1889
|
+
/// After [`run_once`](Shard::run_once) returns `false`, sleep until the
|
|
1890
|
+
/// [`set_wakeup`](Shard::set_wakeup) callback fires or this much time passes, whichever
|
|
1891
|
+
/// comes first, then call `run_once` again. See [`Pigeonhole::open_application_owned`]
|
|
1892
|
+
/// for the loop.
|
|
1893
|
+
///
|
|
1894
|
+
/// ```
|
|
1895
|
+
/// use std::time::Duration;
|
|
1896
|
+
/// use pigeonhole::{Options, Pigeonhole};
|
|
1897
|
+
///
|
|
1898
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1899
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1900
|
+
/// let pigeonhole::AppOwned { db, mut shards, .. } = Pigeonhole::open_application_owned(dir.join("w.phdb"), Options::default().shards(1))?;
|
|
1901
|
+
/// let shard = &mut shards[0];
|
|
1902
|
+
/// while shard.run_once(Duration::from_micros(200)) {}
|
|
1903
|
+
/// // Idle: only the tablet balancer's next pass is waiting for a time (at most 10 s).
|
|
1904
|
+
/// assert!(shard.next_wakeup().is_some_and(|d| d <= Duration::from_secs(10)));
|
|
1905
|
+
/// db.close()?;
|
|
1906
|
+
/// // This thread drives the shard, so `close` cannot wait: drive it until it has closed
|
|
1907
|
+
/// // (a real loop sleeps between calls as above).
|
|
1908
|
+
/// while shard.closed().is_none() {
|
|
1909
|
+
/// shard.run_once(Duration::from_micros(200));
|
|
1910
|
+
/// }
|
|
1911
|
+
/// shard.closed().unwrap()?;
|
|
1912
|
+
/// # Ok(())
|
|
1913
|
+
/// # }
|
|
1914
|
+
/// ```
|
|
1915
|
+
pub fn next_wakeup(&self) -> Option<std::time::Duration> {
|
|
1916
|
+
// I/O on this thread's own ring (`IoBackend::Uring`, #402) completes only when the
|
|
1917
|
+
// thread runs a shard again: due now while any is in flight, unless the thread has a
|
|
1918
|
+
// completion fd to wait on (`io_fd`, #408).
|
|
1919
|
+
// An application that never asked for the fd keeps polling (a loop that only sleeps
|
|
1920
|
+
// for `next_wakeup` would otherwise sleep through its own I/O).
|
|
1921
|
+
if pigeonhole_io::own_io_in_flight()
|
|
1922
|
+
&& !(self.io_fd_used.load(std::sync::atomic::Ordering::Relaxed)
|
|
1923
|
+
&& pigeonhole_io::own_io_fd().is_some())
|
|
1924
|
+
{
|
|
1925
|
+
return Some(std::time::Duration::ZERO);
|
|
1926
|
+
}
|
|
1927
|
+
let deadline = self.inner.next_deadline()?;
|
|
1928
|
+
let now = self.vfs.monotonic_nanos();
|
|
1929
|
+
Some(std::time::Duration::from_nanos(
|
|
1930
|
+
deadline.saturating_sub(now),
|
|
1931
|
+
))
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
/// The database's close result once the close has finished (every shard closed, and the
|
|
1935
|
+
/// clean close recorded), or `None` before (including before [`Pigeonhole::close`]).
|
|
1936
|
+
/// After `close`, keep driving the shard until this is `Some`, then drop it. Every shard
|
|
1937
|
+
/// reports the same result.
|
|
1938
|
+
pub fn closed(&self) -> Option<Result<()>> {
|
|
1939
|
+
self.inner.closed().map(|r| r.map_err(Into::into))
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
/// A file descriptor that turns readable when I/O this thread submitted has finished and
|
|
1943
|
+
/// waits for [`run_once`](Shard::run_once) to complete it (#408), for an application
|
|
1944
|
+
/// that waits in its own event loop: wait until it is readable, the
|
|
1945
|
+
/// [`set_wakeup`](Shard::set_wakeup) callback fires, or [`next_wakeup`](Shard::next_wakeup)
|
|
1946
|
+
/// passes, then call `run_once`, which resets it. Call it on the thread that drives the
|
|
1947
|
+
/// shard, after its first `run_once`. Asking for it is the opt-in: from then on
|
|
1948
|
+
/// `next_wakeup` no longer reports this thread's in-flight I/O as due now, so a loop that
|
|
1949
|
+
/// takes the descriptor must wait on it. `None` where that thread has none: with
|
|
1950
|
+
/// [`IoBackend::Pread`](crate::IoBackend::Pread), on systems without io_uring, or with a
|
|
1951
|
+
/// custom VFS. A thread that drives several shards gets the same descriptor from each.
|
|
1952
|
+
///
|
|
1953
|
+
/// ```no_run
|
|
1954
|
+
/// use std::time::Duration;
|
|
1955
|
+
/// use pigeonhole::{IoBackend, Options, Pigeonhole};
|
|
1956
|
+
///
|
|
1957
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1958
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1959
|
+
/// let options = Options::default().shards(1).io_backend(IoBackend::Auto);
|
|
1960
|
+
/// let pigeonhole::AppOwned { db, mut shards, .. } = Pigeonhole::open_application_owned(dir.join("w.phdb"), options)?;
|
|
1961
|
+
/// let shard = &mut shards[0];
|
|
1962
|
+
/// while shard.run_once(Duration::from_micros(200)) {}
|
|
1963
|
+
/// if let Some(fd) = shard.io_fd() {
|
|
1964
|
+
/// // Add `fd` (readable) to the loop's poll set, with `next_wakeup` as the timeout.
|
|
1965
|
+
/// # let _ = fd;
|
|
1966
|
+
/// }
|
|
1967
|
+
/// # drop(db);
|
|
1968
|
+
/// # Ok(())
|
|
1969
|
+
/// # }
|
|
1970
|
+
/// ```
|
|
1971
|
+
pub fn io_fd(&self) -> Option<i32> {
|
|
1972
|
+
let fd = pigeonhole_io::own_io_fd();
|
|
1973
|
+
if fd.is_some() {
|
|
1974
|
+
self.io_fd_used
|
|
1975
|
+
.store(true, std::sync::atomic::Ordering::Relaxed);
|
|
1976
|
+
}
|
|
1977
|
+
fd
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
/// Waits until this shard has work again: a commit or message arrives for it, a
|
|
1981
|
+
/// [`waker`](Shard::waker) fires, I/O this thread submitted completes, background work
|
|
1982
|
+
/// falls due ([`next_wakeup`](Shard::next_wakeup)), or `timeout` passes (#553). The loop
|
|
1983
|
+
/// for one shard per thread:
|
|
1984
|
+
///
|
|
1985
|
+
/// ```
|
|
1986
|
+
/// use std::time::Duration;
|
|
1987
|
+
/// use pigeonhole::{Options, Pigeonhole};
|
|
1988
|
+
///
|
|
1989
|
+
/// # fn main() -> pigeonhole::Result<()> {
|
|
1990
|
+
/// # let dir = pigeonhole::doc_support::temp_dir();
|
|
1991
|
+
/// let pigeonhole::AppOwned { db, mut shards, .. } =
|
|
1992
|
+
/// Pigeonhole::open_application_owned(dir.join("w.phdb"), Options::default().shards(1))?;
|
|
1993
|
+
/// let shard = &mut shards[0];
|
|
1994
|
+
/// for _ in 0..3 {
|
|
1995
|
+
/// while shard.run_once(Duration::from_micros(200)) {}
|
|
1996
|
+
/// // Poll your own futures here, with `shard.waker()` as their waker.
|
|
1997
|
+
/// shard.wait(Duration::from_millis(10));
|
|
1998
|
+
/// }
|
|
1999
|
+
/// db.close()?;
|
|
2000
|
+
/// while shard.closed().is_none() {
|
|
2001
|
+
/// shard.run_once(Duration::from_micros(200));
|
|
2002
|
+
/// }
|
|
2003
|
+
/// # Ok(())
|
|
2004
|
+
/// # }
|
|
2005
|
+
/// ```
|
|
2006
|
+
///
|
|
2007
|
+
/// Call it on the thread that drives the shard, after [`run_once`](Shard::run_once)
|
|
2008
|
+
/// returns `false`. It may return early, so loop on `run_once`. It needs no completion fd
|
|
2009
|
+
/// and works on every backend: with io_uring it waits in the thread's ring while its own
|
|
2010
|
+
/// I/O is in flight, and parks otherwise. The [`set_wakeup`](Shard::set_wakeup) callback
|
|
2011
|
+
/// still fires. A thread that drives several shards, or waits on other sources too,
|
|
2012
|
+
/// uses its own event loop instead: [`io_fd`](Shard::io_fd), `set_wakeup` and
|
|
2013
|
+
/// `next_wakeup`.
|
|
2014
|
+
pub fn wait(&mut self, timeout: std::time::Duration) {
|
|
2015
|
+
self.inner.wait(timeout);
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
/// A waker that ends this shard's [`wait`](Shard::wait) from any thread. Give it to the
|
|
2019
|
+
/// futures the driving thread polls itself (`commit_async` and the other async calls):
|
|
2020
|
+
/// a commit can complete on another shard's thread, and its wake must reach this one.
|
|
2021
|
+
pub fn waker(&self) -> std::task::Waker {
|
|
2022
|
+
self.inner.waker()
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
/// Registers a callback invoked (from any thread) when work arrives for this shard. It
|
|
2026
|
+
/// does not fire when background work falls due: see [`next_wakeup`](Shard::next_wakeup).
|
|
2027
|
+
pub fn set_wakeup(&mut self, wake: Box<dyn Fn() + Send + Sync>) {
|
|
2028
|
+
self.inner.set_wakeup(wake);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
/// The shared-memory region a writer open creates, kept to explain `ShmUnavailable`: what it
|
|
2033
|
+
/// needed, where, and how to make it fit.
|
|
2034
|
+
struct ShmFootprint {
|
|
2035
|
+
shards: u64,
|
|
2036
|
+
budget: u64,
|
|
2037
|
+
/// The whole region: every arena (each rounded up to 2 MiB) plus the header, the two view
|
|
2038
|
+
/// buffers, the reader slots and the row-epoch table, laid out as the engine lays it out.
|
|
2039
|
+
region_len: u64,
|
|
2040
|
+
dir: Option<std::path::PathBuf>,
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
impl ShmFootprint {
|
|
2044
|
+
fn of(o: &pigeonhole_engine::EngineOptions) -> Self {
|
|
2045
|
+
// As the engine resolves it: 0 shards means one per physical core (D220).
|
|
2046
|
+
let shards = match o.shards {
|
|
2047
|
+
0 => pigeonhole_io::sys::default_shards(),
|
|
2048
|
+
n => n,
|
|
2049
|
+
};
|
|
2050
|
+
let count = u32::try_from(shards).unwrap_or(u32::MAX);
|
|
2051
|
+
let config = pigeonhole_shm::ShmConfig::new(count);
|
|
2052
|
+
let layout = pigeonhole_format::shm::ShmHeader::layout(
|
|
2053
|
+
[0; 16],
|
|
2054
|
+
count,
|
|
2055
|
+
o.reader_slots.max(1),
|
|
2056
|
+
config.view_buffer_bytes,
|
|
2057
|
+
o.memtable_budget,
|
|
2058
|
+
pigeonhole_engine::row_epoch_slots(o.row_cache_bytes),
|
|
2059
|
+
0,
|
|
2060
|
+
0,
|
|
2061
|
+
);
|
|
2062
|
+
Self {
|
|
2063
|
+
shards: shards as u64,
|
|
2064
|
+
budget: o.memtable_budget,
|
|
2065
|
+
region_len: layout.region_len,
|
|
2066
|
+
dir: o.shm_dir.clone(),
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
/// `e` as an [`Error`], with the footprint and remedies when it is `ShmUnavailable`.
|
|
2071
|
+
fn explain(&self, e: pigeonhole_engine::Error) -> Error {
|
|
2072
|
+
if !matches!(e, pigeonhole_engine::Error::ShmUnavailable) {
|
|
2073
|
+
return e.into();
|
|
2074
|
+
}
|
|
2075
|
+
let arenas = self.shards.saturating_mul(self.budget);
|
|
2076
|
+
let need = format!(
|
|
2077
|
+
"{} ({} shards × {} memtable_budget, plus {} for views, reader slots and row epochs)",
|
|
2078
|
+
bytes(self.region_len),
|
|
2079
|
+
self.shards,
|
|
2080
|
+
bytes(self.budget),
|
|
2081
|
+
bytes(self.region_len.saturating_sub(arenas)),
|
|
2082
|
+
);
|
|
2083
|
+
let fix = "or lower Options::memtable_budget or Options::shards";
|
|
2084
|
+
let message = match &self.dir {
|
|
2085
|
+
Some(dir) => format!(
|
|
2086
|
+
"the shared-memory region could not be created in {}: it needs {need}. The \
|
|
2087
|
+
directory must exist and have that much free space; free some, point \
|
|
2088
|
+
Options::shm_dir at a larger one, {fix}",
|
|
2089
|
+
dir.display()
|
|
2090
|
+
),
|
|
2091
|
+
None if cfg!(any(target_os = "linux", target_os = "android")) => format!(
|
|
2092
|
+
"the shared-memory region could not be created in /dev/shm: it needs {need}, \
|
|
2093
|
+
and /dev/shm is too small or missing (Docker and Kubernetes default it to 64 \
|
|
2094
|
+
MiB). Enlarge it (docker run --shm-size; in Kubernetes, mount an emptyDir \
|
|
2095
|
+
with medium: Memory at /dev/shm), point Options::shm_dir at a larger tmpfs, \
|
|
2096
|
+
{fix}"
|
|
2097
|
+
),
|
|
2098
|
+
None => format!(
|
|
2099
|
+
"the shared-memory region could not be created: it needs {need} of shared \
|
|
2100
|
+
memory, more than the system would commit. Free memory, point \
|
|
2101
|
+
Options::shm_dir at a directory with room, {fix}"
|
|
2102
|
+
),
|
|
2103
|
+
};
|
|
2104
|
+
Error::new(ErrorCode::ShmUnavailable, message)
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
/// `n` bytes in MiB when whole, else KiB (rounded up).
|
|
2109
|
+
fn bytes(n: u64) -> String {
|
|
2110
|
+
if n.is_multiple_of(1 << 20) {
|
|
2111
|
+
format!("{} MiB", n >> 20)
|
|
2112
|
+
} else {
|
|
2113
|
+
format!("{} KiB", n.div_ceil(1 << 10))
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
/// The largest value a commit carries inline (decision D16), as `pigeonhole-engine` computes
|
|
2118
|
+
/// it at open: the WAL segment payload, 64 MiB, and half a shard's memtable arena. A longer
|
|
2119
|
+
/// put is separated into a blob file at commit time; a longer merge operand is refused.
|
|
2120
|
+
fn max_value(o: &pigeonhole_engine::EngineOptions) -> usize {
|
|
2121
|
+
(o.wal.segment_size as usize)
|
|
2122
|
+
.saturating_sub(64 * 1024)
|
|
2123
|
+
.min(64 << 20)
|
|
2124
|
+
.min((o.memtable_budget / 2) as usize)
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
#[cfg(test)]
|
|
2128
|
+
mod tests {
|
|
2129
|
+
use super::*;
|
|
2130
|
+
use std::sync::mpsc;
|
|
2131
|
+
use std::time::Instant;
|
|
2132
|
+
|
|
2133
|
+
/// D265 (perf287's R5 on #836): a `close()` that reaches a failed engine before the
|
|
2134
|
+
/// supervisor marked the failure does not wait for a recovery that never starts (the
|
|
2135
|
+
/// supervisor finds the handle closed and ends). It closes the failed engine as a close
|
|
2136
|
+
/// without the option would, and returns well under the stall timeout; the next open
|
|
2137
|
+
/// replays the log. The supervisor is held on its wake by a test hook, so the close
|
|
2138
|
+
/// wins the race for certain.
|
|
2139
|
+
#[test]
|
|
2140
|
+
fn a_close_racing_an_unmarked_failure_closes_the_failed_engine_at_once() {
|
|
2141
|
+
let vfs: VfsRef = pigeonhole_io::sim::SimVfs::new(2651);
|
|
2142
|
+
let options = Options::default()
|
|
2143
|
+
.vfs(Arc::clone(&vfs))
|
|
2144
|
+
.shards(1)
|
|
2145
|
+
.pin_threads(false)
|
|
2146
|
+
.write_stall_timeout(Duration::from_secs(10))
|
|
2147
|
+
.auto_recover(crate::Recovery::Any);
|
|
2148
|
+
let path = Path::new("/db/race.phdb");
|
|
2149
|
+
let db = Pigeonhole::open(path, options.clone()).unwrap();
|
|
2150
|
+
let t = db
|
|
2151
|
+
.table("t")
|
|
2152
|
+
.unwrap()
|
|
2153
|
+
.family("f", crate::Family::default())
|
|
2154
|
+
.create_if_missing()
|
|
2155
|
+
.unwrap();
|
|
2156
|
+
for i in 0..8u8 {
|
|
2157
|
+
t.mutate(&[b'r', i]).put("f", b"q", b"v").commit().unwrap();
|
|
2158
|
+
}
|
|
2159
|
+
// The supervisor, woken by the failure, is held before it looks at it.
|
|
2160
|
+
let (entered_tx, entered_rx) = mpsc::channel();
|
|
2161
|
+
let (go_tx, go_rx) = mpsc::channel::<()>();
|
|
2162
|
+
let engine = db.engine().to_arc();
|
|
2163
|
+
engine.on_next(
|
|
2164
|
+
pigeonhole_engine::HookSite::FailureWake,
|
|
2165
|
+
Box::new(move || {
|
|
2166
|
+
let _ = entered_tx.send(());
|
|
2167
|
+
let _ = go_rx.recv();
|
|
2168
|
+
}),
|
|
2169
|
+
);
|
|
2170
|
+
// The next apply fails after its WAL append: the shard poisons itself (its record
|
|
2171
|
+
// replays at the next open) and the commit gets `OutcomeUnknown`.
|
|
2172
|
+
engine.inject(pigeonhole_engine::Fault::NextApply, true);
|
|
2173
|
+
let e = t
|
|
2174
|
+
.mutate(b"unknown")
|
|
2175
|
+
.put("f", b"q", b"v")
|
|
2176
|
+
.commit()
|
|
2177
|
+
.unwrap_err();
|
|
2178
|
+
assert_eq!(e.code(), crate::ErrorCode::OutcomeUnknown);
|
|
2179
|
+
entered_rx
|
|
2180
|
+
.recv_timeout(Duration::from_secs(10))
|
|
2181
|
+
.expect("the supervisor woke on the failure");
|
|
2182
|
+
assert!(db.is_failed());
|
|
2183
|
+
// `close()` on its own thread (it joins the supervisor at its end): once it has
|
|
2184
|
+
// marked the handle closed, the supervisor is let go, finds the handle closed and
|
|
2185
|
+
// ends without marking the failure.
|
|
2186
|
+
let inner = Arc::clone(&db.db);
|
|
2187
|
+
let closer = std::thread::spawn(move || {
|
|
2188
|
+
let started = Instant::now();
|
|
2189
|
+
(db.close(), started.elapsed())
|
|
2190
|
+
});
|
|
2191
|
+
while !inner.is_closed() {
|
|
2192
|
+
std::thread::sleep(Duration::from_millis(1));
|
|
2193
|
+
}
|
|
2194
|
+
let _ = go_tx.send(());
|
|
2195
|
+
let (result, took) = closer.join().unwrap();
|
|
2196
|
+
assert!(
|
|
2197
|
+
took < Duration::from_secs(2),
|
|
2198
|
+
"the close took {took:?} ({result:?}); it must not wait for a recovery"
|
|
2199
|
+
);
|
|
2200
|
+
drop(t);
|
|
2201
|
+
// The next open replays the log: every row, the unknown commit's included.
|
|
2202
|
+
let db = Pigeonhole::open(path, options.auto_recover(crate::Recovery::Off)).unwrap();
|
|
2203
|
+
let t = db.table("t").unwrap().open().unwrap();
|
|
2204
|
+
for i in 0..8u8 {
|
|
2205
|
+
assert!(t.get(&[b'r', i], "f", b"q").unwrap().is_some(), "row {i}");
|
|
2206
|
+
}
|
|
2207
|
+
assert!(t.get(b"unknown", "f", b"q").unwrap().is_some());
|
|
2208
|
+
db.close().unwrap();
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
/// D265: the engine behind the handle is swapped for one reopened on the first one's
|
|
2212
|
+
/// handover, as the recovery supervisor does. Table handles keep working on the new
|
|
2213
|
+
/// engine; a snapshot, a scan and a transaction from the old one expire.
|
|
2214
|
+
#[test]
|
|
2215
|
+
fn a_swapped_engine_serves_table_handles_and_expires_what_the_old_one_gave_out() {
|
|
2216
|
+
let vfs: VfsRef = pigeonhole_io::sim::SimVfs::new(265);
|
|
2217
|
+
let options = Options::default()
|
|
2218
|
+
.vfs(Arc::clone(&vfs))
|
|
2219
|
+
.shards(2)
|
|
2220
|
+
.pin_threads(false);
|
|
2221
|
+
let path = Path::new("/db/swap.phdb");
|
|
2222
|
+
let db = Pigeonhole::open(path, options.clone()).unwrap();
|
|
2223
|
+
let t = db
|
|
2224
|
+
.table("t")
|
|
2225
|
+
.unwrap()
|
|
2226
|
+
.family("f", crate::Family::default())
|
|
2227
|
+
.create_if_missing()
|
|
2228
|
+
.unwrap();
|
|
2229
|
+
t.mutate(b"row").put("f", b"q", b"old").commit().unwrap();
|
|
2230
|
+
let snap = db.snapshot().unwrap();
|
|
2231
|
+
let mut rows = t
|
|
2232
|
+
.scan_bounds(std::ops::Bound::Unbounded, std::ops::Bound::Unbounded)
|
|
2233
|
+
.iter()
|
|
2234
|
+
.unwrap();
|
|
2235
|
+
let mut txn = db.transaction().unwrap();
|
|
2236
|
+
txn.put(&t, b"row2", "f", b"q", b"txn");
|
|
2237
|
+
assert_eq!(db.db.generation(), 1);
|
|
2238
|
+
|
|
2239
|
+
// The swap: close the engine keeping its locks, reopen on them, swap it in.
|
|
2240
|
+
let old = db.engine().to_arc();
|
|
2241
|
+
let (closed, handover) = old.close_for_reopen();
|
|
2242
|
+
closed.unwrap();
|
|
2243
|
+
let reopened = Engine::open_with(path, options.to_engine().unwrap(), handover.unwrap())
|
|
2244
|
+
.map_err(|(e, _)| e)
|
|
2245
|
+
.unwrap();
|
|
2246
|
+
let previous = db.db.swap_engine(reopened);
|
|
2247
|
+
assert!(Arc::ptr_eq(&previous, &old));
|
|
2248
|
+
drop((previous, old));
|
|
2249
|
+
assert_eq!(db.db.generation(), 2);
|
|
2250
|
+
|
|
2251
|
+
// Table handles keep working, on the new engine.
|
|
2252
|
+
assert_eq!(t.get(b"row", "f", b"q").unwrap().unwrap().value(), b"old");
|
|
2253
|
+
t.mutate(b"row").put("f", b"q", b"new").commit().unwrap();
|
|
2254
|
+
assert_eq!(db.tables(), ["t"]);
|
|
2255
|
+
assert!(!db.is_failed());
|
|
2256
|
+
|
|
2257
|
+
// What the old engine gave out expires before it touches an engine.
|
|
2258
|
+
let expired = |e: &Error| e.code() == ErrorCode::SnapshotExpired;
|
|
2259
|
+
let r = t.get_at(&snap, b"row", "f", b"q");
|
|
2260
|
+
assert!(matches!(&r, Err(e) if expired(e)), "{r:?}");
|
|
2261
|
+
let r = rows.next().expect("an item, the error");
|
|
2262
|
+
assert!(matches!(&r, Err(e) if expired(e)), "{r:?}");
|
|
2263
|
+
let r = txn.commit();
|
|
2264
|
+
assert!(matches!(&r, Err(e) if expired(e)), "{r:?}");
|
|
2265
|
+
|
|
2266
|
+
// A snapshot of the new generation reads the new engine.
|
|
2267
|
+
let snap2 = db.snapshot().unwrap();
|
|
2268
|
+
assert_eq!(
|
|
2269
|
+
t.get_at(&snap2, b"row", "f", b"q")
|
|
2270
|
+
.unwrap()
|
|
2271
|
+
.unwrap()
|
|
2272
|
+
.value(),
|
|
2273
|
+
b"new"
|
|
2274
|
+
);
|
|
2275
|
+
drop(rows);
|
|
2276
|
+
drop((snap, snap2));
|
|
2277
|
+
drop(t);
|
|
2278
|
+
db.close().unwrap();
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
fn footprint(shards: usize, budget: u64, dir: Option<&str>) -> ShmFootprint {
|
|
2282
|
+
let mut o = pigeonhole_engine::EngineOptions::new(pigeonhole_io::sim::SimVfs::new(1));
|
|
2283
|
+
o.shards = shards;
|
|
2284
|
+
o.memtable_budget = budget;
|
|
2285
|
+
o.shm_dir = dir.map(Into::into);
|
|
2286
|
+
ShmFootprint::of(&o)
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
#[test]
|
|
2290
|
+
fn shm_unavailable_names_the_footprint_and_the_remedies() {
|
|
2291
|
+
let e = footprint(4, 64 << 20, None).explain(pigeonhole_engine::Error::ShmUnavailable);
|
|
2292
|
+
assert_eq!(e.code(), ErrorCode::ShmUnavailable);
|
|
2293
|
+
let m = e.message();
|
|
2294
|
+
assert!(
|
|
2295
|
+
m.contains("268 MiB (4 shards × 64 MiB memtable_budget, plus 12 MiB for views"),
|
|
2296
|
+
"{m}"
|
|
2297
|
+
);
|
|
2298
|
+
assert!(
|
|
2299
|
+
m.contains("Options::memtable_budget or Options::shards"),
|
|
2300
|
+
"{m}"
|
|
2301
|
+
);
|
|
2302
|
+
assert!(m.contains("Options::shm_dir"), "{m}");
|
|
2303
|
+
if cfg!(target_os = "linux") {
|
|
2304
|
+
assert!(m.contains("/dev/shm") && m.contains("--shm-size"), "{m}");
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
let e = footprint(3, 192 << 10, Some("/mnt/small"))
|
|
2308
|
+
.explain(pigeonhole_engine::Error::ShmUnavailable);
|
|
2309
|
+
assert_eq!(e.code(), ErrorCode::ShmUnavailable);
|
|
2310
|
+
let m = e.message();
|
|
2311
|
+
assert!(
|
|
2312
|
+
// Each arena rounds up to 2 MiB.
|
|
2313
|
+
m.contains("in /mnt/small: it needs 18 MiB (3 shards × 192 KiB memtable_budget"),
|
|
2314
|
+
"{m}"
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
#[test]
|
|
2319
|
+
fn other_open_errors_pass_through() {
|
|
2320
|
+
let e = footprint(1, 1 << 20, None).explain(pigeonhole_engine::Error::WriterLocked);
|
|
2321
|
+
assert_eq!(e.code(), ErrorCode::WriterLocked);
|
|
2322
|
+
assert!(!e.message().contains("shared-memory region"));
|
|
2323
|
+
}
|
|
2324
|
+
}
|