tigerbeetle-node 0.11.13 → 0.12.1
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/README.md +5 -10
- 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,450 +0,0 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
const testing = std.testing;
|
|
3
|
-
const allocator = testing.allocator;
|
|
4
|
-
const assert = std.debug.assert;
|
|
5
|
-
|
|
6
|
-
const constants = @import("../constants.zig");
|
|
7
|
-
const fuzz = @import("../testing/fuzz.zig");
|
|
8
|
-
const vsr = @import("../vsr.zig");
|
|
9
|
-
|
|
10
|
-
const log = std.log.scoped(.lsm_forest_fuzz);
|
|
11
|
-
const tracer = @import("../tracer.zig");
|
|
12
|
-
|
|
13
|
-
const MessagePool = @import("../message_pool.zig").MessagePool;
|
|
14
|
-
const Transfer = @import("../tigerbeetle.zig").Transfer;
|
|
15
|
-
const Account = @import("../tigerbeetle.zig").Account;
|
|
16
|
-
const Storage = @import("../testing/storage.zig").Storage;
|
|
17
|
-
const StateMachine = @import("../state_machine.zig").StateMachineType(Storage, .{
|
|
18
|
-
.message_body_size_max = constants.message_body_size_max,
|
|
19
|
-
.lsm_batch_multiple = constants.lsm_batch_multiple,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const GridType = @import("grid.zig").GridType;
|
|
23
|
-
const GrooveType = @import("groove.zig").GrooveType;
|
|
24
|
-
const Forest = StateMachine.Forest;
|
|
25
|
-
|
|
26
|
-
const Grid = GridType(Storage);
|
|
27
|
-
const SuperBlock = vsr.SuperBlockType(Storage);
|
|
28
|
-
|
|
29
|
-
pub const tigerbeetle_config = @import("../config.zig").configs.test_min;
|
|
30
|
-
|
|
31
|
-
const FuzzOp = union(enum) {
|
|
32
|
-
// TODO Test secondary index lookups and range queries.
|
|
33
|
-
compact: struct {
|
|
34
|
-
op: u64,
|
|
35
|
-
checkpoint: bool,
|
|
36
|
-
},
|
|
37
|
-
put_account: Account,
|
|
38
|
-
get_account: u128,
|
|
39
|
-
};
|
|
40
|
-
const FuzzOpTag = std.meta.Tag(FuzzOp);
|
|
41
|
-
|
|
42
|
-
const Environment = struct {
|
|
43
|
-
const cluster = 32;
|
|
44
|
-
const replica = 4;
|
|
45
|
-
|
|
46
|
-
const node_count = 1024;
|
|
47
|
-
// This is the smallest size that set_associative_cache will allow us.
|
|
48
|
-
const cache_entries_max = 2048;
|
|
49
|
-
const forest_options = StateMachine.forest_options(.{
|
|
50
|
-
.lsm_forest_node_count = node_count,
|
|
51
|
-
.cache_entries_accounts = cache_entries_max,
|
|
52
|
-
.cache_entries_transfers = cache_entries_max,
|
|
53
|
-
.cache_entries_posted = cache_entries_max,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// We must call compact after every 'batch'.
|
|
57
|
-
// Every `lsm_batch_multiple` batches may put/remove `value_count_max` values per index.
|
|
58
|
-
// Every `FuzzOp.put_account` issues one remove and one put per index.
|
|
59
|
-
const puts_since_compact_max = @divTrunc(
|
|
60
|
-
Forest.groove_config.accounts_mutable.ObjectTree.Table.value_count_max,
|
|
61
|
-
2 * constants.lsm_batch_multiple,
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const compacts_per_checkpoint = std.math.divCeil(
|
|
65
|
-
usize,
|
|
66
|
-
constants.journal_slot_count,
|
|
67
|
-
constants.lsm_batch_multiple,
|
|
68
|
-
) catch unreachable;
|
|
69
|
-
|
|
70
|
-
const State = enum {
|
|
71
|
-
init,
|
|
72
|
-
superblock_format,
|
|
73
|
-
superblock_open,
|
|
74
|
-
forest_init,
|
|
75
|
-
forest_open,
|
|
76
|
-
fuzzing,
|
|
77
|
-
forest_compact,
|
|
78
|
-
forest_checkpoint,
|
|
79
|
-
superblock_checkpoint,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
state: State,
|
|
83
|
-
storage: *Storage,
|
|
84
|
-
message_pool: MessagePool,
|
|
85
|
-
superblock: SuperBlock,
|
|
86
|
-
superblock_context: SuperBlock.Context,
|
|
87
|
-
grid: Grid,
|
|
88
|
-
forest: Forest,
|
|
89
|
-
checkpoint_op: ?u64,
|
|
90
|
-
|
|
91
|
-
pub fn run(storage: *Storage, fuzz_ops: []const FuzzOp) !void {
|
|
92
|
-
var env: Environment = undefined;
|
|
93
|
-
env.state = .init;
|
|
94
|
-
env.storage = storage;
|
|
95
|
-
|
|
96
|
-
env.message_pool = try MessagePool.init(allocator, .replica);
|
|
97
|
-
defer env.message_pool.deinit(allocator);
|
|
98
|
-
|
|
99
|
-
env.superblock = try SuperBlock.init(allocator, .{
|
|
100
|
-
.storage = env.storage,
|
|
101
|
-
.storage_size_limit = constants.storage_size_max,
|
|
102
|
-
.message_pool = &env.message_pool,
|
|
103
|
-
});
|
|
104
|
-
defer env.superblock.deinit(allocator);
|
|
105
|
-
|
|
106
|
-
env.grid = try Grid.init(allocator, &env.superblock);
|
|
107
|
-
defer env.grid.deinit(allocator);
|
|
108
|
-
|
|
109
|
-
env.forest = undefined;
|
|
110
|
-
env.checkpoint_op = null;
|
|
111
|
-
|
|
112
|
-
try env.open_then_apply(fuzz_ops);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
fn change_state(env: *Environment, current_state: State, next_state: State) void {
|
|
116
|
-
assert(env.state == current_state);
|
|
117
|
-
env.state = next_state;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
fn tick_until_state_change(env: *Environment, current_state: State, next_state: State) void {
|
|
121
|
-
// Sometimes operations complete synchronously so we might already be in next_state before ticking.
|
|
122
|
-
//assert(env.state == current_state or env.state == next_state);
|
|
123
|
-
while (env.state == current_state) env.storage.tick();
|
|
124
|
-
assert(env.state == next_state);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
pub fn open_then_apply(env: *Environment, fuzz_ops: []const FuzzOp) !void {
|
|
128
|
-
env.change_state(.init, .superblock_format);
|
|
129
|
-
env.superblock.format(superblock_format_callback, &env.superblock_context, .{
|
|
130
|
-
.cluster = cluster,
|
|
131
|
-
.replica = replica,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
env.tick_until_state_change(.superblock_format, .superblock_open);
|
|
135
|
-
env.superblock.open(superblock_open_callback, &env.superblock_context);
|
|
136
|
-
|
|
137
|
-
env.tick_until_state_change(.superblock_open, .forest_init);
|
|
138
|
-
env.forest = try Forest.init(allocator, &env.grid, node_count, forest_options);
|
|
139
|
-
defer env.forest.deinit(allocator);
|
|
140
|
-
|
|
141
|
-
env.change_state(.forest_init, .forest_open);
|
|
142
|
-
env.forest.open(forest_open_callback);
|
|
143
|
-
|
|
144
|
-
env.tick_until_state_change(.forest_open, .fuzzing);
|
|
145
|
-
try env.apply(fuzz_ops);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
fn superblock_format_callback(superblock_context: *SuperBlock.Context) void {
|
|
149
|
-
const env = @fieldParentPtr(@This(), "superblock_context", superblock_context);
|
|
150
|
-
env.change_state(.superblock_format, .superblock_open);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
fn superblock_open_callback(superblock_context: *SuperBlock.Context) void {
|
|
154
|
-
const env = @fieldParentPtr(@This(), "superblock_context", superblock_context);
|
|
155
|
-
env.change_state(.superblock_open, .forest_init);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
fn forest_open_callback(forest: *Forest) void {
|
|
159
|
-
const env = @fieldParentPtr(@This(), "forest", forest);
|
|
160
|
-
env.change_state(.forest_open, .fuzzing);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
pub fn compact(env: *Environment, op: u64) void {
|
|
164
|
-
env.change_state(.fuzzing, .forest_compact);
|
|
165
|
-
env.forest.compact(forest_compact_callback, op);
|
|
166
|
-
env.tick_until_state_change(.forest_compact, .fuzzing);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
fn forest_compact_callback(forest: *Forest) void {
|
|
170
|
-
const env = @fieldParentPtr(@This(), "forest", forest);
|
|
171
|
-
env.change_state(.forest_compact, .fuzzing);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
pub fn checkpoint(env: *Environment, op: u64) void {
|
|
175
|
-
assert(env.checkpoint_op == null);
|
|
176
|
-
env.checkpoint_op = op - constants.lsm_batch_multiple;
|
|
177
|
-
|
|
178
|
-
env.change_state(.fuzzing, .forest_checkpoint);
|
|
179
|
-
env.forest.checkpoint(forest_checkpoint_callback);
|
|
180
|
-
env.tick_until_state_change(.forest_checkpoint, .superblock_checkpoint);
|
|
181
|
-
env.tick_until_state_change(.superblock_checkpoint, .fuzzing);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
fn forest_checkpoint_callback(forest: *Forest) void {
|
|
185
|
-
const env = @fieldParentPtr(@This(), "forest", forest);
|
|
186
|
-
const op = env.checkpoint_op.?;
|
|
187
|
-
env.checkpoint_op = null;
|
|
188
|
-
|
|
189
|
-
env.change_state(.forest_checkpoint, .superblock_checkpoint);
|
|
190
|
-
env.superblock.checkpoint(superblock_checkpoint_callback, &env.superblock_context, .{
|
|
191
|
-
.commit_min_checksum = env.superblock.working.vsr_state.commit_min_checksum + 1,
|
|
192
|
-
.commit_min = op,
|
|
193
|
-
.commit_max = op + 1,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
fn superblock_checkpoint_callback(superblock_context: *SuperBlock.Context) void {
|
|
198
|
-
const env = @fieldParentPtr(@This(), "superblock_context", superblock_context);
|
|
199
|
-
env.change_state(.superblock_checkpoint, .fuzzing);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
fn prefetch_account(env: *Environment, id: u128) void {
|
|
203
|
-
const groove_immutable = &env.forest.grooves.accounts_immutable;
|
|
204
|
-
const groove_mutable = &env.forest.grooves.accounts_mutable;
|
|
205
|
-
|
|
206
|
-
const GrooveImmutable = @TypeOf(groove_immutable.*);
|
|
207
|
-
const GrooveMutable = @TypeOf(groove_mutable.*);
|
|
208
|
-
const Getter = struct {
|
|
209
|
-
_id: u128,
|
|
210
|
-
_groove_mutable: *GrooveMutable,
|
|
211
|
-
_groove_immutable: *GrooveImmutable,
|
|
212
|
-
|
|
213
|
-
finished: bool = false,
|
|
214
|
-
prefetch_context_mutable: GrooveMutable.PrefetchContext = undefined,
|
|
215
|
-
prefetch_context_immutable: GrooveImmutable.PrefetchContext = undefined,
|
|
216
|
-
|
|
217
|
-
fn prefetch_start(getter: *@This()) void {
|
|
218
|
-
const groove = getter._groove_immutable;
|
|
219
|
-
groove.prefetch_setup(null);
|
|
220
|
-
groove.prefetch_enqueue(getter._id);
|
|
221
|
-
groove.prefetch(@This().prefetch_callback_immuttable, &getter.prefetch_context_immutable);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
fn prefetch_callback_immuttable(prefetch_context: *GrooveImmutable.PrefetchContext) void {
|
|
225
|
-
const getter = @fieldParentPtr(@This(), "prefetch_context_immutable", prefetch_context);
|
|
226
|
-
const groove = getter._groove_mutable;
|
|
227
|
-
groove.prefetch_setup(null);
|
|
228
|
-
|
|
229
|
-
if (getter._groove_immutable.get(getter._id)) |immut| {
|
|
230
|
-
groove.prefetch_enqueue(immut.timestamp);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
groove.prefetch(@This().prefetch_callback_mutable, &getter.prefetch_context_mutable);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
fn prefetch_callback_mutable(prefetch_context: *GrooveMutable.PrefetchContext) void {
|
|
237
|
-
const getter = @fieldParentPtr(@This(), "prefetch_context_mutable", prefetch_context);
|
|
238
|
-
assert(!getter.finished);
|
|
239
|
-
getter.finished = true;
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
var getter = Getter{
|
|
244
|
-
._id = id,
|
|
245
|
-
._groove_mutable = groove_mutable,
|
|
246
|
-
._groove_immutable = groove_immutable,
|
|
247
|
-
};
|
|
248
|
-
getter.prefetch_start();
|
|
249
|
-
while (!getter.finished) env.storage.tick();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
fn put_account(env: *Environment, a: *const Account) void {
|
|
253
|
-
env.forest.grooves.accounts_immutable.put(&StateMachine.AccountImmutable.from_account(a));
|
|
254
|
-
env.forest.grooves.accounts_mutable.put(&StateMachine.AccountMutable.from_account(a));
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
fn get_account(env: *Environment, id: u128) ?Account {
|
|
258
|
-
const immut = env.forest.grooves.accounts_immutable.get(id) orelse return null;
|
|
259
|
-
const mut = env.forest.grooves.accounts_mutable.get(immut.timestamp).?;
|
|
260
|
-
return StateMachine.into_account(immut, mut);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
fn apply(env: *Environment, fuzz_ops: []const FuzzOp) !void {
|
|
264
|
-
// The forest should behave like a simple key-value data-structure.
|
|
265
|
-
// We'll compare it to a hash map.
|
|
266
|
-
var model = std.hash_map.AutoHashMap(u128, Account).init(allocator);
|
|
267
|
-
defer model.deinit();
|
|
268
|
-
|
|
269
|
-
for (fuzz_ops) |fuzz_op, fuzz_op_index| {
|
|
270
|
-
assert(env.state == .fuzzing);
|
|
271
|
-
log.debug("Running fuzz_ops[{}/{}] == {}", .{ fuzz_op_index, fuzz_ops.len, fuzz_op });
|
|
272
|
-
|
|
273
|
-
const storage_size_used = env.storage.size_used();
|
|
274
|
-
log.debug("storage.size_used = {}/{}", .{ storage_size_used, env.storage.size });
|
|
275
|
-
|
|
276
|
-
const model_size = model.count() * @sizeOf(Account);
|
|
277
|
-
log.debug("space_amplification = {d:.2}", .{
|
|
278
|
-
@intToFloat(f64, storage_size_used) / @intToFloat(f64, model_size),
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// Apply fuzz_op to the forest and the model.
|
|
282
|
-
switch (fuzz_op) {
|
|
283
|
-
.compact => |compact| {
|
|
284
|
-
env.compact(compact.op);
|
|
285
|
-
if (compact.checkpoint) env.checkpoint(compact.op);
|
|
286
|
-
},
|
|
287
|
-
.put_account => |account| {
|
|
288
|
-
// The forest requires prefetch before put.
|
|
289
|
-
env.prefetch_account(account.id);
|
|
290
|
-
env.put_account(&account);
|
|
291
|
-
try model.put(account.id, account);
|
|
292
|
-
},
|
|
293
|
-
.get_account => |id| {
|
|
294
|
-
// Get account from lsm.
|
|
295
|
-
env.prefetch_account(id);
|
|
296
|
-
const lsm_account = env.get_account(id);
|
|
297
|
-
|
|
298
|
-
// Compare result to model.
|
|
299
|
-
const model_account = model.get(id);
|
|
300
|
-
if (model_account == null) {
|
|
301
|
-
assert(lsm_account == null);
|
|
302
|
-
} else {
|
|
303
|
-
assert(std.mem.eql(
|
|
304
|
-
u8,
|
|
305
|
-
std.mem.asBytes(&model_account.?),
|
|
306
|
-
std.mem.asBytes(&lsm_account.?),
|
|
307
|
-
));
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
pub fn run_fuzz_ops(storage_options: Storage.Options, fuzz_ops: []const FuzzOp) !void {
|
|
316
|
-
// Init mocked storage.
|
|
317
|
-
var storage = try Storage.init(allocator, constants.storage_size_max, storage_options);
|
|
318
|
-
defer storage.deinit(allocator);
|
|
319
|
-
|
|
320
|
-
try Environment.run(&storage, fuzz_ops);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
fn random_id(random: std.rand.Random, comptime Int: type) Int {
|
|
324
|
-
// We have two opposing desires for random ids:
|
|
325
|
-
const avg_int: Int = if (random.boolean())
|
|
326
|
-
// 1. We want to cause many collisions.
|
|
327
|
-
8
|
|
328
|
-
else
|
|
329
|
-
// 2. We want to generate enough ids that the cache can't hold them all.
|
|
330
|
-
Environment.cache_entries_max;
|
|
331
|
-
return fuzz.random_int_exponential(random, Int, avg_int);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
pub fn generate_fuzz_ops(random: std.rand.Random, fuzz_op_count: usize) ![]const FuzzOp {
|
|
335
|
-
log.info("fuzz_op_count = {}", .{fuzz_op_count});
|
|
336
|
-
|
|
337
|
-
const fuzz_ops = try allocator.alloc(FuzzOp, fuzz_op_count);
|
|
338
|
-
errdefer allocator.free(fuzz_ops);
|
|
339
|
-
|
|
340
|
-
var fuzz_op_distribution = fuzz.Distribution(FuzzOpTag){
|
|
341
|
-
// Maybe compact more often than forced to by `puts_since_compact`.
|
|
342
|
-
.compact = if (random.boolean()) 0 else 1,
|
|
343
|
-
// Always do puts, and always more puts than removes.
|
|
344
|
-
.put_account = constants.lsm_batch_multiple * 2,
|
|
345
|
-
// Maybe do some gets.
|
|
346
|
-
.get_account = if (random.boolean()) 0 else constants.lsm_batch_multiple,
|
|
347
|
-
};
|
|
348
|
-
log.info("fuzz_op_distribution = {d:.2}", .{fuzz_op_distribution});
|
|
349
|
-
|
|
350
|
-
log.info("puts_since_compact_max = {}", .{Environment.puts_since_compact_max});
|
|
351
|
-
log.info("compacts_per_checkpoint = {}", .{Environment.compacts_per_checkpoint});
|
|
352
|
-
|
|
353
|
-
var id_to_account = std.hash_map.AutoHashMap(u128, Account).init(allocator);
|
|
354
|
-
defer id_to_account.deinit();
|
|
355
|
-
|
|
356
|
-
var op: u64 = 1;
|
|
357
|
-
var puts_since_compact: usize = 0;
|
|
358
|
-
for (fuzz_ops) |*fuzz_op, fuzz_op_index| {
|
|
359
|
-
const fuzz_op_tag: FuzzOpTag = if (puts_since_compact >= Environment.puts_since_compact_max)
|
|
360
|
-
// We have to compact before doing any other operations.
|
|
361
|
-
.compact
|
|
362
|
-
else
|
|
363
|
-
// Otherwise pick a random FuzzOp.
|
|
364
|
-
fuzz.random_enum(random, FuzzOpTag, fuzz_op_distribution);
|
|
365
|
-
fuzz_op.* = switch (fuzz_op_tag) {
|
|
366
|
-
.compact => compact: {
|
|
367
|
-
const compact_op = op;
|
|
368
|
-
op += 1;
|
|
369
|
-
const checkpoint =
|
|
370
|
-
// Can only checkpoint on the last beat of the bar.
|
|
371
|
-
compact_op % constants.lsm_batch_multiple == constants.lsm_batch_multiple - 1 and
|
|
372
|
-
compact_op > constants.lsm_batch_multiple and
|
|
373
|
-
// Checkpoint at roughly the same rate as log wraparound.
|
|
374
|
-
random.uintLessThan(usize, Environment.compacts_per_checkpoint) == 0;
|
|
375
|
-
break :compact FuzzOp{
|
|
376
|
-
.compact = .{
|
|
377
|
-
.op = compact_op,
|
|
378
|
-
.checkpoint = checkpoint,
|
|
379
|
-
},
|
|
380
|
-
};
|
|
381
|
-
},
|
|
382
|
-
.put_account => put_account: {
|
|
383
|
-
const id = random_id(random, u128);
|
|
384
|
-
var account = id_to_account.get(id) orelse Account{
|
|
385
|
-
.id = id,
|
|
386
|
-
// `timestamp` must be unique.
|
|
387
|
-
.timestamp = fuzz_op_index,
|
|
388
|
-
.user_data = random_id(random, u128),
|
|
389
|
-
.reserved = [_]u8{0} ** 48,
|
|
390
|
-
.ledger = random_id(random, u32),
|
|
391
|
-
.code = random_id(random, u16),
|
|
392
|
-
.flags = .{
|
|
393
|
-
.debits_must_not_exceed_credits = random.boolean(),
|
|
394
|
-
.credits_must_not_exceed_debits = random.boolean(),
|
|
395
|
-
},
|
|
396
|
-
.debits_pending = 0,
|
|
397
|
-
.debits_posted = 0,
|
|
398
|
-
.credits_pending = 0,
|
|
399
|
-
.credits_posted = 0,
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
// These are the only fields we are allowed to change on existing accounts.
|
|
403
|
-
account.debits_pending = random.int(u64);
|
|
404
|
-
account.debits_posted = random.int(u64);
|
|
405
|
-
account.credits_pending = random.int(u64);
|
|
406
|
-
account.credits_posted = random.int(u64);
|
|
407
|
-
|
|
408
|
-
try id_to_account.put(account.id, account);
|
|
409
|
-
break :put_account FuzzOp{ .put_account = account };
|
|
410
|
-
},
|
|
411
|
-
.get_account => FuzzOp{
|
|
412
|
-
.get_account = random_id(random, u128),
|
|
413
|
-
},
|
|
414
|
-
};
|
|
415
|
-
switch (fuzz_op.*) {
|
|
416
|
-
.compact => puts_since_compact = 0,
|
|
417
|
-
.put_account => puts_since_compact += 1,
|
|
418
|
-
.get_account => {},
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
return fuzz_ops;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
pub fn main() !void {
|
|
426
|
-
try tracer.init(allocator);
|
|
427
|
-
defer tracer.deinit(allocator);
|
|
428
|
-
|
|
429
|
-
const fuzz_args = try fuzz.parse_fuzz_args(allocator);
|
|
430
|
-
var rng = std.rand.DefaultPrng.init(fuzz_args.seed);
|
|
431
|
-
const random = rng.random();
|
|
432
|
-
|
|
433
|
-
const fuzz_op_count = @minimum(
|
|
434
|
-
fuzz_args.events_max orelse @as(usize, 1E7),
|
|
435
|
-
fuzz.random_int_exponential(random, usize, 1E6),
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
const fuzz_ops = try generate_fuzz_ops(random, fuzz_op_count);
|
|
439
|
-
defer allocator.free(fuzz_ops);
|
|
440
|
-
|
|
441
|
-
try run_fuzz_ops(Storage.Options{
|
|
442
|
-
.seed = random.int(u64),
|
|
443
|
-
.read_latency_min = 0,
|
|
444
|
-
.read_latency_mean = 0 + fuzz.random_int_exponential(random, u64, 20),
|
|
445
|
-
.write_latency_min = 0,
|
|
446
|
-
.write_latency_mean = 0 + fuzz.random_int_exponential(random, u64, 20),
|
|
447
|
-
}, fuzz_ops);
|
|
448
|
-
|
|
449
|
-
log.info("Passed!", .{});
|
|
450
|
-
}
|