tigerbeetle 0.0.36 → 0.0.38
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/ext/tb_client/extconf.rb +13 -13
- data/ext/tb_client/tigerbeetle/LICENSE +177 -0
- data/ext/tb_client/tigerbeetle/build.zig +2327 -0
- data/ext/tb_client/tigerbeetle/src/aof.zig +1000 -0
- data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +808 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +1283 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +1704 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +341 -0
- data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +1450 -0
- data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +1659 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +406 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +1092 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +286 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +158 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +229 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +110 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +281 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +312 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +138 -0
- data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +466 -0
- data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +157 -0
- data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +90 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +203 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +79 -0
- data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +542 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +109 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +86 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +370 -0
- data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +167 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +126 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +996 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +748 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +3238 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +1718 -0
- data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +190 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +104 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +75 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +522 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +267 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +3 -0
- data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +379 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +131 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +63 -0
- data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +588 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/assets/tb_client.h +386 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +73 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +106 -0
- data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +305 -0
- data/ext/tb_client/tigerbeetle/src/config.zig +296 -0
- data/ext/tb_client/tigerbeetle/src/constants.zig +790 -0
- data/ext/tb_client/tigerbeetle/src/copyhound.zig +202 -0
- data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +72 -0
- data/ext/tb_client/tigerbeetle/src/direction.zig +120 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +158 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +156 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +252 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +313 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +87 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +63 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +47 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +28 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +61 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +169 -0
- data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +46 -0
- data/ext/tb_client/tigerbeetle/src/ewah.zig +445 -0
- data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +128 -0
- data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +171 -0
- data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +179 -0
- data/ext/tb_client/tigerbeetle/src/integration_tests.zig +662 -0
- data/ext/tb_client/tigerbeetle/src/io/common.zig +155 -0
- data/ext/tb_client/tigerbeetle/src/io/darwin.zig +1093 -0
- data/ext/tb_client/tigerbeetle/src/io/linux.zig +1880 -0
- data/ext/tb_client/tigerbeetle/src/io/test.zig +1005 -0
- data/ext/tb_client/tigerbeetle/src/io/windows.zig +1598 -0
- data/ext/tb_client/tigerbeetle/src/io.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/iops.zig +134 -0
- data/ext/tb_client/tigerbeetle/src/list.zig +236 -0
- data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +848 -0
- data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +179 -0
- data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +424 -0
- data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +420 -0
- data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +2117 -0
- data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +182 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +1119 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +1102 -0
- data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +200 -0
- data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +1495 -0
- data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +739 -0
- data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +166 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +754 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +1294 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +510 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +1263 -0
- data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +628 -0
- data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +247 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +116 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +543 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +938 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +293 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +359 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +99 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +17 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +962 -0
- data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +617 -0
- data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +84 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +1500 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +149 -0
- data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +7 -0
- data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +865 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table.zig +607 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +843 -0
- data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +90 -0
- data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +40 -0
- data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +630 -0
- data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +933 -0
- data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +534 -0
- data/ext/tb_client/tigerbeetle/src/message_buffer.zig +469 -0
- data/ext/tb_client/tigerbeetle/src/message_bus.zig +1214 -0
- data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +936 -0
- data/ext/tb_client/tigerbeetle/src/message_pool.zig +343 -0
- data/ext/tb_client/tigerbeetle/src/multiversion.zig +2195 -0
- data/ext/tb_client/tigerbeetle/src/queue.zig +390 -0
- data/ext/tb_client/tigerbeetle/src/repl/completion.zig +201 -0
- data/ext/tb_client/tigerbeetle/src/repl/parser.zig +1356 -0
- data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +496 -0
- data/ext/tb_client/tigerbeetle/src/repl.zig +1034 -0
- data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +973 -0
- data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +1866 -0
- data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +304 -0
- data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +227 -0
- data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +658 -0
- data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +466 -0
- data/ext/tb_client/tigerbeetle/src/scripts/release.zig +1058 -0
- data/ext/tb_client/tigerbeetle/src/scripts.zig +105 -0
- data/ext/tb_client/tigerbeetle/src/shell.zig +1195 -0
- data/ext/tb_client/tigerbeetle/src/stack.zig +260 -0
- data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +911 -0
- data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +2079 -0
- data/ext/tb_client/tigerbeetle/src/state_machine.zig +4872 -0
- data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +288 -0
- data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +3128 -0
- data/ext/tb_client/tigerbeetle/src/static_allocator.zig +82 -0
- data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +157 -0
- data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +292 -0
- data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +65 -0
- data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +1414 -0
- data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +92 -0
- data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +677 -0
- data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +336 -0
- data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +511 -0
- data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +112 -0
- data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +1160 -0
- data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +142 -0
- data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +361 -0
- data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +275 -0
- data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +295 -0
- data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +436 -0
- data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +48 -0
- data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +402 -0
- data/ext/tb_client/tigerbeetle/src/storage.zig +489 -0
- data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +180 -0
- data/ext/tb_client/tigerbeetle/src/testing/bench.zig +146 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +53 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +61 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +76 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +110 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +412 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +331 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +458 -0
- data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +1198 -0
- data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +128 -0
- data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +181 -0
- data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +144 -0
- data/ext/tb_client/tigerbeetle/src/testing/id.zig +97 -0
- data/ext/tb_client/tigerbeetle/src/testing/io.zig +317 -0
- data/ext/tb_client/tigerbeetle/src/testing/marks.zig +126 -0
- data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +533 -0
- data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +154 -0
- data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +389 -0
- data/ext/tb_client/tigerbeetle/src/testing/storage.zig +1247 -0
- data/ext/tb_client/tigerbeetle/src/testing/table.zig +249 -0
- data/ext/tb_client/tigerbeetle/src/testing/time.zig +98 -0
- data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +212 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +26 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +580 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +39 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +214 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +34 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +766 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +543 -0
- data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +181 -0
- data/ext/tb_client/tigerbeetle/src/tidy.zig +1448 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +227 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +1069 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +1422 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +1658 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +518 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +36 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +646 -0
- data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +958 -0
- data/ext/tb_client/tigerbeetle/src/time.zig +236 -0
- data/ext/tb_client/tigerbeetle/src/trace/event.zig +745 -0
- data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +462 -0
- data/ext/tb_client/tigerbeetle/src/trace.zig +556 -0
- data/ext/tb_client/tigerbeetle/src/unit_tests.zig +321 -0
- data/ext/tb_client/tigerbeetle/src/vopr.zig +1785 -0
- data/ext/tb_client/tigerbeetle/src/vortex.zig +101 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +473 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +208 -0
- data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +43 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client.zig +768 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +532 -0
- data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +338 -0
- data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +1019 -0
- data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +279 -0
- data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +1381 -0
- data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +315 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +1460 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +757 -0
- data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +797 -0
- data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +2586 -0
- data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +308 -0
- data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +1777 -0
- data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +715 -0
- data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +185 -0
- data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +333 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +12355 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +416 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +165 -0
- data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +2928 -0
- data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +1075 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +1603 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +484 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +405 -0
- data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +355 -0
- data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +29 -0
- data/ext/tb_client/tigerbeetle/src/vsr.zig +1727 -0
- data/lib/tb_client/shared_lib.rb +12 -5
- data/lib/tigerbeetle/platforms.rb +9 -0
- data/lib/tigerbeetle/version.rb +2 -2
- data/tigerbeetle.gemspec +22 -5
- metadata +242 -3
- data/ext/tb_client/pkg.tar.gz +0 -0
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
const builtin = @import("builtin");
|
|
2
|
+
const std = @import("std");
|
|
3
|
+
const assert = std.debug.assert;
|
|
4
|
+
const fmt = std.fmt;
|
|
5
|
+
const mem = std.mem;
|
|
6
|
+
const os = std.os;
|
|
7
|
+
const log = std.log.scoped(.main);
|
|
8
|
+
|
|
9
|
+
const vsr = @import("vsr");
|
|
10
|
+
const stdx = vsr.stdx;
|
|
11
|
+
const constants = vsr.constants;
|
|
12
|
+
const config = constants.config;
|
|
13
|
+
|
|
14
|
+
const benchmark_driver = @import("benchmark_driver.zig");
|
|
15
|
+
const cli = @import("cli.zig");
|
|
16
|
+
const inspect = @import("inspect.zig");
|
|
17
|
+
|
|
18
|
+
const IO = vsr.io.IO;
|
|
19
|
+
const Time = vsr.time.Time;
|
|
20
|
+
const TimeOS = vsr.time.TimeOS;
|
|
21
|
+
const Tracer = vsr.trace.Tracer;
|
|
22
|
+
pub const Storage = vsr.storage.StorageType(IO);
|
|
23
|
+
const AOF = vsr.aof.AOFType(IO);
|
|
24
|
+
|
|
25
|
+
const MessageBus = vsr.message_bus.MessageBusType(IO);
|
|
26
|
+
const MessagePool = vsr.message_pool.MessagePool;
|
|
27
|
+
pub const StateMachine = vsr.state_machine.StateMachineType(Storage);
|
|
28
|
+
pub const Grid = vsr.GridType(Storage);
|
|
29
|
+
|
|
30
|
+
const Client = vsr.ClientType(StateMachine.Operation, MessageBus);
|
|
31
|
+
pub const Replica = vsr.ReplicaType(StateMachine, MessageBus, Storage, AOF);
|
|
32
|
+
const ReplicaReformat =
|
|
33
|
+
vsr.ReplicaReformatType(StateMachine, MessageBus, Storage);
|
|
34
|
+
const data_file_size_min = vsr.superblock.data_file_size_min;
|
|
35
|
+
|
|
36
|
+
const KiB = stdx.KiB;
|
|
37
|
+
const MiB = stdx.MiB;
|
|
38
|
+
const GiB = stdx.GiB;
|
|
39
|
+
|
|
40
|
+
/// The runtime maximum log level.
|
|
41
|
+
/// One of: .err, .warn, .info, .debug
|
|
42
|
+
pub var log_level_runtime: std.log.Level = .info;
|
|
43
|
+
|
|
44
|
+
pub fn log_runtime(
|
|
45
|
+
comptime message_level: std.log.Level,
|
|
46
|
+
comptime scope: @Type(.enum_literal),
|
|
47
|
+
comptime format: []const u8,
|
|
48
|
+
args: anytype,
|
|
49
|
+
) void {
|
|
50
|
+
// A microbenchmark places the cost of this if at somewhere around 1600us for 10 million calls.
|
|
51
|
+
if (@intFromEnum(message_level) <= @intFromEnum(log_level_runtime)) {
|
|
52
|
+
stdx.log_with_timestamp(message_level, scope, format, args);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pub const std_options: std.Options = .{
|
|
57
|
+
// The comptime log_level. This needs to be debug - otherwise messages are compiled out.
|
|
58
|
+
// The runtime filtering is handled by log_level_runtime.
|
|
59
|
+
.log_level = .debug,
|
|
60
|
+
.logFn = log_runtime,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
pub fn main() !void {
|
|
64
|
+
if (builtin.os.tag == .windows) try vsr.multiversion.wait_for_parent_to_exit();
|
|
65
|
+
|
|
66
|
+
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
67
|
+
defer arena_instance.deinit();
|
|
68
|
+
|
|
69
|
+
// Arena is an implementation detail, all memory must be freed.
|
|
70
|
+
const gpa = arena_instance.allocator();
|
|
71
|
+
|
|
72
|
+
var arg_iterator = try std.process.argsWithAllocator(gpa);
|
|
73
|
+
defer arg_iterator.deinit();
|
|
74
|
+
|
|
75
|
+
var command = cli.parse_args(&arg_iterator);
|
|
76
|
+
|
|
77
|
+
if (command == .version) {
|
|
78
|
+
try command_version(gpa, command.version.verbose);
|
|
79
|
+
return; // Exit early before initializing IO.
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
log_level_runtime = switch (command) {
|
|
83
|
+
.version => unreachable,
|
|
84
|
+
.inspect => .info,
|
|
85
|
+
inline else => |*args| if (args.log_debug) .debug else .info,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Try and init IO early, before a file has even been created, so if it fails (eg, io_uring
|
|
89
|
+
// is not available) there won't be a dangling file.
|
|
90
|
+
var io = try IO.init(128, 0);
|
|
91
|
+
defer io.deinit();
|
|
92
|
+
|
|
93
|
+
var time_os: TimeOS = .{};
|
|
94
|
+
const time = time_os.time();
|
|
95
|
+
|
|
96
|
+
var trace_file: ?std.fs.File = null;
|
|
97
|
+
defer if (trace_file) |file| file.close();
|
|
98
|
+
|
|
99
|
+
var statsd_address: ?std.net.Address = null;
|
|
100
|
+
var log_trace = true;
|
|
101
|
+
|
|
102
|
+
switch (command) {
|
|
103
|
+
.start => |*args| {
|
|
104
|
+
if (args.trace) |path| {
|
|
105
|
+
trace_file = std.fs.cwd().createFile(path, .{ .exclusive = true }) catch |err| {
|
|
106
|
+
log.err("error creating trace file '{s}': {}", .{ path, err });
|
|
107
|
+
return err;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (args.statsd) |address| statsd_address = address;
|
|
111
|
+
log_trace = args.log_trace;
|
|
112
|
+
},
|
|
113
|
+
.benchmark => {}, // Forwards trace and statsd argument to child tigerbeetle.
|
|
114
|
+
inline else => |args| comptime {
|
|
115
|
+
assert(!@hasField(@TypeOf(args), "trace"));
|
|
116
|
+
assert(!@hasField(@TypeOf(args), "statsd"));
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var tracer = try Tracer.init(gpa, time, .unknown, .{
|
|
121
|
+
.writer = if (trace_file) |file| file.writer().any() else null,
|
|
122
|
+
.statsd_options = if (statsd_address) |address| .{
|
|
123
|
+
.udp = .{
|
|
124
|
+
.io = &io,
|
|
125
|
+
.address = address,
|
|
126
|
+
},
|
|
127
|
+
} else .log,
|
|
128
|
+
.log_trace = log_trace,
|
|
129
|
+
});
|
|
130
|
+
defer tracer.deinit(gpa);
|
|
131
|
+
|
|
132
|
+
switch (command) {
|
|
133
|
+
.version => unreachable, // Handled earlier.
|
|
134
|
+
inline .format, .start, .recover => |*args, command_storage| {
|
|
135
|
+
const direct_io: vsr.io.DirectIO =
|
|
136
|
+
if (!constants.direct_io)
|
|
137
|
+
.direct_io_disabled
|
|
138
|
+
else if (args.development)
|
|
139
|
+
.direct_io_optional
|
|
140
|
+
else
|
|
141
|
+
.direct_io_required;
|
|
142
|
+
|
|
143
|
+
var storage = try Storage.init(&io, &tracer, .{
|
|
144
|
+
.path = args.path,
|
|
145
|
+
.size_min = data_file_size_min,
|
|
146
|
+
.purpose = switch (command_storage) {
|
|
147
|
+
.format, .recover => .format,
|
|
148
|
+
.start => .open,
|
|
149
|
+
else => comptime unreachable,
|
|
150
|
+
},
|
|
151
|
+
.direct_io = direct_io,
|
|
152
|
+
});
|
|
153
|
+
defer storage.deinit();
|
|
154
|
+
|
|
155
|
+
switch (command_storage) {
|
|
156
|
+
.format => try command_format(gpa, &storage, args),
|
|
157
|
+
.start => try command_start(gpa, &io, time, &tracer, &storage, args),
|
|
158
|
+
.recover => try command_reformat(gpa, &io, time, &storage, args),
|
|
159
|
+
else => comptime unreachable,
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
.repl => |*args| try command_repl(gpa, &io, time, args),
|
|
163
|
+
.benchmark => |*args| try benchmark_driver.command_benchmark(gpa, &io, time, args),
|
|
164
|
+
.inspect => |*args| try inspect.command_inspect(gpa, &io, &tracer, args),
|
|
165
|
+
.multiversion => |*args| {
|
|
166
|
+
var stdout_buffer = std.io.bufferedWriter(std.io.getStdOut().writer());
|
|
167
|
+
var stdout_writer = stdout_buffer.writer();
|
|
168
|
+
const stdout = stdout_writer.any();
|
|
169
|
+
|
|
170
|
+
try vsr.multiversion.print_information(gpa, args.path, stdout);
|
|
171
|
+
try stdout_buffer.flush();
|
|
172
|
+
},
|
|
173
|
+
.amqp => |*args| try command_amqp(gpa, time, args),
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
fn command_version(gpa: mem.Allocator, verbose: bool) !void {
|
|
178
|
+
var stdout_buffer = std.io.bufferedWriter(std.io.getStdOut().writer());
|
|
179
|
+
var stdout_writer = stdout_buffer.writer();
|
|
180
|
+
const stdout = stdout_writer.any();
|
|
181
|
+
|
|
182
|
+
try std.fmt.format(stdout, "TigerBeetle version {}\n", .{constants.semver});
|
|
183
|
+
|
|
184
|
+
if (verbose) {
|
|
185
|
+
try stdout.writeAll("\n");
|
|
186
|
+
inline for (.{ "mode", "zig_version" }) |declaration| {
|
|
187
|
+
try print_value(stdout, "build." ++ declaration, @field(builtin, declaration));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Zig 0.10 doesn't see field_name as comptime if this `comptime` isn't used.
|
|
191
|
+
try stdout.writeAll("\n");
|
|
192
|
+
inline for (comptime std.meta.fieldNames(@TypeOf(config.cluster))) |field_name| {
|
|
193
|
+
try print_value(
|
|
194
|
+
stdout,
|
|
195
|
+
"cluster." ++ field_name,
|
|
196
|
+
@field(config.cluster, field_name),
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
try stdout.writeAll("\n");
|
|
201
|
+
inline for (comptime std.meta.fieldNames(@TypeOf(config.process))) |field_name| {
|
|
202
|
+
try print_value(
|
|
203
|
+
stdout,
|
|
204
|
+
"process." ++ field_name,
|
|
205
|
+
@field(config.process, field_name),
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
try stdout.writeAll("\n");
|
|
210
|
+
const self_exe_path = try vsr.multiversion.self_exe_path(gpa);
|
|
211
|
+
defer gpa.free(self_exe_path);
|
|
212
|
+
|
|
213
|
+
vsr.multiversion.print_information(gpa, self_exe_path, stdout) catch {};
|
|
214
|
+
}
|
|
215
|
+
try stdout_buffer.flush();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fn command_format(
|
|
219
|
+
gpa: mem.Allocator,
|
|
220
|
+
storage: *Storage,
|
|
221
|
+
args: *const cli.Command.Format,
|
|
222
|
+
) !void {
|
|
223
|
+
try vsr.format(Storage, gpa, storage, .{
|
|
224
|
+
.cluster = args.cluster,
|
|
225
|
+
.replica = args.replica,
|
|
226
|
+
.replica_count = args.replica_count,
|
|
227
|
+
.release = config.process.release,
|
|
228
|
+
.view = null,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
log.info("{}: formatted: cluster={} replica_count={}", .{
|
|
232
|
+
args.replica,
|
|
233
|
+
args.cluster,
|
|
234
|
+
args.replica_count,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
fn command_start(
|
|
239
|
+
base_allocator: mem.Allocator,
|
|
240
|
+
io: *IO,
|
|
241
|
+
time: vsr.time.Time,
|
|
242
|
+
tracer: *Tracer,
|
|
243
|
+
storage: *Storage,
|
|
244
|
+
args: *const cli.Command.Start,
|
|
245
|
+
) !void {
|
|
246
|
+
var counting_allocator = vsr.CountingAllocator.init(base_allocator);
|
|
247
|
+
const gpa = counting_allocator.allocator();
|
|
248
|
+
|
|
249
|
+
// TODO Panic if the data file's size is larger that args.storage_size_limit.
|
|
250
|
+
// (Here or in Replica.open()?).
|
|
251
|
+
|
|
252
|
+
var message_pool = try MessagePool.init(gpa, .{ .replica = .{
|
|
253
|
+
.members_count = args.addresses.count_as(u8),
|
|
254
|
+
.pipeline_requests_limit = args.pipeline_requests_limit,
|
|
255
|
+
.message_bus = .tcp,
|
|
256
|
+
} });
|
|
257
|
+
defer message_pool.deinit(gpa);
|
|
258
|
+
|
|
259
|
+
var aof: ?AOF = if (args.aof_file) |*aof_file| blk: {
|
|
260
|
+
break :blk try AOF.init(io, aof_file.const_slice());
|
|
261
|
+
} else null;
|
|
262
|
+
defer if (aof != null) aof.?.close();
|
|
263
|
+
|
|
264
|
+
const grid_cache_size = @as(u64, args.cache_grid_blocks) * constants.block_size;
|
|
265
|
+
const grid_cache_size_min = constants.block_size * Grid.Cache.value_count_max_multiple;
|
|
266
|
+
|
|
267
|
+
// The amount of bytes in `--cache-grid` must be a multiple of
|
|
268
|
+
// `constants.block_size` and `SetAssociativeCache.value_count_max_multiple`,
|
|
269
|
+
// and it may have been converted to zero if a smaller value is passed in.
|
|
270
|
+
if (grid_cache_size == 0) {
|
|
271
|
+
if (comptime (grid_cache_size_min >= MiB)) {
|
|
272
|
+
vsr.fatal(.cli, "Grid cache must be greater than {}MiB. See --cache-grid", .{
|
|
273
|
+
@divExact(grid_cache_size_min, MiB),
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
vsr.fatal(.cli, "Grid cache must be greater than {}KiB. See --cache-grid", .{
|
|
277
|
+
@divExact(grid_cache_size_min, KiB),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
assert(grid_cache_size >= grid_cache_size_min);
|
|
282
|
+
|
|
283
|
+
const grid_cache_size_warn = 1 * GiB;
|
|
284
|
+
if (grid_cache_size < grid_cache_size_warn) {
|
|
285
|
+
log.warn("Grid cache size of {}MiB is small. See --cache-grid", .{
|
|
286
|
+
@divExact(grid_cache_size, MiB),
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const nonce = stdx.unique_u128();
|
|
291
|
+
|
|
292
|
+
var self_exe_path: ?[:0]const u8 = null;
|
|
293
|
+
defer if (self_exe_path) |path| gpa.free(path);
|
|
294
|
+
|
|
295
|
+
var multiversion_os: ?vsr.multiversion.MultiversionOS = null;
|
|
296
|
+
defer if (multiversion_os != null) multiversion_os.?.deinit(gpa);
|
|
297
|
+
|
|
298
|
+
const multiversion: vsr.multiversion.Multiversion = blk: {
|
|
299
|
+
if (constants.config.process.release.value ==
|
|
300
|
+
vsr.multiversion.Release.minimum.value)
|
|
301
|
+
{
|
|
302
|
+
log.info("multiversioning: upgrades disabled for development ({}) release.", .{
|
|
303
|
+
constants.config.process.release,
|
|
304
|
+
});
|
|
305
|
+
break :blk .single_release(constants.config.process.release);
|
|
306
|
+
}
|
|
307
|
+
if (args.aof_recovery) {
|
|
308
|
+
log.info("multiversioning: upgrades disabled due to aof_recovery.", .{});
|
|
309
|
+
break :blk .single_release(constants.config.process.release);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (args.addresses_zero) {
|
|
313
|
+
log.info("multiversioning: upgrades disabled due to --addresses=0", .{});
|
|
314
|
+
break :blk .single_release(constants.config.process.release);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
self_exe_path = try vsr.multiversion.self_exe_path(gpa);
|
|
318
|
+
multiversion_os = try vsr.multiversion.MultiversionOS.init(
|
|
319
|
+
gpa,
|
|
320
|
+
io,
|
|
321
|
+
self_exe_path.?,
|
|
322
|
+
.native,
|
|
323
|
+
);
|
|
324
|
+
// The error from .open_sync() is ignored - timeouts and checking for new binaries are still
|
|
325
|
+
// enabled even if the first version fails to load.
|
|
326
|
+
multiversion_os.?.open_sync() catch {};
|
|
327
|
+
|
|
328
|
+
break :blk multiversion_os.?.multiversion();
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
log.info("release={}", .{config.process.release});
|
|
332
|
+
log.info("release_client_min={}", .{config.process.release_client_min});
|
|
333
|
+
log.info("releases_bundled={any}", .{multiversion.releases_bundled().slice()});
|
|
334
|
+
log.info("git_commit={?s}", .{config.process.git_commit});
|
|
335
|
+
|
|
336
|
+
const clients_limit = constants.pipeline_prepare_queue_max + args.pipeline_requests_limit;
|
|
337
|
+
|
|
338
|
+
var replica: Replica = undefined;
|
|
339
|
+
replica.open(
|
|
340
|
+
gpa,
|
|
341
|
+
time,
|
|
342
|
+
storage,
|
|
343
|
+
&message_pool,
|
|
344
|
+
.{
|
|
345
|
+
.node_count = args.addresses.count_as(u8),
|
|
346
|
+
.release = config.process.release,
|
|
347
|
+
.release_client_min = config.process.release_client_min,
|
|
348
|
+
.multiversion = multiversion,
|
|
349
|
+
.pipeline_requests_limit = args.pipeline_requests_limit,
|
|
350
|
+
.storage_size_limit = args.storage_size_limit,
|
|
351
|
+
.aof = if (aof != null) &aof.? else null,
|
|
352
|
+
.aof_recovery = args.aof_recovery,
|
|
353
|
+
.nonce = nonce,
|
|
354
|
+
.timeout_prepare_ticks = args.timeout_prepare_ticks,
|
|
355
|
+
.timeout_grid_repair_message_ticks = args.timeout_grid_repair_message_ticks,
|
|
356
|
+
.commit_stall_probability = args.commit_stall_probability,
|
|
357
|
+
.state_machine_options = .{
|
|
358
|
+
.batch_size_limit = args.request_size_limit - @sizeOf(vsr.Header),
|
|
359
|
+
.lsm_forest_compaction_block_count = args.lsm_forest_compaction_block_count,
|
|
360
|
+
.lsm_forest_node_count = args.lsm_forest_node_count,
|
|
361
|
+
.cache_entries_accounts = args.cache_accounts,
|
|
362
|
+
.cache_entries_transfers = args.cache_transfers,
|
|
363
|
+
.cache_entries_transfers_pending = args.cache_transfers_pending,
|
|
364
|
+
.log_trace = args.log_trace,
|
|
365
|
+
.aof_recovery = args.aof_recovery,
|
|
366
|
+
},
|
|
367
|
+
.message_bus_options = .{
|
|
368
|
+
.configuration = args.addresses.const_slice(),
|
|
369
|
+
.io = io,
|
|
370
|
+
.clients_limit = clients_limit,
|
|
371
|
+
.trace = tracer,
|
|
372
|
+
},
|
|
373
|
+
.grid_cache_blocks_count = args.cache_grid_blocks,
|
|
374
|
+
.tracer = tracer,
|
|
375
|
+
.replicate_options = .{
|
|
376
|
+
.star = args.replicate_star,
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
) catch |err| switch (err) {
|
|
380
|
+
error.NoAddress => vsr.fatal(.cli, "all --addresses must be provided", .{}),
|
|
381
|
+
else => |e| return e,
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
// Mark grid cache as MADV_DONTDUMP, after transitioning to static in replica.open, to reduce
|
|
385
|
+
// core dump size.
|
|
386
|
+
replica.grid.madv_dont_dump() catch |e| {
|
|
387
|
+
log.warn("unable to mark grid cache as MADV_DONTDUMP - " ++
|
|
388
|
+
"core dumps will be large: {}", .{e});
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
if (multiversion_os != null) {
|
|
392
|
+
if (args.development) {
|
|
393
|
+
log.info("multiversioning: upgrade polling disabled due to --development.", .{});
|
|
394
|
+
} else {
|
|
395
|
+
multiversion_os.?.timeout_start(replica.replica);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (args.experimental) {
|
|
399
|
+
log.warn("multiversioning: upgrade polling and --experimental enabled - " ++
|
|
400
|
+
"make sure to check CLI argument compatibility before upgrading.", .{});
|
|
401
|
+
log.warn("If the cluster upgrades automatically, and incompatible experimental " ++
|
|
402
|
+
"CLI arguments are set, it will crash.", .{});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Note that this does not account for the fact that any allocations will be rounded up to
|
|
407
|
+
// the nearest page by `std.heap.page_allocator`.
|
|
408
|
+
log.info("{}: Allocated {}MiB during replica init", .{
|
|
409
|
+
replica.replica,
|
|
410
|
+
@divFloor(counting_allocator.live_size(), MiB),
|
|
411
|
+
});
|
|
412
|
+
log.info("{}: Grid cache: {}MiB, LSM-tree manifests: {}MiB", .{
|
|
413
|
+
replica.replica,
|
|
414
|
+
@divFloor(grid_cache_size, MiB),
|
|
415
|
+
@divFloor(args.lsm_forest_node_count * constants.lsm_manifest_node_size, MiB),
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
log.info("{}: cluster={}: listening on {}", .{
|
|
419
|
+
replica.replica,
|
|
420
|
+
replica.cluster,
|
|
421
|
+
replica.message_bus.accept_address.?,
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
if (args.aof_recovery) {
|
|
425
|
+
log.warn(
|
|
426
|
+
"{}: started in AOF recovery mode. This is potentially dangerous - if it's" ++
|
|
427
|
+
" unexpected, please rerun without --aof-recovery flag.",
|
|
428
|
+
.{replica.replica},
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (constants.verify) {
|
|
433
|
+
log.info("{}: started with extra verification checks", .{replica.replica});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (replica.aof != null) {
|
|
437
|
+
log.warn(
|
|
438
|
+
"{}: started with --aof - expect much reduced performance.",
|
|
439
|
+
.{replica.replica},
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// It is possible to start tigerbeetle passing `0` as an address:
|
|
444
|
+
// $ tigerbeetle start --addresses=0 0_0.tigerbeetle
|
|
445
|
+
// This enables a couple of special behaviors, useful in tests:
|
|
446
|
+
// - The operating system picks a free port, avoiding "address already in use" errors.
|
|
447
|
+
// - The port, and only the port, is printed to the stdout, so that the parent process
|
|
448
|
+
// can learn it.
|
|
449
|
+
// - tigerbeetle process exits when its stdin gets closed.
|
|
450
|
+
if (args.addresses_zero) {
|
|
451
|
+
const port_actual = replica.message_bus.accept_address.?.getPort();
|
|
452
|
+
const stdout = std.io.getStdOut();
|
|
453
|
+
try stdout.writer().print("{}\n", .{port_actual});
|
|
454
|
+
stdout.close();
|
|
455
|
+
|
|
456
|
+
// While it is possible to integrate stdin with our io_uring loop, using a dedicated
|
|
457
|
+
// thread is simpler, and gives us _un_graceful shutdown, which is exactly what we want
|
|
458
|
+
// to keep behavior close to the normal case.
|
|
459
|
+
const watchdog = try std.Thread.spawn(.{}, struct {
|
|
460
|
+
fn thread_main() void {
|
|
461
|
+
var buf: [1]u8 = .{0};
|
|
462
|
+
_ = std.io.getStdIn().read(&buf) catch {};
|
|
463
|
+
log.info("stdin closed, exiting", .{});
|
|
464
|
+
std.process.exit(0);
|
|
465
|
+
}
|
|
466
|
+
}.thread_main, .{});
|
|
467
|
+
watchdog.detach();
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (!args.development) {
|
|
471
|
+
// Try to lock all memory in the process to avoid the kernel swapping pages to disk and
|
|
472
|
+
// potentially introducing undetectable disk corruption into memory.
|
|
473
|
+
// This is a best-effort attempt and not a hard rule as it may not cover all memory edge
|
|
474
|
+
// case. So warn on error to notify the operator to adjust conditions if possible.
|
|
475
|
+
stdx.memory_lock_allocated(.{
|
|
476
|
+
.allocated_size = counting_allocator.live_size(),
|
|
477
|
+
}) catch {
|
|
478
|
+
log.warn(
|
|
479
|
+
"If this is a production replica, consider either " ++
|
|
480
|
+
"running the replica with CAP_IPC_LOCK privilege, " ++
|
|
481
|
+
"increasing the MEMLOCK process limit, " ++
|
|
482
|
+
"or disabling swap system-wide.",
|
|
483
|
+
.{},
|
|
484
|
+
);
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
if (replica.cluster == 0) {
|
|
488
|
+
log.warn("a cluster id of 0 is reserved for testing and benchmarking, " ++
|
|
489
|
+
"do not use in production", .{});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (config.process.release.testing()) {
|
|
494
|
+
if (replica.cluster != 0) {
|
|
495
|
+
// Guard against running test/dev binaries against production clusters.
|
|
496
|
+
@panic("This is a test binary, but the cluster id is non-zero.");
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
while (true) {
|
|
501
|
+
replica.tick();
|
|
502
|
+
|
|
503
|
+
{
|
|
504
|
+
tracer.start(.loop_run_for_ns);
|
|
505
|
+
defer tracer.stop(.loop_run_for_ns);
|
|
506
|
+
|
|
507
|
+
try io.run_for_ns(constants.tick_ms * std.time.ns_per_ms);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
fn command_reformat(
|
|
513
|
+
gpa: mem.Allocator,
|
|
514
|
+
io: *IO,
|
|
515
|
+
time: vsr.time.Time,
|
|
516
|
+
storage: *Storage,
|
|
517
|
+
args: *const cli.Command.Recover,
|
|
518
|
+
) !void {
|
|
519
|
+
var message_pool = try MessagePool.init(gpa, .client);
|
|
520
|
+
defer message_pool.deinit(gpa);
|
|
521
|
+
|
|
522
|
+
var client = try Client.init(
|
|
523
|
+
gpa,
|
|
524
|
+
time,
|
|
525
|
+
&message_pool,
|
|
526
|
+
.{
|
|
527
|
+
.id = stdx.unique_u128(),
|
|
528
|
+
.cluster = args.cluster,
|
|
529
|
+
.replica_count = args.replica_count,
|
|
530
|
+
.aof_recovery = false,
|
|
531
|
+
|
|
532
|
+
.message_bus_options = .{
|
|
533
|
+
.configuration = args.addresses.const_slice(),
|
|
534
|
+
.io = io,
|
|
535
|
+
.clients_limit = null,
|
|
536
|
+
.trace = null,
|
|
537
|
+
},
|
|
538
|
+
.eviction_callback = &reformat_client_eviction_callback,
|
|
539
|
+
},
|
|
540
|
+
);
|
|
541
|
+
defer client.deinit(gpa);
|
|
542
|
+
|
|
543
|
+
var reformatter = try ReplicaReformat.init(gpa, &client, storage, .{
|
|
544
|
+
.cluster = args.cluster,
|
|
545
|
+
.replica = args.replica,
|
|
546
|
+
.replica_count = args.replica_count,
|
|
547
|
+
.release = config.process.release,
|
|
548
|
+
.view = null,
|
|
549
|
+
});
|
|
550
|
+
defer reformatter.deinit(gpa);
|
|
551
|
+
|
|
552
|
+
reformatter.start();
|
|
553
|
+
while (reformatter.done() == null) {
|
|
554
|
+
client.tick();
|
|
555
|
+
try io.run_for_ns(constants.tick_ms * std.time.ns_per_ms);
|
|
556
|
+
}
|
|
557
|
+
switch (reformatter.done().?) {
|
|
558
|
+
.failed => |err| {
|
|
559
|
+
log.err("{}: error: {s}", .{ args.replica, @errorName(err) });
|
|
560
|
+
return err;
|
|
561
|
+
},
|
|
562
|
+
.ok => log.info("{}: success", .{args.replica}),
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
fn reformat_client_eviction_callback(
|
|
567
|
+
client: *Client,
|
|
568
|
+
eviction: *const MessagePool.Message.Eviction,
|
|
569
|
+
) void {
|
|
570
|
+
_ = client;
|
|
571
|
+
std.debug.panic("error: client evicted: {s}", .{@tagName(eviction.header.reason)});
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
fn command_repl(
|
|
575
|
+
gpa: mem.Allocator,
|
|
576
|
+
io: *IO,
|
|
577
|
+
time: Time,
|
|
578
|
+
args: *const cli.Command.Repl,
|
|
579
|
+
) !void {
|
|
580
|
+
const Repl = vsr.repl.ReplType(vsr.message_bus.MessageBusType(IO));
|
|
581
|
+
|
|
582
|
+
var repl_instance = try Repl.init(gpa, io, time, .{
|
|
583
|
+
.cluster_id = args.cluster,
|
|
584
|
+
.addresses = args.addresses.const_slice(),
|
|
585
|
+
.verbose = args.verbose,
|
|
586
|
+
});
|
|
587
|
+
defer repl_instance.deinit(gpa);
|
|
588
|
+
|
|
589
|
+
try repl_instance.run(args.statements);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
fn command_amqp(gpa: mem.Allocator, time: Time, args: *const cli.Command.AMQP) !void {
|
|
593
|
+
var runner: vsr.cdc.Runner = undefined;
|
|
594
|
+
try runner.init(
|
|
595
|
+
gpa,
|
|
596
|
+
time,
|
|
597
|
+
.{
|
|
598
|
+
.cluster_id = args.cluster,
|
|
599
|
+
.addresses = args.addresses.const_slice(),
|
|
600
|
+
.host = args.host,
|
|
601
|
+
.user = args.user,
|
|
602
|
+
.password = args.password,
|
|
603
|
+
.vhost = args.vhost,
|
|
604
|
+
.publish_exchange = args.publish_exchange,
|
|
605
|
+
.publish_routing_key = args.publish_routing_key,
|
|
606
|
+
.event_count_max = args.event_count_max,
|
|
607
|
+
.idle_interval_ms = args.idle_interval_ms,
|
|
608
|
+
.requests_per_second_limit = args.requests_per_second_limit,
|
|
609
|
+
.recovery_mode = if (args.timestamp_last) |timestamp_last|
|
|
610
|
+
.{ .override = timestamp_last }
|
|
611
|
+
else
|
|
612
|
+
.recover,
|
|
613
|
+
},
|
|
614
|
+
);
|
|
615
|
+
defer runner.deinit();
|
|
616
|
+
|
|
617
|
+
while (true) {
|
|
618
|
+
runner.tick();
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
fn print_value(
|
|
623
|
+
writer: anytype,
|
|
624
|
+
field: []const u8,
|
|
625
|
+
value: anytype,
|
|
626
|
+
) !void {
|
|
627
|
+
if (@TypeOf(value) == ?[40]u8) {
|
|
628
|
+
assert(std.mem.eql(u8, field, "process.git_commit"));
|
|
629
|
+
return std.fmt.format(writer, "{s}=\"{?s}\"\n", .{
|
|
630
|
+
field,
|
|
631
|
+
value,
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
switch (@typeInfo(@TypeOf(value))) {
|
|
636
|
+
.@"fn" => {}, // Ignore the log() function.
|
|
637
|
+
.pointer => try std.fmt.format(writer, "{s}=\"{s}\"\n", .{
|
|
638
|
+
field,
|
|
639
|
+
std.fmt.fmtSliceEscapeLower(value),
|
|
640
|
+
}),
|
|
641
|
+
else => try std.fmt.format(writer, "{s}={any}\n", .{
|
|
642
|
+
field,
|
|
643
|
+
value,
|
|
644
|
+
}),
|
|
645
|
+
}
|
|
646
|
+
}
|