tigerbeetle-node 0.11.12 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +212 -196
  2. package/dist/bin/aarch64-linux-gnu/client.node +0 -0
  3. package/dist/bin/aarch64-linux-musl/client.node +0 -0
  4. package/dist/bin/aarch64-macos/client.node +0 -0
  5. package/dist/bin/x86_64-linux-gnu/client.node +0 -0
  6. package/dist/bin/x86_64-linux-musl/client.node +0 -0
  7. package/dist/bin/x86_64-macos/client.node +0 -0
  8. package/dist/index.js +33 -1
  9. package/dist/index.js.map +1 -1
  10. package/package-lock.json +66 -0
  11. package/package.json +8 -17
  12. package/src/index.ts +56 -1
  13. package/src/node.zig +10 -9
  14. package/dist/.client.node.sha256 +0 -1
  15. package/scripts/build_lib.sh +0 -61
  16. package/scripts/download_node_headers.sh +0 -32
  17. package/src/tigerbeetle/scripts/benchmark.bat +0 -48
  18. package/src/tigerbeetle/scripts/benchmark.sh +0 -66
  19. package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
  20. package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
  21. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
  22. package/src/tigerbeetle/scripts/install.bat +0 -7
  23. package/src/tigerbeetle/scripts/install.sh +0 -21
  24. package/src/tigerbeetle/scripts/install_zig.bat +0 -113
  25. package/src/tigerbeetle/scripts/install_zig.sh +0 -90
  26. package/src/tigerbeetle/scripts/lint.zig +0 -199
  27. package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
  28. package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -48
  29. package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
  30. package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
  31. package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
  32. package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
  33. package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
  34. package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
  35. package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
  36. package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
  37. package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
  38. package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
  39. package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
  40. package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
  41. package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
  42. package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
  43. package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
  44. package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
  45. package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
  46. package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
  47. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
  48. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
  49. package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
  50. package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
  51. package/src/tigerbeetle/src/benchmark.zig +0 -314
  52. package/src/tigerbeetle/src/config.zig +0 -234
  53. package/src/tigerbeetle/src/constants.zig +0 -436
  54. package/src/tigerbeetle/src/ewah.zig +0 -286
  55. package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
  56. package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
  57. package/src/tigerbeetle/src/fifo.zig +0 -120
  58. package/src/tigerbeetle/src/io/benchmark.zig +0 -213
  59. package/src/tigerbeetle/src/io/darwin.zig +0 -814
  60. package/src/tigerbeetle/src/io/linux.zig +0 -1062
  61. package/src/tigerbeetle/src/io/test.zig +0 -643
  62. package/src/tigerbeetle/src/io/windows.zig +0 -1183
  63. package/src/tigerbeetle/src/io.zig +0 -34
  64. package/src/tigerbeetle/src/iops.zig +0 -107
  65. package/src/tigerbeetle/src/lsm/README.md +0 -308
  66. package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
  67. package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
  68. package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
  69. package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
  70. package/src/tigerbeetle/src/lsm/direction.zig +0 -11
  71. package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
  72. package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
  73. package/src/tigerbeetle/src/lsm/forest.zig +0 -204
  74. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -401
  75. package/src/tigerbeetle/src/lsm/grid.zig +0 -573
  76. package/src/tigerbeetle/src/lsm/groove.zig +0 -972
  77. package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
  78. package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
  79. package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
  80. package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -877
  81. package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
  82. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
  83. package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
  84. package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
  85. package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -378
  86. package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1328
  87. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
  88. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
  89. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
  90. package/src/tigerbeetle/src/lsm/table.zig +0 -1031
  91. package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -203
  92. package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
  93. package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -220
  94. package/src/tigerbeetle/src/lsm/test.zig +0 -438
  95. package/src/tigerbeetle/src/lsm/tree.zig +0 -1193
  96. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -474
  97. package/src/tigerbeetle/src/message_bus.zig +0 -1012
  98. package/src/tigerbeetle/src/message_pool.zig +0 -156
  99. package/src/tigerbeetle/src/ring_buffer.zig +0 -399
  100. package/src/tigerbeetle/src/simulator.zig +0 -569
  101. package/src/tigerbeetle/src/state_machine/auditor.zig +0 -577
  102. package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
  103. package/src/tigerbeetle/src/state_machine.zig +0 -1881
  104. package/src/tigerbeetle/src/static_allocator.zig +0 -65
  105. package/src/tigerbeetle/src/stdx.zig +0 -162
  106. package/src/tigerbeetle/src/storage.zig +0 -393
  107. package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
  108. package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
  109. package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
  110. package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
  111. package/src/tigerbeetle/src/testing/cluster.zig +0 -443
  112. package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
  113. package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
  114. package/src/tigerbeetle/src/testing/id.zig +0 -99
  115. package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -364
  116. package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
  117. package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
  118. package/src/tigerbeetle/src/testing/state_machine.zig +0 -249
  119. package/src/tigerbeetle/src/testing/storage.zig +0 -757
  120. package/src/tigerbeetle/src/testing/table.zig +0 -247
  121. package/src/tigerbeetle/src/testing/time.zig +0 -84
  122. package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
  123. package/src/tigerbeetle/src/time.zig +0 -112
  124. package/src/tigerbeetle/src/tracer.zig +0 -529
  125. package/src/tigerbeetle/src/unit_tests.zig +0 -42
  126. package/src/tigerbeetle/src/vopr.zig +0 -495
  127. package/src/tigerbeetle/src/vsr/README.md +0 -209
  128. package/src/tigerbeetle/src/vsr/client.zig +0 -544
  129. package/src/tigerbeetle/src/vsr/clock.zig +0 -853
  130. package/src/tigerbeetle/src/vsr/journal.zig +0 -2413
  131. package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
  132. package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
  133. package/src/tigerbeetle/src/vsr/replica.zig +0 -6381
  134. package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
  135. package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
  136. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
  137. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
  138. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
  139. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
  140. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
  141. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
  142. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
  143. package/src/tigerbeetle/src/vsr.zig +0 -1352
