tigerbeetle-node 0.11.13 → 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 (146) hide show
  1. package/dist/bin/aarch64-linux-gnu/client.node +0 -0
  2. package/dist/bin/aarch64-linux-musl/client.node +0 -0
  3. package/dist/bin/aarch64-macos/client.node +0 -0
  4. package/dist/bin/x86_64-linux-gnu/client.node +0 -0
  5. package/dist/bin/x86_64-linux-musl/client.node +0 -0
  6. package/dist/bin/x86_64-macos/client.node +0 -0
  7. package/dist/index.js +33 -1
  8. package/dist/index.js.map +1 -1
  9. package/package-lock.json +66 -0
  10. package/package.json +6 -16
  11. package/src/index.ts +56 -1
  12. package/src/node.zig +9 -9
  13. package/dist/.client.node.sha256 +0 -1
  14. package/scripts/build_lib.sh +0 -61
  15. package/scripts/download_node_headers.sh +0 -32
  16. package/src/tigerbeetle/scripts/benchmark.bat +0 -55
  17. package/src/tigerbeetle/scripts/benchmark.sh +0 -66
  18. package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
  19. package/src/tigerbeetle/scripts/fail_on_diff.sh +0 -9
  20. package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
  21. package/src/tigerbeetle/scripts/fuzz_loop_hash_log.sh +0 -12
  22. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
  23. package/src/tigerbeetle/scripts/install.bat +0 -7
  24. package/src/tigerbeetle/scripts/install.sh +0 -21
  25. package/src/tigerbeetle/scripts/install_zig.bat +0 -113
  26. package/src/tigerbeetle/scripts/install_zig.sh +0 -90
  27. package/src/tigerbeetle/scripts/lint.zig +0 -199
  28. package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
  29. package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -55
  30. package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
  31. package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
  32. package/src/tigerbeetle/scripts/scripts/fail_on_diff.sh +0 -9
  33. package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
  34. package/src/tigerbeetle/scripts/scripts/fuzz_loop_hash_log.sh +0 -12
  35. package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
  36. package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
  37. package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
  38. package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
  39. package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
  40. package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
  41. package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
  42. package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
  43. package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
  44. package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
  45. package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
  46. package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
  47. package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
  48. package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
  49. package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
  50. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
  51. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
  52. package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
  53. package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
  54. package/src/tigerbeetle/src/benchmark.zig +0 -336
  55. package/src/tigerbeetle/src/config.zig +0 -233
  56. package/src/tigerbeetle/src/constants.zig +0 -428
  57. package/src/tigerbeetle/src/ewah.zig +0 -286
  58. package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
  59. package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
  60. package/src/tigerbeetle/src/fifo.zig +0 -120
  61. package/src/tigerbeetle/src/io/benchmark.zig +0 -213
  62. package/src/tigerbeetle/src/io/darwin.zig +0 -814
  63. package/src/tigerbeetle/src/io/linux.zig +0 -1071
  64. package/src/tigerbeetle/src/io/test.zig +0 -643
  65. package/src/tigerbeetle/src/io/windows.zig +0 -1183
  66. package/src/tigerbeetle/src/io.zig +0 -34
  67. package/src/tigerbeetle/src/iops.zig +0 -107
  68. package/src/tigerbeetle/src/lsm/README.md +0 -308
  69. package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
  70. package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
  71. package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
  72. package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
  73. package/src/tigerbeetle/src/lsm/direction.zig +0 -11
  74. package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
  75. package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
  76. package/src/tigerbeetle/src/lsm/forest.zig +0 -205
  77. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -450
  78. package/src/tigerbeetle/src/lsm/grid.zig +0 -573
  79. package/src/tigerbeetle/src/lsm/groove.zig +0 -1036
  80. package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
  81. package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
  82. package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
  83. package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -878
  84. package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
  85. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
  86. package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
  87. package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
  88. package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -381
  89. package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1329
  90. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
  91. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
  92. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
  93. package/src/tigerbeetle/src/lsm/table.zig +0 -1009
  94. package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -192
  95. package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
  96. package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -203
  97. package/src/tigerbeetle/src/lsm/test.zig +0 -439
  98. package/src/tigerbeetle/src/lsm/tree.zig +0 -1169
  99. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -479
  100. package/src/tigerbeetle/src/message_bus.zig +0 -1013
  101. package/src/tigerbeetle/src/message_pool.zig +0 -156
  102. package/src/tigerbeetle/src/ring_buffer.zig +0 -399
  103. package/src/tigerbeetle/src/simulator.zig +0 -580
  104. package/src/tigerbeetle/src/state_machine/auditor.zig +0 -578
  105. package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
  106. package/src/tigerbeetle/src/state_machine.zig +0 -2099
  107. package/src/tigerbeetle/src/static_allocator.zig +0 -65
  108. package/src/tigerbeetle/src/stdx.zig +0 -171
  109. package/src/tigerbeetle/src/storage.zig +0 -393
  110. package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
  111. package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
  112. package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
  113. package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
  114. package/src/tigerbeetle/src/testing/cluster.zig +0 -444
  115. package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
  116. package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
  117. package/src/tigerbeetle/src/testing/id.zig +0 -99
  118. package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -374
  119. package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
  120. package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
  121. package/src/tigerbeetle/src/testing/state_machine.zig +0 -250
  122. package/src/tigerbeetle/src/testing/storage.zig +0 -757
  123. package/src/tigerbeetle/src/testing/table.zig +0 -247
  124. package/src/tigerbeetle/src/testing/time.zig +0 -84
  125. package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
  126. package/src/tigerbeetle/src/time.zig +0 -112
  127. package/src/tigerbeetle/src/tracer.zig +0 -529
  128. package/src/tigerbeetle/src/unit_tests.zig +0 -40
  129. package/src/tigerbeetle/src/vopr.zig +0 -495
  130. package/src/tigerbeetle/src/vsr/README.md +0 -209
  131. package/src/tigerbeetle/src/vsr/client.zig +0 -544
  132. package/src/tigerbeetle/src/vsr/clock.zig +0 -855
  133. package/src/tigerbeetle/src/vsr/journal.zig +0 -2415
  134. package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
  135. package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
  136. package/src/tigerbeetle/src/vsr/replica.zig +0 -6616
  137. package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
  138. package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
  139. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
  140. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
  141. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
  142. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
  143. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
  144. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
  145. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
  146. package/src/tigerbeetle/src/vsr.zig +0 -1425
