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.
Files changed (248) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/ext/tb_client/extconf.rb +13 -13
  4. data/ext/tb_client/tigerbeetle/LICENSE +177 -0
  5. data/ext/tb_client/tigerbeetle/build.zig +2327 -0
  6. data/ext/tb_client/tigerbeetle/src/aof.zig +1000 -0
  7. data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +808 -0
  8. data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +1283 -0
  9. data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +1704 -0
  10. data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +341 -0
  11. data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +1450 -0
  12. data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +1659 -0
  13. data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +406 -0
  14. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +1092 -0
  15. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +286 -0
  16. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +158 -0
  17. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +229 -0
  18. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +110 -0
  19. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +386 -0
  20. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +34 -0
  21. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +281 -0
  22. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +312 -0
  23. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +138 -0
  24. data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +466 -0
  25. data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +157 -0
  26. data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +90 -0
  27. data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +203 -0
  28. data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +79 -0
  29. data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +542 -0
  30. data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +109 -0
  31. data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +86 -0
  32. data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +370 -0
  33. data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +386 -0
  34. data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +167 -0
  35. data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +126 -0
  36. data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +996 -0
  37. data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +748 -0
  38. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +3238 -0
  39. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +1718 -0
  40. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +190 -0
  41. data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +104 -0
  42. data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +75 -0
  43. data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +522 -0
  44. data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +267 -0
  45. data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +3 -0
  46. data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +379 -0
  47. data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +131 -0
  48. data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +63 -0
  49. data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +588 -0
  50. data/ext/tb_client/tigerbeetle/src/clients/rust/assets/tb_client.h +386 -0
  51. data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +73 -0
  52. data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +106 -0
  53. data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +305 -0
  54. data/ext/tb_client/tigerbeetle/src/config.zig +296 -0
  55. data/ext/tb_client/tigerbeetle/src/constants.zig +790 -0
  56. data/ext/tb_client/tigerbeetle/src/copyhound.zig +202 -0
  57. data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +72 -0
  58. data/ext/tb_client/tigerbeetle/src/direction.zig +120 -0
  59. data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +158 -0
  60. data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +156 -0
  61. data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +252 -0
  62. data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +313 -0
  63. data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +87 -0
  64. data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +63 -0
  65. data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +47 -0
  66. data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +28 -0
  67. data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +61 -0
  68. data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +169 -0
  69. data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +46 -0
  70. data/ext/tb_client/tigerbeetle/src/ewah.zig +445 -0
  71. data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +128 -0
  72. data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +171 -0
  73. data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +179 -0
  74. data/ext/tb_client/tigerbeetle/src/integration_tests.zig +662 -0
  75. data/ext/tb_client/tigerbeetle/src/io/common.zig +155 -0
  76. data/ext/tb_client/tigerbeetle/src/io/darwin.zig +1093 -0
  77. data/ext/tb_client/tigerbeetle/src/io/linux.zig +1880 -0
  78. data/ext/tb_client/tigerbeetle/src/io/test.zig +1005 -0
  79. data/ext/tb_client/tigerbeetle/src/io/windows.zig +1598 -0
  80. data/ext/tb_client/tigerbeetle/src/io.zig +34 -0
  81. data/ext/tb_client/tigerbeetle/src/iops.zig +134 -0
  82. data/ext/tb_client/tigerbeetle/src/list.zig +236 -0
  83. data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +848 -0
  84. data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +179 -0
  85. data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +424 -0
  86. data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +420 -0
  87. data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +2117 -0
  88. data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +182 -0
  89. data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +1119 -0
  90. data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +1102 -0
  91. data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +200 -0
  92. data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +1495 -0
  93. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +739 -0
  94. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +166 -0
  95. data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +754 -0
  96. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +1294 -0
  97. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +510 -0
  98. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +1263 -0
  99. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +628 -0
  100. data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +247 -0
  101. data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +116 -0
  102. data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +543 -0
  103. data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +938 -0
  104. data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +293 -0
  105. data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +359 -0
  106. data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +99 -0
  107. data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +17 -0
  108. data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +962 -0
  109. data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +617 -0
  110. data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +84 -0
  111. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +1500 -0
  112. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +149 -0
  113. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +7 -0
  114. data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +865 -0
  115. data/ext/tb_client/tigerbeetle/src/lsm/table.zig +607 -0
  116. data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +843 -0
  117. data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +90 -0
  118. data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +40 -0
  119. data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +630 -0
  120. data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +933 -0
  121. data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +534 -0
  122. data/ext/tb_client/tigerbeetle/src/message_buffer.zig +469 -0
  123. data/ext/tb_client/tigerbeetle/src/message_bus.zig +1214 -0
  124. data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +936 -0
  125. data/ext/tb_client/tigerbeetle/src/message_pool.zig +343 -0
  126. data/ext/tb_client/tigerbeetle/src/multiversion.zig +2195 -0
  127. data/ext/tb_client/tigerbeetle/src/queue.zig +390 -0
  128. data/ext/tb_client/tigerbeetle/src/repl/completion.zig +201 -0
  129. data/ext/tb_client/tigerbeetle/src/repl/parser.zig +1356 -0
  130. data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +496 -0
  131. data/ext/tb_client/tigerbeetle/src/repl.zig +1034 -0
  132. data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +973 -0
  133. data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +1866 -0
  134. data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +304 -0
  135. data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +227 -0
  136. data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +658 -0
  137. data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +466 -0
  138. data/ext/tb_client/tigerbeetle/src/scripts/release.zig +1058 -0
  139. data/ext/tb_client/tigerbeetle/src/scripts.zig +105 -0
  140. data/ext/tb_client/tigerbeetle/src/shell.zig +1195 -0
  141. data/ext/tb_client/tigerbeetle/src/stack.zig +260 -0
  142. data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +911 -0
  143. data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +2079 -0
  144. data/ext/tb_client/tigerbeetle/src/state_machine.zig +4872 -0
  145. data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +288 -0
  146. data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +3128 -0
  147. data/ext/tb_client/tigerbeetle/src/static_allocator.zig +82 -0
  148. data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +157 -0
  149. data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +292 -0
  150. data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +65 -0
  151. data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +1414 -0
  152. data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +92 -0
  153. data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +677 -0
  154. data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +336 -0
  155. data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +511 -0
  156. data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +112 -0
  157. data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +1160 -0
  158. data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +142 -0
  159. data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +361 -0
  160. data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +275 -0
  161. data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +295 -0
  162. data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +436 -0
  163. data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +48 -0
  164. data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +402 -0
  165. data/ext/tb_client/tigerbeetle/src/storage.zig +489 -0
  166. data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +180 -0
  167. data/ext/tb_client/tigerbeetle/src/testing/bench.zig +146 -0
  168. data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +53 -0
  169. data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +61 -0
  170. data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +76 -0
  171. data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +110 -0
  172. data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +412 -0
  173. data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +331 -0
  174. data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +458 -0
  175. data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +1198 -0
  176. data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +128 -0
  177. data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +181 -0
  178. data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +144 -0
  179. data/ext/tb_client/tigerbeetle/src/testing/id.zig +97 -0
  180. data/ext/tb_client/tigerbeetle/src/testing/io.zig +317 -0
  181. data/ext/tb_client/tigerbeetle/src/testing/marks.zig +126 -0
  182. data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +533 -0
  183. data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +154 -0
  184. data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +389 -0
  185. data/ext/tb_client/tigerbeetle/src/testing/storage.zig +1247 -0
  186. data/ext/tb_client/tigerbeetle/src/testing/table.zig +249 -0
  187. data/ext/tb_client/tigerbeetle/src/testing/time.zig +98 -0
  188. data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +212 -0
  189. data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +26 -0
  190. data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +580 -0
  191. data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +39 -0
  192. data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +214 -0
  193. data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +34 -0
  194. data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +766 -0
  195. data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +543 -0
  196. data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +181 -0
  197. data/ext/tb_client/tigerbeetle/src/tidy.zig +1448 -0
  198. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +227 -0
  199. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +1069 -0
  200. data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +1422 -0
  201. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +1658 -0
  202. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +518 -0
  203. data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +36 -0
  204. data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +646 -0
  205. data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +958 -0
  206. data/ext/tb_client/tigerbeetle/src/time.zig +236 -0
  207. data/ext/tb_client/tigerbeetle/src/trace/event.zig +745 -0
  208. data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +462 -0
  209. data/ext/tb_client/tigerbeetle/src/trace.zig +556 -0
  210. data/ext/tb_client/tigerbeetle/src/unit_tests.zig +321 -0
  211. data/ext/tb_client/tigerbeetle/src/vopr.zig +1785 -0
  212. data/ext/tb_client/tigerbeetle/src/vortex.zig +101 -0
  213. data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +473 -0
  214. data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +208 -0
  215. data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +43 -0
  216. data/ext/tb_client/tigerbeetle/src/vsr/client.zig +768 -0
  217. data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +532 -0
  218. data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +338 -0
  219. data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +1019 -0
  220. data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +279 -0
  221. data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +1381 -0
  222. data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +315 -0
  223. data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +1460 -0
  224. data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +757 -0
  225. data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +797 -0
  226. data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +2586 -0
  227. data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +308 -0
  228. data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +1777 -0
  229. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +715 -0
  230. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +185 -0
  231. data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +333 -0
  232. data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +12355 -0
  233. data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +416 -0
  234. data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +165 -0
  235. data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +2928 -0
  236. data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +1075 -0
  237. data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +1603 -0
  238. data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +484 -0
  239. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +405 -0
  240. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +355 -0
  241. data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +29 -0
  242. data/ext/tb_client/tigerbeetle/src/vsr.zig +1727 -0
  243. data/lib/tb_client/shared_lib.rb +12 -5
  244. data/lib/tigerbeetle/platforms.rb +9 -0
  245. data/lib/tigerbeetle/version.rb +2 -2
  246. data/tigerbeetle.gemspec +22 -5
  247. metadata +242 -3
  248. data/ext/tb_client/pkg.tar.gz +0 -0
