tigerbeetle-node 0.11.5 → 0.11.7

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 (77) hide show
  1. package/dist/.client.node.sha256 +1 -1
  2. package/dist/index.d.ts +41 -42
  3. package/dist/index.js +41 -42
  4. package/dist/index.js.map +1 -1
  5. package/package.json +2 -2
  6. package/src/index.ts +0 -1
  7. package/src/tigerbeetle/scripts/benchmark.bat +7 -3
  8. package/src/tigerbeetle/scripts/benchmark.sh +2 -3
  9. package/src/tigerbeetle/scripts/install.bat +7 -0
  10. package/src/tigerbeetle/scripts/install.sh +2 -3
  11. package/src/tigerbeetle/src/benchmark.zig +3 -3
  12. package/src/tigerbeetle/src/config.zig +24 -3
  13. package/src/tigerbeetle/src/constants.zig +8 -5
  14. package/src/tigerbeetle/src/ewah.zig +6 -5
  15. package/src/tigerbeetle/src/ewah_fuzz.zig +1 -1
  16. package/src/tigerbeetle/src/io/darwin.zig +19 -0
  17. package/src/tigerbeetle/src/io/linux.zig +8 -0
  18. package/src/tigerbeetle/src/io/windows.zig +20 -2
  19. package/src/tigerbeetle/src/iops.zig +7 -1
  20. package/src/tigerbeetle/src/lsm/compaction.zig +27 -72
  21. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +10 -11
  22. package/src/tigerbeetle/src/lsm/grid.zig +267 -267
  23. package/src/tigerbeetle/src/lsm/groove.zig +3 -0
  24. package/src/tigerbeetle/src/lsm/level_iterator.zig +18 -1
  25. package/src/tigerbeetle/src/lsm/manifest.zig +29 -1
  26. package/src/tigerbeetle/src/lsm/manifest_level.zig +1 -0
  27. package/src/tigerbeetle/src/lsm/manifest_log.zig +5 -5
  28. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +19 -11
  29. package/src/tigerbeetle/src/lsm/merge_iterator.zig +106 -0
  30. package/src/tigerbeetle/src/lsm/posted_groove.zig +1 -0
  31. package/src/tigerbeetle/src/lsm/segmented_array.zig +1 -0
  32. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +26 -70
  33. package/src/tigerbeetle/src/lsm/table.zig +56 -0
  34. package/src/tigerbeetle/src/lsm/table_iterator.zig +29 -2
  35. package/src/tigerbeetle/src/lsm/table_mutable.zig +49 -15
  36. package/src/tigerbeetle/src/lsm/test.zig +10 -7
  37. package/src/tigerbeetle/src/lsm/tree.zig +27 -6
  38. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +302 -263
  39. package/src/tigerbeetle/src/message_pool.zig +2 -1
  40. package/src/tigerbeetle/src/simulator.zig +22 -84
  41. package/src/tigerbeetle/src/{test/accounting → state_machine}/auditor.zig +8 -8
  42. package/src/tigerbeetle/src/{test/accounting → state_machine}/workload.zig +108 -48
  43. package/src/tigerbeetle/src/state_machine.zig +20 -14
  44. package/src/tigerbeetle/src/storage.zig +58 -6
  45. package/src/tigerbeetle/src/test/cluster.zig +14 -11
  46. package/src/tigerbeetle/src/test/conductor.zig +2 -3
  47. package/src/tigerbeetle/src/test/id.zig +10 -0
  48. package/src/tigerbeetle/src/test/state_checker.zig +1 -1
  49. package/src/tigerbeetle/src/test/state_machine.zig +151 -46
  50. package/src/tigerbeetle/src/test/storage.zig +22 -1
  51. package/src/tigerbeetle/src/tigerbeetle.zig +0 -1
  52. package/src/tigerbeetle/src/tracer.zig +50 -28
  53. package/src/tigerbeetle/src/unit_tests.zig +11 -6
  54. package/src/tigerbeetle/src/vopr.zig +4 -4
  55. package/src/tigerbeetle/src/vsr/client.zig +5 -5
  56. package/src/tigerbeetle/src/vsr/clock.zig +2 -2
  57. package/src/tigerbeetle/src/vsr/journal.zig +647 -537
  58. package/src/tigerbeetle/src/vsr/replica.zig +333 -333
  59. package/src/tigerbeetle/src/vsr/replica_format.zig +7 -4
  60. package/src/tigerbeetle/src/vsr/superblock.zig +87 -39
  61. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +114 -93
  62. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +1 -1
  63. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +11 -8
  64. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +3 -3
  65. package/src/tigerbeetle/src/vsr.zig +60 -13
  66. package/src/tigerbeetle/src/c/tb_client/context.zig +0 -304
  67. package/src/tigerbeetle/src/c/tb_client/echo_client.zig +0 -108
  68. package/src/tigerbeetle/src/c/tb_client/packet.zig +0 -80
  69. package/src/tigerbeetle/src/c/tb_client/signal.zig +0 -286
  70. package/src/tigerbeetle/src/c/tb_client/thread.zig +0 -88
  71. package/src/tigerbeetle/src/c/tb_client.h +0 -221
  72. package/src/tigerbeetle/src/c/tb_client.zig +0 -177
  73. package/src/tigerbeetle/src/c/tb_client_header.zig +0 -218
  74. package/src/tigerbeetle/src/c/tb_client_header_test.zig +0 -135
  75. package/src/tigerbeetle/src/c/test.zig +0 -371
  76. package/src/tigerbeetle/src/cli.zig +0 -375
  77. package/src/tigerbeetle/src/main.zig +0 -245
