LCOV - code coverage report
Current view: top level - app/firedancer-dev/commands - backtest.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 212 0.0 %
Date: 2025-10-13 04:42:14 Functions: 0 6 0.0 %

          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_ssmsg.h"
      26             : #include "../../../discof/tower/fd_tower_tile.h"
      27             : #include "../../../discof/replay/fd_exec.h"
      28             : #include "../../../ballet/lthash/fd_lthash.h"
      29             : #include "../../../flamenco/runtime/context/fd_capture_ctx.h"
      30             : #include "../../../disco/pack/fd_pack_cost.h"
      31             : 
      32             : #include "../main.h"
      33             : 
      34             : #include <errno.h>
      35             : #include <unistd.h>
      36             : #include <fcntl.h>
      37             : 
      38             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      39             : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
      40             : 
      41             : static void
      42           0 : backtest_topo( config_t * config ) {
      43             : 
      44           0 :   config->development.sandbox  = 0;
      45           0 :   config->development.no_clone = 1;
      46             : 
      47           0 :   ulong exec_tile_cnt   = config->firedancer.layout.exec_tile_count;
      48             : 
      49           0 :   int disable_snap_loader = !config->gossip.entrypoints_cnt;
      50           0 :   int solcap_enabled      = strlen( config->capture.solcap_capture )>0;
      51             : 
      52           0 :   fd_topo_t * topo = { fd_topob_new( &config->topo, config->name ) };
      53           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      54           0 :   topo->gigantic_page_threshold = config->hugetlbfs.gigantic_page_threshold_mib << 20;
      55             : 
      56           0 :   ulong cpu_idx = 0;
      57             : 
      58           0 :   fd_topob_wksp( topo, "metric_in" );
      59             : 
      60             :   /**********************************************************************/
      61             :   /* Add the backtest tile to topo                                      */
      62             :   /**********************************************************************/
      63           0 :   fd_topob_wksp( topo, "backt" );
      64           0 :   fd_topo_tile_t * backt_tile = fd_topob_tile( topo, "backt", "backt", "metric_in", cpu_idx++, 0, 0 );
      65             : 
      66             :   /**********************************************************************/
      67             :   /* Add the replay tile to topo                                        */
      68             :   /**********************************************************************/
      69           0 :   fd_topob_wksp( topo, "replay" );
      70           0 :   fd_topo_tile_t * replay_tile = fd_topob_tile( topo, "replay", "replay", "metric_in", cpu_idx++, 0, 0 );
      71             : 
      72             :   /* specified by [tiles.replay] */
      73             : 
      74           0 :   fd_topob_wksp( topo, "funk" );
      75           0 :   fd_topo_obj_t * funk_obj = setup_topo_funk( topo, "funk",
      76           0 :       config->firedancer.funk.max_account_records,
      77           0 :       config->firedancer.funk.max_database_transactions,
      78           0 :       config->firedancer.funk.heap_size_gib,
      79           0 :       config->firedancer.funk.lock_pages );
      80             : 
      81           0 :   fd_topob_tile_uses( topo, replay_tile, funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
      82             : 
      83             :   /**********************************************************************/
      84             :   /* Add the executor tiles to topo                                     */
      85             :   /**********************************************************************/
      86           0 :   fd_topob_wksp( topo, "exec" );
      87           0 :   #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
      88           0 :   FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", cpu_idx++, 0, 0 );
      89             : 
      90             :   /**********************************************************************/
      91             :   /* Add the snapshot tiles to topo                                       */
      92             :   /**********************************************************************/
      93           0 :   fd_topo_tile_t * snapin_tile = NULL;
      94           0 :   if( FD_UNLIKELY( !disable_snap_loader ) ) {
      95           0 :     fd_topob_wksp( topo, "snaprd" );
      96           0 :     fd_topob_wksp( topo, "snapdc" );
      97           0 :     fd_topob_wksp( topo, "snapin" );
      98           0 :     fd_topo_tile_t * snaprd_tile = fd_topob_tile( topo, "snaprd",  "snaprd",  "metric_in",  cpu_idx++, 0, 0 );
      99           0 :     fd_topo_tile_t * snapdc_tile = fd_topob_tile( topo, "snapdc",  "snapdc",  "metric_in",  cpu_idx++, 0, 0 );
     100           0 :     snapin_tile = fd_topob_tile( topo, "snapin",  "snapin",  "metric_in",  cpu_idx++, 0, 0 );
     101           0 :     snaprd_tile->allow_shutdown = 1;
     102           0 :     snapdc_tile->allow_shutdown = 1;
     103           0 :     snapin_tile->allow_shutdown = 1;
     104           0 :   } else {
     105           0 :     fd_topob_wksp( topo, "genesi" );
     106           0 :     fd_topob_tile( topo, "genesi",  "genesi",  "metric_in",  cpu_idx++, 0, 0 )->allow_shutdown = 1;
     107           0 :   }
     108             : 
     109             :   /**********************************************************************/
     110             :   /* Setup backtest->replay link (shred_out) in topo                 */
     111             :   /**********************************************************************/
     112             : 
     113             :   /* The repair tile is replaced by the backtest tile for the repair to
     114             :      replay link.  The frag interface is a "slice", ie. entry batch,
     115             :      which is provided by the backtest tile, which reads in the entry
     116             :      batches from the CLI-specified source (eg. RocksDB). */
     117             : 
     118           0 :   fd_topob_wksp( topo, "shred_out" );
     119           0 :   fd_topob_link( topo, "shred_out", "shred_out", 65536UL, FD_SHRED_OUT_MTU, 1UL );
     120           0 :   fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "shred_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     121           0 :   fd_topob_tile_out( topo, "backt", 0UL, "shred_out", 0UL );
     122             : 
     123             :   /**********************************************************************/
     124             :   /* Setup snapshot links in topo                                       */
     125             :   /**********************************************************************/
     126           0 :   if( FD_LIKELY( !disable_snap_loader ) ) {
     127           0 :     fd_topob_wksp( topo, "snap_zstd" );
     128           0 :     fd_topob_wksp( topo, "snap_stream");
     129           0 :     fd_topob_wksp( topo, "snapdc_rd" );
     130           0 :     fd_topob_wksp( topo, "snapin_rd" );
     131           0 :     fd_topob_wksp( topo, "snap_out" );
     132           0 :     fd_topob_wksp( topo, "snaprd_rp" );
     133             :     /* TODO: Should be depth of 1 or 2, not 4, but it causes backpressure
     134             :       from the replay tile parsing the manifest, remove when this is
     135             :       fixed. */
     136           0 :     fd_topob_link( topo, "snap_out",  "snap_out",  4UL,   sizeof(fd_snapshot_manifest_t), 1UL );
     137           0 :     fd_topob_link( topo, "snaprd_rp", "snaprd_rp", 128UL, 0UL,                            1UL )->permit_no_consumers = 1;
     138             : 
     139           0 :     fd_topob_link( topo, "snap_zstd",   "snap_zstd",   8192UL, 16384UL,  1UL );
     140           0 :     fd_topob_link( topo, "snap_stream", "snap_stream", 2048UL, USHORT_MAX, 1UL );
     141           0 :     fd_topob_link( topo, "snapdc_rd", "snapdc_rd", 128UL, 0UL, 1UL );
     142           0 :     fd_topob_link( topo, "snapin_rd", "snapin_rd", 128UL, 0UL, 1UL );
     143             : 
     144           0 :     fd_topob_tile_out( topo, "snaprd", 0UL, "snap_zstd",   0UL );
     145           0 :     fd_topob_tile_in ( topo, "snapdc", 0UL, "metric_in",   "snap_zstd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     146           0 :     fd_topob_tile_out( topo, "snapdc", 0UL, "snap_stream", 0UL );
     147           0 :     fd_topob_tile_in ( topo, "snapin", 0UL, "metric_in",   "snap_stream", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED   );
     148           0 :     fd_topob_tile_out( topo, "snapin", 0UL, "snap_out",  0UL );
     149           0 :     fd_topob_tile_in ( topo, "replay", 0UL, "metric_in",   "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     150           0 :     fd_topob_tile_out( topo, "snaprd", 0UL, "snaprd_rp", 0UL );
     151             : 
     152           0 :     fd_topob_tile_in( topo, "snaprd", 0UL, "metric_in", "snapdc_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     153           0 :     fd_topob_tile_out( topo, "snapdc", 0UL, "snapdc_rd", 0UL );
     154           0 :     fd_topob_tile_in( topo, "snaprd", 0UL, "metric_in", "snapin_rd", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     155           0 :     fd_topob_tile_out( topo, "snapin", 0UL, "snapin_rd", 0UL );
     156           0 :   } else {
     157           0 :     fd_topob_wksp( topo, "genesi_out" );
     158           0 :     fd_topob_link( topo, "genesi_out", "genesi_out", 2UL, 10UL*1024UL*1024UL+32UL+sizeof(fd_lthash_value_t), 1UL );
     159           0 :     fd_topob_tile_out( topo, "genesi", 0UL, "genesi_out", 0UL );
     160           0 :     fd_topob_tile_in ( topo, "replay", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     161           0 :   }
     162             : 
     163             :   /**********************************************************************/
     164             :   /* More backtest->replay links in topo                                */
     165             :   /**********************************************************************/
     166             : 
     167             :   /* The tower tile is replaced by the backtest tile for the tower to
     168             :      replay link.  The backtest tile simply sends monotonically
     169             :      increasing rooted slot numbers to the replay tile, once after each
     170             :      "replayed a full slot" notification received from the replay tile.
     171             :      This allows the replay tile to advance its watermark, and publish
     172             :      various data structures.  This is an oversimplified barebones mock
     173             :      of the tower tile. */
     174           0 :   fd_topob_wksp( topo, "tower_out" );
     175           0 :   fd_topob_link( topo, "tower_out", "tower_out", 1024UL, sizeof(fd_tower_slot_done_t), 1UL );
     176           0 :   fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "tower_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     177           0 :   fd_topob_tile_out( topo, "backt", 0UL, "tower_out", 0UL );
     178             : 
     179             :   /**********************************************************************/
     180             :   /* Setup replay->stake/send/poh links in topo w/o consumers         */
     181             :   /**********************************************************************/
     182           0 :   fd_topob_wksp( topo, "replay_stake"    );
     183           0 :   fd_topob_wksp( topo, "replay_poh"   );
     184             : 
     185           0 :   fd_topob_link( topo, "replay_stake",   "replay_stake",   128UL, 40UL + 40200UL * 40UL, 1UL );
     186           0 :   ulong bank_tile_cnt   = config->layout.bank_tile_count;
     187           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 );
     188             : 
     189           0 :   fd_topob_tile_out( topo, "replay", 0UL, "replay_stake",   0UL );
     190           0 :   FOR(bank_tile_cnt) fd_topob_tile_out( topo, "replay", 0UL, "replay_poh", i );
     191             : 
     192           0 :   topo->links[ replay_tile->out_link_id[ fd_topo_find_tile_out_link( topo, replay_tile, "replay_stake",   0 ) ] ].permit_no_consumers = 1;
     193           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;
     194             : 
     195             :   /**********************************************************************/
     196             :   /* Setup replay->backtest link (replay_notif) in topo                 */
     197             :   /**********************************************************************/
     198             : 
     199           0 :   fd_topob_wksp( topo, "replay_out" );
     200           0 :   fd_topob_link( topo, "replay_out", "replay_out", 8192UL, sizeof( fd_replay_message_t ), 1UL );
     201           0 :   fd_topob_tile_out( topo, "replay", 0UL, "replay_out", 0UL );
     202           0 :   fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "replay_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     203           0 :   if( FD_LIKELY( !disable_snap_loader ) ) {
     204           0 :     fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "snap_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     205           0 :   } else {
     206           0 :     fd_topob_tile_in ( topo, "backt", 0UL, "metric_in", "genesi_out", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     207           0 :   }
     208             : 
     209             :   /**********************************************************************/
     210             :   /* Setup replay->exec link in topo                                    */
     211             :   /**********************************************************************/
     212           0 :   fd_topob_wksp( topo, "replay_exec" );
     213           0 :   fd_topob_link( topo, "replay_exec", "replay_exec", 16384UL, 2240UL, 1UL );
     214           0 :   fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", 0UL );
     215           0 :   for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
     216           0 :     fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     217           0 :   }
     218             : 
     219             :   /**********************************************************************/
     220             :   /* Setup exec->replay links in topo, to send solcap account updates
     221             :      so that they are serialized, and to notify replay tile that a txn
     222             :      has been finalized by the exec tile. */
     223             :   /**********************************************************************/
     224           0 :   fd_topob_wksp( topo, "exec_replay" );
     225             : 
     226             :   /* If solcap is enabled, we need to overload this link to also send
     227             :      solcap account updates to the replay tile. We can't use a separate
     228             :      link for this without introducing a race. This will get removed with solcap V2. */
     229           0 :   if( FD_UNLIKELY( solcap_enabled ) ) {
     230             :     /* TODO: remove this with solcap V2 */
     231           0 :     FOR(exec_tile_cnt) fd_topob_link( topo, "exec_replay", "exec_replay", 1024UL, FD_CAPTURE_CTX_ACCOUNT_UPDATE_MSG_FOOTPRINT, 1UL );
     232           0 :   } else {
     233           0 :     FOR(exec_tile_cnt) fd_topob_link( topo, "exec_replay", "exec_replay", 16384UL, sizeof(fd_exec_task_done_msg_t), 1UL );
     234           0 :   }
     235             : 
     236           0 :   FOR(exec_tile_cnt) fd_topob_tile_out( topo, "exec", i, "exec_replay", i );
     237           0 :   FOR(exec_tile_cnt) fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "exec_replay", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     238             : 
     239             :   /**********************************************************************/
     240             :   /* Setup the shared objs used by replay and exec tiles                */
     241             :   /**********************************************************************/
     242             : 
     243           0 :   fd_topob_wksp( topo, "store" );
     244           0 :   fd_topo_obj_t * store_obj = setup_topo_store( topo, "store", config->firedancer.store.max_completed_shred_sets, 1 );
     245           0 :   fd_topob_tile_uses( topo, backt_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     246           0 :   fd_topob_tile_uses( topo, replay_tile, store_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     247           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, store_obj->id, "store" ) );
     248             : 
     249             :   /* banks_obj shared by replay and exec tiles */
     250           0 :   fd_topob_wksp( topo, "banks" );
     251           0 :   fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width );
     252           0 :   fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     253           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 );
     254           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
     255             : 
     256             :   /* bank_hash_cmp_obj shared by replay and exec tiles */
     257           0 :   fd_topob_wksp( topo, "bh_cmp" );
     258           0 :   fd_topo_obj_t * bank_hash_cmp_obj = setup_topo_bank_hash_cmp( topo, "bh_cmp" );
     259           0 :   fd_topob_tile_uses( topo, replay_tile, bank_hash_cmp_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     260           0 :   FOR(exec_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], bank_hash_cmp_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     261           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, bank_hash_cmp_obj->id, "bh_cmp" ) );
     262             : 
     263             :   /* exec_spad_obj used by exec tiles */
     264           0 :   fd_topob_wksp( topo, "exec_spad" );
     265           0 :   for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
     266           0 :     fd_topo_obj_t * exec_spad_obj = fd_topob_obj( topo, "exec_spad", "exec_spad" );
     267           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     268           0 :     FD_TEST( fd_pod_insertf_ulong( topo->props, exec_spad_obj->id, "exec_spad.%lu", i ) );
     269           0 :   }
     270             : 
     271             :   /* txncache_obj, busy_obj and poh_slot_obj only by replay tile */
     272           0 :   fd_topob_wksp( topo, "txncache"    );
     273           0 :   fd_topob_wksp( topo, "bank_busy"   );
     274           0 :   fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache",
     275           0 :       config->firedancer.runtime.max_live_slots,
     276           0 :       fd_ulong_pow2_up( FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT ) );
     277           0 :   fd_topob_tile_uses( topo, replay_tile, txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     278           0 :   if( FD_LIKELY( !disable_snap_loader ) ) {
     279           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     280           0 :   }
     281           0 :   for( ulong i=0UL; i<exec_tile_cnt; i++ ) {
     282           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "exec", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     283           0 :   }
     284           0 :   for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
     285           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "bank", i ) ], txncache_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     286           0 :   }
     287             : 
     288           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
     289           0 :   for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
     290           0 :     fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
     291           0 :     fd_topob_tile_uses( topo, replay_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     292           0 :     FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
     293           0 :   }
     294             : 
     295           0 :   if( FD_LIKELY( !disable_snap_loader ) ) {
     296           0 :     fd_topob_tile_uses( topo, snapin_tile, funk_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     297           0 :   }
     298             : 
     299           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     300           0 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     301           0 :     fd_topo_configure_tile( tile, config );
     302             : 
     303           0 :     if( !strcmp( tile->name, "replay" ) ) {
     304           0 :       tile->replay.enable_bank_hash_cmp = 0;
     305           0 :       tile->replay.enable_features_cnt = config->tiles.replay.enable_features_cnt;
     306           0 :       for( ulong i = 0; i < tile->replay.enable_features_cnt; i++ ) {
     307           0 :         strncpy( tile->replay.enable_features[i], config->tiles.replay.enable_features[i], sizeof(tile->replay.enable_features[i]) );
     308           0 :       }
     309           0 :     }
     310           0 :   }
     311             : 
     312             :   // fd_topob_auto_layout( topo, 0 );
     313           0 :   fd_topob_finish( topo, CALLBACKS );
     314           0 : }
     315             : 
     316             : extern int * fd_log_private_shared_lock;
     317             : 
     318             : static void
     319           0 : backtest_cmd_topo( config_t * config ) {
     320           0 :   backtest_topo( config );
     321           0 : }
     322             : 
     323             : static args_t
     324           0 : configure_args( void ) {
     325           0 :   args_t args = {
     326           0 :     .configure.command = CONFIGURE_CMD_INIT,
     327           0 :   };
     328             : 
     329           0 :   ulong stage_idx = 0UL;
     330           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_hugetlbfs;
     331           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_normalpage;
     332           0 :   args.configure.stages[ stage_idx++ ] = &fd_cfg_stage_snapshots;
     333           0 :   args.configure.stages[ stage_idx++ ] = NULL;
     334             : 
     335           0 :   return args;
     336           0 : }
     337             : 
     338             : void
     339             : backtest_cmd_args( int *    pargc,
     340             :                    char *** pargv,
     341           0 :                    args_t * args ) {
     342           0 :   args->backtest.no_watch = fd_env_strip_cmdline_contains( pargc, pargv, "--no-watch" );
     343           0 : }
     344             : 
     345             : void
     346             : backtest_cmd_perm( args_t *         args FD_PARAM_UNUSED,
     347             :                    fd_cap_chk_t *   chk,
     348           0 :                    config_t const * config ) {
     349           0 :   args_t c_args = configure_args();
     350           0 :   configure_cmd_perm( &c_args, chk, config );
     351           0 :   run_cmd_perm( NULL, chk, config );
     352           0 : }
     353             : 
     354             : static void
     355             : backtest_cmd_fn( args_t *   args FD_PARAM_UNUSED,
     356           0 :                  config_t * config ) {
     357           0 :   args_t c_args = configure_args();
     358           0 :   configure_cmd_fn( &c_args, config );
     359             : 
     360           0 :   initialize_workspaces( config );
     361           0 :   initialize_stacks( config );
     362             : 
     363           0 :   fd_log_private_shared_lock[ 1 ] = 0;
     364           0 :   fd_topo_join_workspaces( &config->topo, FD_SHMEM_JOIN_MODE_READ_WRITE );
     365           0 :   fd_topo_fill( &config->topo );
     366             : 
     367           0 :   args_t watch_args;
     368           0 :   int pipefd[2];
     369           0 :   if( !args->backtest.no_watch ) {
     370           0 :     if( FD_UNLIKELY( pipe2( pipefd, O_NONBLOCK ) ) ) FD_LOG_ERR(( "pipe2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     371             : 
     372           0 :     watch_args.watch.drain_output_fd = pipefd[0];
     373           0 :     if( FD_UNLIKELY( -1==dup2( pipefd[ 1 ], STDERR_FILENO ) ) ) FD_LOG_ERR(( "dup2() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     374           0 :   }
     375             : 
     376           0 :   fd_topo_run_single_process( &config->topo, 2, config->uid, config->gid, fdctl_tile_run );
     377           0 :   if( args->backtest.no_watch ) {
     378           0 :     for(;;) pause();
     379           0 :   } else {
     380           0 :     watch_cmd_fn( &watch_args, config );
     381           0 :   }
     382           0 : }
     383             : 
     384             : action_t fd_action_backtest = {
     385             :   .name = "backtest",
     386             :   .args = backtest_cmd_args,
     387             :   .fn   = backtest_cmd_fn,
     388             :   .perm = backtest_cmd_perm,
     389             :   .topo = backtest_cmd_topo,
     390             : };

Generated by: LCOV version 1.14