tigerbeetle 0.0.40 → 0.17.8

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.
Files changed (293) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +0 -25
  3. data/README.md +670 -80
  4. data/docs/migration.md +201 -0
  5. data/sig/tigerbeetle.rbs +271 -0
  6. data/src/ext/tigerbeetle/extconf.rb +47 -0
  7. data/src/ext/tigerbeetle/lib/aarch64-linux-gnu.2.27/libtb_client.so +0 -0
  8. data/src/ext/tigerbeetle/lib/aarch64-linux-musl/libtb_client.so +0 -0
  9. data/src/ext/tigerbeetle/lib/aarch64-macos/libtb_client.dylib +0 -0
  10. data/src/ext/tigerbeetle/lib/x86_64-linux-gnu.2.27/libtb_client.so +0 -0
  11. data/src/ext/tigerbeetle/lib/x86_64-linux-musl/libtb_client.so +0 -0
  12. data/src/ext/tigerbeetle/lib/x86_64-macos/libtb_client.dylib +0 -0
  13. data/src/ext/tigerbeetle/lib/x86_64-windows/tb_client.dll +0 -0
  14. data/src/ext/tigerbeetle/rb_tb_gen.h +458 -0
  15. data/{ext/tb_client/tigerbeetle/src/clients/rust/assets → src/ext/tigerbeetle}/tb_client.h +18 -16
  16. data/src/ext/tigerbeetle/tigerbeetle.c +310 -0
  17. data/src/tigerbeetle/bindings.rb +347 -0
  18. data/src/tigerbeetle/client.rb +129 -0
  19. data/src/tigerbeetle/completion_dispatcher.rb +108 -0
  20. data/src/tigerbeetle/id.rb +40 -0
  21. data/src/tigerbeetle/tb.rb +3 -0
  22. data/src/tigerbeetle/version.rb +3 -0
  23. data/src/tigerbeetle.rb +39 -0
  24. metadata +33 -350
  25. data/CHANGELOG.md +0 -162
  26. data/ext/tb_client/extconf.rb +0 -41
  27. data/ext/tb_client/tigerbeetle/LICENSE +0 -177
  28. data/ext/tb_client/tigerbeetle/build.zig +0 -2296
  29. data/ext/tb_client/tigerbeetle/src/aof.zig +0 -1000
  30. data/ext/tb_client/tigerbeetle/src/build/fetch.zig +0 -112
  31. data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +0 -808
  32. data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +0 -1283
  33. data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +0 -1704
  34. data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +0 -341
  35. data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +0 -1450
  36. data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +0 -1659
  37. data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +0 -406
  38. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +0 -1092
  39. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +0 -286
  40. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +0 -158
  41. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +0 -229
  42. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +0 -110
  43. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +0 -386
  44. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +0 -34
  45. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +0 -281
  46. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +0 -312
  47. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +0 -138
  48. data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +0 -466
  49. data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +0 -157
  50. data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +0 -90
  51. data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +0 -203
  52. data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +0 -79
  53. data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +0 -542
  54. data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +0 -109
  55. data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +0 -86
  56. data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +0 -370
  57. data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +0 -386
  58. data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +0 -167
  59. data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +0 -126
  60. data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +0 -996
  61. data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +0 -748
  62. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +0 -3238
  63. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +0 -1718
  64. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +0 -190
  65. data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +0 -104
  66. data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +0 -75
  67. data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +0 -522
  68. data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +0 -267
  69. data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +0 -3
  70. data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +0 -379
  71. data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +0 -131
  72. data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +0 -63
  73. data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +0 -588
  74. data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +0 -73
  75. data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +0 -106
  76. data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +0 -305
  77. data/ext/tb_client/tigerbeetle/src/config.zig +0 -296
  78. data/ext/tb_client/tigerbeetle/src/constants.zig +0 -790
  79. data/ext/tb_client/tigerbeetle/src/copyhound.zig +0 -202
  80. data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +0 -72
  81. data/ext/tb_client/tigerbeetle/src/direction.zig +0 -120
  82. data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +0 -158
  83. data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +0 -156
  84. data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +0 -252
  85. data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +0 -313
  86. data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +0 -87
  87. data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +0 -63
  88. data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +0 -47
  89. data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +0 -28
  90. data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +0 -61
  91. data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +0 -169
  92. data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +0 -46
  93. data/ext/tb_client/tigerbeetle/src/ewah.zig +0 -445
  94. data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +0 -128
  95. data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +0 -171
  96. data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +0 -179
  97. data/ext/tb_client/tigerbeetle/src/integration_tests.zig +0 -662
  98. data/ext/tb_client/tigerbeetle/src/io/common.zig +0 -155
  99. data/ext/tb_client/tigerbeetle/src/io/darwin.zig +0 -1093
  100. data/ext/tb_client/tigerbeetle/src/io/linux.zig +0 -1880
  101. data/ext/tb_client/tigerbeetle/src/io/test.zig +0 -1005
  102. data/ext/tb_client/tigerbeetle/src/io/windows.zig +0 -1598
  103. data/ext/tb_client/tigerbeetle/src/io.zig +0 -34
  104. data/ext/tb_client/tigerbeetle/src/iops.zig +0 -134
  105. data/ext/tb_client/tigerbeetle/src/list.zig +0 -236
  106. data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +0 -848
  107. data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +0 -179
  108. data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +0 -424
  109. data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +0 -420
  110. data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +0 -2114
  111. data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +0 -185
  112. data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +0 -1146
  113. data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +0 -1102
  114. data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +0 -200
  115. data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +0 -1495
  116. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +0 -739
  117. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +0 -166
  118. data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +0 -754
  119. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +0 -1294
  120. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +0 -510
  121. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +0 -1241
  122. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -628
  123. data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +0 -247
  124. data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +0 -116
  125. data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +0 -543
  126. data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +0 -938
  127. data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +0 -293
  128. data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +0 -359
  129. data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +0 -99
  130. data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +0 -17
  131. data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +0 -962
  132. data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +0 -617
  133. data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +0 -84
  134. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +0 -1500
  135. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -149
  136. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -7
  137. data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +0 -865
  138. data/ext/tb_client/tigerbeetle/src/lsm/table.zig +0 -607
  139. data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +0 -843
  140. data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +0 -90
  141. data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +0 -40
  142. data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +0 -629
  143. data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +0 -933
  144. data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +0 -534
  145. data/ext/tb_client/tigerbeetle/src/message_buffer.zig +0 -469
  146. data/ext/tb_client/tigerbeetle/src/message_bus.zig +0 -1219
  147. data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +0 -936
  148. data/ext/tb_client/tigerbeetle/src/message_pool.zig +0 -343
  149. data/ext/tb_client/tigerbeetle/src/multiversion.zig +0 -2195
  150. data/ext/tb_client/tigerbeetle/src/queue.zig +0 -390
  151. data/ext/tb_client/tigerbeetle/src/repl/completion.zig +0 -201
  152. data/ext/tb_client/tigerbeetle/src/repl/parser.zig +0 -1356
  153. data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +0 -496
  154. data/ext/tb_client/tigerbeetle/src/repl.zig +0 -1034
  155. data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +0 -973
  156. data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +0 -1866
  157. data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +0 -304
  158. data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +0 -227
  159. data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +0 -658
  160. data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +0 -466
  161. data/ext/tb_client/tigerbeetle/src/scripts/release.zig +0 -1058
  162. data/ext/tb_client/tigerbeetle/src/scripts.zig +0 -105
  163. data/ext/tb_client/tigerbeetle/src/shell.zig +0 -1195
  164. data/ext/tb_client/tigerbeetle/src/stack.zig +0 -260
  165. data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +0 -911
  166. data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +0 -2079
  167. data/ext/tb_client/tigerbeetle/src/state_machine.zig +0 -4872
  168. data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +0 -288
  169. data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +0 -3128
  170. data/ext/tb_client/tigerbeetle/src/static_allocator.zig +0 -82
  171. data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +0 -157
  172. data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +0 -292
  173. data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +0 -65
  174. data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +0 -1414
  175. data/ext/tb_client/tigerbeetle/src/stdx/huge_page_allocator.zig +0 -115
  176. data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +0 -92
  177. data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +0 -677
  178. data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +0 -336
  179. data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +0 -511
  180. data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +0 -112
  181. data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +0 -1163
  182. data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +0 -142
  183. data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +0 -361
  184. data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +0 -275
  185. data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +0 -295
  186. data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +0 -436
  187. data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +0 -48
  188. data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +0 -402
  189. data/ext/tb_client/tigerbeetle/src/storage.zig +0 -489
  190. data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +0 -180
  191. data/ext/tb_client/tigerbeetle/src/testing/bench.zig +0 -146
  192. data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +0 -53
  193. data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +0 -61
  194. data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +0 -76
  195. data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +0 -110
  196. data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +0 -412
  197. data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +0 -331
  198. data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -458
  199. data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +0 -1198
  200. data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +0 -128
  201. data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +0 -181
  202. data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +0 -144
  203. data/ext/tb_client/tigerbeetle/src/testing/id.zig +0 -97
  204. data/ext/tb_client/tigerbeetle/src/testing/io.zig +0 -317
  205. data/ext/tb_client/tigerbeetle/src/testing/marks.zig +0 -126
  206. data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +0 -533
  207. data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +0 -154
  208. data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +0 -389
  209. data/ext/tb_client/tigerbeetle/src/testing/storage.zig +0 -1247
  210. data/ext/tb_client/tigerbeetle/src/testing/table.zig +0 -249
  211. data/ext/tb_client/tigerbeetle/src/testing/time.zig +0 -98
  212. data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +0 -212
  213. data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +0 -26
  214. data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +0 -579
  215. data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +0 -39
  216. data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +0 -214
  217. data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +0 -34
  218. data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +0 -785
  219. data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +0 -543
  220. data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +0 -181
  221. data/ext/tb_client/tigerbeetle/src/tidy.zig +0 -1449
  222. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +0 -227
  223. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +0 -1069
  224. data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +0 -1422
  225. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +0 -1658
  226. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +0 -518
  227. data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +0 -36
  228. data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +0 -646
  229. data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +0 -958
  230. data/ext/tb_client/tigerbeetle/src/time.zig +0 -236
  231. data/ext/tb_client/tigerbeetle/src/trace/event.zig +0 -745
  232. data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +0 -462
  233. data/ext/tb_client/tigerbeetle/src/trace.zig +0 -556
  234. data/ext/tb_client/tigerbeetle/src/unit_tests.zig +0 -321
  235. data/ext/tb_client/tigerbeetle/src/vopr.zig +0 -1785
  236. data/ext/tb_client/tigerbeetle/src/vortex.zig +0 -101
  237. data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +0 -473
  238. data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +0 -208
  239. data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +0 -43
  240. data/ext/tb_client/tigerbeetle/src/vsr/client.zig +0 -768
  241. data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +0 -532
  242. data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +0 -338
  243. data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +0 -1019
  244. data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +0 -279
  245. data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +0 -1381
  246. data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +0 -315
  247. data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +0 -1460
  248. data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +0 -757
  249. data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +0 -797
  250. data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +0 -2586
  251. data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +0 -308
  252. data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +0 -1777
  253. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +0 -715
  254. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +0 -185
  255. data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +0 -333
  256. data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +0 -12356
  257. data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +0 -416
  258. data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +0 -165
  259. data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +0 -2928
  260. data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +0 -1075
  261. data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +0 -1603
  262. data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -484
  263. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +0 -405
  264. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -355
  265. data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +0 -29
  266. data/ext/tb_client/tigerbeetle/src/vsr.zig +0 -1727
  267. data/lib/tb_client/shared_lib.rb +0 -66
  268. data/lib/tb_client.rb +0 -282
  269. data/lib/tigerbeetle/account.rb +0 -38
  270. data/lib/tigerbeetle/account_balance.rb +0 -23
  271. data/lib/tigerbeetle/account_filter.rb +0 -31
  272. data/lib/tigerbeetle/atomic_counter.rb +0 -14
  273. data/lib/tigerbeetle/client.rb +0 -214
  274. data/lib/tigerbeetle/converters/account.rb +0 -63
  275. data/lib/tigerbeetle/converters/account_balance.rb +0 -31
  276. data/lib/tigerbeetle/converters/account_filter.rb +0 -32
  277. data/lib/tigerbeetle/converters/base.rb +0 -35
  278. data/lib/tigerbeetle/converters/create_accounts_result.rb +0 -21
  279. data/lib/tigerbeetle/converters/create_transfers_result.rb +0 -21
  280. data/lib/tigerbeetle/converters/query_filter.rb +0 -33
  281. data/lib/tigerbeetle/converters/time.rb +0 -23
  282. data/lib/tigerbeetle/converters/transfer.rb +0 -64
  283. data/lib/tigerbeetle/converters/uint_128.rb +0 -24
  284. data/lib/tigerbeetle/converters.rb +0 -12
  285. data/lib/tigerbeetle/error.rb +0 -4
  286. data/lib/tigerbeetle/id.rb +0 -30
  287. data/lib/tigerbeetle/platforms.rb +0 -9
  288. data/lib/tigerbeetle/query_filter.rb +0 -31
  289. data/lib/tigerbeetle/request.rb +0 -7
  290. data/lib/tigerbeetle/transfer.rb +0 -40
  291. data/lib/tigerbeetle/version.rb +0 -4
  292. data/lib/tigerbeetle.rb +0 -13
  293. data/tigerbeetle.gemspec +0 -60