@@ -1,691 +0,0 @@
1
- //! Fuzz ManifestLog open()/insert()/remove()/compact()/checkpoint().
2
- //!
3
- //! Invariants checked:
4
- //!
5
- //! - Checkpoint flushes all buffered log blocks (including partial blocks).
6
- //! - The state of the ManifestLog/SuperBlock.Manifest immediately after recovery matches
7
- //! the state of the ManifestLog/SuperBlock.Manifest immediately after the latest checkpoint.
8
- //! - SuperBlock.Manifest.open() only returns the latest version of each table.
9
- //! - SuperBlock.Manifest's compaction queue contains any blocks which:
10
- //! - contain fewer than entry_count_max entries, or
11
- //! - contain a "remove" entry, or
12
- //! - contain an overridden entry.
13
- //!
14
- const std = @import("std");
15
- const assert = std.debug.assert;
16
- const log = std.log.scoped(.fuzz_lsm_manifest_log);
17
-
18
- const vsr = @import("../vsr.zig");
19
- const constants = @import("../constants.zig");
20
- const RingBuffer = @import("../ring_buffer.zig").RingBuffer;
21
- const MessagePool = @import("../message_pool.zig").MessagePool;
22
- const SuperBlock = @import("../vsr/superblock.zig").SuperBlockType(Storage);
23
- const data_file_size_min = @import("../vsr/superblock.zig").data_file_size_min;
24
- const TableExtent = @import("../vsr/superblock_manifest.zig").Manifest.TableExtent;
25
- const Storage = @import("../testing/storage.zig").Storage;
26
- const Grid = @import("grid.zig").GridType(Storage);
27
- const BlockType = @import("grid.zig").BlockType;
28
- const ManifestLog = @import("manifest_log.zig").ManifestLogType(Storage, TableInfo);
29
- const fuzz = @import("../testing/fuzz.zig");
30
-
31
- pub const tigerbeetle_config = @import("../config.zig").configs.test_min;
32
-
33
- const entries_max_block = ManifestLog.Block.entry_count_max;
34
- const entries_max_buffered = entries_max_block *
35
- std.meta.fieldInfo(ManifestLog, .blocks).field_type.count_max;
36
-
37
- pub fn main() !void {
38
- const allocator = std.testing.allocator;
39
- const args = try fuzz.parse_fuzz_args(allocator);
40
-
41
- var prng = std.rand.DefaultPrng.init(args.seed);
42
-
43
- const events_count = std.math.min(
44
- args.events_max orelse @as(usize, 2e5),
45
- fuzz.random_int_exponential(prng.random(), usize, 1e4),
46
- );
47
-
48
- const events = try generate_events(allocator, prng.random(), events_count);
49
- defer allocator.free(events);
50
-
51
- try run_fuzz(allocator, prng.random(), events);
52
- }
53
-
54
- fn run_fuzz(
55
- allocator: std.mem.Allocator,
56
- random: std.rand.Random,
57
- events: []const ManifestEvent,
58
- ) !void {
59
- const storage_options = .{
60
- .seed = random.int(u64),
61
- .read_latency_min = 1,
62
- .read_latency_mean = 1 + random.uintLessThan(u64, 40),
63
- .write_latency_min = 1,
64
- .write_latency_mean = 1 + random.uintLessThan(u64, 40),
65
- };
66
-
67
- var storage = try Storage.init(allocator, constants.storage_size_max, storage_options);
68
- defer storage.deinit(allocator);
69
-
70
- var storage_verify = try Storage.init(allocator, constants.storage_size_max, storage_options);
71
- defer storage_verify.deinit(allocator);
72
-
73
- // The MessagePool is shared by both superblocks because they will not use it.
74
- var message_pool = try MessagePool.init(allocator, .replica);
75
- defer message_pool.deinit(allocator);
76
-
77
- var superblock = try SuperBlock.init(allocator, .{
78
- .storage = &storage,
79
- .storage_size_limit = constants.storage_size_max,
80
- .message_pool = &message_pool,
81
- });
82
- defer superblock.deinit(allocator);
83
-
84
- var superblock_verify = try SuperBlock.init(allocator, .{
85
- .storage = &storage_verify,
86
- .storage_size_limit = constants.storage_size_max,
87
- .message_pool = &message_pool,
88
- });
89
- defer superblock_verify.deinit(allocator);
90
-
91
- var grid = try Grid.init(allocator, &superblock);
92
- defer grid.deinit(allocator);
93
-
94
- var grid_verify = try Grid.init(allocator, &superblock_verify);
95
- defer grid_verify.deinit(allocator);
96
-
97
- var env = try Environment.init(allocator, .{
98
- .grid = &grid,
99
- .grid_verify = &grid_verify,
100
- });
101
- defer env.deinit(allocator);
102
-
103
- {
104
- env.format_superblock();
105
- env.wait(&env.manifest_log);
106
-
107
- env.open_superblock();
108
- env.wait(&env.manifest_log);
109
-
110
- env.open();
111
- env.wait(&env.manifest_log);
112
- }
113
-
114
- for (events) |event| {
115
- log.debug("event={}", .{event});
116
- switch (event) {
117
- .insert => |e| try env.insert(e.level, &e.table),
118
- .remove => |e| try env.remove(e.level, &e.table),
119
- .compact => try env.compact(),
120
- .checkpoint => try env.checkpoint(),
121
- .noop => {},
122
- }
123
- }
124
- }
125
-
126
- const ManifestEvent = union(enum) {
127
- insert: struct { level: u7, table: TableInfo },
128
- remove: struct { level: u7, table: TableInfo },
129
- compact: void,
130
- checkpoint: void,
131
- /// The random EventType could not be generated — this simplifies event generation.
132
- noop: void,
133
- };
134
-
135
- fn generate_events(
136
- allocator: std.mem.Allocator,
137
- random: std.rand.Random,
138
- events_count: usize,
139
- ) ![]const ManifestEvent {
140
- const EventType = enum {
141
- insert_new,
142
- insert_change_level,
143
- insert_change_snapshot,
144
- remove,
145
- compact,
146
- checkpoint,
147
- };
148
-
149
- const events = try allocator.alloc(ManifestEvent, events_count);
150
- errdefer allocator.free(events);
151
-
152
- var event_distribution = fuzz.random_enum_distribution(random, EventType);
153
- // Don't remove too often, so that there are plenty of tables accumulating.
154
- event_distribution.remove /= @intToFloat(f64, constants.lsm_levels);
155
- // Don't compact or checkpoint too often, to approximate a real workload.
156
- // Additionally, checkpoint is slow because of the verification, so run it less
157
- // frequently.
158
- event_distribution.compact /= @intToFloat(
159
- f64,
160
- constants.lsm_levels * constants.lsm_batch_multiple,
161
- );
162
- event_distribution.checkpoint /= @intToFloat(
163
- f64,
164
- constants.lsm_levels * constants.journal_slot_count,
165
- );
166
-
167
- log.info("event_distribution = {d:.2}", .{event_distribution});
168
- log.info("event_count = {d}", .{events.len});
169
-
170
- var tables = std.ArrayList(struct {
171
- level: u7,
172
- table: TableInfo,
173
- }).init(allocator);
174
- defer tables.deinit();
175
-
176
- // The number of appends since the last flush (compact or checkpoint).
177
- var append_count: usize = 0;
178
- for (events) |*event, i| {
179
- const event_type = blk: {
180
- if (append_count == ManifestLog.compaction_appends_max) {
181
- // We must compact or checkpoint periodically to avoid overfilling the ManifestLog.
182
- break :blk if (random.boolean()) EventType.compact else EventType.checkpoint;
183
- }
184
-
185
- const event_type_random = fuzz.random_enum(random, EventType, event_distribution);
186
- if (tables.items.len == 0) {
187
- if (event_type_random == .insert_change_level or
188
- event_type_random == .insert_change_snapshot or
189
- event_type_random == .remove)
190
- {
191
- break :blk .insert_new;
192
- }
193
- }
194
-
195
- break :blk event_type_random;
196
- };
197
-
198
- event.* = switch (event_type) {
199
- .insert_new => insert: {
200
- const level = random.uintLessThan(u7, constants.lsm_levels);
201
- const table = TableInfo{
202
- .checksum = 0,
203
- .address = i + 1,
204
- .snapshot_min = 1,
205
- .snapshot_max = 2,
206
- .key_min = 0,
207
- .key_max = 0,
208
- };
209
- try tables.append(.{
210
- .level = level,
211
- .table = table,
212
- });
213
- const insert = ManifestEvent{ .insert = .{
214
- .level = level,
215
- .table = table,
216
- } };
217
- break :insert insert;
218
- },
219
-
220
- .insert_change_level => insert: {
221
- const table = &tables.items[random.uintLessThan(usize, tables.items.len)];
222
- if (table.level == constants.lsm_levels - 1) {
223
- break :insert ManifestEvent{ .noop = {} };
224
- }
225
-
226
- table.level += 1;
227
- const insert = ManifestEvent{ .insert = .{
228
- .level = table.level,
229
- .table = table.table,
230
- } };
231
- break :insert insert;
232
- },
233
-
234
- .insert_change_snapshot => insert: {
235
- const table = &tables.items[random.uintLessThan(usize, tables.items.len)];
236
- table.table.snapshot_max += 1;
237
- const insert = ManifestEvent{ .insert = .{
238
- .level = table.level,
239
- .table = table.table,
240
- } };
241
- break :insert insert;
242
- },
243
-
244
- .remove => remove: {
245
- const table = tables.swapRemove(random.uintLessThan(usize, tables.items.len));
246
- const remove = ManifestEvent{ .remove = .{
247
- .level = table.level,
248
- .table = table.table,
249
- } };
250
- break :remove remove;
251
- },
252
-
253
- .compact => ManifestEvent{ .compact = {} },
254
- .checkpoint => ManifestEvent{ .checkpoint = {} },
255
- };
256
-
257
- switch (event.*) {
258
- .compact, .checkpoint => append_count = 0,
259
- .noop => {},
260
- else => append_count += 1,
261
- }
262
- }
263
- return events;
264
- }
265
-
266
- const TableInfo = extern struct {
267
- checksum: u128,
268
- address: u64,
269
- flags: u64 = 0,
270
- snapshot_min: u64,
271
- snapshot_max: u64 = std.math.maxInt(u64),
272
- key_min: u128,
273
- key_max: u128,
274
-
275
- comptime {
276
- assert(@sizeOf(TableInfo) == 48 + 16 * 2);
277
- assert(@alignOf(TableInfo) == 16);
278
- assert(@bitSizeOf(TableInfo) == @sizeOf(TableInfo) * 8);
279
- }
280
- };
281
-
282
- const Environment = struct {
283
- allocator: std.mem.Allocator,
284
- superblock_context: SuperBlock.Context = undefined,
285
- manifest_log: ManifestLog,
286
- manifest_log_verify: ManifestLog,
287
- manifest_log_model: ManifestLogModel,
288
- manifest_log_opening: ?ManifestLogModel.TableMap = null,
289
- manifest_log_reserved: bool = false,
290
- pending: usize = 0,
291
-
292
- fn init(
293
- allocator: std.mem.Allocator,
294
- options: struct {
295
- grid: *Grid,
296
- grid_verify: *Grid,
297
- },
298
- ) !Environment {
299
- var manifest_log_model = try ManifestLogModel.init(allocator);
300
- errdefer manifest_log_model.deinit();
301
-
302
- const tree_hash = std.math.maxInt(u128);
303
- var manifest_log = try ManifestLog.init(allocator, options.grid, tree_hash);
304
- errdefer manifest_log.deinit(allocator);
305
-
306
- var manifest_log_verify = try ManifestLog.init(allocator, options.grid_verify, tree_hash);
307
- errdefer manifest_log_verify.deinit(allocator);
308
-
309
- return Environment{
310
- .allocator = allocator,
311
- .manifest_log = manifest_log,
312
- .manifest_log_verify = manifest_log_verify,
313
- .manifest_log_model = manifest_log_model,
314
- };
315
- }
316
-
317
- fn deinit(env: *Environment, allocator: std.mem.Allocator) void {
318
- env.manifest_log.deinit(allocator);
319
- env.manifest_log_verify.deinit(env.allocator);
320
- env.manifest_log_model.deinit();
321
- assert(env.manifest_log_opening == null);
322
- }
323
-
324
- fn wait(env: *Environment, manifest_log: *ManifestLog) void {
325
- while (env.pending > 0) {
326
- // manifest_log.grid.tick();
327
- manifest_log.superblock.storage.tick();
328
- }
329
- }
330
-
331
- fn format_superblock(env: *Environment) void {
332
- assert(env.pending == 0);
333
- env.pending += 1;
334
- env.manifest_log.superblock.format(format_superblock_callback, &env.superblock_context, .{
335
- .cluster = 0,
336
- .replica = 0,
337
- });
338
- }
339
-
340
- fn format_superblock_callback(context: *SuperBlock.Context) void {
341
- const env = @fieldParentPtr(Environment, "superblock_context", context);
342
- env.pending -= 1;
343
- }
344
-
345
- fn open_superblock(env: *Environment) void {
346
- assert(env.pending == 0);
347
- env.pending += 1;
348
- env.manifest_log.superblock.open(open_superblock_callback, &env.superblock_context);
349
- }
350
-
351
- fn open_superblock_callback(context: *SuperBlock.Context) void {
352
- const env = @fieldParentPtr(Environment, "superblock_context", context);
353
- env.pending -= 1;
354
- }
355
-
356
- fn open(env: *Environment) void {
357
- assert(env.pending == 0);
358
- assert(!env.manifest_log_reserved);
359
-
360
- env.pending += 1;
361
- env.manifest_log.open(open_event, open_callback);
362
- env.manifest_log.reserve();
363
- env.manifest_log_reserved = true;
364
- }
365
-
366
- fn open_event(manifest_log: *ManifestLog, level: u7, table: *const TableInfo) void {
367
- _ = manifest_log;
368
- _ = level;
369
- _ = table;
370
-
371
- // This ManifestLog is only opened during setup, when it has no blocks.
372
- unreachable;
373
- }
374
-
375
- fn open_callback(manifest_log: *ManifestLog) void {
376
- const env = @fieldParentPtr(Environment, "manifest_log", manifest_log);
377
- env.pending -= 1;
378
- }
379
-
380
- fn insert(env: *Environment, level: u7, table: *const TableInfo) !void {
381
- if (!env.manifest_log_reserved) env.manifest_log.reserve();
382
- env.manifest_log_reserved = true;
383
-
384
- try env.manifest_log_model.insert(level, table);
385
- env.manifest_log.insert(level, table);
386
- }
387
-
388
- fn remove(env: *Environment, level: u7, table: *const TableInfo) !void {
389
- if (!env.manifest_log_reserved) env.manifest_log.reserve();
390
- env.manifest_log_reserved = true;
391
-
392
- try env.manifest_log_model.remove(level, table);
393
- env.manifest_log.remove(level, table);
394
- }
395
-
396
- fn compact(env: *Environment) !void {
397
- if (!env.manifest_log_reserved) env.manifest_log.reserve();
398
- env.manifest_log_reserved = true;
399
-
400
- env.pending += 1;
401
- env.manifest_log.compact(compact_callback);
402
- env.wait(&env.manifest_log);
403
-
404
- env.manifest_log_reserved = false;
405
- }
406
-
407
- fn compact_callback(manifest_log: *ManifestLog) void {
408
- const env = @fieldParentPtr(Environment, "manifest_log", manifest_log);
409
- env.pending -= 1;
410
- }
411
-
412
- fn checkpoint(env: *Environment) !void {
413
- // Checkpoint always follows compaction.
414
- try env.compact();
415
-
416
- try env.manifest_log_model.checkpoint();
417
-
418
- env.pending += 1;
419
- env.manifest_log.checkpoint(checkpoint_callback);
420
- env.wait(&env.manifest_log);
421
-
422
- const vsr_state = &env.manifest_log.superblock.working.vsr_state;
423
-
424
- env.pending += 1;
425
- env.manifest_log.superblock.checkpoint(
426
- checkpoint_superblock_callback,
427
- &env.superblock_context,
428
- .{
429
- .commit_min_checksum = vsr_state.commit_min_checksum + 1,
430
- .commit_min = vsr_state.commit_min + 1,
431
- .commit_max = vsr_state.commit_max + 1,
432
- },
433
- );
434
- env.wait(&env.manifest_log);
435
-
436
- try env.verify();
437
- }
438
-
439
- fn checkpoint_callback(manifest_log: *ManifestLog) void {
440
- const env = @fieldParentPtr(Environment, "manifest_log", manifest_log);
441
- env.pending -= 1;
442
- }
443
-
444
- fn checkpoint_superblock_callback(context: *SuperBlock.Context) void {
445
- const env = @fieldParentPtr(Environment, "superblock_context", context);
446
- env.pending -= 1;
447
- }
448
-
449
- /// Verify that the state of a ManifestLog restored from checkpoint matches the state
450
- /// immediately after the checkpoint was created.
451
- fn verify(env: *Environment) !void {
452
- const test_superblock = env.manifest_log_verify.superblock;
453
- const test_storage = test_superblock.storage;
454
- const test_grid = env.manifest_log_verify.grid;
455
- const test_manifest_log = &env.manifest_log_verify;
456
-
457
- {
458
- test_storage.copy(env.manifest_log.superblock.storage);
459
- test_storage.reset();
460
-
461
- // Reset the state so that the manifest log (and dependencies) can be reused.
462
- // Do not "defer deinit()" because these are cleaned up by Env.deinit().
463
- test_superblock.deinit(env.allocator);
464
- test_superblock.* = try SuperBlock.init(
465
- env.allocator,
466
- .{
467
- .storage = test_storage,
468
- .storage_size_limit = constants.storage_size_max,
469
- .message_pool = env.manifest_log.superblock.client_table.message_pool,
470
- },
471
- );
472
-
473
- test_grid.deinit(env.allocator);
474
- test_grid.* = try Grid.init(env.allocator, test_superblock);
475
-
476
- test_manifest_log.deinit(env.allocator);
477
- test_manifest_log.* = try ManifestLog.init(
478
- env.allocator,
479
- test_grid,
480
- env.manifest_log.tree_hash,
481
- );
482
- }
483
-
484
- env.pending += 1;
485
- test_superblock.open(verify_superblock_open_callback, &env.superblock_context);
486
- env.wait(test_manifest_log);
487
-
488
- assert(env.manifest_log_opening == null);
489
- env.manifest_log_opening = try env.manifest_log_model.tables.clone();
490
- defer {
491
- assert(env.manifest_log_opening.?.count() == 0);
492
- env.manifest_log_opening.?.deinit();
493
- env.manifest_log_opening = null;
494
- }
495
-
496
- env.pending += 1;
497
- test_manifest_log.open(verify_manifest_open_event, verify_manifest_open_callback);
498
- env.wait(test_manifest_log);
499
-
500
- try verify_manifest(&test_superblock.manifest, &env.manifest_log.superblock.manifest);
501
- try verify_manifest_compaction_set(test_superblock, &env.manifest_log_model);
502
- }
503
-
504
- fn verify_superblock_open_callback(superblock_context: *SuperBlock.Context) void {
505
- const env = @fieldParentPtr(Environment, "superblock_context", superblock_context);
506
- env.pending -= 1;
507
- }
508
-
509
- fn verify_manifest_open_event(
510
- manifest_log_verify: *ManifestLog,
511
- level: u7,
512
- table: *const TableInfo,
513
- ) void {
514
- const env = @fieldParentPtr(Environment, "manifest_log_verify", manifest_log_verify);
515
- assert(env.pending > 0);
516
-
517
- const expect = env.manifest_log_opening.?.get(table.address).?;
518
- assert(expect.level == level);
519
- assert(std.meta.eql(expect.table, table.*));
520
- assert(env.manifest_log_opening.?.remove(table.address));
521
- }
522
-
523
- fn verify_manifest_open_callback(manifest_log_verify: *ManifestLog) void {
524
- const env = @fieldParentPtr(Environment, "manifest_log_verify", manifest_log_verify);
525
- env.pending -= 1;
526
- }
527
- };
528
-
529
- const ManifestLogModel = struct {
530
- /// Stores the latest checkpointed version of every table.
531
- /// Indexed by table address.
532
- const TableMap = std.AutoHashMap(u64, TableEntry);
533
-
534
- const TableEntry = struct {
535
- level: u7,
536
- table: TableInfo,
537
- };
538
-
539
- /// Stores table updates that are not yet checkpointed.
540
- const AppendList = std.ArrayList(struct {
541
- event: enum { insert, remove },
542
- level: u7,
543
- table: TableInfo,
544
- });
545
-
546
- tables: TableMap,
547
- appends: AppendList,
548
-
549
- fn init(allocator: std.mem.Allocator) !ManifestLogModel {
550
- const tables = TableMap.init(allocator);
551
- errdefer tables.deinit(allocator);
552
-
553
- const appends = AppendList.init(allocator);
554
- errdefer appends.deinit(allocator);
555
-
556
- return ManifestLogModel{
557
- .tables = tables,
558
- .appends = appends,
559
- };
560
- }
561
-
562
- fn deinit(model: *ManifestLogModel) void {
563
- model.tables.deinit();
564
- model.appends.deinit();
565
- }
566
-
567
- fn current(model: ManifestLogModel, table_address: u64) ?TableEntry {
568
- assert(model.appends.items.len == 0);
569
-
570
- return model.tables.get(table_address);
571
- }
572
-
573
- fn insert(model: *ManifestLogModel, level: u7, table: *const TableInfo) !void {
574
- try model.appends.append(.{
575
- .event = .insert,
576
- .level = level,
577
- .table = table.*,
578
- });
579
- }
580
-
581
- fn remove(model: *ManifestLogModel, level: u7, table: *const TableInfo) !void {
582
- try model.appends.append(.{
583
- .event = .remove,
584
- .level = level,
585
- .table = table.*,
586
- });
587
- }
588
-
589
- fn checkpoint(model: *ManifestLogModel) !void {
590
- for (model.appends.items) |append| {
591
- switch (append.event) {
592
- .insert => {
593
- try model.tables.put(append.table.address, .{
594
- .level = append.level,
595
- .table = append.table,
596
- });
597
- },
598
- .remove => {
599
- const removed = model.tables.get(append.table.address).?;
600
- assert(removed.level == append.level);
601
- assert(std.meta.eql(removed.table, append.table));
602
- assert(model.tables.remove(append.table.address));
603
- },
604
- }
605
- }
606
- model.appends.clearRetainingCapacity();
607
- }
608
- };
609
-
610
- fn verify_manifest(
611
- expect: *const SuperBlock.Manifest,
612
- actual: *const SuperBlock.Manifest,
613
- ) !void {
614
- try std.testing.expectEqual(expect.count, actual.count);
615
- try std.testing.expectEqual(expect.count_max, actual.count_max);
616
-
617
- const c = expect.count;
618
- try std.testing.expect(std.mem.eql(u128, expect.trees[0..c], actual.trees[0..c]));
619
- try std.testing.expect(std.mem.eql(u128, expect.checksums[0..c], actual.checksums[0..c]));
620
- try std.testing.expect(std.mem.eql(u64, expect.addresses[0..c], actual.addresses[0..c]));
621
-
622
- try std.testing.expect(hash_map_equals(
623
- SuperBlock.Manifest.TableExtentKey,
624
- SuperBlock.Manifest.TableExtent,
625
- &expect.tables,
626
- &actual.tables,
627
- ));
628
- try std.testing.expect(hash_map_equals(
629
- u64,
630
- void,
631
- &expect.compaction_set,
632
- &actual.compaction_set,
633
- ));
634
- }
635
-
636
- fn verify_manifest_compaction_set(
637
- superblock: *const SuperBlock,
638
- manifest_log_model: *const ManifestLogModel,
639
- ) !void {
640
- var compact_blocks_checked: u32 = 0;
641
-
642
- // This test doesn't include any actual table blocks, so all blocks are manifest blocks.
643
- var blocks = superblock.free_set.blocks.iterator(.{ .kind = .set });
644
- while (blocks.next()) |block_index| {
645
- const block_address = block_index + 1;
646
- const block = superblock.storage.grid_block(block_address);
647
- const block_header = std.mem.bytesToValue(vsr.Header, block[0..@sizeOf(vsr.Header)]);
648
- try std.testing.expectEqual(BlockType.manifest.operation(), block_header.operation);
649
-
650
- const entry_count = ManifestLog.Block.entry_count(block);
651
- var compact_soon: bool = entry_count < ManifestLog.Block.entry_count_max;
652
- for (ManifestLog.Block.labels_const(block)[0..entry_count]) |label, i| {
653
- const table = &ManifestLog.Block.tables_const(block)[i];
654
- compact_soon = compact_soon or switch (label.event) {
655
- .remove => true,
656
- .insert => blk: {
657
- const table_current = manifest_log_model.current(table.address);
658
- break :blk table_current == null or
659
- table_current.?.level != label.level or
660
- table_current.?.table.snapshot_min != table.snapshot_min or
661
- table_current.?.table.snapshot_max != table.snapshot_max;
662
- },
663
- };
664
- }
665
- try std.testing.expectEqual(
666
- compact_soon,
667
- superblock.manifest.compaction_set.contains(block_address),
668
- );
669
- compact_blocks_checked += @boolToInt(compact_soon);
670
- }
671
-
672
- // There are no blocks queued for compaction which were not allocated in the FreeSet.
673
- try std.testing.expectEqual(superblock.manifest.compaction_set.count(), compact_blocks_checked);
674
- }
675
-
676
- fn hash_map_equals(
677
- comptime K: type,
678
- comptime V: type,
679
- a: *const std.AutoHashMapUnmanaged(K, V),
680
- b: *const std.AutoHashMapUnmanaged(K, V),
681
- ) bool {
682
- if (a.count() != b.count()) return false;
683
-
684
- var a_iterator = a.iterator();
685
- while (a_iterator.next()) |a_entry| {
686
- const a_value = a_entry.value_ptr.*;
687
- const b_value = b.get(a_entry.key_ptr.*) orelse return false;
688
- if (!std.meta.eql(a_value, b_value)) return false;
689
- }
690
- return true;
691
- }