@@ -0,0 +1,101 @@
1
+ /// This is the main entrypoint for the Vortex testing tools, delegating to these programs:
2
+ ///
3
+ /// * _supervisor_: runs a cluster of multiple TigerBeetle replicas, drivers, and a workload, along
4
+ /// with various fault injection, to test the system as a whole.
5
+ /// * _driver_: a separate process communicating over stdio, using `tb_client` to send commands
6
+ /// and queries to the cluster. Drivers in other languages should be implemented elsewhere.
7
+ /// * _workload_: a separate process that, given a driver, runs commands and queries against the
8
+ /// cluster, verifying its correctness.
9
+ ///
10
+ /// For practical use, Vortex should be run in a Linux namespace where it can control the network.
11
+ /// The `run` command sets up a Linux namespace automatically.
12
+ const std = @import("std");
13
+ const stdx = @import("stdx");
14
+ const builtin = @import("builtin");
15
+
16
+ const Supervisor = @import("testing/vortex/supervisor.zig");
17
+ const Workload = @import("testing/vortex/workload.zig");
18
+
19
+ const assert = std.debug.assert;
20
+
21
+ const log = std.log.scoped(.vortex);
22
+
23
+ pub const std_options: std.Options = .{
24
+ .log_level = .info,
25
+ .logFn = stdx.log_with_timestamp,
26
+ };
27
+
28
+ pub const CLIArgs = union(enum) {
29
+ supervisor: Supervisor.CLIArgs,
30
+ workload: WorkloadArgs,
31
+ };
32
+
33
+ const WorkloadArgs = struct {
34
+ cluster_id: u128,
35
+ addresses: []const u8,
36
+ driver_command: []const u8,
37
+ };
38
+
39
+ pub fn main() !void {
40
+ comptime assert(builtin.target.cpu.arch.endian() == .little);
41
+
42
+ if (builtin.os.tag == .windows) {
43
+ log.err("vortex is not supported for Windows", .{});
44
+ return error.NotSupported;
45
+ }
46
+
47
+ var gpa_allocator = std.heap.GeneralPurposeAllocator(.{}){};
48
+ defer switch (gpa_allocator.deinit()) {
49
+ .ok => {},
50
+ .leak => @panic("memory leak"),
51
+ };
52
+
53
+ const allocator = gpa_allocator.allocator();
54
+
55
+ var args = try std.process.argsWithAllocator(allocator);
56
+ defer args.deinit();
57
+
58
+ switch (stdx.flags(&args, CLIArgs)) {
59
+ .supervisor => |supervisor_args| try Supervisor.main(allocator, supervisor_args),
60
+ .workload => |driver_args| {
61
+ var driver = try start_driver(allocator, driver_args);
62
+ defer {
63
+ _ = driver.kill() catch {
64
+ log.err("failed to kill driver", .{});
65
+ };
66
+ }
67
+
68
+ try Workload.main(allocator, &.{
69
+ .input = driver.stdin.?,
70
+ .output = driver.stdout.?,
71
+ });
72
+ },
73
+ }
74
+ }
75
+
76
+ fn start_driver(allocator: std.mem.Allocator, args: WorkloadArgs) !std.process.Child {
77
+ var argv = std.ArrayList([]const u8).init(allocator);
78
+ defer argv.deinit();
79
+
80
+ assert(std.mem.indexOfScalar(u8, args.driver_command, '"') == null);
81
+ var cmd_parts = std.mem.splitScalar(u8, args.driver_command, ' ');
82
+
83
+ while (cmd_parts.next()) |part| {
84
+ try argv.append(part);
85
+ }
86
+
87
+ var cluster_id_argument: [32]u8 = undefined;
88
+ const cluster_id = try std.fmt.bufPrint(cluster_id_argument[0..], "{d}", .{args.cluster_id});
89
+
90
+ try argv.append(cluster_id);
91
+ try argv.append(args.addresses);
92
+
93
+ var child = std.process.Child.init(argv.items, allocator);
94
+ child.stdin_behavior = .Pipe;
95
+ child.stdout_behavior = .Pipe;
96
+ child.stderr_behavior = .Inherit;
97
+
98
+ try child.spawn();
99
+
100
+ return child;
101
+ }
@@ -0,0 +1,473 @@
1
+ const std = @import("std");
2
+ const assert = std.debug.assert;
3
+ const mem = std.mem;
4
+
5
+ const vsr = @import("../vsr.zig");
6
+ const stdx = @import("stdx");
7
+ const schema = @import("../lsm/schema.zig");
8
+ const GridType = @import("../vsr/grid.zig").GridType;
9
+ const BlockPtr = @import("../vsr/grid.zig").BlockPtr;
10
+ const BlockPtrConst = @import("../vsr/grid.zig").BlockPtrConst;
11
+ const allocate_block = @import("../vsr/grid.zig").allocate_block;
12
+ const constants = @import("../constants.zig");
13
+ const FreeSet = @import("./free_set.zig").FreeSet;
14
+ const BlockType = schema.BlockType;
15
+
16
+ // Body of the block which holds encoded trailer data.
17
+ // All chunks except for possibly the last one are full.
18
+ const chunk_size_max = constants.block_size - @sizeOf(vsr.Header);
19
+
20
+ // Chunk describes a slice of encoded trailer that goes into nth block on disk.
21
+ const Chunk = struct {
22
+ fn size(options: struct {
23
+ block_index: u32,
24
+ block_count: u32,
25
+ trailer_size: u64,
26
+ }) u32 {
27
+ assert(options.block_count > 0);
28
+ assert(options.block_count == stdx.div_ceil(options.trailer_size, chunk_size_max));
29
+ assert(options.block_index < options.block_count);
30
+
31
+ const last_block = options.block_index == options.block_count - 1;
32
+ const chunk_size: u32 = if (last_block)
33
+ @intCast(options.trailer_size - (options.block_count - 1) * chunk_size_max)
34
+ else
35
+ chunk_size_max;
36
+
37
+ return chunk_size;
38
+ }
39
+ };
40
+
41
+ /// CheckpointTrailer is the persistent representation of the free set and client sessions.
42
+ /// It defines the layout of the free set and client sessions as stored in the grid between
43
+ /// checkpoints.
44
+ ///
45
+ /// - Free set is stored as a linked list of blocks containing EWAH-encoding of a bitset of acquired
46
+ /// blocks. The length of the linked list is proportional to the degree of fragmentation, rather
47
+ /// that to the size of the data file. The common case is a single block.
48
+ ///
49
+ /// The blocks holding free set itself are marked as free in the on-disk encoding, because the
50
+ /// number of blocks required to store the compressed bitset becomes known only after encoding.
51
+ /// This might or might not be related to Russell's paradox.
52
+ ///
53
+ /// - Client sessions is stored as a linked list of blocks containing reply headers and session
54
+ /// numbers.
55
+ ///
56
+ /// Linked list is a FIFO. While the blocks are written in the direct order, they have to be read in
57
+ /// the reverse order.
58
+ pub fn CheckpointTrailerType(comptime Storage: type) type {
59
+ const Grid = GridType(Storage);
60
+
61
+ return struct {
62
+ const CheckpointTrailer = @This();
63
+
64
+ // Reference to the grid is late-initialized in `open`, because the free set is part of
65
+ // the grid, which doesn't have access to a stable grid pointer. It is set to null by
66
+ // `reset`, to verify that the free set is not used before it is opened during sync.
67
+ grid: ?*Grid = null,
68
+ trailer_type: TrailerType,
69
+
70
+ next_tick: Grid.NextTick = undefined,
71
+ read: Grid.Read = undefined,
72
+ write: Grid.Write = undefined,
73
+
74
+ // TODO(Grid pool): Acquire blocks as-needed from the grid pool. The common-case number of
75
+ // blocks needed is much less than the worst-case number of blocks.
76
+ blocks: []BlockPtr,
77
+ /// `encode_chunks()`/`decode_chunks()` return slices into this memory.
78
+ block_bodies: [][]align(@sizeOf(u256)) u8,
79
+
80
+ // SoA representation of block references holding the trailer itself.
81
+ //
82
+ // After the set is read from disk and decoded, these blocks are manually marked as
83
+ // acquired.
84
+ block_addresses: []u64,
85
+ block_checksums: []u128,
86
+ // The current block that is being read or written. It counts from 0 to block_count()
87
+ // during checkpoint, and from block_count() to zero during open.
88
+ block_index: u32 = 0,
89
+
90
+ // Size of the encoded set in bytes.
91
+ // (Does not include block headers.)
92
+ size: u64 = 0,
93
+ // The number of trailer bytes read or written during disk IO. Used to cross-check that we
94
+ // haven't lost any bytes along the way.
95
+ size_transferred: u64 = 0,
96
+
97
+ // Checksum covering the entire encoded trailer.
98
+ // (Does not include block headers.)
99
+ checksum: u128 = 0,
100
+
101
+ callback: union(enum) {
102
+ none,
103
+ open: *const fn (trailer: *CheckpointTrailer) void,
104
+ checkpoint: *const fn (trailer: *CheckpointTrailer) void,
105
+ } = .none,
106
+
107
+ pub fn init(
108
+ allocator: mem.Allocator,
109
+ trailer_type: TrailerType,
110
+ buffer_size: usize,
111
+ ) !CheckpointTrailer {
112
+ const block_count_max_ = block_count_for_trailer_size(buffer_size);
113
+ const blocks = try allocator.alloc(BlockPtr, block_count_max_);
114
+ errdefer allocator.free(blocks);
115
+
116
+ for (blocks, 0..) |*block, i| {
117
+ errdefer for (blocks[0..i]) |b| allocator.free(b);
118
+ block.* = try allocate_block(allocator);
119
+ }
120
+ errdefer for (blocks) |block| allocator.free(block);
121
+
122
+ const block_bodies = try allocator.alloc([]align(@sizeOf(u256)) u8, block_count_max_);
123
+ errdefer allocator.free(block_bodies);
124
+ @memset(block_bodies, undefined);
125
+
126
+ const block_addresses = try allocator.alloc(u64, block_count_max_);
127
+ errdefer allocator.free(block_addresses);
128
+
129
+ const block_checksums = try allocator.alloc(u128, block_count_max_);
130
+ errdefer allocator.free(block_checksums);
131
+
132
+ return .{
133
+ .trailer_type = trailer_type,
134
+ .blocks = blocks,
135
+ .block_bodies = block_bodies,
136
+ .block_addresses = block_addresses,
137
+ .block_checksums = block_checksums,
138
+ };
139
+ }
140
+
141
+ pub fn deinit(trailer: *CheckpointTrailer, allocator: mem.Allocator) void {
142
+ allocator.free(trailer.block_checksums);
143
+ allocator.free(trailer.block_addresses);
144
+ allocator.free(trailer.block_bodies);
145
+ for (trailer.blocks) |block| allocator.free(block);
146
+ allocator.free(trailer.blocks);
147
+ }
148
+
149
+ pub fn reset(trailer: *CheckpointTrailer) void {
150
+ switch (trailer.callback) {
151
+ .none, .open => {},
152
+ // Checkpointing doesn't need to read blocks, so it's not cancellable.
153
+ .checkpoint => unreachable,
154
+ }
155
+ trailer.* = .{
156
+ .trailer_type = trailer.trailer_type,
157
+ .blocks = trailer.blocks,
158
+ .block_bodies = trailer.block_bodies,
159
+ .block_addresses = trailer.block_addresses,
160
+ .block_checksums = trailer.block_checksums,
161
+ };
162
+ }
163
+
164
+ pub fn block_count(trailer: *const CheckpointTrailer) u32 {
165
+ return block_count_for_trailer_size(trailer.size);
166
+ }
167
+
168
+ /// Each returned chunk has `chunk.len == chunk_size_max`.
169
+ pub fn encode_chunks(trailer: *CheckpointTrailer) []const []align(@sizeOf(u256)) u8 {
170
+ for (trailer.block_bodies, trailer.blocks) |*block_body, block| {
171
+ block_body.* = block[@sizeOf(vsr.Header)..];
172
+
173
+ assert(block_body.*.len == chunk_size_max);
174
+ }
175
+ return trailer.block_bodies;
176
+ }
177
+
178
+ pub fn decode_chunks(
179
+ trailer: *const CheckpointTrailer,
180
+ ) []const []align(@sizeOf(u256)) const u8 {
181
+ const chunk_count: u32 = @intCast(stdx.div_ceil(trailer.size, chunk_size_max));
182
+ for (
183
+ trailer.block_bodies[0..chunk_count],
184
+ trailer.blocks[0..chunk_count],
185
+ 0..,
186
+ ) |*block_body, block, block_index| {
187
+ const chunk_size = Chunk.size(.{
188
+ .block_index = @intCast(block_index),
189
+ .block_count = chunk_count,
190
+ .trailer_size = trailer.size,
191
+ });
192
+
193
+ block_body.* = block[@sizeOf(vsr.Header)..][0..chunk_size];
194
+ }
195
+ return trailer.block_bodies[0..chunk_count];
196
+ }
197
+
198
+ // These data are stored in the superblock header.
199
+ pub fn checkpoint_reference(
200
+ trailer: *const CheckpointTrailer,
201
+ ) vsr.SuperBlockTrailerReference {
202
+ assert(trailer.size == trailer.size_transferred);
203
+ assert(trailer.callback == .none);
204
+
205
+ const reference: vsr.SuperBlockTrailerReference = if (trailer.size == 0) .{
206
+ .checksum = vsr.checksum(&.{}),
207
+ .last_block_address = 0,
208
+ .last_block_checksum = 0,
209
+ .trailer_size = 0,
210
+ } else .{
211
+ .checksum = trailer.checksum,
212
+ .last_block_address = trailer.block_addresses[trailer.block_count() - 1],
213
+ .last_block_checksum = trailer.block_checksums[trailer.block_count() - 1],
214
+ .trailer_size = trailer.size,
215
+ };
216
+ assert(reference.empty() == (trailer.size == 0));
217
+
218
+ return reference;
219
+ }
220
+
221
+ pub fn open(
222
+ trailer: *CheckpointTrailer,
223
+ grid: *Grid,
224
+ reference: vsr.SuperBlockTrailerReference,
225
+ callback: *const fn (trailer: *CheckpointTrailer) void,
226
+ ) void {
227
+ assert(trailer.grid == null);
228
+ trailer.grid = grid;
229
+
230
+ assert(trailer.callback == .none);
231
+ defer assert(trailer.callback == .open);
232
+
233
+ assert(reference.trailer_size % trailer.trailer_type.item_size() == 0);
234
+ assert(trailer.size == 0);
235
+ assert(trailer.size_transferred == 0);
236
+ assert(trailer.block_index == 0);
237
+
238
+ trailer.size = reference.trailer_size;
239
+ trailer.checksum = reference.checksum;
240
+ trailer.callback = .{ .open = callback };
241
+
242
+ // Start from the last block, as the linked list arranges data in the reverse order.
243
+ trailer.block_index = trailer.block_count();
244
+
245
+ if (trailer.size == 0) {
246
+ assert(reference.last_block_address == 0);
247
+ trailer.grid.?.on_next_tick(open_next_tick, &trailer.next_tick);
248
+ } else {
249
+ assert(reference.last_block_address != 0);
250
+ trailer.open_read_next(reference.last_block_address, reference.last_block_checksum);
251
+ }
252
+ }
253
+
254
+ fn open_next_tick(next_tick: *Grid.NextTick) void {
255
+ const trailer: *CheckpointTrailer = @alignCast(@fieldParentPtr("next_tick", next_tick));
256
+ assert(trailer.callback == .open);
257
+ assert(trailer.size == 0);
258
+ trailer.open_done();
259
+ }
260
+
261
+ fn open_read_next(trailer: *CheckpointTrailer, address: u64, checksum: u128) void {
262
+ assert(trailer.callback == .open);
263
+ assert(trailer.size > 0);
264
+ assert((trailer.size_transferred == 0) ==
265
+ (trailer.block_index == trailer.block_count()));
266
+ assert(address != 0);
267
+
268
+ assert(trailer.block_index <= trailer.block_count());
269
+ assert(trailer.block_index > 0);
270
+ trailer.block_index -= 1;
271
+
272
+ trailer.block_addresses[trailer.block_index] = address;
273
+ trailer.block_checksums[trailer.block_index] = checksum;
274
+ for (trailer.block_index + 1..trailer.block_count()) |index| {
275
+ assert(trailer.block_addresses[index] != address);
276
+ assert(trailer.block_checksums[index] != checksum);
277
+ }
278
+
279
+ trailer.grid.?.read_block(
280
+ .{ .from_local_or_global_storage = open_read_next_callback },
281
+ &trailer.read,
282
+ address,
283
+ checksum,
284
+ .{ .cache_read = true, .cache_write = false },
285
+ );
286
+ }
287
+
288
+ fn open_read_next_callback(read: *Grid.Read, block: BlockPtrConst) void {
289
+ const trailer: *CheckpointTrailer = @fieldParentPtr("read", read);
290
+ assert(trailer.callback == .open);
291
+ assert(trailer.size > 0);
292
+ assert(trailer.block_index < trailer.block_count());
293
+
294
+ const block_header = schema.header_from_block(block);
295
+ assert(block_header.block_type == trailer.trailer_type.block_type());
296
+
297
+ const chunk_size = Chunk.size(.{
298
+ .block_index = trailer.block_index,
299
+ .block_count = trailer.block_count(),
300
+ .trailer_size = trailer.size,
301
+ });
302
+
303
+ stdx.copy_disjoint(
304
+ .exact,
305
+ u8,
306
+ trailer.blocks[trailer.block_index][@sizeOf(vsr.Header)..][0..chunk_size],
307
+ schema.TrailerNode.body(block),
308
+ );
309
+ trailer.size_transferred += chunk_size;
310
+
311
+ if (schema.TrailerNode.previous(block)) |previous| {
312
+ assert(trailer.block_index > 0);
313
+ trailer.open_read_next(previous.address, previous.checksum);
314
+ } else {
315
+ assert(trailer.block_index == 0);
316
+ trailer.open_done();
317
+ }
318
+ }
319
+
320
+ fn open_done(trailer: *CheckpointTrailer) void {
321
+ assert(trailer.callback == .open);
322
+ defer assert(trailer.callback == .none);
323
+
324
+ assert(trailer.block_index == 0);
325
+ assert(trailer.size_transferred == trailer.size);
326
+
327
+ var checksum_stream = vsr.ChecksumStream.init();
328
+ for (trailer.decode_chunks()) |chunk| checksum_stream.add(chunk);
329
+ assert(trailer.checksum == checksum_stream.checksum());
330
+
331
+ const callback = trailer.callback.open;
332
+ trailer.callback = .none;
333
+ callback(trailer);
334
+ }
335
+
336
+ pub fn checkpoint(
337
+ trailer: *CheckpointTrailer,
338
+ callback: *const fn (trailer: *CheckpointTrailer) void,
339
+ ) void {
340
+ assert(trailer.callback == .none);
341
+ defer assert(trailer.callback == .checkpoint);
342
+
343
+ var checksum_stream = vsr.ChecksumStream.init();
344
+ for (trailer.decode_chunks()) |chunk| checksum_stream.add(chunk);
345
+
346
+ trailer.size_transferred = 0;
347
+ trailer.checksum = checksum_stream.checksum();
348
+
349
+ if (trailer.size > 0) {
350
+ assert(trailer.grid.?.free_set.count_reservations() == 0);
351
+ const reservation = trailer.grid.?.free_set.reserve(trailer.block_count()).?;
352
+ defer trailer.grid.?.free_set.forfeit(reservation);
353
+
354
+ for (
355
+ trailer.block_addresses[0..trailer.block_count()],
356
+ trailer.block_checksums[0..trailer.block_count()],
357
+ ) |*address, *checksum| {
358
+ address.* = trailer.grid.?.free_set.acquire(reservation).?;
359
+ checksum.* = undefined;
360
+ }
361
+ // Reservation should be fully used up.
362
+ assert(trailer.grid.?.free_set.acquire(reservation) == null);
363
+ }
364
+
365
+ trailer.block_index = 0;
366
+ trailer.callback = .{ .checkpoint = callback };
367
+ if (trailer.size == 0) {
368
+ trailer.grid.?.on_next_tick(checkpoint_next_tick, &trailer.next_tick);
369
+ } else {
370
+ trailer.checkpoint_write_next();
371
+ }
372
+ }
373
+
374
+ fn checkpoint_next_tick(next_tick: *Grid.NextTick) void {
375
+ const trailer: *CheckpointTrailer = @alignCast(@fieldParentPtr("next_tick", next_tick));
376
+ assert(trailer.callback == .checkpoint);
377
+ assert(trailer.size == 0);
378
+ assert(trailer.block_index == 0);
379
+ trailer.checkpoint_done();
380
+ }
381
+
382
+ fn checkpoint_write_next(trailer: *CheckpointTrailer) void {
383
+ assert(trailer.callback == .checkpoint);
384
+ assert(trailer.size > 0);
385
+ assert(trailer.block_index < trailer.block_count());
386
+ assert((trailer.size_transferred == 0) == (trailer.block_index == 0));
387
+
388
+ const chunk_size = Chunk.size(.{
389
+ .block_index = trailer.block_index,
390
+ .block_count = trailer.block_count(),
391
+ .trailer_size = trailer.size,
392
+ });
393
+
394
+ const block_index = trailer.block_index;
395
+ const block = &trailer.blocks[block_index];
396
+ const metadata: schema.TrailerNode.Metadata = if (block_index == 0) .{
397
+ .previous_trailer_block_checksum = 0,
398
+ .previous_trailer_block_address = 0,
399
+ } else .{
400
+ .previous_trailer_block_checksum = trailer.block_checksums[block_index - 1],
401
+ .previous_trailer_block_address = trailer.block_addresses[block_index - 1],
402
+ };
403
+
404
+ const header = mem.bytesAsValue(vsr.Header.Block, block.*[0..@sizeOf(vsr.Header)]);
405
+ header.* = .{
406
+ .cluster = trailer.grid.?.superblock.working.cluster,
407
+ .metadata_bytes = @bitCast(metadata),
408
+ .address = trailer.block_addresses[trailer.block_index],
409
+ .snapshot = 0, // TODO(snapshots): Set this properly; it is useful for debugging.
410
+ .size = @sizeOf(vsr.Header) + chunk_size,
411
+ .command = .block,
412
+ .release = trailer.grid.?.superblock.working.vsr_state.checkpoint.release,
413
+ .block_type = trailer.trailer_type.block_type(),
414
+ };
415
+ trailer.size_transferred += chunk_size;
416
+ header.set_checksum_body(block.*[@sizeOf(vsr.Header)..][0..chunk_size]);
417
+ header.set_checksum();
418
+ schema.TrailerNode.assert_valid_header(block.*);
419
+
420
+ trailer.block_checksums[block_index] = header.checksum;
421
+ // create_block swaps out the `blocks` BlockPtr, so our reference to it will be invalid.
422
+ trailer.block_bodies[block_index] = undefined;
423
+ trailer.grid.?.create_block(checkpoint_write_next_callback, &trailer.write, block);
424
+ }
425
+
426
+ fn checkpoint_write_next_callback(write: *Grid.Write) void {
427
+ const trailer: *CheckpointTrailer = @fieldParentPtr("write", write);
428
+ assert(trailer.callback == .checkpoint);
429
+
430
+ trailer.block_index += 1;
431
+ if (trailer.block_index == trailer.block_count()) {
432
+ trailer.checkpoint_done();
433
+ } else {
434
+ trailer.checkpoint_write_next();
435
+ }
436
+ }
437
+
438
+ fn checkpoint_done(trailer: *CheckpointTrailer) void {
439
+ assert(trailer.callback == .checkpoint);
440
+ defer assert(trailer.callback == .none);
441
+
442
+ assert(trailer.block_index == trailer.block_count());
443
+ assert(trailer.size_transferred == trailer.size);
444
+
445
+ const callback = trailer.callback.checkpoint;
446
+ trailer.callback = .none;
447
+ callback(trailer);
448
+ }
449
+ };
450
+ }
451
+
452
+ pub fn block_count_for_trailer_size(trailer_size: u64) u32 {
453
+ return @intCast(stdx.div_ceil(trailer_size, chunk_size_max));
454
+ }
455
+
456
+ pub const TrailerType = enum {
457
+ free_set,
458
+ client_sessions,
459
+
460
+ fn block_type(trailer_type: TrailerType) schema.BlockType {
461
+ return switch (trailer_type) {
462
+ .free_set => .free_set,
463
+ .client_sessions => .client_sessions,
464
+ };
465
+ }
466
+
467
+ fn item_size(trailer_type: TrailerType) usize {
468
+ return switch (trailer_type) {
469
+ .free_set => @sizeOf(FreeSet.Word),
470
+ .client_sessions => @sizeOf(vsr.Header) + @sizeOf(u64),
471
+ };
472
+ }
473
+ };