@@ -11,7 +11,7 @@ const Message = MessagePool.Message;
11
11
  const Network = @import("network.zig").Network;
12
12
  const NetworkOptions = @import("network.zig").NetworkOptions;
13
13
 
14
- pub const StateMachine = @import("../state_machine.zig").StateMachineType(Storage, .{
14
+ pub const StateMachine = constants.StateMachineType(Storage, .{
15
15
  .message_body_size_max = constants.message_body_size_max,
16
16
  });
17
17
  const MessageBus = @import("message_bus.zig").MessageBus;
@@ -29,7 +29,7 @@ pub const ClusterOptions = struct {
29
29
  cluster: u32,
30
30
  replica_count: u8,
31
31
  client_count: u8,
32
- grid_size_max: usize,
32
+ storage_size_limit: u64,
33
33
 
34
34
  seed: u64,
35
35
  on_change_state: fn (replica: *const Replica) void,
@@ -76,8 +76,8 @@ pub const Cluster = struct {
76
76
  pub fn create(allocator: mem.Allocator, prng: std.rand.Random, options: ClusterOptions) !*Cluster {
77
77
  assert(options.replica_count > 0);
78
78
  assert(options.client_count > 0);
79
- assert(options.grid_size_max > 0);
80
- assert(options.grid_size_max % constants.sector_size == 0);
79
+ assert(options.storage_size_limit % constants.sector_size == 0);
80
+ assert(options.storage_size_limit <= constants.storage_size_max);
81
81
  assert(options.health_options.crash_probability < 1.0);
82
82
  assert(options.health_options.crash_probability >= 0.0);
83
83
  assert(options.health_options.restart_probability < 1.0);
@@ -136,17 +136,19 @@ pub const Cluster = struct {
136
136
  var storage_options = options.storage_options;
137
137
  storage_options.replica_index = @intCast(u8, replica_index);
138
138
  storage_options.faulty_wal_areas = faulty_wal_areas[replica_index];
139
- storage.* = try Storage.init(
140
- allocator,
141
- superblock_zone_size + constants.journal_size_max + options.grid_size_max,
142
- storage_options,
143
- );
139
+ storage.* = try Storage.init(allocator, options.storage_size_limit, storage_options);
140
+ // Disable most faults at startup, so that the replicas don't get stuck in recovery mode.
141
+ storage.faulty = replica_index >= vsr.quorums(options.replica_count).view_change;
144
142
  }
145
143
  errdefer for (cluster.storages) |*storage| storage.deinit(allocator);
146
144
 
147
145
  // Format each replica's storage (equivalent to "tigerbeetle format ...").
148
146
  for (cluster.storages) |*storage, replica_index| {
149
- var superblock = try SuperBlock.init(allocator, storage, &cluster.pools[replica_index]);
147
+ var superblock = try SuperBlock.init(allocator, .{
148
+ .storage = storage,
149
+ .message_pool = &cluster.pools[replica_index],
150
+ .storage_size_limit = options.storage_size_limit,
151
+ });
150
152
  defer superblock.deinit(allocator);
151
153
 
152
154
  try vsr.format(
@@ -330,6 +332,8 @@ pub const Cluster = struct {
330
332
  .{
331
333
  .replica_count = @intCast(u8, cluster.replicas.len),
332
334
  .storage = &cluster.storages[replica_index],
335
+ // TODO Test restarting with a higher storage limit.
336
+ .storage_size_limit = cluster.options.storage_size_limit,
333
337
  .message_pool = &cluster.pools[replica_index],
334
338
  .time = time,
335
339
  .state_machine_options = cluster.options.state_machine_options,
@@ -339,7 +343,6 @@ pub const Cluster = struct {
339
343
  assert(replica.cluster == cluster.options.cluster);
340
344
  assert(replica.replica == replica_index);
341
345
  assert(replica.replica_count == cluster.replicas.len);
342
- assert(replica.status == .recovering);
343
346
 
344
347
  replica.on_change_state = cluster.options.on_change_state;
345
348
  replica.on_compact = cluster.options.on_compact;
@@ -36,7 +36,6 @@ pub fn ConductorType(
36
36
  comptime Client: type,
37
37
  comptime MessageBus: type,
38
38
  comptime StateMachine: type,
39
- comptime Workload: type,
40
39
  ) type {
41
40
  return struct {
42
41
  const Self = @This();
@@ -51,7 +50,7 @@ pub fn ConductorType(
51
50
  constants.clients_max * constants.client_request_queue_max * 2;
52
51
 
53
52
  random: std.rand.Random,
54
- workload: *Workload,
53
+ workload: *StateMachine.Workload,
55
54
  options: Options,
56
55
  client_id_permutation: IdPermutation,
57
56
 
@@ -90,7 +89,7 @@ pub fn ConductorType(
90
89
  pub fn init(
91
90
  allocator: std.mem.Allocator,
92
91
  random: std.rand.Random,
93
- workload: *Workload,
92
+ workload: *StateMachine.Workload,
94
93
  options: Options,
95
94
  ) !Self {
96
95
  assert(options.replica_count >= 1);
@@ -62,6 +62,16 @@ pub const IdPermutation = union(enum) {
62
62
  .random => @truncate(usize, id >> 32),
63
63
  };
64
64
  }
65
+
66
+ pub fn generate(random: std.rand.Random) IdPermutation {
67
+ return switch (random.uintLessThan(usize, 4)) {
68
+ 0 => .{ .identity = {} },
69
+ 1 => .{ .inversion = {} },
70
+ 2 => .{ .zigzag = {} },
71
+ 3 => .{ .random = random.int(u64) },
72
+ else => unreachable,
73
+ };
74
+ }
65
75
  };
66
76
 
67
77
  test "IdPermutation" {
@@ -70,7 +70,7 @@ pub const StateChecker = struct {
70
70
  }
71
71
 
72
72
  pub fn check_state(state_checker: *StateChecker, replica_index: u8) !void {
73
- const replica = state_checker.replicas[replica_index];
73
+ const replica = &state_checker.replicas[replica_index];
74
74
  const commit_header = header: {
75
75
  if (replica.journal.status == .recovered) {
76
76
  const commit_header = replica.journal.header_with_op(replica.commit_min);
@@ -1,68 +1,65 @@
1
1
  const std = @import("std");
2
2
  const assert = std.debug.assert;
3
3
 
4
+ const constants = @import("../constants.zig");
5
+ const vsr = @import("../vsr.zig");
4
6
  const log = std.log.scoped(.state_machine);
5
7
 
6
- pub fn StateMachineType(comptime Storage: type) type {
8
+ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
9
+ message_body_size_max: usize,
10
+ }) type {
7
11
  _ = Storage;
12
+ _ = constants_;
13
+
8
14
  return struct {
9
15
  const StateMachine = @This();
10
16
  const Grid = @import("../lsm/grid.zig").GridType(Storage);
11
17
 
18
+ pub const Workload = WorkloadType(StateMachine);
19
+
12
20
  pub const Operation = enum(u8) {
13
21
  /// Operations reserved by VR protocol (for all state machines):
14
22
  reserved,
15
23
  root,
16
24
  register,
17
25
 
18
- random,
26
+ echo,
19
27
  };
20
28
 
21
- /// Minimum/mean number of ticks to perform the specified operation.
22
- /// Each mean must be greater-or-equal-to their respective minimum.
23
- pub const Options = struct {
24
- seed: u64,
25
- prefetch_mean: u64,
26
- compact_mean: u64,
27
- checkpoint_mean: u64,
28
- };
29
+ pub const Options = struct {};
29
30
 
30
31
  options: Options,
31
- prng: std.rand.DefaultPrng,
32
+ grid: *Grid,
33
+ grid_block: Grid.BlockPtr,
34
+ grid_write: Grid.Write = undefined,
32
35
  prepare_timestamp: u64 = 0,
33
36
  commit_timestamp: u64 = 0,
34
37
 
35
38
  callback: ?fn (state_machine: *StateMachine) void = null,
36
- callback_ticks: usize = 0,
37
39
 
38
- pub fn init(_: std.mem.Allocator, _: *Grid, options: Options) !StateMachine {
40
+ pub fn init(allocator: std.mem.Allocator, grid: *Grid, options: Options) !StateMachine {
41
+ const grid_block = try allocator.alignedAlloc(
42
+ u8,
43
+ constants.sector_size,
44
+ constants.block_size,
45
+ );
46
+ errdefer allocator.free(grid_block);
47
+ std.mem.set(u8, grid_block, 0);
48
+
39
49
  return StateMachine{
40
50
  .options = options,
41
- .prng = std.rand.DefaultPrng.init(options.seed),
51
+ .grid = grid,
52
+ .grid_block = grid_block[0..constants.block_size],
42
53
  };
43
54
  }
44
55
 
45
- pub fn deinit(_: *StateMachine, _: std.mem.Allocator) void {}
46
-
47
- // TODO This is dead code — tick() has been removed from the StateMachine
48
- // interface. If we start using the test StateMachine again, tick will need
49
- // to be called explicitly from the simulator to ensure async operations can
50
- // finish.
51
- pub fn tick(state_machine: *StateMachine) void {
52
- if (state_machine.callback) |callback| {
53
- if (state_machine.callback_ticks == 0) {
54
- state_machine.callback = null;
55
- callback(state_machine);
56
- } else {
57
- state_machine.callback_ticks -= 1;
58
- }
59
- }
56
+ pub fn deinit(state_machine: *StateMachine, allocator: std.mem.Allocator) void {
57
+ allocator.free(state_machine.grid_block);
60
58
  }
61
59
 
62
- /// Don't add latency to `StateMachine.open`: the simulator calls it synchronously during
63
- /// replica setup.
64
- pub fn open(self: *StateMachine, callback: fn (*StateMachine) void) void {
65
- callback(self);
60
+ // TODO Grid.next_tick
61
+ pub fn open(state_machine: *StateMachine, callback: fn (*StateMachine) void) void {
62
+ callback(state_machine);
66
63
  }
67
64
 
68
65
  pub fn prepare(
@@ -86,10 +83,8 @@ pub fn StateMachineType(comptime Storage: type) type {
86
83
  _ = op;
87
84
  _ = operation;
88
85
  _ = input;
89
- assert(state_machine.callback == null);
90
- assert(state_machine.callback_ticks == 0);
91
- state_machine.callback = callback;
92
- state_machine.callback_ticks = state_machine.latency(state_machine.options.prefetch_mean);
86
+
87
+ state_machine.next_tick(callback);
93
88
  }
94
89
 
95
90
  pub fn commit(
@@ -109,34 +104,144 @@ pub fn StateMachineType(comptime Storage: type) type {
109
104
  switch (operation) {
110
105
  .reserved, .root => unreachable,
111
106
  .register => return 0,
112
- .random => return 0,
107
+ .echo => {
108
+ std.mem.copy(u8, output, input);
109
+ return input.len;
110
+ },
113
111
  }
114
112
  }
115
113
 
114
+ // TODO(Grid Recovery): Actually write blocks so that this state machine can be used
115
+ // to test grid recovery.
116
116
  pub fn compact(
117
117
  state_machine: *StateMachine,
118
118
  callback: fn (*StateMachine) void,
119
119
  op: u64,
120
120
  ) void {
121
121
  _ = op;
122
- assert(state_machine.callback == null);
123
- assert(state_machine.callback_ticks == 0);
124
- state_machine.callback = callback;
125
- state_machine.callback_ticks = state_machine.latency(state_machine.options.compact_mean);
122
+ state_machine.next_tick(callback);
126
123
  }
127
124
 
128
125
  pub fn checkpoint(
129
126
  state_machine: *StateMachine,
130
127
  callback: fn (*StateMachine) void,
131
128
  ) void {
129
+ state_machine.next_tick(callback);
130
+ }
131
+
132
+ // TODO Replace with Grid.next_tick()
133
+ fn next_tick(state_machine: *StateMachine, callback: fn (*StateMachine) void) void {
134
+ // TODO This is a hack to defer till the next tick; use Grid.next_tick instead.
135
+ var free_set = state_machine.grid.superblock.free_set;
136
+ const reservation = free_set.reserve(1).?;
137
+ defer free_set.forfeit(reservation);
138
+
139
+ const address = free_set.acquire(reservation).?;
140
+ const header = std.mem.bytesAsValue(
141
+ vsr.Header,
142
+ state_machine.grid_block[0..@sizeOf(vsr.Header)],
143
+ );
144
+ header.op = address;
145
+
132
146
  assert(state_machine.callback == null);
133
- assert(state_machine.callback_ticks == 0);
134
147
  state_machine.callback = callback;
135
- state_machine.callback_ticks = state_machine.latency(state_machine.options.checkpoint_mean);
148
+ state_machine.grid.write_block(
149
+ next_tick_callback,
150
+ &state_machine.grid_write,
151
+ state_machine.grid_block,
152
+ address,
153
+ );
136
154
  }
137
155
 
138
- fn latency(state_machine: *StateMachine, mean: u64) u64 {
139
- return state_machine.prng.random().uintLessThan(u64, 2 * mean);
156
+ fn next_tick_callback(write: *Grid.Write) void {
157
+ const state_machine = @fieldParentPtr(StateMachine, "grid_write", write);
158
+ const callback = state_machine.callback.?;
159
+ state_machine.callback = null;
160
+ callback(state_machine);
140
161
  }
141
162
  };
142
163
  }
164
+
165
+ fn WorkloadType(comptime StateMachine: type) type {
166
+ return struct {
167
+ const Workload = @This();
168
+
169
+ random: std.rand.Random,
170
+ requests_sent: usize = 0,
171
+ requests_delivered: usize = 0,
172
+
173
+ pub fn init(
174
+ allocator: std.mem.Allocator,
175
+ random: std.rand.Random,
176
+ options: Options,
177
+ ) !Workload {
178
+ _ = allocator;
179
+ _ = options;
180
+
181
+ return Workload{
182
+ .random = random,
183
+ };
184
+ }
185
+
186
+ pub fn deinit(workload: *Workload, allocator: std.mem.Allocator) void {
187
+ _ = workload;
188
+ _ = allocator;
189
+ }
190
+
191
+ pub fn done(workload: *const Workload) bool {
192
+ return workload.requests_sent == workload.requests_delivered;
193
+ }
194
+
195
+ pub fn build_request(
196
+ workload: *Workload,
197
+ client_index: usize,
198
+ body: []align(@alignOf(vsr.Header)) u8,
199
+ ) struct {
200
+ operation: StateMachine.Operation,
201
+ size: usize,
202
+ } {
203
+ _ = client_index;
204
+
205
+ workload.requests_sent += 1;
206
+
207
+ // +1 for inclusive limit.
208
+ const size = workload.random.uintLessThan(usize, constants.message_body_size_max + 1);
209
+ workload.random.bytes(body[0..size]);
210
+
211
+ return .{
212
+ .operation = .echo,
213
+ .size = size,
214
+ };
215
+ }
216
+
217
+ pub fn on_reply(
218
+ workload: *Workload,
219
+ client_index: usize,
220
+ operation: vsr.Operation,
221
+ timestamp: u64,
222
+ request_body: []align(@alignOf(vsr.Header)) const u8,
223
+ reply_body: []align(@alignOf(vsr.Header)) const u8,
224
+ ) void {
225
+ _ = workload;
226
+ _ = client_index;
227
+ _ = timestamp;
228
+
229
+ workload.requests_delivered += 1;
230
+ assert(workload.requests_delivered <= workload.requests_sent);
231
+
232
+ assert(operation.cast(StateMachine) == .echo);
233
+ assert(std.mem.eql(u8, request_body, reply_body));
234
+ }
235
+
236
+ pub const Options = struct {
237
+ pub fn generate(random: std.rand.Random, options: struct {
238
+ client_count: usize,
239
+ in_flight_max: usize,
240
+ }) Options {
241
+ _ = random;
242
+ _ = options;
243
+ return .{};
244
+ }
245
+ };
246
+ };
247
+ }
@@ -25,6 +25,7 @@ const assert = std.debug.assert;
25
25
  const math = std.math;
26
26
  const mem = std.mem;
27
27
 
28
+ const FIFO = @import("../fifo.zig").FIFO;
28
29
  const constants = @import("../constants.zig");
29
30
  const vsr = @import("../vsr.zig");
30
31
  const superblock = @import("../vsr/superblock.zig");
@@ -119,6 +120,11 @@ pub const Storage = struct {
119
120
  }
120
121
  };
121
122
 
123
+ pub const NextTick = struct {
124
+ next: ?*NextTick = null,
125
+ callback: fn (next_tick: *NextTick) void,
126
+ };
127
+
122
128
  /// Faulty areas are always sized to message_size_max
123
129
  /// If the faulty areas of all replicas are superimposed, the padding between them is always message_size_max.
124
130
  /// For a single replica, the padding between faulty areas depends on the number of other replicas.
@@ -148,6 +154,7 @@ pub const Storage = struct {
148
154
  writes: std.PriorityQueue(*Storage.Write, void, Storage.Write.less_than),
149
155
 
150
156
  ticks: u64 = 0,
157
+ next_tick_queue: FIFO(NextTick) = .{},
151
158
 
152
159
  pub fn init(allocator: mem.Allocator, size: u64, options: Storage.Options) !Storage {
153
160
  assert(options.write_latency_mean >= options.write_latency_min);
@@ -222,6 +229,7 @@ pub const Storage = struct {
222
229
  }
223
230
 
224
231
  pub fn deinit(storage: *Storage, allocator: mem.Allocator) void {
232
+ assert(storage.next_tick_queue.empty());
225
233
  allocator.free(storage.memory);
226
234
  storage.memory_written.deinit(allocator);
227
235
  storage.faults.deinit(allocator);
@@ -280,6 +288,19 @@ pub const Storage = struct {
280
288
  _ = storage.writes.remove();
281
289
  storage.write_sectors_finish(write);
282
290
  }
291
+
292
+ var queue = storage.next_tick_queue;
293
+ storage.next_tick_queue = .{};
294
+ while (queue.pop()) |next_tick| next_tick.callback(next_tick);
295
+ }
296
+
297
+ pub fn on_next_tick(
298
+ storage: *Storage,
299
+ callback: fn (next_tick: *Storage.NextTick) void,
300
+ next_tick: *Storage.NextTick,
301
+ ) void {
302
+ next_tick.* = .{ .callback = callback };
303
+ storage.next_tick_queue.push(next_tick);
283
304
  }
284
305
 
285
306
  /// * Verifies that the read fits within the target sector.
@@ -787,7 +808,7 @@ pub const Storage = struct {
787
808
  pub fn grid_block(
788
809
  storage: *const Storage,
789
810
  address: u64,
790
- ) *align(constants.sector_size) const [constants.block_size]u8 {
811
+ ) *align(constants.sector_size) [constants.block_size]u8 {
791
812
  assert(address > 0);
792
813
 
793
814
  const block_offset = vsr.Zone.grid.offset((address - 1) * constants.block_size);
@@ -134,7 +134,6 @@ pub const CreateTransferResult = enum(u32) {
134
134
  accounts_must_be_different,
135
135
 
136
136
  pending_id_must_be_zero,
137
- pending_transfer_must_timeout,
138
137
 
139
138
  ledger_must_not_be_zero,
140
139
  code_must_not_be_zero,
@@ -73,15 +73,11 @@ pub const Event = union(enum) {
73
73
  state_machine_prefetch,
74
74
  state_machine_commit,
75
75
  state_machine_compact,
76
- tree_compaction_beat: struct {
77
- tree_name: []const u8,
78
- },
76
+ tree_compaction_beat,
79
77
  tree_compaction_tick: struct {
80
- tree_name: []const u8,
81
78
  level_b: u8,
82
79
  },
83
80
  tree_compaction_merge: struct {
84
- tree_name: []const u8,
85
81
  level_b: u8,
86
82
  },
87
83
 
@@ -95,24 +91,50 @@ pub const Event = union(enum) {
95
91
  _ = options;
96
92
 
97
93
  switch (event) {
98
- .tracer_flush => try writer.print("tracer_flush", .{}),
94
+ .tracer_flush,
95
+ .checkpoint,
96
+ .state_machine_prefetch,
97
+ .state_machine_commit,
98
+ .state_machine_compact,
99
+ .tree_compaction_beat,
100
+ => try writer.writeAll(@tagName(event)),
99
101
  .commit => |commit| try writer.print("commit({})", .{commit.op}),
100
- .checkpoint => try writer.print("checkpoint", .{}),
101
- .state_machine_prefetch => try writer.print("state_machine_prefetch", .{}),
102
- .state_machine_commit => try writer.print("state_machine_commit", .{}),
103
- .state_machine_compact => try writer.print("state_machine_compact", .{}),
104
- .tree_compaction_beat => |tree_compaction_tick| try writer.print(
105
- "tree_compaction_beat({s})",
106
- .{tree_compaction_tick.tree_name},
107
- ),
108
- .tree_compaction_tick => |tree_compaction_tick| try writer.print(
109
- "tree_compaction_tick({s}, {})",
110
- .{ tree_compaction_tick.tree_name, tree_compaction_tick.level_b },
111
- ),
112
- .tree_compaction_merge => |tree_compaction_merge| try writer.print(
113
- "tree_compaction_merge({s}, {})",
114
- .{ tree_compaction_merge.tree_name, tree_compaction_merge.level_b },
115
- ),
102
+ .tree_compaction_tick => |args| {
103
+ if (args.level_b == 0)
104
+ try writer.print(
105
+ "tree_compaction_tick({s}->{})",
106
+ .{
107
+ "immutable",
108
+ args.level_b,
109
+ },
110
+ )
111
+ else
112
+ try writer.print(
113
+ "tree_compaction_tick({}->{})",
114
+ .{
115
+ args.level_b - 1,
116
+ args.level_b,
117
+ },
118
+ );
119
+ },
120
+ .tree_compaction_merge => |args| {
121
+ if (args.level_b == 0)
122
+ try writer.print(
123
+ "tree_compaction_merge({s}->{})",
124
+ .{
125
+ "immutable",
126
+ args.level_b,
127
+ },
128
+ )
129
+ else
130
+ try writer.print(
131
+ "tree_compaction_merge({}->{})",
132
+ .{
133
+ args.level_b - 1,
134
+ args.level_b,
135
+ },
136
+ );
137
+ },
116
138
  }
117
139
  }
118
140
  };
@@ -124,12 +146,16 @@ pub const EventGroup = union(enum) {
124
146
  tree: struct {
125
147
  tree_name: [:0]const u8,
126
148
  },
149
+ tree_compaction: struct {
150
+ compaction_name: [:0]const u8,
151
+ },
127
152
 
128
153
  fn name(event_group: EventGroup) [:0]const u8 {
129
154
  return switch (event_group) {
130
155
  .main => "main",
131
156
  .tracer => "tracer",
132
- .tree => |tree| tree.tree_name,
157
+ .tree => |args| args.tree_name,
158
+ .tree_compaction => |args| args.compaction_name,
133
159
  };
134
160
  }
135
161
  };
@@ -317,11 +343,7 @@ pub const TracerPerfetto = struct {
317
343
  },
318
344
  };
319
345
 
320
- const tid_64 = switch (span.group) {
321
- .main => 0,
322
- .tracer => 1,
323
- .tree => |tree| std.hash_map.hashString(tree.tree_name),
324
- };
346
+ const tid_64 = std.hash_map.hashString(span.group.name());
325
347
  const tid = @truncate(u32, tid_64) ^ @truncate(u32, tid_64 >> 32);
326
348
 
327
349
  var buffered_writer = std.io.bufferedWriter(log_file.writer());
@@ -11,18 +11,18 @@ test {
11
11
  //_ = @import("vsr/clock.zig");
12
12
 
13
13
  _ = @import("state_machine.zig");
14
+ _ = @import("state_machine/auditor.zig");
15
+ _ = @import("state_machine/workload.zig");
14
16
 
15
17
  _ = @import("fifo.zig");
16
18
  _ = @import("ring_buffer.zig");
17
19
 
18
20
  _ = @import("io.zig");
19
-
20
- _ = @import("cli.zig");
21
21
  _ = @import("ewah.zig");
22
22
  _ = @import("util.zig");
23
23
 
24
- _ = @import("c/test.zig");
25
- _ = @import("c/tb_client_header_test.zig");
24
+ _ = @import("clients/c/test.zig");
25
+ _ = @import("clients/c/tb_client_header_test.zig");
26
26
 
27
27
  // TODO Add remaining unit tests from lsm namespace.
28
28
  _ = @import("lsm/forest.zig");
@@ -30,8 +30,13 @@ test {
30
30
  _ = @import("lsm/segmented_array.zig");
31
31
 
32
32
  _ = @import("test/id.zig");
33
- _ = @import("test/accounting/auditor.zig");
34
- _ = @import("test/accounting/workload.zig");
35
33
  _ = @import("test/storage.zig");
36
34
  _ = @import("test/table.zig");
35
+
36
+ _ = @import("clients/go/go_bindings_test.zig");
37
+ _ = @import("clients/dotnet/dotnet_bindings_test.zig");
38
+ _ = @import("clients/java/java_bindings.zig");
39
+
40
+ // This one is a bit sketchy: we rely on tests not actually using the `vsr` package.
41
+ _ = @import("tigerbeetle/cli.zig");
37
42
  }
@@ -138,14 +138,14 @@ fn build_simulator(
138
138
  mode: std.builtin.Mode,
139
139
  ) void {
140
140
  const mode_str = switch (mode) {
141
- .Debug => "-ODebug",
142
- .ReleaseSafe => "-OReleaseSafe",
141
+ .Debug => "-Ddebug",
142
+ .ReleaseSafe => "-Drelease-safe",
143
143
  else => unreachable,
144
144
  };
145
145
 
146
146
  const exec_result = std.ChildProcess.exec(.{
147
147
  .allocator = allocator,
148
- .argv = &.{ "zig/zig", "build-exe", "./src/simulator.zig", mode_str },
148
+ .argv = &.{ "zig/zig", "build", "simulator", mode_str },
149
149
  }) catch |err| {
150
150
  fatal("unable to build the simulator binary. Error: {}", .{err});
151
151
  };
@@ -184,7 +184,7 @@ fn run_simulator(
184
184
  // simulator's exit code.
185
185
  const exit_code = run_child_process(
186
186
  allocator,
187
- &.{ "./simulator", seed_str.items },
187
+ &.{ "./zig-out/bin/simulator", seed_str.items },
188
188
  );
189
189
 
190
190
  const result = switch (exit_code) {