tigerbeetle-node 0.11.8 → 0.11.9
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.
- package/dist/.client.node.sha256 +1 -1
- package/package.json +4 -3
- package/scripts/build_lib.sh +29 -0
- package/src/node.zig +1 -1
- package/src/tigerbeetle/scripts/validate_docs.sh +7 -1
- package/src/tigerbeetle/src/benchmark.zig +3 -3
- package/src/tigerbeetle/src/config.zig +29 -16
- package/src/tigerbeetle/src/constants.zig +30 -9
- package/src/tigerbeetle/src/ewah.zig +5 -5
- package/src/tigerbeetle/src/ewah_fuzz.zig +1 -1
- package/src/tigerbeetle/src/lsm/binary_search.zig +1 -1
- package/src/tigerbeetle/src/lsm/bloom_filter.zig +1 -1
- package/src/tigerbeetle/src/lsm/compaction.zig +34 -21
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +85 -103
- package/src/tigerbeetle/src/lsm/grid.zig +19 -13
- package/src/tigerbeetle/src/lsm/manifest_log.zig +8 -10
- package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +12 -8
- package/src/tigerbeetle/src/lsm/merge_iterator.zig +1 -1
- package/src/tigerbeetle/src/lsm/segmented_array.zig +17 -17
- package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +1 -1
- package/src/tigerbeetle/src/lsm/set_associative_cache.zig +1 -1
- package/src/tigerbeetle/src/lsm/table.zig +8 -20
- package/src/tigerbeetle/src/lsm/table_immutable.zig +1 -1
- package/src/tigerbeetle/src/lsm/table_iterator.zig +3 -3
- package/src/tigerbeetle/src/lsm/table_mutable.zig +14 -2
- package/src/tigerbeetle/src/lsm/tree.zig +31 -5
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +86 -114
- package/src/tigerbeetle/src/message_bus.zig +4 -4
- package/src/tigerbeetle/src/message_pool.zig +7 -10
- package/src/tigerbeetle/src/ring_buffer.zig +22 -12
- package/src/tigerbeetle/src/simulator.zig +360 -214
- package/src/tigerbeetle/src/state_machine/auditor.zig +5 -5
- package/src/tigerbeetle/src/state_machine/workload.zig +3 -3
- package/src/tigerbeetle/src/state_machine.zig +190 -178
- package/src/tigerbeetle/src/{util.zig → stdx.zig} +2 -0
- package/src/tigerbeetle/src/storage.zig +13 -6
- package/src/tigerbeetle/src/{test → testing/cluster}/message_bus.zig +3 -3
- package/src/tigerbeetle/src/{test → testing/cluster}/network.zig +46 -22
- package/src/tigerbeetle/src/testing/cluster/state_checker.zig +169 -0
- package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +202 -0
- package/src/tigerbeetle/src/testing/cluster.zig +537 -0
- package/src/tigerbeetle/src/{test → testing}/fuzz.zig +0 -0
- package/src/tigerbeetle/src/testing/hash_log.zig +66 -0
- package/src/tigerbeetle/src/{test → testing}/id.zig +0 -0
- package/src/tigerbeetle/src/testing/packet_simulator.zig +365 -0
- package/src/tigerbeetle/src/{test → testing}/priority_queue.zig +1 -1
- package/src/tigerbeetle/src/testing/reply_sequence.zig +139 -0
- package/src/tigerbeetle/src/{test → testing}/state_machine.zig +3 -1
- package/src/tigerbeetle/src/testing/storage.zig +754 -0
- package/src/tigerbeetle/src/{test → testing}/table.zig +21 -0
- package/src/tigerbeetle/src/{test → testing}/time.zig +0 -0
- package/src/tigerbeetle/src/tigerbeetle.zig +2 -0
- package/src/tigerbeetle/src/tracer.zig +3 -3
- package/src/tigerbeetle/src/unit_tests.zig +4 -4
- package/src/tigerbeetle/src/vopr.zig +2 -2
- package/src/tigerbeetle/src/vsr/client.zig +5 -2
- package/src/tigerbeetle/src/vsr/clock.zig +93 -53
- package/src/tigerbeetle/src/vsr/journal.zig +29 -14
- package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +2 -2
- package/src/tigerbeetle/src/vsr/replica.zig +1383 -774
- package/src/tigerbeetle/src/vsr/replica_format.zig +2 -2
- package/src/tigerbeetle/src/vsr/superblock.zig +59 -43
- package/src/tigerbeetle/src/vsr/superblock_client_table.zig +7 -7
- package/src/tigerbeetle/src/vsr/superblock_free_set.zig +1 -1
- package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +1 -1
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +15 -7
- package/src/tigerbeetle/src/vsr/superblock_manifest.zig +38 -19
- package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +1 -1
- package/src/tigerbeetle/src/vsr.zig +6 -4
- package/src/tigerbeetle/src/demo.zig +0 -132
- package/src/tigerbeetle/src/demo_01_create_accounts.zig +0 -35
- package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +0 -7
- package/src/tigerbeetle/src/demo_03_create_transfers.zig +0 -37
- package/src/tigerbeetle/src/demo_04_create_pending_transfers.zig +0 -61
- package/src/tigerbeetle/src/demo_05_post_pending_transfers.zig +0 -37
- package/src/tigerbeetle/src/demo_06_void_pending_transfers.zig +0 -24
- package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +0 -7
- package/src/tigerbeetle/src/test/cluster.zig +0 -352
- package/src/tigerbeetle/src/test/conductor.zig +0 -366
- package/src/tigerbeetle/src/test/packet_simulator.zig +0 -398
- package/src/tigerbeetle/src/test/state_checker.zig +0 -169
- package/src/tigerbeetle/src/test/storage.zig +0 -864
- package/src/tigerbeetle/src/test/storage_checker.zig +0 -204
|
@@ -4,8 +4,8 @@ const assert = std.debug.assert;
|
|
|
4
4
|
const math = std.math;
|
|
5
5
|
const mem = std.mem;
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const div_ceil = @import("../
|
|
7
|
+
const stdx = @import("../stdx.zig");
|
|
8
|
+
const div_ceil = @import("../stdx.zig").div_ceil;
|
|
9
9
|
const binary_search_values_raw = @import("binary_search.zig").binary_search_values_raw;
|
|
10
10
|
const binary_search_keys = @import("binary_search.zig").binary_search_keys;
|
|
11
11
|
const Direction = @import("direction.zig").Direction;
|
|
@@ -280,13 +280,13 @@ fn SegmentedArrayType(
|
|
|
280
280
|
|
|
281
281
|
const total = array.count(a) + @intCast(u32, elements.len);
|
|
282
282
|
if (total <= node_capacity) {
|
|
283
|
-
|
|
283
|
+
stdx.copy_right(
|
|
284
284
|
.inexact,
|
|
285
285
|
T,
|
|
286
286
|
a_pointer[cursor.relative_index + elements.len ..],
|
|
287
287
|
a_pointer[cursor.relative_index..array.count(a)],
|
|
288
288
|
);
|
|
289
|
-
|
|
289
|
+
stdx.copy_disjoint(.inexact, T, a_pointer[cursor.relative_index..], elements);
|
|
290
290
|
|
|
291
291
|
array.increment_indexes_after(a, @intCast(u32, elements.len));
|
|
292
292
|
return;
|
|
@@ -348,7 +348,7 @@ fn SegmentedArrayType(
|
|
|
348
348
|
|
|
349
349
|
if (a_half < cursor.relative_index) {
|
|
350
350
|
// Move the part of `a` that is past the half-way point into `b`.
|
|
351
|
-
|
|
351
|
+
stdx.copy_right(
|
|
352
352
|
.inexact,
|
|
353
353
|
T,
|
|
354
354
|
b_half_pointer,
|
|
@@ -383,10 +383,10 @@ fn SegmentedArrayType(
|
|
|
383
383
|
const source_a = source[0..target_a.len];
|
|
384
384
|
const source_b = source[target_a.len..];
|
|
385
385
|
if (target_b.ptr != source_b.ptr) {
|
|
386
|
-
|
|
386
|
+
stdx.copy_right(.exact, T, target_b, source_b);
|
|
387
387
|
}
|
|
388
388
|
if (target_a.ptr != source_a.ptr) {
|
|
389
|
-
|
|
389
|
+
stdx.copy_right(.exact, T, target_a, source_a);
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
|
|
@@ -395,13 +395,13 @@ fn SegmentedArrayType(
|
|
|
395
395
|
assert(node <= array.node_count);
|
|
396
396
|
assert(array.node_count + 1 <= node_count_max);
|
|
397
397
|
|
|
398
|
-
|
|
398
|
+
stdx.copy_right(
|
|
399
399
|
.exact,
|
|
400
400
|
?*[node_capacity]T,
|
|
401
401
|
array.nodes[node + 1 .. array.node_count + 1],
|
|
402
402
|
array.nodes[node..array.node_count],
|
|
403
403
|
);
|
|
404
|
-
|
|
404
|
+
stdx.copy_right(
|
|
405
405
|
.exact,
|
|
406
406
|
u32,
|
|
407
407
|
array.indexes[node + 1 .. array.node_count + 2],
|
|
@@ -470,7 +470,7 @@ fn SegmentedArrayType(
|
|
|
470
470
|
|
|
471
471
|
// Remove elements from exactly one node:
|
|
472
472
|
if (a_remaining + remove_count <= array.count(a)) {
|
|
473
|
-
|
|
473
|
+
stdx.copy_left(
|
|
474
474
|
.inexact,
|
|
475
475
|
T,
|
|
476
476
|
a_pointer[a_remaining..],
|
|
@@ -497,7 +497,7 @@ fn SegmentedArrayType(
|
|
|
497
497
|
assert(a_remaining > 0 or b_remaining.len > 0);
|
|
498
498
|
|
|
499
499
|
if (a_remaining >= half) {
|
|
500
|
-
|
|
500
|
+
stdx.copy_left(.inexact, T, b_pointer, b_remaining);
|
|
501
501
|
|
|
502
502
|
array.indexes[b] = array.indexes[a] + a_remaining;
|
|
503
503
|
array.decrement_indexes_after(b, remove_count);
|
|
@@ -514,7 +514,7 @@ fn SegmentedArrayType(
|
|
|
514
514
|
assert(a_remaining < half and b_remaining.len < half);
|
|
515
515
|
assert(a_remaining + b_remaining.len <= node_capacity);
|
|
516
516
|
|
|
517
|
-
|
|
517
|
+
stdx.copy_disjoint(.inexact, T, a_pointer[a_remaining..], b_remaining);
|
|
518
518
|
|
|
519
519
|
array.indexes[b] = array.indexes[a] + a_remaining + @intCast(u32, b_remaining.len);
|
|
520
520
|
array.decrement_indexes_after(b, remove_count);
|
|
@@ -576,7 +576,7 @@ fn SegmentedArrayType(
|
|
|
576
576
|
|
|
577
577
|
const total = array.count(a) + @intCast(u32, b_elements.len);
|
|
578
578
|
if (total <= node_capacity) {
|
|
579
|
-
|
|
579
|
+
stdx.copy_disjoint(.inexact, T, a_pointer[array.count(a)..], b_elements);
|
|
580
580
|
|
|
581
581
|
array.indexes[b] = array.indexes[b + 1];
|
|
582
582
|
array.remove_empty_node_at(node_pool, b);
|
|
@@ -588,13 +588,13 @@ fn SegmentedArrayType(
|
|
|
588
588
|
assert(a_half >= b_half);
|
|
589
589
|
assert(a_half + b_half == total);
|
|
590
590
|
|
|
591
|
-
|
|
591
|
+
stdx.copy_disjoint(
|
|
592
592
|
.exact,
|
|
593
593
|
T,
|
|
594
594
|
a_pointer[array.count(a)..a_half],
|
|
595
595
|
b_elements[0 .. a_half - array.count(a)],
|
|
596
596
|
);
|
|
597
|
-
|
|
597
|
+
stdx.copy_left(.inexact, T, b_pointer, b_elements[a_half - array.count(a) ..]);
|
|
598
598
|
|
|
599
599
|
array.indexes[b] = array.indexes[a] + a_half;
|
|
600
600
|
|
|
@@ -616,13 +616,13 @@ fn SegmentedArrayType(
|
|
|
616
616
|
@ptrCast(NodePool.Node, @alignCast(NodePool.node_alignment, array.nodes[node].?)),
|
|
617
617
|
);
|
|
618
618
|
|
|
619
|
-
|
|
619
|
+
stdx.copy_left(
|
|
620
620
|
.exact,
|
|
621
621
|
?*[node_capacity]T,
|
|
622
622
|
array.nodes[node .. array.node_count - 1],
|
|
623
623
|
array.nodes[node + 1 .. array.node_count],
|
|
624
624
|
);
|
|
625
|
-
|
|
625
|
+
stdx.copy_left(
|
|
626
626
|
.exact,
|
|
627
627
|
u32,
|
|
628
628
|
array.indexes[node..array.node_count],
|
|
@@ -8,7 +8,7 @@ const meta = std.meta;
|
|
|
8
8
|
const Vector = meta.Vector;
|
|
9
9
|
|
|
10
10
|
const constants = @import("../constants.zig");
|
|
11
|
-
const div_ceil = @import("../
|
|
11
|
+
const div_ceil = @import("../stdx.zig").div_ceil;
|
|
12
12
|
const verify = constants.verify;
|
|
13
13
|
|
|
14
14
|
pub const Layout = struct {
|
|
@@ -8,12 +8,13 @@ const vsr = @import("../vsr.zig");
|
|
|
8
8
|
const binary_search = @import("binary_search.zig");
|
|
9
9
|
const bloom_filter = @import("bloom_filter.zig");
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const div_ceil =
|
|
11
|
+
const stdx = @import("../stdx.zig");
|
|
12
|
+
const div_ceil = stdx.div_ceil;
|
|
13
13
|
const eytzinger = @import("eytzinger.zig").eytzinger;
|
|
14
14
|
const snapshot_latest = @import("tree.zig").snapshot_latest;
|
|
15
15
|
|
|
16
16
|
const BlockType = @import("grid.zig").BlockType;
|
|
17
|
+
const alloc_block = @import("grid.zig").alloc_block;
|
|
17
18
|
const TableInfoType = @import("manifest.zig").TableInfoType;
|
|
18
19
|
|
|
19
20
|
pub const TableUsage = enum {
|
|
@@ -484,13 +485,13 @@ pub fn TableType(
|
|
|
484
485
|
data_blocks_in_filter: u32 = 0,
|
|
485
486
|
|
|
486
487
|
pub fn init(allocator: mem.Allocator) !Builder {
|
|
487
|
-
const index_block = try allocator
|
|
488
|
+
const index_block = try alloc_block(allocator);
|
|
488
489
|
errdefer allocator.free(index_block);
|
|
489
490
|
|
|
490
|
-
const filter_block = try allocator
|
|
491
|
+
const filter_block = try alloc_block(allocator);
|
|
491
492
|
errdefer allocator.free(filter_block);
|
|
492
493
|
|
|
493
|
-
const data_block = try allocator
|
|
494
|
+
const data_block = try alloc_block(allocator);
|
|
494
495
|
errdefer allocator.free(data_block);
|
|
495
496
|
|
|
496
497
|
return Builder{
|
|
@@ -527,7 +528,7 @@ pub fn TableType(
|
|
|
527
528
|
const values_max = data_block_values(builder.data_block);
|
|
528
529
|
assert(values_max.len == data.value_count_max);
|
|
529
530
|
|
|
530
|
-
|
|
531
|
+
stdx.copy_disjoint(.inexact, Value, values_max[builder.value..], values);
|
|
531
532
|
builder.value += @intCast(u32, values.len);
|
|
532
533
|
|
|
533
534
|
for (values) |*value| {
|
|
@@ -596,8 +597,6 @@ pub fn TableType(
|
|
|
596
597
|
|
|
597
598
|
const values_padding = mem.sliceAsBytes(values_max[builder.value..]);
|
|
598
599
|
const block_padding = block[data.padding_offset..][0..data.padding_size];
|
|
599
|
-
mem.set(u8, values_padding, 0);
|
|
600
|
-
mem.set(u8, block_padding, 0);
|
|
601
600
|
assert(compare_keys(key_from_value(&values[values.len - 1]), key_max) == .eq);
|
|
602
601
|
|
|
603
602
|
const header_bytes = block[0..@sizeOf(vsr.Header)];
|
|
@@ -712,17 +711,6 @@ pub fn TableType(
|
|
|
712
711
|
|
|
713
712
|
const index_block = builder.index_block;
|
|
714
713
|
|
|
715
|
-
const index_data_keys_padding = index_data_keys(index_block)[builder.data_block_count..];
|
|
716
|
-
const index_data_keys_padding_bytes = mem.sliceAsBytes(index_data_keys_padding);
|
|
717
|
-
mem.set(u8, index_data_keys_padding_bytes, 0);
|
|
718
|
-
mem.set(u64, index_data_addresses(index_block)[builder.data_block_count..], 0);
|
|
719
|
-
mem.set(u128, index_data_checksums(index_block)[builder.data_block_count..], 0);
|
|
720
|
-
|
|
721
|
-
mem.set(u64, index_filter_addresses(index_block)[builder.filter_block_count..], 0);
|
|
722
|
-
mem.set(u128, index_filter_checksums(index_block)[builder.filter_block_count..], 0);
|
|
723
|
-
|
|
724
|
-
mem.set(u8, index_block[index.padding_offset..][0..index.padding_size], 0);
|
|
725
|
-
|
|
726
714
|
const header_bytes = index_block[0..@sizeOf(vsr.Header)];
|
|
727
715
|
const header = mem.bytesAsValue(vsr.Header, header_bytes);
|
|
728
716
|
|
|
@@ -992,7 +980,7 @@ pub fn TableType(
|
|
|
992
980
|
key_min: ?Key,
|
|
993
981
|
key_max: ?Key,
|
|
994
982
|
) void {
|
|
995
|
-
if (Storage != @import("../
|
|
983
|
+
if (Storage != @import("../testing/storage.zig").Storage)
|
|
996
984
|
// Too complicated to do async verification
|
|
997
985
|
return;
|
|
998
986
|
|
|
@@ -4,7 +4,7 @@ const math = std.math;
|
|
|
4
4
|
const assert = std.debug.assert;
|
|
5
5
|
|
|
6
6
|
const constants = @import("../constants.zig");
|
|
7
|
-
const div_ceil = @import("../
|
|
7
|
+
const div_ceil = @import("../stdx.zig").div_ceil;
|
|
8
8
|
const binary_search = @import("binary_search.zig");
|
|
9
9
|
const snapshot_latest = @import("tree.zig").snapshot_latest;
|
|
10
10
|
|
|
@@ -5,7 +5,7 @@ const assert = std.debug.assert;
|
|
|
5
5
|
|
|
6
6
|
const constants = @import("../constants.zig");
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const stdx = @import("../stdx.zig");
|
|
9
9
|
const RingBuffer = @import("../ring_buffer.zig").RingBuffer;
|
|
10
10
|
const ManifestType = @import("manifest.zig").ManifestType;
|
|
11
11
|
const GridType = @import("grid.zig").GridType;
|
|
@@ -208,7 +208,7 @@ pub fn TableIteratorType(comptime Table: type, comptime Storage: type) type {
|
|
|
208
208
|
|
|
209
209
|
// Copy the bytes read into a buffer owned by the iterator since the Grid
|
|
210
210
|
// only guarantees the provided pointer to be valid in this callback.
|
|
211
|
-
|
|
211
|
+
stdx.copy_disjoint(.exact, u8, it.index_block, block);
|
|
212
212
|
|
|
213
213
|
if (it.index_block_callback) |callback| {
|
|
214
214
|
it.index_block_callback = null;
|
|
@@ -240,7 +240,7 @@ pub fn TableIteratorType(comptime Table: type, comptime Storage: type) type {
|
|
|
240
240
|
|
|
241
241
|
// Copy the bytes read into a buffer owned by the iterator since the Grid
|
|
242
242
|
// only guarantees the provided pointer to be valid in this callback.
|
|
243
|
-
|
|
243
|
+
stdx.copy_disjoint(.exact, u8, it.data_blocks.next_tail().?, block);
|
|
244
244
|
|
|
245
245
|
it.data_blocks.advance_tail();
|
|
246
246
|
it.data_block_index += 1;
|
|
@@ -4,7 +4,7 @@ const math = std.math;
|
|
|
4
4
|
const assert = std.debug.assert;
|
|
5
5
|
|
|
6
6
|
const constants = @import("../constants.zig");
|
|
7
|
-
const div_ceil = @import("../
|
|
7
|
+
const div_ceil = @import("../stdx.zig").div_ceil;
|
|
8
8
|
const SetAssociativeCache = @import("set_associative_cache.zig").SetAssociativeCache;
|
|
9
9
|
|
|
10
10
|
/// Range queries are not supported on the TableMutable, it must first be made immutable.
|
|
@@ -43,6 +43,13 @@ pub fn TableMutableType(comptime Table: type) type {
|
|
|
43
43
|
value_count_max: u32,
|
|
44
44
|
values: Values = .{},
|
|
45
45
|
|
|
46
|
+
/// Rather than using values.count(), we count how many values we could have had if every
|
|
47
|
+
/// operation had been on a different key. This means that mistakes in calculating
|
|
48
|
+
/// commit_entries_max are much easier to catch when fuzzing, rather than requiring very
|
|
49
|
+
/// specific workloads.
|
|
50
|
+
/// Invariant: value_count_worst_case <= value_count_max
|
|
51
|
+
value_count_worst_case: u32 = 0,
|
|
52
|
+
|
|
46
53
|
/// This is used to accelerate point lookups and is not used for range queries.
|
|
47
54
|
/// Secondary index trees used only for range queries can therefore set this to null.
|
|
48
55
|
///
|
|
@@ -98,6 +105,8 @@ pub fn TableMutableType(comptime Table: type) type {
|
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
pub fn put(table: *TableMutable, value: *const Value) void {
|
|
108
|
+
assert(table.value_count_worst_case < table.value_count_max);
|
|
109
|
+
table.value_count_worst_case += 1;
|
|
101
110
|
switch (usage) {
|
|
102
111
|
.secondary_index => {
|
|
103
112
|
const existing = table.values.fetchRemove(value.*);
|
|
@@ -123,6 +132,8 @@ pub fn TableMutableType(comptime Table: type) type {
|
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
pub fn remove(table: *TableMutable, value: *const Value) void {
|
|
135
|
+
assert(table.value_count_worst_case < table.value_count_max);
|
|
136
|
+
table.value_count_worst_case += 1;
|
|
126
137
|
switch (usage) {
|
|
127
138
|
.secondary_index => {
|
|
128
139
|
const existing = table.values.fetchRemove(value.*);
|
|
@@ -152,11 +163,12 @@ pub fn TableMutableType(comptime Table: type) type {
|
|
|
152
163
|
/// assumes that none of the batch's keys are already in `table.values`.
|
|
153
164
|
pub fn can_commit_batch(table: *TableMutable, batch_count: u32) bool {
|
|
154
165
|
assert(batch_count <= table.value_count_max);
|
|
155
|
-
return (table.
|
|
166
|
+
return (table.value_count_worst_case + batch_count) <= table.value_count_max;
|
|
156
167
|
}
|
|
157
168
|
|
|
158
169
|
pub fn clear(table: *TableMutable) void {
|
|
159
170
|
assert(table.values.count() > 0);
|
|
171
|
+
table.value_count_worst_case = 0;
|
|
160
172
|
table.values.clearRetainingCapacity();
|
|
161
173
|
assert(table.values.count() == 0);
|
|
162
174
|
}
|
|
@@ -10,7 +10,7 @@ const log = std.log.scoped(.tree);
|
|
|
10
10
|
const tracer = @import("../tracer.zig");
|
|
11
11
|
|
|
12
12
|
const constants = @import("../constants.zig");
|
|
13
|
-
const div_ceil = @import("../
|
|
13
|
+
const div_ceil = @import("../stdx.zig").div_ceil;
|
|
14
14
|
const eytzinger = @import("eytzinger.zig").eytzinger;
|
|
15
15
|
const vsr = @import("../vsr.zig");
|
|
16
16
|
const bloom_filter = @import("bloom_filter.zig");
|
|
@@ -145,6 +145,7 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
145
145
|
|
|
146
146
|
compaction_io_pending: usize,
|
|
147
147
|
compaction_callback: ?fn (*Tree) void,
|
|
148
|
+
compaction_next_tick: Grid.NextTick = undefined,
|
|
148
149
|
|
|
149
150
|
checkpoint_callback: ?fn (*Tree) void,
|
|
150
151
|
open_callback: ?fn (*Tree) void,
|
|
@@ -336,7 +337,8 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
336
337
|
}
|
|
337
338
|
|
|
338
339
|
if (index_block_count == 0) {
|
|
339
|
-
callback
|
|
340
|
+
context.callback = callback;
|
|
341
|
+
tree.grid.on_next_tick(lookup_invalid_tick_callback, &context.next_tick);
|
|
340
342
|
return;
|
|
341
343
|
}
|
|
342
344
|
|
|
@@ -346,6 +348,7 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
346
348
|
context.* = .{
|
|
347
349
|
.tree = tree,
|
|
348
350
|
.completion = undefined,
|
|
351
|
+
.next_tick = undefined,
|
|
349
352
|
|
|
350
353
|
.key = key,
|
|
351
354
|
.fingerprint = fingerprint,
|
|
@@ -360,12 +363,18 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
360
363
|
context.read_index_block();
|
|
361
364
|
}
|
|
362
365
|
|
|
366
|
+
fn lookup_invalid_tick_callback(next_tick: *Grid.NextTick) void {
|
|
367
|
+
const context = @fieldParentPtr(LookupContext, "next_tick", next_tick);
|
|
368
|
+
context.callback(context, null);
|
|
369
|
+
}
|
|
370
|
+
|
|
363
371
|
pub const LookupContext = struct {
|
|
364
372
|
const Read = Grid.Read;
|
|
365
373
|
const BlockPtrConst = Grid.BlockPtrConst;
|
|
366
374
|
|
|
367
375
|
tree: *Tree,
|
|
368
376
|
completion: Read,
|
|
377
|
+
next_tick: Grid.NextTick,
|
|
369
378
|
|
|
370
379
|
key: Key,
|
|
371
380
|
fingerprint: bloom_filter.Fingerprint,
|
|
@@ -560,8 +569,8 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
560
569
|
tree.compact_mutable_table_into_immutable();
|
|
561
570
|
}
|
|
562
571
|
|
|
563
|
-
|
|
564
|
-
|
|
572
|
+
tree.compaction_callback = callback;
|
|
573
|
+
tree.grid.on_next_tick(compact_skip_tick_callback, &tree.compaction_next_tick);
|
|
565
574
|
return;
|
|
566
575
|
}
|
|
567
576
|
|
|
@@ -589,6 +598,13 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
589
598
|
tree.compact_drive();
|
|
590
599
|
}
|
|
591
600
|
|
|
601
|
+
fn compact_skip_tick_callback(next_tick: *Grid.NextTick) void {
|
|
602
|
+
const tree = @fieldParentPtr(Tree, "compaction_next_tick", next_tick);
|
|
603
|
+
const callback = tree.compaction_callback.?;
|
|
604
|
+
tree.compaction_callback = null;
|
|
605
|
+
callback(tree);
|
|
606
|
+
}
|
|
607
|
+
|
|
592
608
|
fn compact_start(tree: *Tree, callback: fn (*Tree) void) void {
|
|
593
609
|
assert(tree.compaction_io_pending == 0);
|
|
594
610
|
assert(tree.compaction_callback == null);
|
|
@@ -858,7 +874,7 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
858
874
|
// We are at the end of a half-bar, but the compactions have not finished.
|
|
859
875
|
// We keep ticking them until they finish.
|
|
860
876
|
log.debug(tree_name ++ ": compact_done: driving outstanding compactions", .{});
|
|
861
|
-
tree.
|
|
877
|
+
tree.grid.on_next_tick(compact_drive_tick_callback, &tree.compaction_next_tick);
|
|
862
878
|
return;
|
|
863
879
|
}
|
|
864
880
|
|
|
@@ -936,6 +952,16 @@ pub fn TreeType(comptime TreeTable: type, comptime Storage: type, comptime tree_
|
|
|
936
952
|
tree.manifest.compact(compact_manifest_callback);
|
|
937
953
|
}
|
|
938
954
|
|
|
955
|
+
/// Asynchronously continue to drive the compactions when they haven't finished at the time
|
|
956
|
+
/// they were supposed to at the end of a half-bar.
|
|
957
|
+
fn compact_drive_tick_callback(next_tick: *Grid.NextTick) void {
|
|
958
|
+
const tree = @fieldParentPtr(Tree, "compaction_next_tick", next_tick);
|
|
959
|
+
assert(tree.compaction_io_pending == 0);
|
|
960
|
+
assert(tree.compaction_callback != null);
|
|
961
|
+
assert(tree.compaction_op == tree.lookup_snapshot_max);
|
|
962
|
+
tree.compact_drive();
|
|
963
|
+
}
|
|
964
|
+
|
|
939
965
|
/// Called after the last beat of a full compaction bar.
|
|
940
966
|
fn compact_mutable_table_into_immutable(tree: *Tree) void {
|
|
941
967
|
assert(tree.table_immutable.free);
|