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.
- package/dist/bin/aarch64-linux-gnu/client.node +0 -0
- package/dist/bin/aarch64-linux-musl/client.node +0 -0
- package/dist/bin/aarch64-macos/client.node +0 -0
- package/dist/bin/x86_64-linux-gnu/client.node +0 -0
- package/dist/bin/x86_64-linux-musl/client.node +0 -0
- package/dist/bin/x86_64-macos/client.node +0 -0
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/package-lock.json +66 -0
- package/package.json +6 -16
- package/src/index.ts +56 -1
- package/src/node.zig +9 -9
- package/dist/.client.node.sha256 +0 -1
- package/scripts/build_lib.sh +0 -61
- package/scripts/download_node_headers.sh +0 -32
- package/src/tigerbeetle/scripts/benchmark.bat +0 -55
- package/src/tigerbeetle/scripts/benchmark.sh +0 -66
- package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
- package/src/tigerbeetle/scripts/fail_on_diff.sh +0 -9
- package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
- package/src/tigerbeetle/scripts/fuzz_loop_hash_log.sh +0 -12
- package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
- package/src/tigerbeetle/scripts/install.bat +0 -7
- package/src/tigerbeetle/scripts/install.sh +0 -21
- package/src/tigerbeetle/scripts/install_zig.bat +0 -113
- package/src/tigerbeetle/scripts/install_zig.sh +0 -90
- package/src/tigerbeetle/scripts/lint.zig +0 -199
- package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -55
- package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
- package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
- package/src/tigerbeetle/scripts/scripts/fail_on_diff.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
- package/src/tigerbeetle/scripts/scripts/fuzz_loop_hash_log.sh +0 -12
- package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
- package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
- package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
- package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
- package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
- package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
- package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
- package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
- package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
- package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
- package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
- package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
- package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
- package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
- package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
- package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
- package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
- package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
- package/src/tigerbeetle/src/benchmark.zig +0 -336
- package/src/tigerbeetle/src/config.zig +0 -233
- package/src/tigerbeetle/src/constants.zig +0 -428
- package/src/tigerbeetle/src/ewah.zig +0 -286
- package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
- package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
- package/src/tigerbeetle/src/fifo.zig +0 -120
- package/src/tigerbeetle/src/io/benchmark.zig +0 -213
- package/src/tigerbeetle/src/io/darwin.zig +0 -814
- package/src/tigerbeetle/src/io/linux.zig +0 -1071
- package/src/tigerbeetle/src/io/test.zig +0 -643
- package/src/tigerbeetle/src/io/windows.zig +0 -1183
- package/src/tigerbeetle/src/io.zig +0 -34
- package/src/tigerbeetle/src/iops.zig +0 -107
- package/src/tigerbeetle/src/lsm/README.md +0 -308
- package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
- package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
- package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
- package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
- package/src/tigerbeetle/src/lsm/direction.zig +0 -11
- package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
- package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
- package/src/tigerbeetle/src/lsm/forest.zig +0 -205
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -450
- package/src/tigerbeetle/src/lsm/grid.zig +0 -573
- package/src/tigerbeetle/src/lsm/groove.zig +0 -1036
- package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
- package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
- package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
- package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -878
- package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
- package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
- package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
- package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
- package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -381
- package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1329
- package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
- package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
- package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
- package/src/tigerbeetle/src/lsm/table.zig +0 -1009
- package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -192
- package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
- package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -203
- package/src/tigerbeetle/src/lsm/test.zig +0 -439
- package/src/tigerbeetle/src/lsm/tree.zig +0 -1169
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -479
- package/src/tigerbeetle/src/message_bus.zig +0 -1013
- package/src/tigerbeetle/src/message_pool.zig +0 -156
- package/src/tigerbeetle/src/ring_buffer.zig +0 -399
- package/src/tigerbeetle/src/simulator.zig +0 -580
- package/src/tigerbeetle/src/state_machine/auditor.zig +0 -578
- package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
- package/src/tigerbeetle/src/state_machine.zig +0 -2099
- package/src/tigerbeetle/src/static_allocator.zig +0 -65
- package/src/tigerbeetle/src/stdx.zig +0 -171
- package/src/tigerbeetle/src/storage.zig +0 -393
- package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
- package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
- package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
- package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
- package/src/tigerbeetle/src/testing/cluster.zig +0 -444
- package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
- package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
- package/src/tigerbeetle/src/testing/id.zig +0 -99
- package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -374
- package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
- package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
- package/src/tigerbeetle/src/testing/state_machine.zig +0 -250
- package/src/tigerbeetle/src/testing/storage.zig +0 -757
- package/src/tigerbeetle/src/testing/table.zig +0 -247
- package/src/tigerbeetle/src/testing/time.zig +0 -84
- package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
- package/src/tigerbeetle/src/time.zig +0 -112
- package/src/tigerbeetle/src/tracer.zig +0 -529
- package/src/tigerbeetle/src/unit_tests.zig +0 -40
- package/src/tigerbeetle/src/vopr.zig +0 -495
- package/src/tigerbeetle/src/vsr/README.md +0 -209
- package/src/tigerbeetle/src/vsr/client.zig +0 -544
- package/src/tigerbeetle/src/vsr/clock.zig +0 -855
- package/src/tigerbeetle/src/vsr/journal.zig +0 -2415
- package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
- package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
- package/src/tigerbeetle/src/vsr/replica.zig +0 -6616
- package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
- package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
- package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
- package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
- package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
- package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
- package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
- package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
- package/src/tigerbeetle/src/vsr.zig +0 -1425
|
@@ -1,381 +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
|
-
|
|
9
|
-
const TableType = @import("table.zig").TableType;
|
|
10
|
-
const TreeType = @import("tree.zig").TreeType;
|
|
11
|
-
const GridType = @import("grid.zig").GridType;
|
|
12
|
-
const NodePool = @import("node_pool.zig").NodePool(constants.lsm_manifest_node_size, 16);
|
|
13
|
-
|
|
14
|
-
const snapshot_latest = @import("tree.zig").snapshot_latest;
|
|
15
|
-
const compaction_snapshot_for_op = @import("tree.zig").compaction_snapshot_for_op;
|
|
16
|
-
|
|
17
|
-
/// This type wraps a single LSM tree in the API needed to integrate it with the Forest.
|
|
18
|
-
/// TigerBeetle's state machine requires a map from u128 ID to posted boolean for transfers
|
|
19
|
-
/// and this type implements that.
|
|
20
|
-
/// TODO Make the LSM Forest library flexible enough to be able to get rid of this special case.
|
|
21
|
-
pub fn PostedGrooveType(comptime Storage: type, value_count_max: usize) type {
|
|
22
|
-
return struct {
|
|
23
|
-
const PostedGroove = @This();
|
|
24
|
-
|
|
25
|
-
const Value = extern struct {
|
|
26
|
-
id: u128,
|
|
27
|
-
data: enum(u8) {
|
|
28
|
-
posted,
|
|
29
|
-
voided,
|
|
30
|
-
tombstone,
|
|
31
|
-
},
|
|
32
|
-
padding: [15]u8 = [_]u8{0} ** 15,
|
|
33
|
-
|
|
34
|
-
comptime {
|
|
35
|
-
// Assert that there is no implicit padding.
|
|
36
|
-
assert(@sizeOf(Value) == 32);
|
|
37
|
-
assert(@bitSizeOf(Value) == 32 * 8);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
inline fn compare_keys(a: u128, b: u128) math.Order {
|
|
41
|
-
return math.order(a, b);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
inline fn key_from_value(value: *const Value) u128 {
|
|
45
|
-
return value.id;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const sentinel_key = math.maxInt(u128);
|
|
49
|
-
|
|
50
|
-
inline fn tombstone(value: *const Value) bool {
|
|
51
|
-
return value.data == .tombstone;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
inline fn tombstone_from_key(id: u128) Value {
|
|
55
|
-
return .{
|
|
56
|
-
.id = id,
|
|
57
|
-
.data = .tombstone,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const Table = TableType(
|
|
63
|
-
u128,
|
|
64
|
-
Value,
|
|
65
|
-
Value.compare_keys,
|
|
66
|
-
Value.key_from_value,
|
|
67
|
-
Value.sentinel_key,
|
|
68
|
-
Value.tombstone,
|
|
69
|
-
Value.tombstone_from_key,
|
|
70
|
-
value_count_max,
|
|
71
|
-
.general,
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const Tree = TreeType(Table, Storage, "posted_groove");
|
|
75
|
-
const Grid = GridType(Storage);
|
|
76
|
-
|
|
77
|
-
const PrefetchIDs = std.AutoHashMapUnmanaged(u128, void);
|
|
78
|
-
const PrefetchObjects = std.AutoHashMapUnmanaged(u128, bool); // true:posted, false:voided
|
|
79
|
-
|
|
80
|
-
tree: Tree,
|
|
81
|
-
|
|
82
|
-
/// Object IDs enqueued to be prefetched.
|
|
83
|
-
/// Prefetching ensures that point lookups against the latest snapshot are synchronous.
|
|
84
|
-
/// This shields state machine implementations from the challenges of concurrency and I/O,
|
|
85
|
-
/// and enables simple state machine function signatures that commit writes atomically.
|
|
86
|
-
prefetch_ids: PrefetchIDs,
|
|
87
|
-
|
|
88
|
-
/// The prefetched Objects. This hash map holds the subset of objects in the LSM tree
|
|
89
|
-
/// that are required for the current commit. All get()/put()/remove() operations during
|
|
90
|
-
/// the commit are both passed to the LSM trees and mirrored in this hash map. It is always
|
|
91
|
-
/// sufficient to query this hashmap alone to know the state of the LSM trees.
|
|
92
|
-
prefetch_objects: PrefetchObjects,
|
|
93
|
-
|
|
94
|
-
/// The snapshot to prefetch from.
|
|
95
|
-
prefetch_snapshot: ?u64,
|
|
96
|
-
|
|
97
|
-
/// This field is necessary to expose the same open()/compact()/checkpoint() function
|
|
98
|
-
/// signatures as the real Groove type.
|
|
99
|
-
callback: ?fn (*PostedGroove) void = null,
|
|
100
|
-
|
|
101
|
-
/// See comments for Groove.Options.
|
|
102
|
-
pub const Options = struct {
|
|
103
|
-
cache_entries_max: u32,
|
|
104
|
-
prefetch_entries_max: u32,
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
pub fn init(
|
|
108
|
-
allocator: mem.Allocator,
|
|
109
|
-
node_pool: *NodePool,
|
|
110
|
-
grid: *Grid,
|
|
111
|
-
options: Options,
|
|
112
|
-
) !PostedGroove {
|
|
113
|
-
var tree = try Tree.init(
|
|
114
|
-
allocator,
|
|
115
|
-
node_pool,
|
|
116
|
-
grid,
|
|
117
|
-
.{
|
|
118
|
-
.cache_entries_max = options.cache_entries_max,
|
|
119
|
-
},
|
|
120
|
-
);
|
|
121
|
-
errdefer tree.deinit(allocator);
|
|
122
|
-
|
|
123
|
-
var prefetch_ids = PrefetchIDs{};
|
|
124
|
-
try prefetch_ids.ensureTotalCapacity(allocator, options.prefetch_entries_max);
|
|
125
|
-
errdefer prefetch_ids.deinit(allocator);
|
|
126
|
-
|
|
127
|
-
var prefetch_objects = PrefetchObjects{};
|
|
128
|
-
try prefetch_objects.ensureTotalCapacity(allocator, options.prefetch_entries_max);
|
|
129
|
-
errdefer prefetch_objects.deinit(allocator);
|
|
130
|
-
|
|
131
|
-
return PostedGroove{
|
|
132
|
-
.tree = tree,
|
|
133
|
-
|
|
134
|
-
.prefetch_ids = prefetch_ids,
|
|
135
|
-
.prefetch_objects = prefetch_objects,
|
|
136
|
-
.prefetch_snapshot = null,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
pub fn deinit(groove: *PostedGroove, allocator: mem.Allocator) void {
|
|
141
|
-
groove.tree.deinit(allocator);
|
|
142
|
-
|
|
143
|
-
groove.prefetch_ids.deinit(allocator);
|
|
144
|
-
groove.prefetch_objects.deinit(allocator);
|
|
145
|
-
|
|
146
|
-
groove.* = undefined;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
pub fn get(groove: *const PostedGroove, id: u128) ?bool {
|
|
150
|
-
return groove.prefetch_objects.get(id);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/// Must be called directly before the state machine begins queuing ids for prefetch.
|
|
154
|
-
/// When `snapshot` is null, prefetch from the current snapshot.
|
|
155
|
-
pub fn prefetch_setup(groove: *PostedGroove, snapshot: ?u64) void {
|
|
156
|
-
// We may query the input tables of an ongoing compaction, but must not query the
|
|
157
|
-
// output tables until the compaction is complete. (Until then, the output tables may
|
|
158
|
-
// be in the manifest but not yet on disk).
|
|
159
|
-
const snapshot_max = groove.tree.lookup_snapshot_max;
|
|
160
|
-
const snapshot_target = snapshot orelse snapshot_max;
|
|
161
|
-
assert(snapshot_target <= snapshot_max);
|
|
162
|
-
|
|
163
|
-
if (groove.prefetch_snapshot == null) {
|
|
164
|
-
groove.prefetch_objects.clearRetainingCapacity();
|
|
165
|
-
} else {
|
|
166
|
-
// If there is a snapshot already set from the previous prefetch_setup(), then its
|
|
167
|
-
// prefetch() was never called, so there must already be no queued objects or ids.
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
groove.prefetch_snapshot = snapshot_target;
|
|
171
|
-
assert(groove.prefetch_objects.count() == 0);
|
|
172
|
-
assert(groove.prefetch_ids.count() == 0);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/// This must be called by the state machine for every key to be prefetched.
|
|
176
|
-
/// We tolerate duplicate IDs enqueued by the state machine.
|
|
177
|
-
/// For example, if all unique operations require the same two dependencies.
|
|
178
|
-
pub fn prefetch_enqueue(groove: *PostedGroove, id: u128) void {
|
|
179
|
-
if (groove.tree.lookup_from_memory(groove.prefetch_snapshot.?, id)) |value| {
|
|
180
|
-
assert(value.id == id);
|
|
181
|
-
switch (value.data) {
|
|
182
|
-
.posted => groove.prefetch_objects.putAssumeCapacity(value.id, true),
|
|
183
|
-
.voided => groove.prefetch_objects.putAssumeCapacity(value.id, false),
|
|
184
|
-
.tombstone => {}, // Leave the ID out of prefetch_objects.
|
|
185
|
-
}
|
|
186
|
-
} else {
|
|
187
|
-
groove.prefetch_ids.putAssumeCapacity(id, {});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/// Ensure the objects corresponding to all ids enqueued with prefetch_enqueue() are
|
|
192
|
-
/// available in `prefetch_objects`.
|
|
193
|
-
pub fn prefetch(
|
|
194
|
-
groove: *PostedGroove,
|
|
195
|
-
callback: fn (*PrefetchContext) void,
|
|
196
|
-
context: *PrefetchContext,
|
|
197
|
-
) void {
|
|
198
|
-
context.* = .{
|
|
199
|
-
.groove = groove,
|
|
200
|
-
.callback = callback,
|
|
201
|
-
.snapshot = groove.prefetch_snapshot.?,
|
|
202
|
-
.id_iterator = groove.prefetch_ids.keyIterator(),
|
|
203
|
-
};
|
|
204
|
-
groove.prefetch_snapshot = null;
|
|
205
|
-
context.start_workers();
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
pub const PrefetchContext = struct {
|
|
209
|
-
groove: *PostedGroove,
|
|
210
|
-
callback: fn (*PrefetchContext) void,
|
|
211
|
-
snapshot: u64,
|
|
212
|
-
|
|
213
|
-
id_iterator: PrefetchIDs.KeyIterator,
|
|
214
|
-
|
|
215
|
-
/// The goal is to fully utilize the disk I/O to ensure the prefetch completes as
|
|
216
|
-
/// quickly as possible, so we run multiple lookups in parallel based on the max
|
|
217
|
-
/// I/O depth of the Grid.
|
|
218
|
-
workers: [Grid.read_iops_max]PrefetchWorker = undefined,
|
|
219
|
-
/// The number of workers that are currently running in parallel.
|
|
220
|
-
workers_busy: u32 = 0,
|
|
221
|
-
|
|
222
|
-
fn start_workers(context: *PrefetchContext) void {
|
|
223
|
-
assert(context.workers_busy == 0);
|
|
224
|
-
|
|
225
|
-
// Track an extra "worker" that will finish after the loop.
|
|
226
|
-
//
|
|
227
|
-
// This prevents `context.finish()` from being called within the loop body when
|
|
228
|
-
// every worker finishes synchronously. `context.finish()` calls the user-provided
|
|
229
|
-
// callback which may re-use the memory of this `PrefetchContext`. However, we
|
|
230
|
-
// rely on `context` being well-defined for the loop condition.
|
|
231
|
-
context.workers_busy += 1;
|
|
232
|
-
|
|
233
|
-
for (context.workers) |*worker| {
|
|
234
|
-
worker.* = .{ .context = context };
|
|
235
|
-
context.workers_busy += 1;
|
|
236
|
-
worker.lookup_start_next();
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
assert(context.workers_busy >= 1);
|
|
240
|
-
context.worker_finished();
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
fn worker_finished(context: *PrefetchContext) void {
|
|
244
|
-
context.workers_busy -= 1;
|
|
245
|
-
if (context.workers_busy == 0) context.finish();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
fn finish(context: *PrefetchContext) void {
|
|
249
|
-
assert(context.workers_busy == 0);
|
|
250
|
-
|
|
251
|
-
assert(context.id_iterator.next() == null);
|
|
252
|
-
context.groove.prefetch_ids.clearRetainingCapacity();
|
|
253
|
-
assert(context.groove.prefetch_ids.count() == 0);
|
|
254
|
-
|
|
255
|
-
context.callback(context);
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
pub const PrefetchWorker = struct {
|
|
260
|
-
context: *PrefetchContext,
|
|
261
|
-
lookup_id: Tree.LookupContext = undefined,
|
|
262
|
-
|
|
263
|
-
/// Returns true if asynchronous I/O has been started.
|
|
264
|
-
/// Returns false if there are no more IDs to prefetch.
|
|
265
|
-
fn lookup_start_next(worker: *PrefetchWorker) void {
|
|
266
|
-
const id = worker.context.id_iterator.next() orelse {
|
|
267
|
-
worker.context.worker_finished();
|
|
268
|
-
return;
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
if (constants.verify) {
|
|
272
|
-
// This was checked in prefetch_enqueue().
|
|
273
|
-
assert(worker.context.groove.tree.lookup_from_memory(worker.context.snapshot, id.*) == null);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// If not in the LSM tree's cache, the object must be read from disk and added
|
|
277
|
-
// to the auxillary prefetch_objects hash map.
|
|
278
|
-
// TODO: this LSM tree function needlessly checks the LSM tree's cache a
|
|
279
|
-
// second time. Adding API to the LSM tree to avoid this may be worthwhile.
|
|
280
|
-
worker.context.groove.tree.lookup_from_levels(
|
|
281
|
-
lookup_id_callback,
|
|
282
|
-
&worker.lookup_id,
|
|
283
|
-
worker.context.snapshot,
|
|
284
|
-
id.*,
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
fn lookup_id_callback(
|
|
289
|
-
completion: *Tree.LookupContext,
|
|
290
|
-
result: ?*const Value,
|
|
291
|
-
) void {
|
|
292
|
-
const worker = @fieldParentPtr(PrefetchWorker, "lookup_id", completion);
|
|
293
|
-
const groove = worker.context.groove;
|
|
294
|
-
|
|
295
|
-
if (result) |value| {
|
|
296
|
-
switch (value.data) {
|
|
297
|
-
.posted => {
|
|
298
|
-
groove.prefetch_objects.putAssumeCapacityNoClobber(value.id, true);
|
|
299
|
-
},
|
|
300
|
-
.voided => {
|
|
301
|
-
groove.prefetch_objects.putAssumeCapacityNoClobber(value.id, false);
|
|
302
|
-
},
|
|
303
|
-
.tombstone => {
|
|
304
|
-
// Leave the ID out of prefetch_objects.
|
|
305
|
-
},
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
worker.lookup_start_next();
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
pub fn put_no_clobber(groove: *PostedGroove, id: u128, posted: bool) void {
|
|
313
|
-
const gop = groove.prefetch_objects.getOrPutAssumeCapacity(id);
|
|
314
|
-
assert(!gop.found_existing);
|
|
315
|
-
|
|
316
|
-
const value: Value = .{
|
|
317
|
-
.id = id,
|
|
318
|
-
.data = if (posted) .posted else .voided,
|
|
319
|
-
};
|
|
320
|
-
groove.tree.put(&value);
|
|
321
|
-
gop.value_ptr.* = posted;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
pub fn remove(groove: *PostedGroove, id: u128) void {
|
|
325
|
-
assert(groove.prefetch_objects.remove(id));
|
|
326
|
-
groove.tree.remove(&Value{ .id = id, .data = .tombstone });
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
fn tree_callback(tree: *Tree) void {
|
|
330
|
-
const groove = @fieldParentPtr(PostedGroove, "tree", tree);
|
|
331
|
-
const callback = groove.callback.?;
|
|
332
|
-
groove.callback = null;
|
|
333
|
-
callback(groove);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
pub fn open(groove: *PostedGroove, callback: fn (*PostedGroove) void) void {
|
|
337
|
-
assert(groove.callback == null);
|
|
338
|
-
groove.callback = callback;
|
|
339
|
-
groove.tree.open(tree_callback);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
pub fn compact(groove: *PostedGroove, callback: fn (*PostedGroove) void, op: u64) void {
|
|
343
|
-
assert(groove.callback == null);
|
|
344
|
-
groove.callback = callback;
|
|
345
|
-
groove.tree.compact(tree_callback, op);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
pub fn checkpoint(groove: *PostedGroove, callback: fn (*PostedGroove) void) void {
|
|
349
|
-
assert(groove.callback == null);
|
|
350
|
-
groove.callback = callback;
|
|
351
|
-
groove.tree.checkpoint(tree_callback);
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
test "PostedGroove" {
|
|
357
|
-
const Storage = @import("../storage.zig").Storage;
|
|
358
|
-
|
|
359
|
-
const PostedGroove = PostedGrooveType(
|
|
360
|
-
Storage,
|
|
361
|
-
// Doesn't matter for this test.
|
|
362
|
-
1,
|
|
363
|
-
);
|
|
364
|
-
|
|
365
|
-
_ = PostedGroove.init;
|
|
366
|
-
_ = PostedGroove.deinit;
|
|
367
|
-
|
|
368
|
-
_ = PostedGroove.get;
|
|
369
|
-
_ = PostedGroove.put_no_clobber;
|
|
370
|
-
_ = PostedGroove.remove;
|
|
371
|
-
|
|
372
|
-
_ = PostedGroove.compact;
|
|
373
|
-
_ = PostedGroove.checkpoint;
|
|
374
|
-
|
|
375
|
-
_ = PostedGroove.prefetch_enqueue;
|
|
376
|
-
_ = PostedGroove.prefetch;
|
|
377
|
-
_ = PostedGroove.prefetch_setup;
|
|
378
|
-
|
|
379
|
-
std.testing.refAllDecls(PostedGroove.PrefetchWorker);
|
|
380
|
-
std.testing.refAllDecls(PostedGroove.PrefetchContext);
|
|
381
|
-
}
|