@@ -1,474 +0,0 @@
1
- const std = @import("std");
2
- const testing = std.testing;
3
- const allocator = testing.allocator;
4
- const assert = std.debug.assert;
5
-
6
- const constants = @import("../constants.zig");
7
- const fuzz = @import("../testing/fuzz.zig");
8
- const vsr = @import("../vsr.zig");
9
-
10
- const log = std.log.scoped(.lsm_tree_fuzz);
11
- const tracer = @import("../tracer.zig");
12
-
13
- const MessagePool = @import("../message_pool.zig").MessagePool;
14
- const Transfer = @import("../tigerbeetle.zig").Transfer;
15
- const Account = @import("../tigerbeetle.zig").Account;
16
- const Storage = @import("../testing/storage.zig").Storage;
17
- const StateMachine = @import("../state_machine.zig").StateMachineType(Storage, .{
18
- .message_body_size_max = constants.message_body_size_max,
19
- });
20
-
21
- const GridType = @import("grid.zig").GridType;
22
- const NodePool = @import("node_pool.zig").NodePool(constants.lsm_manifest_node_size, 16);
23
- const TableUsage = @import("table.zig").TableUsage;
24
- const TableType = @import("table.zig").TableType;
25
-
26
- const Grid = GridType(Storage);
27
- const SuperBlock = vsr.SuperBlockType(Storage);
28
-
29
- pub const tigerbeetle_config = @import("../config.zig").configs.test_min;
30
-
31
- const Key = packed struct {
32
- id: u64 align(@alignOf(u64)),
33
-
34
- const Value = packed struct {
35
- id: u64,
36
- value: u63,
37
- tombstone: u1 = 0,
38
- };
39
-
40
- inline fn compare_keys(a: Key, b: Key) std.math.Order {
41
- return std.math.order(a.id, b.id);
42
- }
43
-
44
- inline fn key_from_value(value: *const Key.Value) Key {
45
- return Key{ .id = value.id };
46
- }
47
-
48
- const sentinel_key = Key{
49
- .id = std.math.maxInt(u64),
50
- };
51
-
52
- inline fn tombstone(value: *const Key.Value) bool {
53
- return value.tombstone != 0;
54
- }
55
-
56
- inline fn tombstone_from_key(key: Key) Key.Value {
57
- return Key.Value{
58
- .id = key.id,
59
- .value = 0,
60
- .tombstone = 1,
61
- };
62
- }
63
- };
64
-
65
- const FuzzOpTag = std.meta.Tag(FuzzOp);
66
- const FuzzOp = union(enum) {
67
- // TODO Test range queries.
68
- compact: struct {
69
- op: u64,
70
- checkpoint: bool,
71
- },
72
- put: Key.Value,
73
- remove: Key.Value,
74
- get: Key,
75
- };
76
-
77
- const batch_size_max = constants.message_size_max - @sizeOf(vsr.Header);
78
- const commit_entries_max = @divFloor(batch_size_max, @sizeOf(Key.Value));
79
-
80
- const cluster = 32;
81
- const replica = 4;
82
- const node_count = 1024;
83
- const tree_options = .{
84
- .commit_entries_max = commit_entries_max,
85
- // This is the smallest size that set_associative_cache will allow us.
86
- .cache_entries_max = 2048,
87
- };
88
-
89
- const puts_since_compact_max = commit_entries_max;
90
- const compacts_per_checkpoint = std.math.divCeil(
91
- usize,
92
- constants.journal_slot_count,
93
- constants.lsm_batch_multiple,
94
- ) catch unreachable;
95
-
96
- fn EnvironmentType(comptime table_usage: TableUsage) type {
97
- return struct {
98
- const Environment = @This();
99
-
100
- const Tree = @import("tree.zig").TreeType(Table, Storage, "Key.Value");
101
- const Table = TableType(
102
- Key,
103
- Key.Value,
104
- Key.compare_keys,
105
- Key.key_from_value,
106
- Key.sentinel_key,
107
- Key.tombstone,
108
- Key.tombstone_from_key,
109
- table_usage,
110
- );
111
-
112
- const State = enum {
113
- init,
114
- superblock_format,
115
- superblock_open,
116
- tree_init,
117
- tree_open,
118
- fuzzing,
119
- tree_compact,
120
- tree_checkpoint,
121
- superblock_checkpoint,
122
- tree_lookup,
123
- };
124
-
125
- state: State,
126
- storage: *Storage,
127
- message_pool: MessagePool,
128
- superblock: SuperBlock,
129
- superblock_context: SuperBlock.Context,
130
- grid: Grid,
131
- node_pool: NodePool,
132
- tree: Tree,
133
- lookup_context: Tree.LookupContext,
134
- lookup_value: ?*const Key.Value,
135
- checkpoint_op: ?u64,
136
-
137
- pub fn run(storage: *Storage, fuzz_ops: []const FuzzOp) !void {
138
- var env: Environment = undefined;
139
- env.state = .init;
140
- env.storage = storage;
141
-
142
- env.message_pool = try MessagePool.init(allocator, .replica);
143
- defer env.message_pool.deinit(allocator);
144
-
145
- env.superblock = try SuperBlock.init(allocator, .{
146
- .storage = env.storage,
147
- .storage_size_limit = constants.storage_size_max,
148
- .message_pool = &env.message_pool,
149
- });
150
- defer env.superblock.deinit(allocator);
151
-
152
- env.grid = try Grid.init(allocator, &env.superblock);
153
- defer env.grid.deinit(allocator);
154
-
155
- env.node_pool = try NodePool.init(allocator, node_count);
156
- defer env.node_pool.deinit(allocator);
157
-
158
- env.tree = undefined;
159
- env.lookup_value = null;
160
- env.checkpoint_op = null;
161
-
162
- try env.open_then_apply(fuzz_ops);
163
- }
164
-
165
- fn change_state(env: *Environment, current_state: State, next_state: State) void {
166
- assert(env.state == current_state);
167
- env.state = next_state;
168
- }
169
-
170
- fn tick_until_state_change(env: *Environment, current_state: State, next_state: State) void {
171
- // Sometimes operations complete synchronously so we might already be in next_state before ticking.
172
- //assert(env.state == current_state or env.state == next_state);
173
- while (env.state == current_state) env.storage.tick();
174
- assert(env.state == next_state);
175
- }
176
-
177
- pub fn open_then_apply(env: *Environment, fuzz_ops: []const FuzzOp) !void {
178
- env.change_state(.init, .superblock_format);
179
- env.superblock.format(superblock_format_callback, &env.superblock_context, .{
180
- .cluster = cluster,
181
- .replica = replica,
182
- });
183
-
184
- env.tick_until_state_change(.superblock_format, .superblock_open);
185
- env.superblock.open(superblock_open_callback, &env.superblock_context);
186
-
187
- env.tick_until_state_change(.superblock_open, .tree_init);
188
- env.tree = try Tree.init(allocator, &env.node_pool, &env.grid, tree_options);
189
- defer env.tree.deinit(allocator);
190
-
191
- env.change_state(.tree_init, .tree_open);
192
- env.tree.open(tree_open_callback);
193
-
194
- env.tick_until_state_change(.tree_open, .fuzzing);
195
- try env.apply(fuzz_ops);
196
- }
197
-
198
- fn superblock_format_callback(superblock_context: *SuperBlock.Context) void {
199
- const env = @fieldParentPtr(@This(), "superblock_context", superblock_context);
200
- env.change_state(.superblock_format, .superblock_open);
201
- }
202
-
203
- fn superblock_open_callback(superblock_context: *SuperBlock.Context) void {
204
- const env = @fieldParentPtr(@This(), "superblock_context", superblock_context);
205
- env.change_state(.superblock_open, .tree_init);
206
- }
207
-
208
- fn tree_open_callback(tree: *Tree) void {
209
- const env = @fieldParentPtr(@This(), "tree", tree);
210
- env.change_state(.tree_open, .fuzzing);
211
- }
212
-
213
- pub fn compact(env: *Environment, op: u64) void {
214
- env.change_state(.fuzzing, .tree_compact);
215
- env.tree.compact(tree_compact_callback, op);
216
- env.tick_until_state_change(.tree_compact, .fuzzing);
217
- }
218
-
219
- fn tree_compact_callback(tree: *Tree) void {
220
- const env = @fieldParentPtr(@This(), "tree", tree);
221
- env.change_state(.tree_compact, .fuzzing);
222
- }
223
-
224
- pub fn checkpoint(env: *Environment, op: u64) void {
225
- assert(env.checkpoint_op == null);
226
- env.checkpoint_op = op - constants.lsm_batch_multiple;
227
-
228
- env.change_state(.fuzzing, .tree_checkpoint);
229
- env.tree.checkpoint(tree_checkpoint_callback);
230
- env.tick_until_state_change(.tree_checkpoint, .superblock_checkpoint);
231
- env.tick_until_state_change(.superblock_checkpoint, .fuzzing);
232
- }
233
-
234
- fn tree_checkpoint_callback(tree: *Tree) void {
235
- const env = @fieldParentPtr(@This(), "tree", tree);
236
- const op = env.checkpoint_op.?;
237
- env.checkpoint_op = null;
238
-
239
- env.change_state(.tree_checkpoint, .superblock_checkpoint);
240
- env.superblock.checkpoint(superblock_checkpoint_callback, &env.superblock_context, .{
241
- .commit_min_checksum = env.superblock.working.vsr_state.commit_min_checksum + 1,
242
- .commit_min = op,
243
- .commit_max = op + 1,
244
- });
245
- }
246
-
247
- fn superblock_checkpoint_callback(superblock_context: *SuperBlock.Context) void {
248
- const env = @fieldParentPtr(@This(), "superblock_context", superblock_context);
249
- env.change_state(.superblock_checkpoint, .fuzzing);
250
- }
251
-
252
- pub fn get(env: *Environment, key: Key) ?*const Key.Value {
253
- env.change_state(.fuzzing, .tree_lookup);
254
-
255
- if (env.tree.lookup_from_memory(env.tree.lookup_snapshot_max, key)) |value| {
256
- env.change_state(.tree_lookup, .fuzzing);
257
- return Tree.unwrap_tombstone(value);
258
- }
259
-
260
- env.lookup_value = null;
261
- env.tree.lookup_from_levels(get_callback, &env.lookup_context, env.tree.lookup_snapshot_max, key);
262
- env.tick_until_state_change(.tree_lookup, .fuzzing);
263
- return env.lookup_value;
264
- }
265
-
266
- fn get_callback(lookup_context: *Tree.LookupContext, value: ?*const Key.Value) void {
267
- const env = @fieldParentPtr(Environment, "lookup_context", lookup_context);
268
- assert(env.lookup_value == null);
269
- env.lookup_value = value;
270
- env.change_state(.tree_lookup, .fuzzing);
271
- }
272
-
273
- pub fn apply(env: *Environment, fuzz_ops: []const FuzzOp) !void {
274
- // The tree should behave like a simple key-value data-structure.
275
- // We'll compare it to a hash map.
276
- var model = std.hash_map.AutoHashMap(Key, Key.Value).init(allocator);
277
- defer model.deinit();
278
-
279
- for (fuzz_ops) |fuzz_op, fuzz_op_index| {
280
- assert(env.state == .fuzzing);
281
- log.debug("Running fuzz_ops[{}/{}] == {}", .{ fuzz_op_index, fuzz_ops.len, fuzz_op });
282
-
283
- const storage_size_used = env.storage.size_used();
284
- log.debug("storage.size_used = {}/{}", .{ storage_size_used, env.storage.size });
285
-
286
- const model_size = model.count() * @sizeOf(Key.Value);
287
- log.debug("space_amplification = {d:.2}", .{
288
- @intToFloat(f64, storage_size_used) / @intToFloat(f64, model_size),
289
- });
290
-
291
- // Apply fuzz_op to the tree and the model.
292
- switch (fuzz_op) {
293
- .compact => |compact| {
294
- env.compact(compact.op);
295
- if (compact.checkpoint) env.checkpoint(compact.op);
296
- },
297
- .put => |value| {
298
- if (table_usage == .secondary_index) {
299
- if (model.get(Key.key_from_value(&value))) |old_value| {
300
- // Not allowed to put a present key without removing the old value first.
301
- env.tree.remove(&old_value);
302
- }
303
- }
304
- env.tree.put(&value);
305
- try model.put(Key.key_from_value(&value), value);
306
- },
307
- .remove => |value| {
308
- if (table_usage == .secondary_index and !model.contains((Key.key_from_value(&value)))) {
309
- // Not allowed to remove non-present keys
310
- } else {
311
- env.tree.remove(&value);
312
- }
313
- _ = model.remove(Key.key_from_value(&value));
314
- },
315
- .get => |key| {
316
- // Get account from lsm.
317
- const tree_value = env.get(key);
318
-
319
- // Compare result to model.
320
- const model_value = model.get(key);
321
- if (model_value == null) {
322
- assert(tree_value == null);
323
- } else {
324
- switch (table_usage) {
325
- .general => {
326
- assert(std.mem.eql(
327
- u8,
328
- std.mem.asBytes(&model_value.?),
329
- std.mem.asBytes(tree_value.?),
330
- ));
331
- },
332
- .secondary_index => {
333
- // secondary_index only preserves keys - may return old values
334
- assert(std.mem.eql(
335
- u8,
336
- std.mem.asBytes(&Key.key_from_value(&model_value.?)),
337
- std.mem.asBytes(&Key.key_from_value(tree_value.?)),
338
- ));
339
- },
340
- }
341
- }
342
- },
343
- }
344
- }
345
- }
346
- };
347
- }
348
-
349
- fn random_id(random: std.rand.Random, comptime Int: type) Int {
350
- // We have two opposing desires for random ids:
351
- const avg_int: Int = if (random.boolean())
352
- // 1. We want to cause many collisions.
353
- //8
354
- 100 * constants.lsm_growth_factor * tree_options.cache_entries_max
355
- else
356
- // 2. We want to generate enough ids that the cache can't hold them all.
357
- constants.lsm_growth_factor * tree_options.cache_entries_max;
358
- return fuzz.random_int_exponential(random, Int, avg_int);
359
- }
360
-
361
- pub fn generate_fuzz_ops(random: std.rand.Random, fuzz_op_count: usize) ![]const FuzzOp {
362
- log.info("fuzz_op_count = {}", .{fuzz_op_count});
363
-
364
- const fuzz_ops = try allocator.alloc(FuzzOp, fuzz_op_count);
365
- errdefer allocator.free(fuzz_ops);
366
-
367
- var fuzz_op_distribution = fuzz.Distribution(FuzzOpTag){
368
- // Maybe compact more often than forced to by `puts_since_compact`.
369
- .compact = if (random.boolean()) 0 else 1,
370
- // Always do puts, and always more puts than removes.
371
- .put = constants.lsm_batch_multiple * 2,
372
- // Maybe do some removes.
373
- .remove = if (random.boolean()) 0 else constants.lsm_batch_multiple,
374
- // Maybe do some gets.
375
- .get = if (random.boolean()) 0 else constants.lsm_batch_multiple,
376
- };
377
- log.info("fuzz_op_distribution = {d:.2}", .{fuzz_op_distribution});
378
-
379
- log.info("puts_since_compact_max = {}", .{puts_since_compact_max});
380
- log.info("compacts_per_checkpoint = {}", .{compacts_per_checkpoint});
381
-
382
- var op: u64 = 1;
383
- var puts_since_compact: usize = 0;
384
- for (fuzz_ops) |*fuzz_op| {
385
- const fuzz_op_tag = if (puts_since_compact >= puts_since_compact_max)
386
- // We have to compact before doing any other operations.
387
- FuzzOpTag.compact
388
- else
389
- // Otherwise pick a random FuzzOp.
390
- fuzz.random_enum(random, FuzzOpTag, fuzz_op_distribution);
391
- fuzz_op.* = switch (fuzz_op_tag) {
392
- .compact => compact: {
393
- const compact_op = op;
394
- op += 1;
395
- const is_checkpoint =
396
- // Can only checkpoint on the last beat of the bar.
397
- compact_op % constants.lsm_batch_multiple == constants.lsm_batch_multiple - 1 and
398
- compact_op > constants.lsm_batch_multiple and
399
- // Checkpoint at roughly the same rate as log wraparound.
400
- random.uintLessThan(usize, compacts_per_checkpoint) == 0;
401
- break :compact FuzzOp{
402
- .compact = .{
403
- .op = compact_op,
404
- .checkpoint = is_checkpoint,
405
- },
406
- };
407
- },
408
- .put => FuzzOp{ .put = .{
409
- .id = random_id(random, u64),
410
- .value = random.int(u63),
411
- } },
412
- .remove => FuzzOp{ .remove = .{
413
- .id = random_id(random, u64),
414
- .value = random.int(u63),
415
- } },
416
- .get => FuzzOp{ .get = .{
417
- .id = random_id(random, u64),
418
- } },
419
- };
420
- switch (fuzz_op.*) {
421
- .compact => puts_since_compact = 0,
422
- // Tree.remove() works by inserting a tombstone, so it counts as a put.
423
- .put, .remove => puts_since_compact += 1,
424
- .get => {},
425
- }
426
- }
427
-
428
- return fuzz_ops;
429
- }
430
-
431
- pub fn main() !void {
432
- try tracer.init(allocator);
433
- defer tracer.deinit(allocator);
434
-
435
- const fuzz_args = try fuzz.parse_fuzz_args(allocator);
436
-
437
- var rng = std.rand.DefaultPrng.init(fuzz_args.seed);
438
- const random = rng.random();
439
-
440
- const table_usage = random.enumValue(TableUsage);
441
- log.info("table_usage={}", .{table_usage});
442
-
443
- const storage_options = .{
444
- .seed = random.int(u64),
445
- .read_latency_min = 0,
446
- .read_latency_mean = 0 + fuzz.random_int_exponential(random, u64, 20),
447
- .write_latency_min = 0,
448
- .write_latency_mean = 0 + fuzz.random_int_exponential(random, u64, 20),
449
- };
450
-
451
- const fuzz_op_count = @minimum(
452
- fuzz_args.events_max orelse @as(usize, 1E7),
453
- fuzz.random_int_exponential(random, usize, 1E6),
454
- );
455
-
456
- const fuzz_ops = try generate_fuzz_ops(random, fuzz_op_count);
457
- defer allocator.free(fuzz_ops);
458
-
459
- // Init mocked storage.
460
- var storage = try Storage.init(allocator, constants.storage_size_max, storage_options);
461
- defer storage.deinit(allocator);
462
-
463
- // TODO Use inline switch after upgrading to zig 0.10
464
- switch (table_usage) {
465
- .general => {
466
- try EnvironmentType(.general).run(&storage, fuzz_ops);
467
- },
468
- .secondary_index => {
469
- try EnvironmentType(.secondary_index).run(&storage, fuzz_ops);
470
- },
471
- }
472
-
473
- log.info("Passed!", .{});
474
- }