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,203 +0,0 @@
1
- const std = @import("std");
2
- const mem = std.mem;
3
- const math = std.math;
4
- const assert = std.debug.assert;
5
-
6
- const constants = @import("../constants.zig");
7
- const div_ceil = @import("../stdx.zig").div_ceil;
8
- const binary_search = @import("binary_search.zig");
9
- const snapshot_latest = @import("tree.zig").snapshot_latest;
10
-
11
- pub fn TableImmutableType(comptime Table: type) type {
12
- const Key = Table.Key;
13
- const Value = Table.Value;
14
- const compare_keys = Table.compare_keys;
15
- const key_from_value = Table.key_from_value;
16
-
17
- return struct {
18
- const TableImmutable = @This();
19
-
20
- value_count_max: u32,
21
- values: []Value,
22
- snapshot_min: u64,
23
- free: bool,
24
-
25
- /// `commit_entries_max` is the maximum number of Values that can be inserted by a single commit.
26
- pub fn init(allocator: mem.Allocator, commit_entries_max: u32) !TableImmutable {
27
- assert(commit_entries_max > 0);
28
-
29
- // The in-memory immutable table is the same size as the mutable table:
30
- const value_count_max = commit_entries_max * constants.lsm_batch_multiple;
31
- const data_block_count = div_ceil(value_count_max, Table.data.value_count_max);
32
- assert(data_block_count <= Table.data_block_count_max);
33
-
34
- const values = try allocator.alloc(Value, value_count_max);
35
- errdefer allocator.free(values);
36
-
37
- return TableImmutable{
38
- .value_count_max = value_count_max,
39
- .snapshot_min = undefined,
40
- .values = values,
41
- .free = true,
42
- };
43
- }
44
-
45
- pub inline fn values_max(table: *const TableImmutable) []Value {
46
- assert(table.values.len <= table.value_count_max);
47
- return table.values.ptr[0..table.value_count_max];
48
- }
49
-
50
- pub inline fn key_min(table: *const TableImmutable) Key {
51
- assert(!table.free);
52
- assert(table.values.len > 0);
53
- return key_from_value(&table.values[0]);
54
- }
55
-
56
- pub inline fn key_max(table: *const TableImmutable) Key {
57
- assert(!table.free);
58
- assert(table.values.len > 0);
59
- return key_from_value(&table.values[table.values.len - 1]);
60
- }
61
-
62
- pub fn deinit(table: *TableImmutable, allocator: mem.Allocator) void {
63
- allocator.free(table.values_max());
64
- }
65
-
66
- pub fn clear(table: *TableImmutable) void {
67
- // This hack works around the stage1 compiler's problematic handling of pointers to
68
- // zero-bit types. In particular, `slice = slice[0..0]` is not equivalent to
69
- // `slice.len = 0` but in fact sets `slice.ptr = undefined` as well. This happens
70
- // since the type of `slice[0..0]` is `*[0]Value` which is a pointer to a zero-bit
71
- // type. Using slice bounds that are not comptime known avoids the issue.
72
- // See: https://github.com/ziglang/zig/issues/6706
73
- // TODO(zig) Remove this hack when upgrading to 0.10.0.
74
- var runtime_zero: usize = 0;
75
-
76
- table.* = .{
77
- .value_count_max = table.value_count_max,
78
- .snapshot_min = undefined,
79
- .values = table.values[runtime_zero..runtime_zero],
80
- .free = true,
81
- };
82
- }
83
-
84
- pub fn reset_with_sorted_values(
85
- table: *TableImmutable,
86
- snapshot_min: u64,
87
- sorted_values: []const Value,
88
- ) void {
89
- assert(table.free);
90
- assert(snapshot_min > 0);
91
- assert(snapshot_min < snapshot_latest);
92
-
93
- assert(sorted_values.ptr == table.values.ptr);
94
- assert(sorted_values.len > 0);
95
- assert(sorted_values.len <= table.value_count_max);
96
- assert(sorted_values.len <= Table.data.value_count_max * Table.data_block_count_max);
97
-
98
- if (constants.verify) {
99
- var i: usize = 1;
100
- while (i < sorted_values.len) : (i += 1) {
101
- assert(i > 0);
102
- const left_key = key_from_value(&sorted_values[i - 1]);
103
- const right_key = key_from_value(&sorted_values[i]);
104
- assert(compare_keys(left_key, right_key) == .lt);
105
- }
106
- }
107
-
108
- table.* = .{
109
- .value_count_max = table.value_count_max,
110
- .values = table.values.ptr[0..sorted_values.len],
111
- .snapshot_min = snapshot_min,
112
- .free = false,
113
- };
114
- }
115
-
116
- // TODO(ifreund) This would be great to unit test.
117
- pub fn get(table: *const TableImmutable, key: Key) ?*const Value {
118
- assert(!table.free);
119
-
120
- const result = binary_search.binary_search_values(
121
- Key,
122
- Value,
123
- key_from_value,
124
- compare_keys,
125
- table.values,
126
- key,
127
- .{},
128
- );
129
- if (result.exact) {
130
- const value = &table.values[result.index];
131
- if (constants.verify) assert(compare_keys(key, key_from_value(value)) == .eq);
132
- return value;
133
- }
134
-
135
- return null;
136
- }
137
- };
138
- }
139
-
140
- pub fn TableImmutableIteratorType(comptime Table: type, comptime Storage: type) type {
141
- _ = Storage;
142
-
143
- return struct {
144
- const TableImmutableIterator = @This();
145
- const TableImmutable = TableImmutableType(Table);
146
-
147
- table: *const TableImmutable,
148
- values_index: u32,
149
-
150
- pub fn init(allocator: mem.Allocator) !TableImmutableIterator {
151
- _ = allocator; // This only iterates an existing immutable table.
152
-
153
- return TableImmutableIterator{
154
- .table = undefined,
155
- .values_index = undefined,
156
- };
157
- }
158
-
159
- pub fn deinit(it: *TableImmutableIterator, allocator: mem.Allocator) void {
160
- _ = allocator; // No memory allocation was initially performed.
161
- it.* = undefined;
162
- }
163
-
164
- pub const Context = struct {
165
- table: *const TableImmutable,
166
- };
167
-
168
- pub fn start(
169
- it: *TableImmutableIterator,
170
- context: Context,
171
- read_done: fn (*TableImmutableIterator) void,
172
- ) void {
173
- _ = read_done; // No asynchronous operations are performed.
174
- it.* = .{
175
- .table = context.table,
176
- .values_index = 0,
177
- };
178
- }
179
-
180
- pub fn tick(it: *const TableImmutableIterator) bool {
181
- assert(!it.table.free);
182
- return false; // No I/O is performed as it's all in memory.
183
- }
184
-
185
- pub fn buffered_all_values(it: *const TableImmutableIterator) bool {
186
- assert(!it.table.free);
187
- return true; // All values are "buffered" in memory.
188
- }
189
-
190
- pub fn peek(it: *const TableImmutableIterator) error{ Empty, Drained }!Table.Key {
191
- // NOTE: This iterator is never Drained as all values are in memory (tick is a no-op).
192
- assert(!it.table.free);
193
- if (it.values_index == it.table.values.len) return error.Empty;
194
- return Table.key_from_value(&it.table.values[it.values_index]);
195
- }
196
-
197
- pub fn pop(it: *TableImmutableIterator) Table.Value {
198
- assert(!it.table.free);
199
- defer it.values_index += 1;
200
- return it.table.values[it.values_index];
201
- }
202
- };
203
- }
@@ -1,340 +0,0 @@
1
- const std = @import("std");
2
- const mem = std.mem;
3
- const math = std.math;
4
- const assert = std.debug.assert;
5
-
6
- const constants = @import("../constants.zig");
7
-
8
- const stdx = @import("../stdx.zig");
9
- const RingBuffer = @import("../ring_buffer.zig").RingBuffer;
10
- const ManifestType = @import("manifest.zig").ManifestType;
11
- const GridType = @import("grid.zig").GridType;
12
-
13
- /// A TableIterator iterates a table's values in ascending-key order.
14
- pub fn TableIteratorType(comptime Table: type, comptime Storage: type) type {
15
- return struct {
16
- const TableIterator = @This();
17
-
18
- const Grid = GridType(Storage);
19
- const Manifest = ManifestType(Table, Storage);
20
- const ValuesRingBuffer = RingBuffer(Table.Value, Table.data.value_count_max, .pointer);
21
-
22
- const BlockPtrConst = *align(constants.sector_size) const [constants.block_size]u8;
23
- const IndexBlockCallback = fn (it: *TableIterator, index_block: BlockPtrConst) void;
24
-
25
- grid: *Grid,
26
- read_done: fn (*TableIterator) void,
27
- read_table_index: bool,
28
-
29
- /// We store only the address and checksum of the table's index block to save memory,
30
- /// since TableIterator is used in every LevelIterator.
31
- address: u64,
32
- checksum: u128,
33
-
34
- index_block: Grid.BlockPtr,
35
- index_block_callback: ?IndexBlockCallback,
36
- /// The index of the current block in the table index block.
37
- data_block_index: u32,
38
-
39
- /// This ring buffer is used to hold not yet popped values in the case that we run
40
- /// out of blocks in the blocks ring buffer but haven't buffered a full block of
41
- /// values in memory. In this case, we copy values from the head of blocks to this
42
- /// ring buffer to make that block available for reading further values.
43
- /// Thus, we guarantee that iterators will always have at least a block's worth
44
- /// of values buffered.
45
- values: ValuesRingBuffer,
46
-
47
- data_blocks: RingBuffer(Grid.BlockPtr, 2, .array),
48
- /// The index of the current value in the head of the blocks ring buffer.
49
- value: u32,
50
-
51
- read: Grid.Read = undefined,
52
- /// This field is only used for safety checks, it does not affect the behavior.
53
- read_pending: bool = false,
54
-
55
- // Used for verifying key order when constants.verify == true.
56
- key_prev: ?Table.Key,
57
-
58
- pub fn init(allocator: mem.Allocator) !TableIterator {
59
- const index_block = try allocator.alignedAlloc(
60
- u8,
61
- constants.sector_size,
62
- constants.block_size,
63
- );
64
- errdefer allocator.free(index_block);
65
-
66
- var values = try ValuesRingBuffer.init(allocator);
67
- errdefer values.deinit(allocator);
68
-
69
- const block_a = try allocator.alignedAlloc(
70
- u8,
71
- constants.sector_size,
72
- constants.block_size,
73
- );
74
- errdefer allocator.free(block_a);
75
-
76
- const block_b = try allocator.alignedAlloc(
77
- u8,
78
- constants.sector_size,
79
- constants.block_size,
80
- );
81
- errdefer allocator.free(block_b);
82
-
83
- return TableIterator{
84
- .grid = undefined,
85
- .read_done = undefined,
86
- .read_table_index = undefined,
87
- // Use 0 so that we can assert(address != 0) in tick().
88
- .address = 0,
89
- .checksum = undefined,
90
- .index_block = index_block[0..constants.block_size],
91
- .index_block_callback = null,
92
- .data_block_index = undefined,
93
- .values = values,
94
- .data_blocks = .{
95
- .buffer = .{
96
- block_a[0..constants.block_size],
97
- block_b[0..constants.block_size],
98
- },
99
- },
100
- .value = undefined,
101
- .key_prev = null,
102
- };
103
- }
104
-
105
- pub fn deinit(it: *TableIterator, allocator: mem.Allocator) void {
106
- allocator.free(it.index_block);
107
- it.values.deinit(allocator);
108
- for (it.data_blocks.buffer) |block| allocator.free(block);
109
- it.* = undefined;
110
- }
111
-
112
- pub const Context = struct {
113
- grid: *Grid,
114
- address: u64, // Table index block address.
115
- checksum: u128, // Table index block checksum.
116
- index_block_callback: ?IndexBlockCallback = null,
117
- };
118
-
119
- pub fn start(
120
- it: *TableIterator,
121
- context: Context,
122
- read_done: fn (*TableIterator) void,
123
- ) void {
124
- assert(!it.read_pending);
125
- assert(it.index_block_callback == null);
126
-
127
- it.* = .{
128
- .grid = context.grid,
129
- .read_done = read_done,
130
- .read_table_index = true,
131
- .address = context.address,
132
- .checksum = context.checksum,
133
- .index_block = it.index_block,
134
- .index_block_callback = context.index_block_callback,
135
- .data_block_index = 0,
136
- .values = .{ .buffer = it.values.buffer },
137
- .data_blocks = .{ .buffer = it.data_blocks.buffer },
138
- .value = 0,
139
- .key_prev = null,
140
- };
141
-
142
- assert(it.values.empty());
143
- assert(it.data_blocks.empty());
144
-
145
- if (constants.verify) {
146
- Table.verify(
147
- Storage,
148
- context.grid.superblock.storage,
149
- context.address,
150
- null,
151
- null,
152
- );
153
- }
154
- }
155
-
156
- /// Try to buffer at least a full block of values to be peek()'d.
157
- /// A full block may not always be buffered if all 3 blocks are partially full
158
- /// or if the end of the table is reached.
159
- /// Returns true if an IO operation was started. If this returns true,
160
- /// then read_done() will be called on completion.
161
- pub fn tick(it: *TableIterator) bool {
162
- assert(!it.read_pending);
163
- assert(it.address != 0);
164
-
165
- if (it.read_table_index) {
166
- assert(!it.read_pending);
167
- it.read_pending = true;
168
- it.grid.read_block(
169
- on_read_table_index,
170
- &it.read,
171
- it.address,
172
- it.checksum,
173
- .index,
174
- );
175
- return true;
176
- }
177
-
178
- if (it.buffered_enough_values()) {
179
- return false;
180
- } else {
181
- it.read_next_data_block();
182
- return true;
183
- }
184
- }
185
-
186
- fn read_next_data_block(it: *TableIterator) void {
187
- assert(!it.read_table_index);
188
- assert(it.data_block_index < Table.index_data_blocks_used(it.index_block));
189
-
190
- const addresses = Table.index_data_addresses(it.index_block);
191
- const checksums = Table.index_data_checksums(it.index_block);
192
- const address = addresses[it.data_block_index];
193
- const checksum = checksums[it.data_block_index];
194
-
195
- assert(!it.read_pending);
196
- it.read_pending = true;
197
- it.grid.read_block(on_read, &it.read, address, checksum, .data);
198
- }
199
-
200
- fn on_read_table_index(read: *Grid.Read, block: Grid.BlockPtrConst) void {
201
- const it = @fieldParentPtr(TableIterator, "read", read);
202
- assert(it.read_pending);
203
- assert(it.data_block_index == 0);
204
- it.read_pending = false;
205
-
206
- assert(it.read_table_index);
207
- it.read_table_index = false;
208
-
209
- // Copy the bytes read into a buffer owned by the iterator since the Grid
210
- // only guarantees the provided pointer to be valid in this callback.
211
- stdx.copy_disjoint(.exact, u8, it.index_block, block);
212
-
213
- if (it.index_block_callback) |callback| {
214
- it.index_block_callback = null;
215
- callback(it, block);
216
- }
217
-
218
- const read_pending = it.tick();
219
- // After reading the table index, we always read at least one data block.
220
- assert(read_pending);
221
- assert(it.read_pending);
222
- }
223
-
224
- fn on_read(read: *Grid.Read, block: Grid.BlockPtrConst) void {
225
- const it = @fieldParentPtr(TableIterator, "read", read);
226
- assert(it.read_pending);
227
- it.read_pending = false;
228
-
229
- assert(!it.read_table_index);
230
-
231
- // If there is not currently a buffer available, copy remaining values to
232
- // an overflow ring buffer to make space.
233
- if (it.data_blocks.next_tail() == null) {
234
- const values = Table.data_block_values_used(it.data_blocks.head().?);
235
- const values_remaining = values[it.value..];
236
- it.values.push_slice(values_remaining) catch unreachable;
237
- it.value = 0;
238
- it.data_blocks.advance_head();
239
- }
240
-
241
- // Copy the bytes read into a buffer owned by the iterator since the Grid
242
- // only guarantees the provided pointer to be valid in this callback.
243
- stdx.copy_disjoint(.exact, u8, it.data_blocks.next_tail().?, block);
244
-
245
- it.data_blocks.advance_tail();
246
- it.data_block_index += 1;
247
-
248
- if (!it.tick()) {
249
- assert(it.buffered_enough_values());
250
- it.read_done(it);
251
- }
252
- }
253
-
254
- /// Return true if all remaining values in the table have been buffered in memory.
255
- pub fn buffered_all_values(it: TableIterator) bool {
256
- assert(!it.read_pending);
257
-
258
- const data_blocks_used = Table.index_data_blocks_used(it.index_block);
259
- assert(it.data_block_index <= data_blocks_used);
260
- return it.data_block_index == data_blocks_used;
261
- }
262
-
263
- pub fn buffered_value_count(it: TableIterator) u32 {
264
- assert(!it.read_pending);
265
-
266
- var value_count = it.values.count;
267
- var blocks_it = it.data_blocks.iterator();
268
- while (blocks_it.next()) |block| {
269
- value_count += Table.data_block_values_used(block).len;
270
- }
271
- // We do this subtraction last to avoid underflow.
272
- value_count -= it.value;
273
-
274
- return @intCast(u32, value_count);
275
- }
276
-
277
- fn buffered_enough_values(it: TableIterator) bool {
278
- assert(!it.read_pending);
279
-
280
- return it.buffered_all_values() or
281
- it.buffered_value_count() >= Table.data.value_count_max;
282
- }
283
-
284
- /// Returns either:
285
- /// - the next Key, if available.
286
- /// - error.Empty when there are no values remaining to iterate.
287
- /// - error.Drained when the iterator isn't empty, but some values
288
- /// still need to be buffered into memory via tick().
289
- pub fn peek(it: TableIterator) error{ Empty, Drained }!Table.Key {
290
- assert(!it.read_pending);
291
- assert(!it.read_table_index);
292
-
293
- if (it.values.head_ptr_const()) |value| return Table.key_from_value(value);
294
-
295
- const block = it.data_blocks.head() orelse {
296
- // NOTE: Even if there are no values to peek, some may be unbuffered.
297
- // We call buffered_all_values() to distinguish between the iterator
298
- // being empty and needing to tick() to refill values.
299
- if (!it.buffered_all_values()) return error.Drained;
300
- return error.Empty;
301
- };
302
-
303
- const values = Table.data_block_values_used(block);
304
- return Table.key_from_value(&values[it.value]);
305
- }
306
-
307
- /// This may only be called after peek() returns a Key (and not Empty or Drained)
308
- pub fn pop(it: *TableIterator) Table.Value {
309
- const value = it.pop_internal();
310
-
311
- if (constants.verify) {
312
- const key = Table.key_from_value(&value);
313
- if (it.key_prev) |k| assert(Table.compare_keys(k, key) == .lt);
314
- it.key_prev = key;
315
- }
316
-
317
- return value;
318
- }
319
-
320
- fn pop_internal(it: *TableIterator) Table.Value {
321
- assert(!it.read_pending);
322
- assert(!it.read_table_index);
323
-
324
- if (it.values.pop()) |value| return value;
325
-
326
- const block = it.data_blocks.head().?;
327
-
328
- const values = Table.data_block_values_used(block);
329
- const value = values[it.value];
330
-
331
- it.value += 1;
332
- if (it.value == values.len) {
333
- it.value = 0;
334
- it.data_blocks.advance_head();
335
- }
336
-
337
- return value;
338
- }
339
- };
340
- }