@@ -1,1422 +0,0 @@
1
- //! Parse and validate command-line arguments for the tigerbeetle binary.
2
- //!
3
- //! Everything that can be validated without reading the data file must be validated here.
4
- //! Caller must additionally assert validity of arguments as a defense in depth.
5
- //!
6
- //! Some flags are experimental: intentionally undocumented and are not a part of the official
7
- //! surface area. Even experimental features must adhere to the same strict standard of safety,
8
- //! but they come without any performance or usability guarantees.
9
- //!
10
- //! Experimental features are not gated by comptime option for safety: it is much easier to review
11
- //! code for correctness when it is initially added to the main branch, rather when a comptime flag
12
- //! is lifted.
13
-
14
- const std = @import("std");
15
- const assert = std.debug.assert;
16
- const fmt = std.fmt;
17
- const net = std.net;
18
-
19
- const vsr = @import("vsr");
20
- const stdx = vsr.stdx;
21
- const constants = vsr.constants;
22
- const tigerbeetle = vsr.tigerbeetle;
23
- const data_file_size_min = vsr.superblock.data_file_size_min;
24
- const StateMachine = @import("./main.zig").StateMachine;
25
- const Grid = @import("./main.zig").Grid;
26
- const Ratio = stdx.PRNG.Ratio;
27
- const ByteSize = stdx.ByteSize;
28
- const Operation = tigerbeetle.Operation;
29
- const Duration = stdx.Duration;
30
-
31
- comptime {
32
- // Make sure we are running the Accounting StateMachine.
33
- assert(StateMachine.Operation == tigerbeetle.Operation);
34
- }
35
-
36
- const KiB = stdx.KiB;
37
- const GiB = stdx.GiB;
38
-
39
- const CLIArgs = union(enum) {
40
- const Format = struct {
41
- cluster: ?u128 = null,
42
- replica: ?u8 = null,
43
- // Experimental: standbys don't have a concrete practical use-case yet.
44
- standby: ?u8 = null,
45
- replica_count: u8,
46
- development: bool = false,
47
- log_debug: bool = false,
48
-
49
- @"--": void,
50
- path: []const u8,
51
- };
52
-
53
- const Recover = struct {
54
- cluster: u128,
55
- addresses: []const u8,
56
- replica: u8,
57
- replica_count: u8,
58
- development: bool = false,
59
- log_debug: bool = false,
60
-
61
- @"--": void,
62
- path: []const u8,
63
- };
64
-
65
- const Start = struct {
66
- // Stable CLI arguments.
67
- addresses: []const u8,
68
- cache_grid: ?ByteSize = null,
69
- development: bool = false,
70
-
71
- // Everything from here until positional arguments is considered experimental, and requires
72
- // `--experimental` to be set. Experimental flags disable automatic upgrades with
73
- // multiversion binaries; each replica has to be manually restarted. Experimental flags must
74
- // default to null, except for bools which must be false.
75
- experimental: bool = false,
76
-
77
- limit_storage: ?ByteSize = null,
78
- limit_pipeline_requests: ?u32 = null,
79
- limit_request: ?ByteSize = null,
80
- cache_accounts: ?ByteSize = null,
81
- cache_transfers: ?ByteSize = null,
82
- cache_transfers_pending: ?ByteSize = null,
83
- memory_lsm_manifest: ?ByteSize = null,
84
- memory_lsm_compaction: ?ByteSize = null,
85
- trace: ?[]const u8 = null,
86
- log_debug: bool = false,
87
- log_trace: bool = false,
88
- timeout_prepare_ms: ?u64 = null,
89
- timeout_grid_repair_message_ms: ?u64 = null,
90
- commit_stall_probability: ?Ratio = null,
91
-
92
- // Highly experimental options that will be removed in a future release:
93
- replicate_star: bool = false,
94
-
95
- statsd: ?[]const u8 = null,
96
-
97
- /// AOF (Append Only File) logs all transactions synchronously to disk before replying
98
- /// to the client. The logic behind this code has been kept as simple as possible -
99
- /// io_uring or kqueue aren't used, there aren't any fancy data structures. Just a simple
100
- /// log consisting of logged requests. Much like a redis AOF with fsync=on.
101
- /// Enabling this will have performance implications.
102
- aof_file: ?[]const u8 = null,
103
-
104
- /// Legacy AOF option. Mutually exclusive with aof_file, and will have the same effect as
105
- /// setting aof_file to '<data file path>.aof'.
106
- aof: bool = false,
107
-
108
- /// AOF recovery mode: accept timestamps passed by the client.
109
- /// Only enable this when recovering cluster from AOF.
110
- aof_recovery: bool = false,
111
-
112
- @"--": void,
113
- path: []const u8,
114
- };
115
-
116
- const Version = struct {
117
- verbose: bool = false,
118
- };
119
-
120
- const Repl = struct {
121
- addresses: []const u8,
122
- cluster: u128,
123
- verbose: bool = false,
124
- command: []const u8 = "",
125
- log_debug: bool = false,
126
- };
127
-
128
- // Experimental: the interface is subject to change.
129
- const Benchmark = struct {
130
- cache_accounts: ?[]const u8 = null,
131
- cache_transfers: ?[]const u8 = null,
132
- cache_transfers_pending: ?[]const u8 = null,
133
- cache_grid: ?[]const u8 = null,
134
- account_count: u64 = 10_000,
135
- account_count_hot: u32 = 0,
136
- log_debug: bool = false,
137
- log_debug_replica: bool = false,
138
- /// The probability distribution used to select accounts when making transfers or queries.
139
- account_distribution: Command.Benchmark.Distribution = .uniform,
140
- no_history: bool = false,
141
- imported: bool = false,
142
- account_batch_count: u32 = Operation.create_accounts.event_max(
143
- constants.message_body_size_max,
144
- ),
145
- transfer_count: u64 = 10_000_000,
146
- transfer_hot_percent: u32 = 100,
147
- transfer_pending: bool = false,
148
- transfer_batch_count: u32 = Operation.create_transfers.event_max(
149
- constants.message_body_size_max,
150
- ),
151
- transfer_batch_delay: Duration = .ms(0),
152
- validate: bool = false,
153
- checksum_performance: bool = false,
154
- query_count: u32 = 100,
155
- print_batch_timings: bool = false,
156
- id_order: Command.Benchmark.IdOrder = .sequential,
157
- clients: u32 = 1,
158
- statsd: ?[]const u8 = null,
159
- trace: ?[]const u8 = null,
160
- /// When set, don't delete the data file when the benchmark completes.
161
- file: ?[]const u8 = null,
162
- addresses: ?[]const u8 = null,
163
- seed: ?[]const u8 = null,
164
- };
165
-
166
- // Experimental: the interface is subject to change.
167
- const Inspect = union(enum) {
168
- constants,
169
- metrics,
170
- op: struct {
171
- @"--": void,
172
- op: u64,
173
- },
174
- superblock: struct {
175
- @"--": void,
176
- path: []const u8,
177
- },
178
- wal: struct {
179
- slot: ?usize = null,
180
-
181
- @"--": void,
182
- path: []const u8,
183
- },
184
- replies: struct {
185
- slot: ?usize = null,
186
- superblock_copy: ?u8 = null,
187
-
188
- @"--": void,
189
- path: []const u8,
190
- },
191
- grid: struct {
192
- block: ?u64 = null,
193
- superblock_copy: ?u8 = null,
194
-
195
- @"--": void,
196
- path: []const u8,
197
- },
198
- manifest: struct {
199
- superblock_copy: ?u8 = null,
200
-
201
- @"--": void,
202
- path: []const u8,
203
- },
204
- tables: struct {
205
- superblock_copy: ?u8 = null,
206
- tree: []const u8,
207
- level: ?u6 = null,
208
-
209
- @"--": void,
210
- path: []const u8,
211
- },
212
- integrity: struct {
213
- log_debug: bool = false,
214
- seed: ?[]const u8 = null,
215
- memory_lsm_manifest: ?ByteSize = null,
216
- skip_wal: bool = false,
217
- skip_client_replies: bool = false,
218
- skip_grid: bool = false,
219
-
220
- @"--": void,
221
- path: [:0]const u8,
222
- },
223
-
224
- pub const help =
225
- \\Usage:
226
- \\
227
- \\ tigerbeetle inspect [-h | --help]
228
- \\
229
- \\ tigerbeetle inspect constants
230
- \\
231
- \\ tigerbeetle inspect metrics
232
- \\
233
- \\ tigerbeetle inspect op <op>
234
- \\
235
- \\ tigerbeetle inspect superblock <path>
236
- \\
237
- \\ tigerbeetle inspect wal [--slot=<slot>] <path>
238
- \\
239
- \\ tigerbeetle inspect replies [--slot=<slot>] <path>
240
- \\
241
- \\ tigerbeetle inspect grid [--block=<address>] <path>
242
- \\
243
- \\ tigerbeetle inspect manifest <path>
244
- \\
245
- \\ tigerbeetle inspect tables --tree=<name|id> [--level=<integer>] <path>
246
- \\
247
- \\ tigerbeetle inspect integrity [--log-debug] [--seed=<seed>]
248
- \\ [--memory-lsm-manifest=<size>]
249
- \\ [--skip-wal] [--skip-client-replies] [--skip-grid]
250
- \\ <path>
251
- \\
252
- \\Options:
253
- \\
254
- \\ When `--superblock-copy` is set, use the trailer referenced by that superblock copy.
255
- \\ Otherwise, the current quorum will be used by default.
256
- \\
257
- \\ -h, --help
258
- \\ Print this help message and exit.
259
- \\
260
- \\ constants
261
- \\ Print most important compile-time parameters.
262
- \\
263
- \\ metrics
264
- \\ List metrics and their cardinalities.
265
- \\
266
- \\ op
267
- \\ Print op numbers for adjacent checkpoints and triggers.
268
- \\
269
- \\ superblock
270
- \\ Inspect the superblock header copies.
271
- \\
272
- \\ wal
273
- \\ Inspect the WAL headers and prepares.
274
- \\
275
- \\ wal --slot=<slot>
276
- \\ Inspect the WAL header/prepare in the given slot.
277
- \\
278
- \\ replies [--superblock-copy=<copy>]
279
- \\ Inspect the client reply headers and session numbers.
280
- \\
281
- \\ replies --slot=<slot> [--superblock-copy=<copy>]
282
- \\ Inspect a particular client reply.
283
- \\
284
- \\ grid [--superblock-copy=<copy>]
285
- \\ Inspect the free set.
286
- \\
287
- \\ grid --block=<address>
288
- \\ Inspect the block at the given address.
289
- \\
290
- \\ manifest [--superblock-copy=<copy>]
291
- \\ Inspect the LSM manifest.
292
- \\
293
- \\ tables --tree=<name|id> [--level=<integer>] [--superblock-copy=<copy>]
294
- \\ List the tables matching the given tree/level.
295
- \\ Example tree names: "transfers" (object table), "transfers.amount" (index table).
296
- \\
297
- \\ integrity
298
- \\ Scans the data file and checks all internal checksums to verify internal
299
- \\ integrity.
300
- \\
301
- ;
302
- };
303
-
304
- // Internal: used to validate multiversion binaries.
305
- const Multiversion = struct {
306
- log_debug: bool = false,
307
-
308
- @"--": void,
309
- path: []const u8,
310
- };
311
-
312
- // CDC connector for AMQP targets.
313
- const AMQP = struct {
314
- addresses: []const u8,
315
- cluster: u128,
316
- host: []const u8,
317
- user: []const u8,
318
- password: []const u8,
319
- vhost: []const u8,
320
- publish_exchange: ?[]const u8 = null,
321
- publish_routing_key: ?[]const u8 = null,
322
- event_count_max: ?u32 = null,
323
- idle_interval_ms: ?u32 = null,
324
- requests_per_second_limit: ?u32 = null,
325
- timestamp_last: ?u64 = null,
326
- verbose: bool = false,
327
- };
328
-
329
- format: Format,
330
- recover: Recover,
331
- start: Start,
332
- version: Version,
333
- repl: Repl,
334
- benchmark: Benchmark,
335
- inspect: Inspect,
336
- multiversion: Multiversion,
337
- amqp: AMQP,
338
-
339
- // TODO Document --cache-accounts, --cache-transfers, --cache-transfers-posted, --limit-storage,
340
- // --limit-pipeline-requests
341
- pub const help = fmt.comptimePrint(
342
- \\Usage:
343
- \\
344
- \\ tigerbeetle [-h | --help]
345
- \\
346
- \\ tigerbeetle format [--cluster=<integer>] --replica=<index> --replica-count=<integer> <path>
347
- \\
348
- \\ tigerbeetle start --addresses=<addresses> [--cache-grid=<size><KiB|MiB|GiB>] <path>
349
- \\
350
- \\ tigerbeetle recover --cluster=<integer> --addresses=<addresses>
351
- \\ --replica=<index> --replica-count=<integer> <path>
352
- \\
353
- \\ tigerbeetle version [--verbose]
354
- \\
355
- \\ tigerbeetle repl --cluster=<integer> --addresses=<addresses>
356
- \\
357
- \\Commands:
358
- \\
359
- \\ format Create a TigerBeetle replica data file at <path>.
360
- \\ The --replica and --replica-count arguments are required.
361
- \\ Each TigerBeetle replica must have its own data file.
362
- \\
363
- \\ start Run a TigerBeetle replica from the data file at <path>.
364
- \\
365
- \\ recover Create a TigerBeetle replica data file at <path> for recovery.
366
- \\ Used when a replica's data file is completely lost.
367
- \\ Replicas with recovered data files must sync with the cluster before
368
- \\ they can participate in consensus.
369
- \\
370
- \\ version Print the TigerBeetle build version and the compile-time config values.
371
- \\
372
- \\ repl Enter the TigerBeetle client REPL.
373
- \\
374
- \\ amqp CDC connector for AMQP targets.
375
- \\
376
- \\Options:
377
- \\
378
- \\ -h, --help
379
- \\ Print this help message and exit.
380
- \\
381
- \\ --cluster=<integer>
382
- \\ Set the cluster ID to the provided 128-bit unsigned decimal integer.
383
- \\ Defaults to generating a random cluster ID.
384
- \\
385
- \\ --replica=<index>
386
- \\ Set the zero-based index that will be used for the replica process.
387
- \\ An index greater than or equal to "replica-count" makes the replica a standby.
388
- \\ The value of this argument will be interpreted as an index into the --addresses array.
389
- \\
390
- \\ --replica-count=<integer>
391
- \\ Set the number of replicas participating in replication.
392
- \\
393
- \\ --addresses=<addresses>
394
- \\ The addresses of all replicas in the cluster.
395
- \\ Accepts a comma-separated list of IPv4/IPv6 addresses with port numbers.
396
- \\ The order is significant and must match across all replicas and clients.
397
- \\ Either the address or port number (but not both) may be omitted,
398
- \\ in which case a default of {[default_address]s} or {[default_port]d} will be used.
399
- \\ "addresses[i]" corresponds to replica "i".
400
- \\
401
- \\ --cache-grid=<size><KiB|MiB|GiB>
402
- \\ Set the grid cache size. The grid cache acts like a page cache for TigerBeetle,
403
- \\ and should be set as large as possible.
404
- \\ On a machine running only TigerBeetle, this is somewhere around
405
- \\ (Total RAM) - 3GiB (TigerBeetle) - 1GiB (System), eg 12GiB for a 16GiB machine.
406
- \\ Defaults to {[default_cache_grid_gb]d}GiB.
407
- \\
408
- \\ --verbose
409
- \\ Print compile-time configuration along with the build version.
410
- \\
411
- \\ --development
412
- \\ Allow the replica to format/start/recover even when Direct IO is unavailable.
413
- \\ Additionally, use smaller cache sizes and batch size by default.
414
- \\
415
- \\ Since this shrinks the batch size, note that:
416
- \\ * All replicas should use the same batch size. That is, if any replica in the cluster has
417
- \\ "--development", then all replicas should have "--development".
418
- \\ * It is always possible to increase the batch size by restarting without "--development".
419
- \\ * Shrinking the batch size of an existing cluster is possible, but not recommended.
420
- \\
421
- \\ For safety, production replicas should always enforce Direct IO -- this flag should only be
422
- \\ used for testing and development. It should not be used for production or benchmarks.
423
- \\
424
- \\Examples:
425
- \\
426
- \\ tigerbeetle format --cluster=0 --replica=0 --replica-count=3 0_0.tigerbeetle
427
- \\ tigerbeetle format --cluster=0 --replica=1 --replica-count=3 0_1.tigerbeetle
428
- \\ tigerbeetle format --cluster=0 --replica=2 --replica-count=3 0_2.tigerbeetle
429
- \\
430
- \\ tigerbeetle start --addresses=127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002 0_0.tigerbeetle
431
- \\ tigerbeetle start --addresses=3000,3001,3002 0_1.tigerbeetle
432
- \\ tigerbeetle start --addresses=3000,3001,3002 0_2.tigerbeetle
433
- \\
434
- \\ tigerbeetle start --addresses=192.168.0.1,192.168.0.2,192.168.0.3 0_0.tigerbeetle
435
- \\
436
- \\ tigerbeetle start --addresses='[::1]:3000,[::1]:3001,[::1]:3002' 0_0.tigerbeetle
437
- \\
438
- \\ tigerbeetle recover --cluster=0 --addresses=3003,3001,3002 \
439
- \\ --replica=1 --replica-count=3 0_1.tigerbeetle
440
- \\
441
- \\ tigerbeetle version --verbose
442
- \\
443
- \\ tigerbeetle repl --addresses=3000,3001,3002 --cluster=0
444
- \\
445
- \\ tigerbeetle amqp --addresses=3000,3001,3002 --cluster=0 \
446
- \\ --host=127.0.0.1 --vhost=/ --user=guest --password=guest \
447
- \\ --publish-exchange=my_exhange_name
448
- \\
449
- , .{
450
- .default_address = constants.address,
451
- .default_port = constants.port,
452
- .default_cache_grid_gb = @divExact(
453
- constants.grid_cache_size_default,
454
- GiB,
455
- ),
456
- });
457
- };
458
-
459
- const StartDefaults = struct {
460
- limit_pipeline_requests: u32,
461
- limit_request: ByteSize,
462
- cache_accounts: ByteSize,
463
- cache_transfers: ByteSize,
464
- cache_transfers_pending: ByteSize,
465
- cache_grid: ByteSize,
466
- memory_lsm_compaction: ByteSize,
467
- };
468
-
469
- const start_defaults_production = StartDefaults{
470
- .limit_pipeline_requests = vsr.stdx.div_ceil(constants.clients_max, 2) -
471
- constants.pipeline_prepare_queue_max,
472
- .limit_request = .{ .value = constants.message_size_max },
473
- .cache_accounts = .{ .value = constants.cache_accounts_size_default },
474
- .cache_transfers = .{ .value = constants.cache_transfers_size_default },
475
- .cache_transfers_pending = .{ .value = constants.cache_transfers_pending_size_default },
476
- .cache_grid = .{ .value = constants.grid_cache_size_default },
477
- .memory_lsm_compaction = .{
478
- // By default, add a few extra blocks for beat-scoped work.
479
- .value = (lsm_compaction_block_count_min + 16) * constants.block_size,
480
- },
481
- };
482
-
483
- const start_defaults_development = StartDefaults{
484
- .limit_pipeline_requests = 0,
485
- .limit_request = .{ .value = 32 * KiB },
486
- .cache_accounts = .{ .value = 0 },
487
- .cache_transfers = .{ .value = 0 },
488
- .cache_transfers_pending = .{ .value = 0 },
489
- .cache_grid = .{ .value = constants.block_size * Grid.Cache.value_count_max_multiple },
490
- .memory_lsm_compaction = .{ .value = lsm_compaction_block_memory_min },
491
- };
492
-
493
- const lsm_compaction_block_count_min = StateMachine.Forest.Options.compaction_block_count_min;
494
- const lsm_compaction_block_memory_min = lsm_compaction_block_count_min * constants.block_size;
495
-
496
- /// While CLIArgs store raw arguments as passed on the command line, Command ensures that arguments
497
- /// are properly validated and desugared (e.g, sizes converted to counts where appropriate).
498
- pub const Command = union(enum) {
499
- const Addresses = stdx.BoundedArrayType(std.net.Address, constants.members_max);
500
- const Path = stdx.BoundedArrayType(u8, std.fs.max_path_bytes);
501
-
502
- pub const Format = struct {
503
- cluster: u128,
504
- replica: u8,
505
- replica_count: u8,
506
- development: bool,
507
- path: []const u8,
508
- log_debug: bool,
509
- };
510
-
511
- pub const Recover = struct {
512
- cluster: u128,
513
- addresses: Addresses,
514
- replica: u8,
515
- replica_count: u8,
516
- development: bool,
517
- path: []const u8,
518
- log_debug: bool,
519
- };
520
-
521
- pub const Start = struct {
522
- addresses: Addresses,
523
- // true when the value of `--addresses` is exactly `0`. Used to enable "magic zero" mode for
524
- // testing. We check the raw string rather then the parsed address to prevent triggering
525
- // this logic by accident.
526
- addresses_zero: bool,
527
- cache_accounts: u32,
528
- cache_transfers: u32,
529
- cache_transfers_pending: u32,
530
- storage_size_limit: u64,
531
- pipeline_requests_limit: u32,
532
- request_size_limit: u32,
533
- cache_grid_blocks: u32,
534
- lsm_forest_compaction_block_count: u32,
535
- lsm_forest_node_count: u32,
536
- timeout_prepare_ticks: ?u64,
537
- timeout_grid_repair_message_ticks: ?u64,
538
- commit_stall_probability: ?Ratio,
539
- trace: ?[]const u8,
540
- development: bool,
541
- experimental: bool,
542
- replicate_star: bool,
543
- aof_file: ?Path,
544
- aof_recovery: bool,
545
- path: []const u8,
546
- log_debug: bool,
547
- log_trace: bool,
548
- statsd: ?std.net.Address,
549
- };
550
-
551
- pub const Version = struct {
552
- verbose: bool,
553
- };
554
-
555
- pub const Repl = struct {
556
- addresses: Addresses,
557
- cluster: u128,
558
- verbose: bool,
559
- statements: []const u8,
560
- log_debug: bool,
561
- };
562
-
563
- pub const Benchmark = struct {
564
- /// The ID order can affect the results of a benchmark significantly. Specifically,
565
- /// sequential is expected to be the best (since it can take advantage of various
566
- /// optimizations such as avoiding negative prefetch) while random/reversed can't.
567
- pub const IdOrder = enum {
568
- // Use TBIDs (time-based IDs) for transfers and a random start for account IDs.
569
- // Avoids ID collisions between benchmark runs against the same cluster.
570
- // Incompatible with --validate (IDs are not deterministically replayable).
571
- tbid,
572
- sequential,
573
- random,
574
- reversed,
575
- };
576
-
577
- pub const Distribution = enum {
578
- /// Shuffled zipfian numbers where relatively few indexes are selected frequently.
579
- zipfian,
580
- /// Also zipfian, but the most recent indexes are selected frequently.
581
- latest,
582
- /// Uniform distribution; unrealistic workloads.
583
- uniform,
584
- };
585
-
586
- cache_accounts: ?[]const u8,
587
- cache_transfers: ?[]const u8,
588
- cache_transfers_pending: ?[]const u8,
589
- cache_grid: ?[]const u8,
590
- log_debug: bool,
591
- log_debug_replica: bool,
592
- account_count: u64,
593
- account_count_hot: u32,
594
- account_distribution: Distribution,
595
- no_history: bool,
596
- imported: bool,
597
- account_batch_count: u32,
598
- transfer_count: u64,
599
- transfer_hot_percent: u32,
600
- transfer_pending: bool,
601
- transfer_batch_count: u32,
602
- transfer_batch_delay: Duration,
603
- validate: bool,
604
- checksum_performance: bool,
605
- query_count: u32,
606
- print_batch_timings: bool,
607
- id_order: IdOrder,
608
- clients: u32,
609
- statsd: ?[]const u8,
610
- trace: ?[]const u8,
611
- file: ?[]const u8,
612
- addresses: ?Addresses,
613
- seed: ?[]const u8,
614
- };
615
-
616
- pub const Inspect = union(enum) {
617
- constants,
618
- metrics,
619
- op: u64,
620
- data_file: DataFile,
621
- integrity: Integrity,
622
-
623
- pub const DataFile = struct {
624
- path: []const u8,
625
- query: union(enum) {
626
- superblock,
627
- wal: struct {
628
- slot: ?usize,
629
- },
630
- replies: struct {
631
- slot: ?usize,
632
- superblock_copy: ?u8,
633
- },
634
- grid: struct {
635
- block: ?u64,
636
- superblock_copy: ?u8,
637
- },
638
- manifest: struct {
639
- superblock_copy: ?u8,
640
- },
641
- tables: struct {
642
- superblock_copy: ?u8,
643
- tree: []const u8,
644
- level: ?u6,
645
- },
646
- },
647
- };
648
-
649
- pub const Integrity = struct {
650
- log_debug: bool,
651
- seed: ?[]const u8,
652
- lsm_forest_node_count: u32,
653
- skip_wal: bool,
654
- skip_client_replies: bool,
655
- skip_grid: bool,
656
- path: [:0]const u8,
657
- };
658
- };
659
-
660
- pub const Multiversion = struct {
661
- path: []const u8,
662
- log_debug: bool,
663
- };
664
-
665
- pub const AMQP = struct {
666
- addresses: Addresses,
667
- cluster: u128,
668
- host: std.net.Address,
669
- user: []const u8,
670
- password: []const u8,
671
- vhost: []const u8,
672
- publish_exchange: ?[]const u8,
673
- publish_routing_key: ?[]const u8,
674
- event_count_max: ?u32,
675
- idle_interval_ms: ?u32,
676
- requests_per_second_limit: ?u32,
677
- timestamp_last: ?u64,
678
- log_debug: bool,
679
- };
680
-
681
- format: Format,
682
- recover: Recover,
683
- start: Start,
684
- version: Version,
685
- repl: Repl,
686
- benchmark: Benchmark,
687
- inspect: Inspect,
688
- multiversion: Multiversion,
689
- amqp: AMQP,
690
- };
691
-
692
- /// Parse the command line arguments passed to the `tigerbeetle` binary.
693
- /// Exits the program with a non-zero exit code if an error is found.
694
- pub fn parse_args(args_iterator: *std.process.ArgIterator) Command {
695
- const cli_args = stdx.flags(args_iterator, CLIArgs);
696
-
697
- return switch (cli_args) {
698
- .format => |format| .{ .format = parse_args_format(format) },
699
- .recover => |recover| .{ .recover = parse_args_recover(recover) },
700
- .start => |start| .{ .start = parse_args_start(start) },
701
- .version => |version| .{ .version = parse_args_version(version) },
702
- .repl => |repl| .{ .repl = parse_args_repl(repl) },
703
- .benchmark => |benchmark| .{ .benchmark = parse_args_benchmark(benchmark) },
704
- .inspect => |inspect| .{ .inspect = parse_args_inspect(inspect) },
705
- .multiversion => |multiversion| .{ .multiversion = parse_args_multiversion(multiversion) },
706
- .amqp => |amqp| .{ .amqp = parse_args_amqp(amqp) },
707
- };
708
- }
709
-
710
- fn parse_args_format(format: CLIArgs.Format) Command.Format {
711
- if (format.replica_count == 0) {
712
- vsr.fatal(.cli, "--replica-count: value needs to be greater than zero", .{});
713
- }
714
- if (format.replica_count > constants.replicas_max) {
715
- vsr.fatal(.cli, "--replica-count: value is too large ({}), at most {} is allowed", .{
716
- format.replica_count,
717
- constants.replicas_max,
718
- });
719
- }
720
-
721
- if (format.replica == null and format.standby == null) {
722
- vsr.fatal(.cli, "--replica: argument is required", .{});
723
- }
724
-
725
- if (format.replica != null and format.standby != null) {
726
- vsr.fatal(.cli, "--standby: conflicts with '--replica'", .{});
727
- }
728
-
729
- if (format.replica) |replica| {
730
- if (replica >= format.replica_count) {
731
- vsr.fatal(.cli, "--replica: value is too large ({}), at most {} is allowed", .{
732
- replica,
733
- format.replica_count - 1,
734
- });
735
- }
736
- }
737
-
738
- if (format.standby) |standby| {
739
- if (standby < format.replica_count) {
740
- vsr.fatal(.cli, "--standby: value is too small ({}), at least {} is required", .{
741
- standby,
742
- format.replica_count,
743
- });
744
- }
745
- if (standby >= format.replica_count + constants.standbys_max) {
746
- vsr.fatal(.cli, "--standby: value is too large ({}), at most {} is allowed", .{
747
- standby,
748
- format.replica_count + constants.standbys_max - 1,
749
- });
750
- }
751
- }
752
-
753
- const replica = (format.replica orelse format.standby).?;
754
- assert(replica < constants.members_max);
755
- assert(replica < format.replica_count + constants.standbys_max);
756
-
757
- const cluster_random = std.crypto.random.int(u128);
758
- assert(cluster_random != 0);
759
- const cluster = format.cluster orelse cluster_random;
760
- if (format.cluster == null) {
761
- std.log.info("generated random cluster id: {}\n", .{cluster});
762
- } else if (format.cluster.? == 0) {
763
- std.log.warn("a cluster id of 0 is reserved for testing and benchmarking, " ++
764
- "do not use in production", .{});
765
- std.log.warn("omit --cluster=0 to randomly generate a suitable id\n", .{});
766
- }
767
-
768
- return .{
769
- .cluster = cluster, // just an ID, any value is allowed
770
- .replica = replica,
771
- .replica_count = format.replica_count,
772
- .development = format.development,
773
- .path = format.path,
774
- .log_debug = format.log_debug,
775
- };
776
- }
777
-
778
- fn parse_args_recover(recover: CLIArgs.Recover) Command.Recover {
779
- if (recover.replica_count == 0) {
780
- vsr.fatal(.cli, "--replica-count: value needs to be greater than zero", .{});
781
- }
782
- if (recover.replica_count > constants.replicas_max) {
783
- vsr.fatal(.cli, "--replica-count: value is too large ({}), at most {} is allowed", .{
784
- recover.replica_count,
785
- constants.replicas_max,
786
- });
787
- }
788
-
789
- if (recover.replica >= recover.replica_count) {
790
- vsr.fatal(.cli, "--replica: value is too large ({}), at most {} is allowed", .{
791
- recover.replica,
792
- recover.replica_count - 1,
793
- });
794
- }
795
- if (recover.replica_count <= 2) {
796
- vsr.fatal(.cli, "--replica-count: 1- or 2- replica clusters don't support 'recover'", .{});
797
- }
798
-
799
- const replica = recover.replica;
800
- assert(replica < constants.members_max);
801
- assert(replica < recover.replica_count);
802
-
803
- return .{
804
- .cluster = recover.cluster,
805
- .addresses = parse_addresses(recover.addresses, "--addresses", Command.Addresses),
806
- .replica = replica,
807
- .replica_count = recover.replica_count,
808
- .development = recover.development,
809
- .path = recover.path,
810
- .log_debug = recover.log_debug,
811
- };
812
- }
813
-
814
- fn parse_args_start(start: CLIArgs.Start) Command.Start {
815
- // Allowlist of stable flags. --development will disable automatic multiversion
816
- // upgrades too, but the flag itself is stable.
817
- const stable_args = .{
818
- "addresses", "cache_grid",
819
- "development", "experimental",
820
- };
821
- inline for (std.meta.fields(@TypeOf(start))) |field| {
822
- @setEvalBranchQuota(4_000);
823
- // Positional arguments can't be experimental.
824
- comptime if (std.mem.eql(u8, field.name, "--")) break;
825
-
826
- const stable_field = comptime for (stable_args) |stable_arg| {
827
- assert(std.meta.fieldIndex(@TypeOf(start), stable_arg) != null);
828
- if (std.mem.eql(u8, field.name, stable_arg)) {
829
- break true;
830
- }
831
- } else false;
832
- if (stable_field) continue;
833
-
834
- const flag_name = comptime blk: {
835
- var result: [2 + field.name.len]u8 = ("--" ++ field.name).*;
836
- std.mem.replaceScalar(u8, &result, '_', '-');
837
- break :blk result;
838
- };
839
-
840
- // If you've added a flag and get a comptime error here, it's likely because
841
- // we require experimental flags to default to null.
842
- const required_default = if (field.type == bool) false else null;
843
- assert(field.defaultValue().? == required_default);
844
-
845
- if (@field(start, field.name) != required_default and !start.experimental) {
846
- vsr.fatal(
847
- .cli,
848
- "{s} is marked experimental, add `--experimental` to continue.",
849
- .{flag_name},
850
- );
851
- }
852
- } else unreachable;
853
-
854
- const groove_config = StateMachine.Forest.groove_config;
855
- const AccountsValuesCache = groove_config.accounts.ObjectsCache.Cache;
856
- const TransfersValuesCache = groove_config.transfers.ObjectsCache.Cache;
857
- const TransfersPendingValuesCache = groove_config.transfers_pending.ObjectsCache.Cache;
858
-
859
- const addresses = parse_addresses(start.addresses, "--addresses", Command.Addresses);
860
- const defaults =
861
- if (start.development) start_defaults_development else start_defaults_production;
862
-
863
- const start_limit_storage: ByteSize = start.limit_storage orelse
864
- .{ .value = constants.storage_size_limit_default };
865
- const start_memory_lsm_manifest: ByteSize = start.memory_lsm_manifest orelse
866
- .{ .value = constants.lsm_manifest_memory_size_default };
867
-
868
- const storage_size_limit = start_limit_storage.bytes();
869
- const storage_size_limit_min = data_file_size_min;
870
- const storage_size_limit_max = constants.storage_size_limit_max;
871
- if (storage_size_limit > storage_size_limit_max) {
872
- vsr.fatal(.cli, "--limit-storage: size {}{s} exceeds maximum: {}", .{
873
- start_limit_storage.value,
874
- start_limit_storage.suffix(),
875
- vsr.stdx.fmt_int_size_bin_exact(storage_size_limit_max),
876
- });
877
- }
878
- if (storage_size_limit < storage_size_limit_min) {
879
- vsr.fatal(.cli, "--limit-storage: size {}{s} is below minimum: {}", .{
880
- start_limit_storage.value,
881
- start_limit_storage.suffix(),
882
- vsr.stdx.fmt_int_size_bin_exact(storage_size_limit_min),
883
- });
884
- }
885
- if (storage_size_limit % constants.sector_size != 0) {
886
- vsr.fatal(
887
- .cli,
888
- "--limit-storage: size {}{s} must be a multiple of sector size ({})",
889
- .{
890
- start_limit_storage.value,
891
- start_limit_storage.suffix(),
892
- vsr.stdx.fmt_int_size_bin_exact(constants.sector_size),
893
- },
894
- );
895
- }
896
-
897
- const pipeline_limit =
898
- start.limit_pipeline_requests orelse defaults.limit_pipeline_requests;
899
- const pipeline_limit_min = 0;
900
- const pipeline_limit_max = constants.pipeline_request_queue_max;
901
- if (pipeline_limit > pipeline_limit_max) {
902
- vsr.fatal(.cli, "--limit-pipeline-requests: count {} exceeds maximum: {}", .{
903
- pipeline_limit,
904
- pipeline_limit_max,
905
- });
906
- }
907
- if (pipeline_limit < pipeline_limit_min) {
908
- vsr.fatal(.cli, "--limit-pipeline-requests: count {} is below minimum: {}", .{
909
- pipeline_limit,
910
- pipeline_limit_min,
911
- });
912
- }
913
-
914
- // The minimum is chosen rather arbitrarily as 4096 since it is the sector size.
915
- const request_size_limit = start.limit_request orelse defaults.limit_request;
916
- const request_size_limit_min = 4096;
917
- const request_size_limit_max = constants.message_size_max;
918
- if (request_size_limit.bytes() > request_size_limit_max) {
919
- vsr.fatal(.cli, "--limit-request: size {}{s} exceeds maximum: {}", .{
920
- request_size_limit.value,
921
- request_size_limit.suffix(),
922
- vsr.stdx.fmt_int_size_bin_exact(request_size_limit_max),
923
- });
924
- }
925
- if (request_size_limit.bytes() < request_size_limit_min) {
926
- vsr.fatal(.cli, "--limit-request: size {}{s} is below minimum: {}", .{
927
- request_size_limit.value,
928
- request_size_limit.suffix(),
929
- vsr.stdx.fmt_int_size_bin_exact(request_size_limit_min),
930
- });
931
- }
932
-
933
- const lsm_manifest_memory = start_memory_lsm_manifest.bytes();
934
- const lsm_manifest_memory_max = constants.lsm_manifest_memory_size_max;
935
- const lsm_manifest_memory_min = constants.lsm_manifest_memory_size_min;
936
- const lsm_manifest_memory_multiplier = constants.lsm_manifest_memory_size_multiplier;
937
- if (lsm_manifest_memory > lsm_manifest_memory_max) {
938
- vsr.fatal(.cli, "--memory-lsm-manifest: size {}{s} exceeds maximum: {}", .{
939
- start_memory_lsm_manifest.value,
940
- start_memory_lsm_manifest.suffix(),
941
- vsr.stdx.fmt_int_size_bin_exact(lsm_manifest_memory_max),
942
- });
943
- }
944
- if (lsm_manifest_memory < lsm_manifest_memory_min) {
945
- vsr.fatal(.cli, "--memory-lsm-manifest: size {}{s} is below minimum: {}", .{
946
- start_memory_lsm_manifest.value,
947
- start_memory_lsm_manifest.suffix(),
948
- vsr.stdx.fmt_int_size_bin_exact(lsm_manifest_memory_min),
949
- });
950
- }
951
- if (lsm_manifest_memory % lsm_manifest_memory_multiplier != 0) {
952
- vsr.fatal(
953
- .cli,
954
- "--memory-lsm-manifest: size {}{s} must be a multiple of {}",
955
- .{
956
- start_memory_lsm_manifest.value,
957
- start_memory_lsm_manifest.suffix(),
958
- vsr.stdx.fmt_int_size_bin_exact(lsm_manifest_memory_multiplier),
959
- },
960
- );
961
- }
962
-
963
- const lsm_compaction_block_memory =
964
- start.memory_lsm_compaction orelse defaults.memory_lsm_compaction;
965
- const lsm_compaction_block_memory_max = constants.compaction_block_memory_size_max;
966
- if (lsm_compaction_block_memory.bytes() > lsm_compaction_block_memory_max) {
967
- vsr.fatal(.cli, "--memory-lsm-compaction: size {}{s} exceeds maximum: {}", .{
968
- lsm_compaction_block_memory.value,
969
- lsm_compaction_block_memory.suffix(),
970
- vsr.stdx.fmt_int_size_bin_exact(lsm_compaction_block_memory_max),
971
- });
972
- }
973
- if (lsm_compaction_block_memory.bytes() < lsm_compaction_block_memory_min) {
974
- vsr.fatal(.cli, "--memory-lsm-compaction: size {}{s} is below minimum: {}", .{
975
- lsm_compaction_block_memory.value,
976
- lsm_compaction_block_memory.suffix(),
977
- vsr.stdx.fmt_int_size_bin_exact(lsm_compaction_block_memory_min),
978
- });
979
- }
980
- if (lsm_compaction_block_memory.bytes() % constants.block_size != 0) {
981
- vsr.fatal(
982
- .cli,
983
- "--memory-lsm-compaction: size {}{s} must be a multiple of {}",
984
- .{
985
- lsm_compaction_block_memory.value,
986
- lsm_compaction_block_memory.suffix(),
987
- vsr.stdx.fmt_int_size_bin_exact(constants.block_size),
988
- },
989
- );
990
- }
991
-
992
- const lsm_forest_compaction_block_count: u32 =
993
- @intCast(@divExact(lsm_compaction_block_memory.bytes(), constants.block_size));
994
- const lsm_forest_node_count: u32 =
995
- @intCast(@divExact(lsm_manifest_memory, constants.lsm_manifest_node_size));
996
-
997
- const aof_file: ?Command.Path = if (start.aof) blk: {
998
- if (start.aof_file != null) {
999
- vsr.fatal(.cli, "--aof is mutually exclusive with --aof-file", .{});
1000
- }
1001
-
1002
- var aof_file: Command.Path = .{};
1003
- if (aof_file.capacity() < start.path.len + 4) {
1004
- vsr.fatal(.cli, "data file path is too long for --aof. use --aof-file", .{});
1005
- }
1006
- aof_file.push_slice(start.path);
1007
- aof_file.push_slice(".aof");
1008
-
1009
- std.log.warn(
1010
- "--aof is deprecated. consider switching to '--aof-file={s}'",
1011
- .{aof_file.const_slice()},
1012
- );
1013
-
1014
- break :blk aof_file;
1015
- } else if (start.aof_file) |start_aof_file| blk: {
1016
- if (!std.mem.endsWith(u8, start_aof_file, ".aof")) {
1017
- vsr.fatal(.cli, "--aof-file must end with .aof: '{s}'", .{start_aof_file});
1018
- }
1019
-
1020
- var aof_file: Command.Path = .{};
1021
- if (aof_file.capacity() < start.path.len) {
1022
- vsr.fatal(.cli, "--aof-file path is too long", .{});
1023
- }
1024
- aof_file.push_slice(start_aof_file);
1025
-
1026
- break :blk aof_file;
1027
- } else null;
1028
-
1029
- if (start.log_trace and !start.log_debug) {
1030
- vsr.fatal(.cli, "--log-debug must be provided when using --log-trace", .{});
1031
- }
1032
-
1033
- return .{
1034
- .addresses = addresses,
1035
- .addresses_zero = std.mem.eql(u8, start.addresses, "0"),
1036
- .storage_size_limit = storage_size_limit,
1037
- .pipeline_requests_limit = pipeline_limit,
1038
- .request_size_limit = @intCast(request_size_limit.bytes()),
1039
- .cache_accounts = parse_cache_size_to_count(
1040
- tigerbeetle.Account,
1041
- AccountsValuesCache,
1042
- start.cache_accounts orelse defaults.cache_accounts,
1043
- "--cache-accounts",
1044
- ),
1045
- .cache_transfers = parse_cache_size_to_count(
1046
- tigerbeetle.Transfer,
1047
- TransfersValuesCache,
1048
- start.cache_transfers orelse defaults.cache_transfers,
1049
- "--cache-transfers",
1050
- ),
1051
- .cache_transfers_pending = parse_cache_size_to_count(
1052
- vsr.state_machine.TransferPending,
1053
- TransfersPendingValuesCache,
1054
- start.cache_transfers_pending orelse defaults.cache_transfers_pending,
1055
- "--cache-transfers-pending",
1056
- ),
1057
- .cache_grid_blocks = parse_cache_size_to_count(
1058
- [constants.block_size]u8,
1059
- Grid.Cache,
1060
- start.cache_grid orelse defaults.cache_grid,
1061
- "--cache-grid",
1062
- ),
1063
- .lsm_forest_compaction_block_count = lsm_forest_compaction_block_count,
1064
- .lsm_forest_node_count = lsm_forest_node_count,
1065
- .timeout_prepare_ticks = parse_timeout_to_ticks(
1066
- start.timeout_prepare_ms,
1067
- "--timeout-prepare-ms",
1068
- ),
1069
- .timeout_grid_repair_message_ticks = parse_timeout_to_ticks(
1070
- start.timeout_grid_repair_message_ms,
1071
- "--timeout-grid-repair-message-ms",
1072
- ),
1073
- .commit_stall_probability = start.commit_stall_probability,
1074
- .development = start.development,
1075
- .experimental = start.experimental,
1076
- .trace = start.trace,
1077
- .replicate_star = start.replicate_star,
1078
- .aof_file = aof_file,
1079
- .aof_recovery = start.aof_recovery,
1080
- .path = start.path,
1081
- .log_debug = start.log_debug,
1082
- .log_trace = start.log_trace,
1083
- .statsd = if (start.statsd) |statsd_address|
1084
- parse_address_and_port(statsd_address, "--statsd", 8125)
1085
- else
1086
- null,
1087
- };
1088
- }
1089
-
1090
- fn parse_args_version(version: CLIArgs.Version) Command.Version {
1091
- return .{
1092
- .verbose = version.verbose,
1093
- };
1094
- }
1095
-
1096
- fn parse_args_repl(repl: CLIArgs.Repl) Command.Repl {
1097
- const addresses = parse_addresses(repl.addresses, "--addresses", Command.Addresses);
1098
-
1099
- return .{
1100
- .addresses = addresses,
1101
- .cluster = repl.cluster,
1102
- .verbose = repl.verbose,
1103
- .statements = repl.command,
1104
- .log_debug = repl.log_debug,
1105
- };
1106
- }
1107
-
1108
- const account_batch_count_max = @divExact(
1109
- constants.message_size_max - @sizeOf(vsr.Header),
1110
- @sizeOf(tigerbeetle.Account),
1111
- );
1112
-
1113
- const transfer_batch_count_max = @divExact(
1114
- constants.message_size_max - @sizeOf(vsr.Header),
1115
- @sizeOf(tigerbeetle.Transfer),
1116
- );
1117
-
1118
- fn parse_args_benchmark(benchmark: CLIArgs.Benchmark) Command.Benchmark {
1119
- const addresses = if (benchmark.addresses) |addresses|
1120
- parse_addresses(addresses, "--addresses", Command.Addresses)
1121
- else
1122
- null;
1123
-
1124
- if (benchmark.addresses != null and benchmark.file != null) {
1125
- vsr.fatal(.cli, "--file: --addresses and --file are mutually exclusive", .{});
1126
- }
1127
-
1128
- if (benchmark.account_batch_count == 0) {
1129
- vsr.fatal(.cli, "--account-batch-count must be greater than 0", .{});
1130
- }
1131
-
1132
- if (benchmark.account_batch_count > account_batch_count_max) {
1133
- vsr.fatal(
1134
- .cli,
1135
- "--account-batch-count must be less than or equal to {}",
1136
- .{account_batch_count_max},
1137
- );
1138
- }
1139
-
1140
- if (benchmark.transfer_batch_count == 0) {
1141
- vsr.fatal(.cli, "--transfer-batch-count must be greater than 0", .{});
1142
- }
1143
-
1144
- if (benchmark.transfer_batch_count > transfer_batch_count_max) {
1145
- vsr.fatal(
1146
- .cli,
1147
- "--transfer-batch-count must be less than or equal to {}",
1148
- .{transfer_batch_count_max},
1149
- );
1150
- }
1151
-
1152
- return .{
1153
- .cache_accounts = benchmark.cache_accounts,
1154
- .cache_transfers = benchmark.cache_transfers,
1155
- .cache_transfers_pending = benchmark.cache_transfers_pending,
1156
- .cache_grid = benchmark.cache_grid,
1157
- .log_debug = benchmark.log_debug,
1158
- .log_debug_replica = benchmark.log_debug_replica,
1159
- .account_count = benchmark.account_count,
1160
- .account_count_hot = benchmark.account_count_hot,
1161
- .account_distribution = benchmark.account_distribution,
1162
- .no_history = benchmark.no_history,
1163
- .imported = benchmark.imported,
1164
- .account_batch_count = benchmark.account_batch_count,
1165
- .transfer_count = benchmark.transfer_count,
1166
- .transfer_hot_percent = benchmark.transfer_hot_percent,
1167
- .transfer_pending = benchmark.transfer_pending,
1168
- .transfer_batch_count = benchmark.transfer_batch_count,
1169
- .transfer_batch_delay = benchmark.transfer_batch_delay,
1170
- .validate = benchmark.validate,
1171
- .checksum_performance = benchmark.checksum_performance,
1172
- .query_count = benchmark.query_count,
1173
- .print_batch_timings = benchmark.print_batch_timings,
1174
- .clients = benchmark.clients,
1175
- .id_order = benchmark.id_order,
1176
- .statsd = benchmark.statsd,
1177
- .trace = benchmark.trace,
1178
- .file = benchmark.file,
1179
- .addresses = addresses,
1180
- .seed = benchmark.seed,
1181
- };
1182
- }
1183
-
1184
- fn parse_args_inspect_integrity(args: CLIArgs.Inspect) Command.Inspect.Integrity {
1185
- const integrity = args.integrity;
1186
-
1187
- const scrub_memory_lsm_manifest: ByteSize = integrity.memory_lsm_manifest orelse
1188
- .{ .value = constants.lsm_manifest_memory_size_default };
1189
-
1190
- const lsm_manifest_memory = scrub_memory_lsm_manifest.bytes();
1191
- const lsm_manifest_memory_max = constants.lsm_manifest_memory_size_max;
1192
- const lsm_manifest_memory_min = constants.lsm_manifest_memory_size_min;
1193
- const lsm_manifest_memory_multiplier = constants.lsm_manifest_memory_size_multiplier;
1194
- if (lsm_manifest_memory > lsm_manifest_memory_max) {
1195
- vsr.fatal(.cli, "--memory-lsm-manifest: size {}{s} exceeds maximum: {}", .{
1196
- scrub_memory_lsm_manifest.value,
1197
- scrub_memory_lsm_manifest.suffix(),
1198
- vsr.stdx.fmt_int_size_bin_exact(lsm_manifest_memory_max),
1199
- });
1200
- }
1201
- if (lsm_manifest_memory < lsm_manifest_memory_min) {
1202
- vsr.fatal(.cli, "--memory-lsm-manifest: size {}{s} is below minimum: {}", .{
1203
- scrub_memory_lsm_manifest.value,
1204
- scrub_memory_lsm_manifest.suffix(),
1205
- vsr.stdx.fmt_int_size_bin_exact(lsm_manifest_memory_min),
1206
- });
1207
- }
1208
- if (lsm_manifest_memory % lsm_manifest_memory_multiplier != 0) {
1209
- vsr.fatal(
1210
- .cli,
1211
- "--memory-lsm-manifest: size {}{s} must be a multiple of {}",
1212
- .{
1213
- scrub_memory_lsm_manifest.value,
1214
- scrub_memory_lsm_manifest.suffix(),
1215
- vsr.stdx.fmt_int_size_bin_exact(lsm_manifest_memory_multiplier),
1216
- },
1217
- );
1218
- }
1219
-
1220
- const lsm_forest_node_count: u32 =
1221
- @intCast(@divExact(lsm_manifest_memory, constants.lsm_manifest_node_size));
1222
-
1223
- return .{
1224
- .path = integrity.path,
1225
- .log_debug = integrity.log_debug,
1226
- .seed = integrity.seed,
1227
- .skip_wal = integrity.skip_wal,
1228
- .skip_client_replies = integrity.skip_client_replies,
1229
- .skip_grid = integrity.skip_grid,
1230
- .lsm_forest_node_count = lsm_forest_node_count,
1231
- };
1232
- }
1233
-
1234
- fn parse_args_inspect(inspect: CLIArgs.Inspect) Command.Inspect {
1235
- const path = switch (inspect) {
1236
- .constants => return .constants,
1237
- .metrics => return .metrics,
1238
- .op => |args| return .{ .op = args.op },
1239
- .integrity => return .{ .integrity = parse_args_inspect_integrity(inspect) },
1240
- inline else => |args| args.path,
1241
- };
1242
-
1243
- return .{ .data_file = .{
1244
- .path = path,
1245
- .query = switch (inspect) {
1246
- .constants,
1247
- .metrics,
1248
- .op,
1249
- .integrity,
1250
- => unreachable,
1251
- .superblock => .superblock,
1252
- .wal => |args| .{ .wal = .{ .slot = args.slot } },
1253
- .replies => |args| .{ .replies = .{
1254
- .slot = args.slot,
1255
- .superblock_copy = args.superblock_copy,
1256
- } },
1257
- .grid => |args| .{ .grid = .{
1258
- .block = args.block,
1259
- .superblock_copy = args.superblock_copy,
1260
- } },
1261
- .manifest => |args| .{ .manifest = .{
1262
- .superblock_copy = args.superblock_copy,
1263
- } },
1264
- .tables => |args| .{ .tables = .{
1265
- .superblock_copy = args.superblock_copy,
1266
- .tree = args.tree,
1267
- .level = args.level,
1268
- } },
1269
- },
1270
- } };
1271
- }
1272
-
1273
- fn parse_args_multiversion(multiversion: CLIArgs.Multiversion) Command.Multiversion {
1274
- return .{
1275
- .path = multiversion.path,
1276
- .log_debug = multiversion.log_debug,
1277
- };
1278
- }
1279
-
1280
- fn parse_args_amqp(amqp: CLIArgs.AMQP) Command.AMQP {
1281
- const addresses = parse_addresses(amqp.addresses, "--addresses", Command.Addresses);
1282
- const host = parse_address_and_port(
1283
- amqp.host,
1284
- "--host",
1285
- vsr.cdc.amqp.tcp_port_default,
1286
- );
1287
-
1288
- if (amqp.publish_exchange == null and amqp.publish_routing_key == null) {
1289
- vsr.fatal(
1290
- .cli,
1291
- "--publish-exchange and --publish-routing-key cannot both be empty.",
1292
- .{},
1293
- );
1294
- }
1295
-
1296
- if (amqp.requests_per_second_limit) |requests_per_second_limit| {
1297
- if (requests_per_second_limit == 0) {
1298
- vsr.fatal(
1299
- .cli,
1300
- "--requests-per-second-limit must not be zero.",
1301
- .{},
1302
- );
1303
- }
1304
- }
1305
-
1306
- return .{
1307
- .addresses = addresses,
1308
- .cluster = amqp.cluster,
1309
- .host = host,
1310
- .user = amqp.user,
1311
- .password = amqp.password,
1312
- .vhost = amqp.vhost,
1313
- .publish_exchange = amqp.publish_exchange,
1314
- .publish_routing_key = amqp.publish_routing_key,
1315
- .event_count_max = amqp.event_count_max,
1316
- .idle_interval_ms = amqp.idle_interval_ms,
1317
- .requests_per_second_limit = amqp.requests_per_second_limit,
1318
- .timestamp_last = amqp.timestamp_last,
1319
- .log_debug = amqp.verbose,
1320
- };
1321
- }
1322
-
1323
- /// Parse and allocate the addresses returning a slice into that array.
1324
- fn parse_addresses(
1325
- raw_addresses: []const u8,
1326
- comptime flag: []const u8,
1327
- comptime BoundedArray: type,
1328
- ) BoundedArray {
1329
- comptime assert(std.mem.startsWith(u8, flag, "--"));
1330
- var result: BoundedArray = .{};
1331
-
1332
- const addresses_parsed = vsr.parse_addresses(
1333
- raw_addresses,
1334
- result.unused_capacity_slice(),
1335
- ) catch |err| switch (err) {
1336
- error.AddressHasTrailingComma => {
1337
- vsr.fatal(.cli, flag ++ ": invalid trailing comma", .{});
1338
- },
1339
- error.AddressLimitExceeded => {
1340
- vsr.fatal(.cli, flag ++ ": too many addresses, at most {d} are allowed", .{
1341
- result.capacity(),
1342
- });
1343
- },
1344
- error.AddressHasMoreThanOneColon => {
1345
- vsr.fatal(.cli, flag ++ ": invalid address with more than one colon", .{});
1346
- },
1347
- error.PortOverflow => vsr.fatal(.cli, flag ++ ": port exceeds 65535", .{}),
1348
- error.PortInvalid => vsr.fatal(.cli, flag ++ ": invalid port", .{}),
1349
- error.AddressInvalid => vsr.fatal(.cli, flag ++ ": invalid IPv4 or IPv6 address", .{}),
1350
- };
1351
- assert(addresses_parsed.len > 0);
1352
- assert(addresses_parsed.len <= result.capacity());
1353
- result.resize(addresses_parsed.len) catch unreachable;
1354
- return result;
1355
- }
1356
-
1357
- fn parse_address_and_port(
1358
- raw_address: []const u8,
1359
- comptime flag: []const u8,
1360
- port_default: u16,
1361
- ) std.net.Address {
1362
- comptime assert(std.mem.startsWith(u8, flag, "--"));
1363
-
1364
- const address = vsr.parse_address_and_port(.{
1365
- .string = raw_address,
1366
- .port_default = port_default,
1367
- }) catch |err| switch (err) {
1368
- error.AddressHasMoreThanOneColon => {
1369
- vsr.fatal(.cli, flag ++ ": invalid address with more than one colon", .{});
1370
- },
1371
- error.PortOverflow => vsr.fatal(.cli, flag ++ ": port exceeds 65535", .{}),
1372
- error.PortInvalid => vsr.fatal(.cli, flag ++ ": invalid port", .{}),
1373
- error.AddressInvalid => vsr.fatal(.cli, flag ++ ": invalid IPv4 or IPv6 address", .{}),
1374
- };
1375
- return address;
1376
- }
1377
-
1378
- /// Given a limit like `10GiB`, a SetAssociativeCache and T return the largest `value_count_max`
1379
- /// that can fit in the limit.
1380
- fn parse_cache_size_to_count(
1381
- comptime T: type,
1382
- comptime SetAssociativeCache: type,
1383
- size: ByteSize,
1384
- cli_flag: []const u8,
1385
- ) u32 {
1386
- const value_count_max_multiple = SetAssociativeCache.value_count_max_multiple;
1387
-
1388
- const count_limit = @divFloor(size.bytes(), @sizeOf(T));
1389
- const count_rounded = @divFloor(
1390
- count_limit,
1391
- value_count_max_multiple,
1392
- ) * value_count_max_multiple;
1393
-
1394
- if (count_rounded > std.math.maxInt(u32)) {
1395
- vsr.fatal(.cli, "{s}: exceeds the limit", .{cli_flag});
1396
- }
1397
-
1398
- const result: u32 = @intCast(count_rounded);
1399
- assert(@as(u64, result) * @sizeOf(T) <= size.bytes());
1400
-
1401
- return result;
1402
- }
1403
-
1404
- fn parse_timeout_to_ticks(timeout_ms: ?u64, cli_flag: []const u8) ?u64 {
1405
- if (timeout_ms) |ms| {
1406
- if (ms == 0) {
1407
- vsr.fatal(.cli, "{s}: timeout {}ms be nonzero", .{ cli_flag, ms });
1408
- }
1409
-
1410
- if (ms % constants.tick_ms != 0) {
1411
- vsr.fatal(
1412
- .cli,
1413
- "{s}: timeout {}ms must be a multiple of {}ms",
1414
- .{ cli_flag, ms, constants.tick_ms },
1415
- );
1416
- }
1417
-
1418
- return @divExact(ms, constants.tick_ms);
1419
- } else {
1420
- return null;
1421
- }
1422
- }