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,330 +0,0 @@
1
- const std = @import("std");
2
- const assert = std.debug.assert;
3
- const math = std.math;
4
-
5
- const binary_search_keys_raw = @import("./binary_search.zig").binary_search_keys_raw;
6
- const binary_search_values_raw = @import("./binary_search.zig").binary_search_values_raw;
7
- const eytzinger = @import("./eytzinger.zig").eytzinger;
8
-
9
- const GiB = 1 << 30;
10
- const searches = 500_000;
11
-
12
- const kv_types = .{
13
- .{ .key_size = 8, .value_size = 128 },
14
- .{ .key_size = 8, .value_size = 64 },
15
- .{ .key_size = 16, .value_size = 16 },
16
- .{ .key_size = 32, .value_size = 32 },
17
- };
18
-
19
- // keys_per_summary = values_per_page / summary_fraction
20
- const summary_fractions = .{ 4, 8, 16, 32 };
21
- const values_per_page = .{ 128, 256, 512, 1024, 2048, 4096, 8192 };
22
- const body_fmt = "{:_>2}B/{:_>3}B {:_>4}/{:_>4} {s}{s}: WT={:_>6}ns UT={:_>6}ns" ++
23
- " CY={:_>6} IN={:_>6} CR={:_>5} CM={:_>5} BM={}\n";
24
-
25
- const summary_sizes = blk: {
26
- var sizes: [values_per_page.len][summary_fractions.len]usize = undefined;
27
- for (values_per_page) |values_count, v| {
28
- for (summary_fractions) |fraction, k| {
29
- // Set in reverse order so that the summary sizes ascend.
30
- sizes[v][summary_fractions.len - k - 1] = values_count / fraction;
31
- }
32
- }
33
- break :blk sizes;
34
- };
35
-
36
- pub fn main() !void {
37
- std.log.info("Samples: {}", .{searches});
38
- std.log.info("WT: Wall time/search", .{});
39
- std.log.info("UT: utime time/search", .{});
40
- std.log.info("CY: CPU cycles/search", .{});
41
- std.log.info("IN: instructions/search", .{});
42
- std.log.info("CR: cache references/search", .{});
43
- std.log.info("CM: cache misses/search", .{});
44
- std.log.info("BM: branch misses/search", .{});
45
-
46
- var seed: u64 = undefined;
47
- try std.os.getrandom(std.mem.asBytes(&seed));
48
- var prng = std.rand.DefaultPrng.init(seed);
49
-
50
- // Allocate on the heap just once.
51
- // All page allocations reuse this buffer to speed up the run time.
52
- var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
53
- defer arena.deinit();
54
-
55
- const blob_size = GiB;
56
- var blob = try arena.allocator().alloc(u8, blob_size);
57
-
58
- inline for (kv_types) |kv| {
59
- inline for (values_per_page) |values_count, v| {
60
- inline for (summary_sizes[v]) |keys_count| {
61
- try run_benchmark(.{
62
- .blob_size = blob_size,
63
- .key_size = kv.key_size,
64
- .value_size = kv.value_size,
65
- .keys_count = keys_count,
66
- .values_count = values_count,
67
- .searches = searches,
68
- }, blob, prng.random());
69
- }
70
- }
71
- }
72
- }
73
-
74
- fn run_benchmark(comptime layout: Layout, blob: []u8, random: std.rand.Random) !void {
75
- assert(blob.len == layout.blob_size);
76
- const Eytzinger = eytzinger(layout.keys_count - 1, layout.values_count);
77
- const V = Value(layout);
78
- const K = V.Key;
79
- const Page = struct {
80
- keys: [layout.keys_count]K,
81
- values: [layout.values_count]V,
82
- };
83
- const page_count = layout.blob_size / @sizeOf(Page);
84
-
85
- // Search pages and keys in random order.
86
- var page_picker = shuffled_index(page_count, random);
87
- var value_picker = shuffled_index(layout.values_count, random);
88
-
89
- // Generate 1GiB worth of 24KiB pages.
90
- var blob_alloc = std.heap.FixedBufferAllocator.init(blob);
91
- var pages = try blob_alloc.allocator().alloc(Page, page_count);
92
- random.bytes(std.mem.sliceAsBytes(pages));
93
- for (pages) |*page| {
94
- for (page.values) |*value, i| value.key = i;
95
- Eytzinger.layout_from_keys_or_values(K, V, V.key_from_value, V.max_key, &page.values, &page.keys);
96
- }
97
-
98
- const stdout = std.io.getStdOut().writer();
99
- {
100
- var benchmark = try Benchmark.begin();
101
- var i: usize = 0;
102
- var v: usize = 0;
103
- while (i < layout.searches) : (i += 1) {
104
- const page_index = page_picker[i % page_picker.len];
105
- const target = value_picker[v % value_picker.len];
106
- const page = &pages[page_index];
107
- const bounds = Eytzinger.search_values(K, V, V.key_compare, &page.keys, &page.values, target);
108
- const hit = bounds[
109
- binary_search_values_raw(
110
- K,
111
- V,
112
- V.key_from_value,
113
- V.key_compare,
114
- bounds,
115
- target,
116
- .{},
117
- )
118
- ];
119
-
120
- assert(hit.key == target);
121
- if (i % pages.len == 0) v += 1;
122
- }
123
-
124
- const result = try benchmark.end(layout.searches);
125
- try stdout.print(body_fmt, .{
126
- layout.key_size,
127
- layout.value_size,
128
- layout.keys_count,
129
- layout.values_count,
130
- "E",
131
- "B",
132
- result.wall_time,
133
- result.utime,
134
- result.cpu_cycles,
135
- result.instructions,
136
- result.cache_references,
137
- result.cache_misses,
138
- result.branch_misses,
139
- });
140
- }
141
-
142
- {
143
- var benchmark = try Benchmark.begin();
144
- var i: usize = 0;
145
- var v: usize = 0;
146
- while (i < layout.searches) : (i += 1) {
147
- const target = value_picker[v % value_picker.len];
148
- const page = &pages[page_picker[i % page_picker.len]];
149
- const hit = page.values[
150
- binary_search_values_raw(
151
- K,
152
- V,
153
- V.key_from_value,
154
- V.key_compare,
155
- page.values[0..],
156
- target,
157
- .{},
158
- )
159
- ];
160
-
161
- assert(hit.key == target);
162
- if (i % pages.len == 0) v += 1;
163
- }
164
- const result = try benchmark.end(layout.searches);
165
- try stdout.print(body_fmt, .{
166
- layout.key_size,
167
- layout.value_size,
168
- layout.keys_count,
169
- layout.values_count,
170
- "_",
171
- "B",
172
- result.wall_time,
173
- result.utime,
174
- result.cpu_cycles,
175
- result.instructions,
176
- result.cache_references,
177
- result.cache_misses,
178
- result.branch_misses,
179
- });
180
- }
181
- }
182
-
183
- const Layout = struct {
184
- blob_size: usize, // bytes allocated for all pages
185
- key_size: usize, // bytes per key
186
- value_size: usize, // bytes per value
187
- keys_count: usize, // keys per page (in the summary)
188
- values_count: usize, // values per page
189
- searches: usize,
190
- };
191
-
192
- fn Value(comptime layout: Layout) type {
193
- return struct {
194
- pub const max_key = 1 << (8 * layout.key_size) - 1;
195
- pub const Key = math.IntFittingRange(0, max_key);
196
- const Self = @This();
197
- key: Key,
198
- body: [layout.value_size - layout.key_size]u8,
199
-
200
- comptime {
201
- assert(@sizeOf(Key) == layout.key_size);
202
- assert(@sizeOf(Self) == layout.value_size);
203
- }
204
-
205
- inline fn key_from_value(self: *const Self) Key {
206
- return self.key;
207
- }
208
-
209
- inline fn key_compare(a: Key, b: Key) math.Order {
210
- return math.order(a, b);
211
- }
212
- };
213
- }
214
-
215
- const BenchmarkResult = struct {
216
- wall_time: u64, // nanoseconds
217
- utime: u64, // nanoseconds
218
- cpu_cycles: usize,
219
- instructions: usize,
220
- cache_references: usize,
221
- cache_misses: usize,
222
- branch_misses: usize,
223
- };
224
-
225
- const PERF = std.os.linux.PERF;
226
- const perf_counters = [_]PERF.COUNT.HW{
227
- PERF.COUNT.HW.CPU_CYCLES,
228
- PERF.COUNT.HW.INSTRUCTIONS,
229
- PERF.COUNT.HW.CACHE_REFERENCES,
230
- PERF.COUNT.HW.CACHE_MISSES,
231
- PERF.COUNT.HW.BRANCH_MISSES,
232
- };
233
-
234
- const Benchmark = struct {
235
- timer: std.time.Timer,
236
- rusage: std.os.rusage,
237
- perf_fds: [perf_counters.len]std.os.fd_t,
238
-
239
- fn begin() !Benchmark {
240
- var perf_fds = [1]std.os.fd_t{-1} ** perf_counters.len;
241
- for (perf_counters) |counter, i| {
242
- var attr: std.os.linux.perf_event_attr = .{
243
- .type = PERF.TYPE.HARDWARE,
244
- .config = @enumToInt(counter),
245
- .flags = .{
246
- .disabled = true,
247
- .exclude_kernel = true,
248
- .exclude_hv = true,
249
- },
250
- };
251
- perf_fds[i] = try std.os.perf_event_open(&attr, 0, -1, perf_fds[0], PERF.FLAG.FD_CLOEXEC);
252
- }
253
- const err = std.os.linux.ioctl(perf_fds[0], PERF.EVENT_IOC.ENABLE, PERF.IOC_FLAG_GROUP);
254
- if (err == -1) return error.Unexpected;
255
-
256
- // Start the wall clock after perf, since setup is slow.
257
- const timer = try std.time.Timer.start();
258
- return Benchmark{
259
- .timer = timer,
260
- // TODO pass std.os.linux.rusage.SELF once Zig is upgraded
261
- .rusage = std.os.getrusage(0),
262
- .perf_fds = perf_fds,
263
- };
264
- }
265
-
266
- fn end(self: *Benchmark, samples: usize) !BenchmarkResult {
267
- defer {
268
- for (perf_counters) |_, i| {
269
- std.os.close(self.perf_fds[i]);
270
- self.perf_fds[i] = -1;
271
- }
272
- }
273
-
274
- const rusage = std.os.getrusage(0);
275
- const err = std.os.linux.ioctl(self.perf_fds[0], PERF.EVENT_IOC.DISABLE, PERF.IOC_FLAG_GROUP);
276
- if (err == -1) return error.Unexpected;
277
- return BenchmarkResult{
278
- .wall_time = self.timer.read() / samples,
279
- .utime = (timeval_to_ns(rusage.utime) - timeval_to_ns(self.rusage.utime)) / samples,
280
- .cpu_cycles = (try readPerfFd(self.perf_fds[0])) / samples,
281
- .instructions = (try readPerfFd(self.perf_fds[1])) / samples,
282
- .cache_references = (try readPerfFd(self.perf_fds[2])) / samples,
283
- .cache_misses = (try readPerfFd(self.perf_fds[3])) / samples,
284
- .branch_misses = (try readPerfFd(self.perf_fds[4])) / samples,
285
- };
286
- }
287
- };
288
-
289
- // shuffle([0,1,…,n-1])
290
- fn shuffled_index(comptime n: usize, rand: std.rand.Random) [n]usize {
291
- var indices: [n]usize = undefined;
292
- for (indices) |*i, j| i.* = j;
293
- rand.shuffle(usize, indices[0..]);
294
- return indices;
295
- }
296
-
297
- fn timeval_to_ns(tv: std.os.timeval) u64 {
298
- const ns_per_us = std.time.ns_per_s / std.time.us_per_s;
299
- return @bitCast(u64, tv.tv_sec) * std.time.ns_per_s +
300
- @bitCast(u64, tv.tv_usec) * ns_per_us;
301
- }
302
-
303
- fn readPerfFd(fd: std.os.fd_t) !usize {
304
- var result: usize = 0;
305
- const n = try std.os.read(fd, std.mem.asBytes(&result));
306
- assert(n == @sizeOf(usize));
307
-
308
- return result;
309
- }
310
-
311
- fn binary_search_keys(
312
- comptime layout: Layout,
313
- comptime Key: type,
314
- comptime V: type,
315
- comptime compare_keys: fn (Key, Key) math.Order,
316
- keys: []const Key,
317
- values: []const V,
318
- key: Key,
319
- ) []const V {
320
- assert(keys.len == layout.keys_count);
321
- assert(values.len == layout.values_count);
322
-
323
- const key_index = binary_search_keys_raw(Key, compare_keys, keys, key, .{});
324
- const key_stride = layout.values_count / layout.keys_count;
325
- const high = key_index * key_stride;
326
- if (key_index < keys.len and keys[key_index] == key) {
327
- return if (high == 0) values[0..1] else values[high - 1 .. high];
328
- }
329
- return values[high - key_stride .. high];
330
- }
@@ -1,204 +0,0 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
- const assert = std.debug.assert;
4
- const math = std.math;
5
- const mem = std.mem;
6
-
7
- const constants = @import("../constants.zig");
8
- const vsr = @import("../vsr.zig");
9
-
10
- const GridType = @import("grid.zig").GridType;
11
- const NodePool = @import("node_pool.zig").NodePool(constants.lsm_manifest_node_size, 16);
12
-
13
- pub fn ForestType(comptime Storage: type, comptime groove_config: anytype) type {
14
- var groove_fields: []const std.builtin.TypeInfo.StructField = &.{};
15
- var groove_options_fields: []const std.builtin.TypeInfo.StructField = &.{};
16
-
17
- for (std.meta.fields(@TypeOf(groove_config))) |field| {
18
- const Groove = @field(groove_config, field.name);
19
- groove_fields = groove_fields ++ [_]std.builtin.TypeInfo.StructField{
20
- .{
21
- .name = field.name,
22
- .field_type = Groove,
23
- .default_value = null,
24
- .is_comptime = false,
25
- .alignment = @alignOf(Groove),
26
- },
27
- };
28
-
29
- groove_options_fields = groove_options_fields ++ [_]std.builtin.TypeInfo.StructField{
30
- .{
31
- .name = field.name,
32
- .field_type = Groove.Options,
33
- .default_value = null,
34
- .is_comptime = false,
35
- .alignment = @alignOf(Groove),
36
- },
37
- };
38
- }
39
-
40
- const Grooves = @Type(.{
41
- .Struct = .{
42
- .layout = .Auto,
43
- .fields = groove_fields,
44
- .decls = &.{},
45
- .is_tuple = false,
46
- },
47
- });
48
-
49
- const _GroovesOptions = @Type(.{
50
- .Struct = .{
51
- .layout = .Auto,
52
- .fields = groove_options_fields,
53
- .decls = &.{},
54
- .is_tuple = false,
55
- },
56
- });
57
-
58
- return struct {
59
- const Forest = @This();
60
-
61
- const Grid = GridType(Storage);
62
-
63
- const Callback = fn (*Forest) void;
64
- const JoinOp = enum {
65
- compacting,
66
- checkpoint,
67
- open,
68
- };
69
-
70
- pub const GroovesOptions = _GroovesOptions;
71
-
72
- join_op: ?JoinOp = null,
73
- join_pending: usize = 0,
74
- join_callback: ?Callback = null,
75
-
76
- grid: *Grid,
77
- grooves: Grooves,
78
- node_pool: *NodePool,
79
-
80
- pub fn init(
81
- allocator: mem.Allocator,
82
- grid: *Grid,
83
- node_count: u32,
84
- // (e.g.) .{ .transfers = .{ .cache_entries_max = 128, … }, .accounts = … }
85
- grooves_options: GroovesOptions,
86
- ) !Forest {
87
- // NodePool must be allocated to pass in a stable address for the Grooves.
88
- const node_pool = try allocator.create(NodePool);
89
- errdefer allocator.destroy(node_pool);
90
-
91
- // TODO: look into using lsm_table_size_max for the node_count.
92
- node_pool.* = try NodePool.init(allocator, node_count);
93
- errdefer node_pool.deinit(allocator);
94
-
95
- var grooves: Grooves = undefined;
96
- var grooves_initialized: usize = 0;
97
-
98
- errdefer inline for (std.meta.fields(Grooves)) |field, field_index| {
99
- if (grooves_initialized >= field_index + 1) {
100
- @field(grooves, field.name).deinit(allocator);
101
- }
102
- };
103
-
104
- inline for (std.meta.fields(Grooves)) |groove_field| {
105
- const groove = &@field(grooves, groove_field.name);
106
- const Groove = @TypeOf(groove.*);
107
- const groove_options: Groove.Options = @field(grooves_options, groove_field.name);
108
-
109
- groove.* = try Groove.init(
110
- allocator,
111
- node_pool,
112
- grid,
113
- groove_options,
114
- );
115
-
116
- grooves_initialized += 1;
117
- }
118
-
119
- return Forest{
120
- .grid = grid,
121
- .grooves = grooves,
122
- .node_pool = node_pool,
123
- };
124
- }
125
-
126
- pub fn deinit(forest: *Forest, allocator: mem.Allocator) void {
127
- inline for (std.meta.fields(Grooves)) |field| {
128
- @field(forest.grooves, field.name).deinit(allocator);
129
- }
130
-
131
- forest.node_pool.deinit(allocator);
132
- allocator.destroy(forest.node_pool);
133
- }
134
-
135
- fn JoinType(comptime join_op: JoinOp) type {
136
- return struct {
137
- pub fn start(forest: *Forest, callback: Callback) void {
138
- assert(forest.join_op == null);
139
- assert(forest.join_pending == 0);
140
- assert(forest.join_callback == null);
141
-
142
- forest.join_op = join_op;
143
- forest.join_pending = std.meta.fields(Grooves).len;
144
- forest.join_callback = callback;
145
- }
146
-
147
- fn GrooveFor(comptime groove_field_name: []const u8) type {
148
- return @TypeOf(@field(@as(Grooves, undefined), groove_field_name));
149
- }
150
-
151
- pub fn groove_callback(
152
- comptime groove_field_name: []const u8,
153
- ) fn (*GrooveFor(groove_field_name)) void {
154
- return struct {
155
- fn groove_cb(groove: *GrooveFor(groove_field_name)) void {
156
- const grooves = @fieldParentPtr(Grooves, groove_field_name, groove);
157
- const forest = @fieldParentPtr(Forest, "grooves", grooves);
158
-
159
- assert(forest.join_op == join_op);
160
- assert(forest.join_callback != null);
161
- assert(forest.join_pending <= std.meta.fields(Grooves).len);
162
-
163
- forest.join_pending -= 1;
164
- if (forest.join_pending > 0) return;
165
-
166
- const callback = forest.join_callback.?;
167
- forest.join_op = null;
168
- forest.join_callback = null;
169
- callback(forest);
170
- }
171
- }.groove_cb;
172
- }
173
- };
174
- }
175
-
176
- pub fn open(forest: *Forest, callback: Callback) void {
177
- const Join = JoinType(.open);
178
- Join.start(forest, callback);
179
-
180
- inline for (std.meta.fields(Grooves)) |field| {
181
- @field(forest.grooves, field.name).open(Join.groove_callback(field.name));
182
- }
183
- }
184
-
185
- pub fn compact(forest: *Forest, callback: Callback, op: u64) void {
186
- // Start a compacting join.
187
- const Join = JoinType(.compacting);
188
- Join.start(forest, callback);
189
-
190
- inline for (std.meta.fields(Grooves)) |field| {
191
- @field(forest.grooves, field.name).compact(Join.groove_callback(field.name), op);
192
- }
193
- }
194
-
195
- pub fn checkpoint(forest: *Forest, callback: Callback) void {
196
- const Join = JoinType(.checkpoint);
197
- Join.start(forest, callback);
198
-
199
- inline for (std.meta.fields(Grooves)) |field| {
200
- @field(forest.grooves, field.name).checkpoint(Join.groove_callback(field.name));
201
- }
202
- }
203
- };
204
- }