Line data Source code
1 : /* The backtest command spawns a smaller topology for replaying shreds from
2 : rocksdb (or other sources TBD) and reproduce the behavior of replay tile.
3 :
4 : The smaller topology is:
5 : shred_out replay_exec
6 : backtest-------------->replay------------->exec
7 : ^ |^ | ^ |
8 : |____________________|| | |________________|
9 : replay_out | | exec_replay
10 : | |------------------------------>no consumer
11 : no producer------------- stake_out, send_out, poh_out
12 : store_replay
13 :
14 : */
15 : #define _GNU_SOURCE
16 : #include "../../firedancer/topology.h"
17 : #include "../../shared/commands/configure/configure.h"
18 : #include "../../shared/commands/run/run.h" /* initialize_workspaces */
19 : #include "../../shared/commands/watch/watch.h"
20 : #include "../../shared/fd_config.h" /* config_t */
21 : #include "../../../disco/tiles.h"
22 : #include "../../../disco/topo/fd_topob.h"
23 : #include "../../../util/pod/fd_pod_format.h"
24 : #include "../../../discof/replay/fd_replay_tile.h"
25 : #include "../../../discof/restore/utils/fd_ssctrl.h"
26 : #include "../../../discof/restore/utils/fd_ssmsg.h"
27 : #include "../../../discof/tower/fd_tower_tile.h"
28 : #include "../../../discof/replay/fd_exec.h"
29 : #include "../../../ballet/lthash/fd_lthash.h"
30 : #include "../../../flamenco/runtime/context/fd_capture_ctx.h"
31 : #include "../../../disco/pack/fd_pack_cost.h"
32 : #include "../../../flamenco/progcache/fd_progcache_admin.h"
33 :
34 : #include "../main.h"
35 :
36 : #include <errno.h>
37 : #include <unistd.h>
38 : #include <fcntl.h>
39 :
40 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
41 : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
42 :
43 : static void
44 0 : backtest_topo( config_t * config ) {
45 :
46 0 : config->development.sandbox = 0;
47 0 : config->development.no_clone = 1;
48 :
49 0 : ulong exec_tile_cnt = config->firedancer.layout.exec_tile_count;
50 0 : ulong lta_tile_cnt = config->firedancer.layout.snapla_tile_count;
51 :
52 0 : int disable_snap_loader = !config->gossip.entrypoints_cnt;
53 0 : int snap_vinyl = !!config->firedancer.vinyl.enabled;
54 0 : int solcap_enabled = strlen( config->capture.solcap_capture )>0;
55 0 : int snapshot_lthash_disabled = config->development.snapshots.disable_lthash_verification;
56 :
57 0 : fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) };
58 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
59 0 : topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
60 :
61 0 : ulong cpu_idx = 0;
62 :
63 0 : fd_topob_wksp( topo, "metric_in" );
64 :
65 : /**********************************************************************/
66 : /* Add the backtest tile to topo */
67 : /**********************************************************************/
68 0 : fd_topob_wksp( topo, "backt" );
69 0 : fd_topo_tile_t * backt_tile = fd_topob_tile( topo, "backt", "backt", "metric_in", cpu_idx++, 0, 0 );
70 :
71 : /**********************************************************************/
72 : /* Add the replay tile to topo */
73 : /**********************************************************************/
74 0 : fd_topob_wksp( topo, "replay" );
75 0 : fd_topo_tile_t * replay_tile = fd_topob_tile( topo, "replay", "replay", "metric_in", cpu_idx++, 0, 0 );
76 :
77 : /* specified by [tiles.replay] */
78 :
79 0 : fd_topob_wksp( topo, "funk" );
80 0 : fd_topo_obj_t * funk_obj = setup_topo_funk( topo, "funk",
81 0 : config->firedancer.funk.max_account_records,
82 0 : config->firedancer.funk.max_database_transactions,
83 0 : config->firedancer.funk.heap_size_gib );
84 0 : fd_topob_tile_uses( topo, replay_tile, funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
85 :
86 0 : fd_topob_wksp( topo, "progcache" );
87 0 : fd_topo_obj_t * progcache_obj = setup_topo_progcache( topo, "progcache",
88 0 : fd_progcache_est_rec_max( config->firedancer.runtime.program_cache.heap_size_mib<<20,
89 0 : config->firedancer.runtime.program_cache.mean_cache_entry_size ),
90 0 : config->firedancer.funk.max_database_transactions,
91 0 : config->firedancer.runtime.program_cache.heap_size_mib<<20 );
92 0 : fd_topob_tile_uses( topo, replay_tile, progcache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
93 :
94 0 : if( snap_vinyl ) {
95 0 : setup_topo_vinyl_meta( topo, &config->firedancer );
96 0 : }
97 :
98 : /**********************************************************************/
99 : /* Add the executor tiles to topo */
100 : /**********************************************************************/
101 0 : fd_topob_wksp( topo, "exec" );
102 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
103 0 : FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", cpu_idx++, 0, 0 );
104 :
105 : /**********************************************************************/
106 : /* Add the snapshot tiles to topo */
107 : /**********************************************************************/
108 0 : int vinyl_enabled = config->firedancer.vinyl.enabled;
109 0 : fd_topo_tile_t * snapin_tile = NULL;
110 0 : fd_topo_tile_t * snapwr_tile = NULL;
111 0 : if( FD_UNLIKELY( !disable_snap_loader ) ) {
112 0 : fd_topob_wksp( topo, "snapct" );
113 0 : fd_topob_wksp( topo, "snapld" );
114 0 : fd_topob_wksp( topo, "snapdc" );
115 0 : fd_topob_wksp( topo, "snapin" );
116 :
117 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
118 0 : fd_topob_wksp( topo, "snapla" );
119 0 : fd_topob_wksp( topo, "snapls" );
120 0 : }
121 :
122 0 : fd_topo_tile_t * snapct_tile = fd_topob_tile( topo, "snapct", "snapct", "metric_in", cpu_idx++, 0, 0 );
123 0 : fd_topo_tile_t * snapld_tile = fd_topob_tile( topo, "snapld", "snapld", "metric_in", cpu_idx++, 0, 0 );
124 0 : fd_topo_tile_t * snapdc_tile = fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", cpu_idx++, 0, 0 );
125 0 : snapin_tile = fd_topob_tile( topo, "snapin", "snapin", "metric_in", cpu_idx++, 0, 0 );
126 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
127 0 : FOR(lta_tile_cnt) fd_topob_tile( topo, "snapla", "snapla", "metric_in", cpu_idx++, 0, 0 )->allow_shutdown = 1;
128 0 : /**/ fd_topob_tile( topo, "snapls", "snapls", "metric_in", cpu_idx++, 0, 0 )->allow_shutdown = 1;
129 0 : }
130 0 : snapct_tile->allow_shutdown = 1;
131 0 : snapld_tile->allow_shutdown = 1;
132 0 : snapdc_tile->allow_shutdown = 1;
133 0 : snapin_tile->allow_shutdown = 1;
134 :
135 0 : if( vinyl_enabled ) {
136 0 : fd_topob_wksp( topo, "snapwh" );
137 0 : fd_topo_tile_t * snapwh_tile = fd_topob_tile( topo, "snapwh", "snapwh", "metric_in", cpu_idx++, 0, 0 );
138 0 : snapwh_tile->allow_shutdown = 1;
139 :
140 0 : fd_topob_wksp( topo, "snapwr" );
141 0 : snapwr_tile = fd_topob_tile( topo, "snapwr", "snapwr", "metric_in", cpu_idx++, 0, 0 );
142 0 : snapwr_tile->allow_shutdown = 1;
143 0 : }
144 0 : } else {
145 0 : fd_topob_wksp( topo, "genesi" );
146 0 : fd_topob_tile( topo, "genesi", "genesi", "metric_in", cpu_idx++, 0, 0 )->allow_shutdown = 1;
147 0 : }
148 :
149 : /**********************************************************************/
150 : /* Setup backtest->replay link (shred_out) in topo */
151 : /**********************************************************************/
152 :
153 : /* The repair tile is replaced by the backtest tile for the repair to
154 : replay link. The frag interface is a "slice", ie. entry batch,
155 : which is provided by the backtest tile, which reads in the entry
156 : batches from the CLI-specified source (eg. RocksDB). */
157 :
158 0 : fd_topob_wksp( topo, "shred_out" );
159 0 : fd_topob_link( topo, "shred_out", "shred_out", 65536UL, FD_SHRED_OUT_MTU, 1UL );
160 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "shred_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
161 0 : fd_topob_tile_out( topo, "backt", 0UL, "shred_out", 0UL );
162 :
163 : /**********************************************************************/
164 : /* Setup snapshot links in topo */
165 : /**********************************************************************/
166 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
167 0 : fd_topob_wksp( topo, "snapct_ld" );
168 0 : fd_topob_wksp( topo, "snapld_dc" );
169 0 : fd_topob_wksp( topo, "snapdc_in" );
170 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
171 0 : fd_topob_wksp( topo, "snapin_ct" );
172 0 : } else {
173 0 : fd_topob_wksp( topo, "snapls_ct" );
174 0 : }
175 :
176 0 : fd_topob_wksp( topo, "snapin_manif" );
177 0 : fd_topob_wksp( topo, "snapct_repr" );
178 :
179 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
180 0 : fd_topob_wksp( topo, "snapla_ls" );
181 0 : fd_topob_wksp( topo, "snapin_ls" );
182 0 : }
183 :
184 0 : if( vinyl_enabled ) {
185 0 : fd_topob_wksp( topo, "snapin_wr" );
186 0 : }
187 :
188 0 : fd_topob_link( topo, "snapct_ld", "snapct_ld", 128UL, sizeof(fd_ssctrl_init_t), 1UL );
189 0 : fd_topob_link( topo, "snapld_dc", "snapld_dc", 16384UL, USHORT_MAX, 1UL );
190 0 : fd_topob_link( topo, "snapdc_in", "snapdc_in", 16384UL, USHORT_MAX, 1UL );
191 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
192 0 : fd_topob_link( topo, "snapin_ct", "snapin_ct", 128UL, 0UL, 1UL );
193 0 : }
194 0 : fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL, sizeof(fd_snapshot_manifest_t), 1UL ); /* TODO: Should be depth 1 or 2 but replay backpressures */
195 0 : fd_topob_link( topo, "snapct_repr", "snapct_repr", 128UL, 0UL, 1UL )->permit_no_consumers = 1;
196 :
197 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
198 0 : FOR(lta_tile_cnt) fd_topob_link( topo, "snapla_ls", "snapla_ls", 128UL, sizeof(fd_lthash_value_t), 1UL );
199 0 : /**/ fd_topob_link( topo, "snapin_ls", "snapin_ls", 256UL, sizeof(fd_snapshot_full_account_t), 1UL );
200 0 : /**/ fd_topob_link( topo, "snapls_ct", "snapls_ct", 128UL, 0UL, 1UL );
201 0 : }
202 :
203 0 : if( vinyl_enabled ) {
204 0 : fd_topo_link_t * snapin_wh = fd_topob_link( topo, "snapin_wh", "snapin_wr", 4UL, 16UL<<20, 1UL );
205 0 : fd_topob_link( topo, "snapwh_wr", "snapin_wr", 4UL, 0UL, 1UL );
206 0 : fd_pod_insertf_ulong( topo->props, 8UL, "obj.%lu.app_sz", snapin_wh->dcache_obj_id );
207 0 : }
208 :
209 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
210 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapin_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
211 0 : } else {
212 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapls_ct", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
213 0 : }
214 0 : fd_topob_tile_in ( topo, "snapct", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
215 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_ld", 0UL );
216 0 : fd_topob_tile_out( topo, "snapct", 0UL, "snapct_repr", 0UL );
217 0 : fd_topob_tile_in ( topo, "snapld", 0UL, "metric_in", "snapct_ld", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
218 0 : fd_topob_tile_out( topo, "snapld", 0UL, "snapld_dc", 0UL );
219 0 : fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in", "snapld_dc", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
220 0 : fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_in", 0UL );
221 0 : fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
222 0 : if( FD_UNLIKELY( snapshot_lthash_disabled ) ) {
223 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ct", 0UL );
224 0 : } else {
225 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_ls", 0UL );
226 0 : }
227 :
228 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_manif", 0UL );
229 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
230 :
231 0 : if( FD_LIKELY( !snapshot_lthash_disabled ) ) {
232 0 : FOR(lta_tile_cnt) fd_topob_tile_in ( topo, "snapla", i, "metric_in", "snapdc_in", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
233 0 : FOR(lta_tile_cnt) fd_topob_tile_out( topo, "snapla", i, "snapla_ls", i );
234 0 : /**/ fd_topob_tile_in ( topo, "snapls", 0UL, "metric_in", "snapin_ls", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
235 0 : FOR(lta_tile_cnt) fd_topob_tile_in ( topo, "snapls", 0UL, "metric_in", "snapla_ls", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
236 0 : /**/ fd_topob_tile_out( topo, "snapls", 0UL, "snapls_ct", 0UL );
237 0 : }
238 :
239 0 : if( vinyl_enabled ) {
240 0 : fd_topob_tile_out( topo, "snapin", 0UL, "snapin_wh", 0UL );
241 0 : fd_topob_tile_in ( topo, "snapwh", 0UL, "metric_in", "snapin_wh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
242 0 : fd_topob_tile_out( topo, "snapwh", 0UL, "snapwh_wr", 0UL );
243 0 : fd_topob_tile_in ( topo, "snapwr", 0UL, "metric_in", "snapwh_wr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
244 0 : fd_topob_tile_uses( topo, snapwr_tile, &topo->objs[ topo->links[ fd_topo_find_link( topo, "snapin_wh", 0UL ) ].dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
245 0 : }
246 0 : } else {
247 0 : fd_topob_wksp( topo, "genesi_out" );
248 0 : fd_topob_link( topo, "genesi_out", "genesi_out", 2UL, 10UL*1024UL*1024UL+32UL+sizeof(fd_lthash_value_t), 1UL );
249 0 : fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
250 0 : fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
251 0 : }
252 :
253 : /**********************************************************************/
254 : /* More backtest->replay links in topo */
255 : /**********************************************************************/
256 :
257 : /* The tower tile is replaced by the backtest tile for the tower to
258 : replay link. The backtest tile simply sends monotonically
259 : increasing rooted slot numbers to the replay tile, once after each
260 : "replayed a full slot" notification received from the replay tile.
261 : This allows the replay tile to advance its watermark, and publish
262 : various data structures. This is an oversimplified barebones mock
263 : of the tower tile. */
264 0 : fd_topob_wksp( topo, "tower_out" );
265 0 : fd_topob_link( topo, "tower_out", "tower_out", 1024UL, sizeof(fd_tower_slot_done_t), 1UL );
266 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
267 0 : fd_topob_tile_out( topo, "backt", 0UL, "tower_out", 0UL );
268 :
269 : /**********************************************************************/
270 : /* Setup replay->stake/send/poh links in topo w/o consumers */
271 : /**********************************************************************/
272 0 : fd_topob_wksp( topo, "replay_stake" );
273 0 : fd_topob_wksp( topo, "replay_poh" );
274 :
275 0 : fd_topob_link( topo, "replay_stake", "replay_stake", 128UL, 40UL + 40200UL * 40UL, 1UL );
276 0 : ulong bank_tile_cnt = config->layout.bank_tile_count;
277 0 : FOR(bank_tile_cnt) fd_topob_link( topo, "replay_poh", "replay_poh", 128UL, (4096UL*sizeof(fd_txn_p_t))+sizeof(fd_microblock_trailer_t), 1UL );
278 :
279 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_stake", 0UL );
280 0 : FOR(bank_tile_cnt) fd_topob_tile_out( topo, "replay", 0UL, "replay_poh", i );
281 :
282 0 : topo->links[ replay_tile->out_link_id[ fd_topo_find_tile_out_link( topo, replay_tile, "replay_stake", 0 ) ] ].permit_no_consumers = 1;
283 0 : FOR(bank_tile_cnt) topo->links[ replay_tile->out_link_id[ fd_topo_find_tile_out_link( topo, replay_tile, "replay_poh", i ) ] ].permit_no_consumers = 1;
284 :
285 : /**********************************************************************/
286 : /* Setup replay->backtest link (replay_notif) in topo */
287 : /**********************************************************************/
288 :
289 0 : fd_topob_wksp( topo, "replay_out" );
290 0 : fd_topob_link( topo, "replay_out", "replay_out", 8192UL, sizeof( fd_replay_message_t ), 1UL );
291 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
292 0 : fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
293 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
294 0 : fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "snapin_manif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
295 0 : } else {
296 0 : fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
297 0 : }
298 :
299 : /**********************************************************************/
300 : /* Setup replay->exec link in topo */
301 : /**********************************************************************/
302 0 : fd_topob_wksp( topo, "replay_exec" );
303 0 : fd_topob_link( topo, "replay_exec", "replay_exec", 16384UL, 2240UL, 1UL );
304 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", 0UL );
305 0 : for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
306 0 : fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
307 0 : }
308 :
309 : /**********************************************************************/
310 : /* Setup exec->replay links in topo, to send solcap account updates
311 : so that they are serialized, and to notify replay tile that a txn
312 : has been finalized by the exec tile. */
313 : /**********************************************************************/
314 0 : fd_topob_wksp( topo, "exec_replay" );
315 :
316 : /* If solcap is enabled, we need to overload this link to also send
317 : solcap account updates to the replay tile. We can't use a separate
318 : link for this without introducing a race. This will get removed with solcap V2. */
319 0 : if( FD_UNLIKELY( solcap_enabled ) ) {
320 : /* TODO: remove this with solcap V2 */
321 0 : FOR(exec_tile_cnt) fd_topob_link( topo, "exec_replay", "exec_replay", 1024UL, FD_CAPTURE_CTX_ACCOUNT_UPDATE_MSG_FOOTPRINT, 1UL );
322 0 : } else {
323 0 : FOR(exec_tile_cnt) fd_topob_link( topo, "exec_replay", "exec_replay", 16384UL, sizeof(fd_exec_task_done_msg_t), 1UL );
324 0 : }
325 :
326 0 : FOR(exec_tile_cnt) fd_topob_tile_out( topo, "exec", i, "exec_replay", i );
327 0 : FOR(exec_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "exec_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
328 :
329 : /**********************************************************************/
330 : /* Setup the shared objs used by replay and exec tiles */
331 : /**********************************************************************/
332 :
333 0 : fd_topob_wksp( topo, "store" );
334 0 : fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", config->firedancer.store.max_completed_shred_sets, 1 );
335 0 : fd_topob_tile_uses( topo, backt_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
336 0 : fd_topob_tile_uses( topo, replay_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
337 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
338 :
339 : /* banks_obj shared by replay and exec tiles */
340 0 : fd_topob_wksp( topo, "banks" );
341 0 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width, 0 );
342 0 : fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
343 0 : FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
344 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
345 :
346 : /* txncache_obj, busy_obj and poh_slot_obj only by replay tile */
347 0 : fd_topob_wksp( topo, "txncache" );
348 0 : fd_topob_wksp( topo, "bank_busy" );
349 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache",
350 0 : config->firedancer.runtime.max_live_slots,
351 0 : fd_ulong_pow2_up( FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT ) );
352 0 : fd_topob_tile_uses( topo, replay_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
353 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
354 0 : fd_topob_tile_uses( topo, snapin_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
355 0 : if( snap_vinyl ) {
356 0 : ulong vinyl_map_obj_id = fd_pod_query_ulong( topo->props, "vinyl.meta_map", ULONG_MAX ); FD_TEST( vinyl_map_obj_id !=ULONG_MAX );
357 0 : ulong vinyl_pool_obj_id = fd_pod_query_ulong( topo->props, "vinyl.meta_pool", ULONG_MAX ); FD_TEST( vinyl_pool_obj_id!=ULONG_MAX );
358 0 : fd_topo_obj_t * vinyl_map_obj = &topo->objs[ vinyl_map_obj_id ];
359 0 : fd_topo_obj_t * vinyl_pool_obj = &topo->objs[ vinyl_pool_obj_id ];
360 0 : fd_topob_tile_uses( topo, snapin_tile, vinyl_map_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
361 0 : fd_topob_tile_uses( topo, snapin_tile, vinyl_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
362 0 : }
363 0 : }
364 0 : for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
365 0 : fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
366 0 : }
367 :
368 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
369 0 : for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
370 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
371 0 : fd_topob_tile_uses( topo, replay_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
372 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
373 0 : }
374 :
375 0 : if( FD_LIKELY( !disable_snap_loader ) ) {
376 0 : fd_topob_tile_uses( topo, snapin_tile, funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
377 0 : }
378 :
379 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
380 0 : fd_topo_tile_t * tile = &topo->tiles[ i ];
381 0 : fd_topo_configure_tile( tile, config );
382 :
383 0 : if( !strcmp( tile->name, "replay" ) ) {
384 0 : tile->replay.enable_features_cnt = config->tiles.replay.enable_features_cnt;
385 0 : for( ulong i = 0; i < tile->replay.enable_features_cnt; i++ ) {
386 0 : strncpy( tile->replay.enable_features[i], config->tiles.replay.enable_features[i], sizeof(tile->replay.enable_features[i]) );
387 0 : }
388 0 : }
389 0 : }
390 :
391 : // fd_topob_auto_layout( topo, 0 );
392 0 : fd_topob_finish( topo, CALLBACKS );
393 0 : }
394 :
395 : extern int * fd_log_private_shared_lock;
396 :
397 : static void
398 0 : backtest_cmd_topo( config_t * config ) {
399 0 : backtest_topo( config );
400 0 : }
401 :
402 : extern configure_stage_t fd_cfg_stage_vinyl;
403 :
404 : static args_t
405 0 : configure_args( void ) {
406 0 : args_t args = {
407 0 : .configure.command = CONFIGURE_CMD_INIT,
408 0 : };
409 :
410 0 : ulong stage_idx = 0UL;
411 0 : args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
412 0 : args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_snapshots;
413 0 : args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_vinyl;
414 0 : args.configure.stages[ stage_idx++ ] = NULL;
415 :
416 0 : return args;
417 0 : }
418 :
419 : void
420 : backtest_cmd_args( int * pargc,
421 : char *** pargv,
422 0 : args_t * args ) {
423 0 : args->backtest.no_watch = fd_env_strip_cmdline_contains( pargc, pargv, "--no-watch" );
424 0 : }
425 :
426 : void
427 : backtest_cmd_perm( args_t * args FD_PARAM_UNUSED,
428 : fd_cap_chk_t * chk,
429 0 : config_t const * config ) {
430 0 : args_t c_args = configure_args();
431 0 : configure_cmd_perm( &c_args, chk, config );
432 0 : run_cmd_perm( NULL, chk, config );
433 0 : }
434 :
435 : static void
436 : backtest_cmd_fn( args_t * args FD_PARAM_UNUSED,
437 0 : config_t * config ) {
438 0 : args_t c_args = configure_args();
439 0 : configure_cmd_fn( &c_args, config );
440 :
441 0 : initialize_workspaces( config );
442 0 : initialize_stacks( config );
443 :
444 0 : fd_log_private_shared_lock[ 1 ] = 0;
445 0 : fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE );
446 0 : fd_topo_fill( &config->topo );
447 :
448 0 : args_t watch_args;
449 0 : int pipefd[2];
450 0 : if( !args->backtest.no_watch ) {
451 0 : if( FD_UNLIKELY( pipe2( pipefd, O_NONBLOCK ) ) ) FD_LOG_ERR(( "pipe2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
452 :
453 0 : watch_args.watch.drain_output_fd = pipefd[0];
454 0 : if( FD_UNLIKELY( -1==dup2( pipefd[ 1 ], STDERR_FILENO ) ) ) FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
455 0 : }
456 :
457 0 : fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
458 0 : if( args->backtest.no_watch ) {
459 0 : for(;;) pause();
460 0 : } else {
461 0 : watch_cmd_fn( &watch_args, config );
462 0 : }
463 0 : }
464 :
465 : action_t fd_action_backtest = {
466 : .name = "backtest",
467 : .args = backtest_cmd_args,
468 : .fn = backtest_cmd_fn,
469 : .perm = backtest_cmd_perm,
470 : .topo = backtest_cmd_topo,
471 : };
|