@@ -43,6 +43,11 @@ pub const TrackedAccount = struct {
43
43
44
44
pub const RunCmd = struct {
45
45
max_slots : ? Slot ,
46
+ non_sequential_slots : bool ,
47
+ index_allocation : ? IndexAllocation ,
48
+ enable_manager : bool ,
49
+
50
+ pub const IndexAllocation = enum { ram , disk };
46
51
47
52
pub const parser = cli .Parser (RunCmd , .{
48
53
.help = .{
@@ -58,10 +63,36 @@ pub const RunCmd = struct {
58
63
.config = {},
59
64
.help = "The number of slots number which, when surpassed, will exit the fuzzer." ,
60
65
},
66
+ .non_sequential_slots = .{
67
+ .kind = .named ,
68
+ .name_override = null ,
69
+ .alias = .none ,
70
+ .default_value = false ,
71
+ .config = {},
72
+ .help = "Enable non-sequential slots." ,
73
+ },
74
+ .index_allocation = .{
75
+ .kind = .named ,
76
+ .name_override = null ,
77
+ .alias = .none ,
78
+ .default_value = null ,
79
+ .config = {},
80
+ .help = "Whether to use ram or disk for index allocation. Defaults to a random value based on the seed." ,
81
+ },
82
+ .enable_manager = .{
83
+ .kind = .named ,
84
+ .name_override = null ,
85
+ .alias = .none ,
86
+ .default_value = false ,
87
+ .config = {},
88
+ .help = "Enable the accountsdb manager during fuzzer." ,
89
+ },
61
90
},
62
91
});
63
92
};
64
93
94
+ const Logger = sig .trace .Logger ("accountsdb.fuzz" );
95
+
65
96
pub fn run (seed : u64 , args : * std.process.ArgIterator ) ! void {
66
97
var prng_state : std.Random.DefaultPrng = .init (seed );
67
98
const random = prng_state .random ();
@@ -83,7 +114,7 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
83
114
.max_buffer = 1 << 20 ,
84
115
}, null );
85
116
defer std_logger .deinit ();
86
- const logger = std_logger .logger ("accountsdb.fuzz" );
117
+ const logger : Logger = std_logger .logger ("accountsdb.fuzz" );
87
118
88
119
const run_cmd : RunCmd = cmd : {
89
120
var argv_list : std .ArrayListUnmanaged ([]const u8 ) = .empty ;
@@ -102,6 +133,11 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
102
133
};
103
134
104
135
const maybe_max_slots = run_cmd .max_slots ;
136
+ const non_sequential_slots = run_cmd .non_sequential_slots ;
137
+ const enable_manager = run_cmd .enable_manager ;
138
+ const index_allocation =
139
+ run_cmd .index_allocation orelse
140
+ random .enumValue (RunCmd .IndexAllocation );
105
141
106
142
var fuzz_data_dir = try std .fs .cwd ().makeOpenPath (sig .FUZZ_DATA_DIR , .{});
107
143
defer fuzz_data_dir .close ();
@@ -126,18 +162,20 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
126
162
};
127
163
};
128
164
129
- var last_full_snapshot_validated_slot : Slot = 0 ;
130
- var last_inc_snapshot_validated_slot : Slot = 0 ;
165
+ logger .info ().logf ("enable manager: {}" , .{enable_manager });
166
+ logger .info ().logf ("index allocation: {s}" , .{@tagName (index_allocation )});
167
+ logger .info ().logf ("non-sequential slots: {}" , .{non_sequential_slots });
131
168
132
- const use_disk = random .boolean ();
133
- logger .info ().logf ("use disk: {}" , .{use_disk });
134
169
var accounts_db : AccountsDB = try .init (.{
135
170
.allocator = allocator ,
136
171
.logger = .from (logger ),
137
172
.snapshot_dir = main_accountsdb_dir ,
138
173
.geyser_writer = null ,
139
174
.gossip_view = null ,
140
- .index_allocation = if (use_disk ) .disk else .ram ,
175
+ .index_allocation = switch (index_allocation ) {
176
+ .ram = > .ram ,
177
+ .disk = > .disk ,
178
+ },
141
179
.number_of_index_shards = sig .accounts_db .db .ACCOUNT_INDEX_SHARDS ,
142
180
});
143
181
defer accounts_db .deinit ();
@@ -146,18 +184,13 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
146
184
try accounts_db .account_index .expandRefCapacity (1_000_000 );
147
185
148
186
var manager_exit : std .atomic .Value (bool ) = .init (false );
149
- const manager_handle : std.Thread = try .spawn (.{}, sig .accounts_db .manager .runLoop , .{
150
- & accounts_db , sig.accounts_db.manager.ManagerLoopConfig {
151
- .exit = & manager_exit ,
152
- .slots_per_full_snapshot = 50_000 ,
153
- .slots_per_incremental_snapshot = 5_000 ,
154
- .zstd_nb_workers = @intCast (std .Thread .getCpuCount () catch 0 ),
155
- },
187
+ var manager : sig.accounts_db.manager.Manager = try .init (allocator , & accounts_db , .{
188
+ .exit = & manager_exit ,
189
+ .slots_per_full_snapshot = 50_000 ,
190
+ .slots_per_incremental_snapshot = 5_000 ,
191
+ .zstd_nb_workers = @intCast (std .Thread .getCpuCount () catch 0 ),
156
192
});
157
- defer {
158
- manager_exit .store (true , .release );
159
- manager_handle .join ();
160
- }
193
+ defer manager .deinit (allocator );
161
194
162
195
var tracked_accounts_rw : sig .sync .RwMux (TrackedAccountsMap ) = .init (.empty );
163
196
defer {
@@ -185,32 +218,48 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
185
218
// any validation (in the .get block of the main fuzzer
186
219
// loop, we perform validation)
187
220
threads .appendAssumeCapacity (try .spawn (.{}, readRandomAccounts , .{
221
+ logger ,
188
222
& accounts_db ,
189
223
& tracked_accounts_rw ,
190
224
seed + thread_i ,
191
225
& reader_exit ,
192
226
thread_i ,
193
227
}));
194
- logger .debug ().logf ("started readRandomAccounts thread: {}" , .{thread_i });
195
228
}
196
229
230
+ var last_full_snapshot_validated_slot : Slot = 0 ;
231
+ var last_inc_snapshot_validated_slot : Slot = 0 ;
197
232
var largest_rooted_slot : Slot = 0 ;
198
- var slot : Slot = 0 ;
233
+ var top_slot : Slot = 0 ;
199
234
200
235
var ancestors : sig.core.Ancestors = .EMPTY ;
201
236
defer ancestors .deinit (allocator );
202
237
203
238
// get/put a bunch of accounts
204
239
while (true ) {
205
- if (maybe_max_slots ) | max_slots | if (slot >= max_slots ) {
240
+ if (maybe_max_slots ) | max_slots | if (top_slot >= max_slots ) {
206
241
logger .info ().logf ("reached max slots: {}" , .{max_slots });
207
242
break ;
208
243
};
209
- defer switch (random .int (u2 )) {
210
- 0 = > slot += random .intRangeAtMost (Slot , 1 , 2 ),
211
- 1 , 2 , 3 = > {},
244
+ const will_inc_slot = switch (random .int (u2 )) {
245
+ 0 = > true ,
246
+ 1 , 2 , 3 = > false ,
247
+ };
248
+ defer if (will_inc_slot ) {
249
+ top_slot += random .intRangeAtMost (Slot , 1 , 2 );
250
+ };
251
+ try ancestors .addSlot (allocator , top_slot );
252
+
253
+ const current_slot = if (! non_sequential_slots ) top_slot else slot : {
254
+ const ancestor_slots : []const Slot = ancestors .ancestors .keys ();
255
+ std .debug .assert (ancestor_slots [ancestor_slots .len - 1 ] == top_slot );
256
+ const ancestor_index = random .intRangeLessThan (
257
+ usize ,
258
+ ancestor_slots .len - | 10 ,
259
+ ancestor_slots .len ,
260
+ );
261
+ break :slot ancestor_slots [ancestor_index ];
212
262
};
213
- try ancestors .addSlot (allocator , slot );
214
263
215
264
const action = random .enumValue (enum { put , get });
216
265
switch (action ) {
@@ -222,7 +271,7 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
222
271
var pubkeys_this_slot : std .AutoHashMapUnmanaged (Pubkey , void ) = .empty ;
223
272
defer pubkeys_this_slot .deinit (allocator );
224
273
for (0.. N_ACCOUNTS_PER_SLOT ) | _ | {
225
- var tracked_account = TrackedAccount .initRandom (random , slot );
274
+ var tracked_account : TrackedAccount = .initRandom (random , current_slot );
226
275
227
276
const update_all_existing =
228
277
tracked_accounts .count () > N_ACCOUNTS_MAX ;
@@ -243,7 +292,7 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
243
292
244
293
const account_shared_data = try tracked_account .toAccount (allocator );
245
294
defer account_shared_data .deinit (allocator );
246
- try accounts_db .putAccount (slot , pubkey , account_shared_data );
295
+ try accounts_db .putAccount (current_slot , pubkey , account_shared_data );
247
296
248
297
// always overwrite the old slot
249
298
try tracked_accounts .put (allocator , pubkey , tracked_account );
@@ -281,7 +330,10 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
281
330
282
331
const account =
283
332
try accounts_db .getAccountWithAncestors (& pubkey , & ancestors_sub ) orelse {
284
- logger .err ().logf ("accounts_db missing tracked account '{}': {}" , .{ pubkey , tracked_account });
333
+ logger .err ().logf (
334
+ "accounts_db missing tracked account '{}': {}" ,
335
+ .{ pubkey , tracked_account },
336
+ );
285
337
return error .MissingAccount ;
286
338
};
287
339
defer account .deinit (allocator );
@@ -297,13 +349,15 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
297
349
},
298
350
}
299
351
300
- const create_new_root = random .boolean ();
301
- if (create_new_root ) {
302
- largest_rooted_slot = @min (slot , largest_rooted_slot + 2 );
352
+ const create_new_root =
353
+ enable_manager and
354
+ will_inc_slot and
355
+ random .int (u8 ) == 0 ;
356
+ if (create_new_root ) snapshot_validation : {
357
+ largest_rooted_slot = @min (top_slot , largest_rooted_slot + 2 );
303
358
accounts_db .largest_rooted_slot .store (largest_rooted_slot , .monotonic );
304
- }
359
+ try manager . manage ( allocator );
305
360
306
- snapshot_validation : {
307
361
// holding the lock here means that the snapshot archive(s) wont be deleted
308
362
// since deletion requires a write lock
309
363
const maybe_latest_snapshot_info , //
@@ -449,20 +503,21 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void {
449
503
}
450
504
451
505
fn readRandomAccounts (
506
+ logger : Logger ,
452
507
db : * AccountsDB ,
453
508
tracked_accounts_rw : * sig .sync .RwMux (TrackedAccountsMap ),
454
509
seed : u64 ,
455
510
exit : * std .atomic .Value (bool ),
456
511
thread_id : usize ,
457
512
) void {
458
- var prng = std .Random .DefaultPrng .init (seed );
513
+ logger .debug ().logf ("started readRandomAccounts thread: {}" , .{thread_id });
514
+ defer logger .debug ().logf ("finishing readRandomAccounts thread: {}" , .{thread_id });
515
+
516
+ var prng : std.Random.DefaultPrng = .init (seed );
459
517
const random = prng .random ();
460
518
461
519
while (true ) {
462
- if (exit .load (.seq_cst )) {
463
- std .debug .print ("finishing readRandomAccounts thread: {}\n " , .{thread_id });
464
- return ;
465
- }
520
+ if (exit .load (.seq_cst )) return ;
466
521
467
522
var pubkeys : [50 ]Pubkey = undefined ;
468
523
{
0 commit comments