LCOV - code coverage report
Current view: top level - app/firedancer-dev/commands - snapshot_load.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 725 0.0 %
Date: 2026-03-19 18:19:27 Functions: 0 13 0.0 %

          Line data    Source code
       1             : #include "../../firedancer/topology.h"
       2             : #include "../../platform/fd_sys_util.h"
       3             : #include "../../shared/commands/configure/configure.h"
       4             : #include "../../shared/commands/run/run.h"
       5             : #include "../../shared_dev/commands/dev.h"
       6             : #include "../../../disco/metrics/fd_metrics.h"
       7             : #include "../../../disco/topo/fd_topob.h"
       8             : #include "../../../disco/pack/fd_pack.h"
       9             : #include "../../../disco/pack/fd_pack_cost.h"
      10             : #include "../../../util/pod/fd_pod_format.h"
      11             : #include "../../../discof/restore/fd_snapin_tile_private.h"
      12             : #include "../../../discof/restore/fd_snaplv_tile_private.h"
      13             : #include "../../../discof/restore/fd_snapwm_tile_private.h"
      14             : #include "../../../discof/restore/utils/fd_slot_delta_parser.h"
      15             : #include "../../../discof/restore/utils/fd_ssctrl.h"
      16             : #include "../../../discof/restore/utils/fd_ssmsg.h"
      17             : #include "../../../flamenco/accdb/fd_accdb_fsck.h"
      18             : #include "../../../funk/fd_funk.h"
      19             : #include "../../../ballet/lthash/fd_lthash.h"
      20             : 
      21             : #include <errno.h>
      22             : #include <fcntl.h> /* open */
      23             : #include <sys/resource.h>
      24             : #include <linux/capability.h>
      25             : #include <unistd.h> /* close, sleep */
      26             : #include <stdlib.h>
      27             : #include <stdio.h>
      28             : 
      29             : #define NAME "snapshot-load"
      30             : 
      31             : extern fd_topo_obj_callbacks_t * CALLBACKS[];
      32             : 
      33             : fd_topo_run_tile_t
      34             : fdctl_tile_run( fd_topo_tile_t const * tile );
      35             : 
      36             : static void
      37           0 : snapshot_load_topo( config_t * config ) {
      38           0 :   fd_topo_t * topo = &config->topo;
      39           0 :   fd_topob_new( &config->topo, config->name );
      40           0 :   topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
      41             : 
      42           0 :   fd_topob_wksp( topo, "txncache" );
      43           0 :   fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache",
      44           0 :       config->firedancer.runtime.max_live_slots,
      45           0 :       FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT );
      46           0 :   FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
      47             : 
      48           0 :   fd_topob_wksp( topo, "funk" );
      49           0 :   fd_topob_wksp( topo, "funk_locks" );
      50           0 :   setup_topo_funk( topo,
      51           0 :       config->firedancer.accounts.max_accounts,
      52           0 :       config->firedancer.runtime.max_live_slots + config->firedancer.accounts.write_delay_slots,
      53           0 :       config->firedancer.accounts.in_memory_only
      54           0 :           ? config->firedancer.accounts.file_size_gib
      55           0 :           : config->firedancer.accounts.max_unrooted_account_size_gib );
      56             : 
      57           0 :   int snapshot_lthash_disabled = config->development.snapshots.disable_lthash_verification;
      58           0 :   ulong lta_tile_cnt           = config->firedancer.layout.snapshot_hash_tile_count;
      59           0 :   ulong snapwr_tile_cnt        = config->firedancer.layout.snapwr_tile_count;
      60           0 :   ulong snaplh_tile_cnt        = config->firedancer.layout.snapshot_hash_tile_count;
      61             : 
      62           0 :   if( !config->firedancer.accounts.in_memory_only ) {
      63           0 :     setup_topo_accdb_meta( topo, &config->firedancer );
      64           0 :   }
      65             : 
      66           0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
      67             : 
      68             :   /* metrics tile *****************************************************/
      69           0 :   fd_topob_wksp( topo, "metric_in" );
      70           0 :   fd_topob_wksp( topo, "metric" );
      71           0 :   fd_topob_tile( topo, "metric",  "metric", "metric_in", ULONG_MAX, 0, 0, 0 );
      72             : 
      73             :   /* read() tile */
      74           0 :   fd_topob_wksp( topo, "snapct" );
      75           0 :   fd_topo_tile_t * snapct_tile = fd_topob_tile( topo, "snapct", "snapct", "metric_in", ULONG_MAX, 0, 0, 0 );
      76           0 :   snapct_tile->allow_shutdown = 1;
      77             : 
      78             :   /* load tile */
      79           0 :   fd_topob_wksp( topo, "snapld" );
      80           0 :   fd_topo_tile_t * snapld_tile = fd_topob_tile( topo, "snapld", "snapld", "metric_in", ULONG_MAX, 0, 0, 0 );
      81           0 :   snapld_tile->allow_shutdown = 1;
      82             : 
      83             :   /* "snapdc": Zstandard decompress tile */
      84           0 :   fd_topob_wksp( topo, "snapdc" );
      85           0 :   fd_topo_tile_t * snapdc_tile = fd_topob_tile( topo, "snapdc", "snapdc", "metric_in", ULONG_MAX, 0, 0, 0 );
      86           0 :   snapdc_tile->allow_shutdown = 1;
      87             : 
      88             :   /* "snapin": Snapshot parser tile */
      89           0 :   fd_topob_wksp( topo, "snapin" );
      90           0 :   fd_topo_tile_t * snapin_tile = fd_topob_tile( topo, "snapin", "snapin", "metric_in", ULONG_MAX, 0, 0, 0 );
      91           0 :   snapin_tile->allow_shutdown = 1;
      92             : 
      93             :   /* "snapwr": Snapshot writer tile */
      94           0 :   int vinyl_enabled = !config->firedancer.accounts.in_memory_only;
      95           0 :   if( vinyl_enabled ) {
      96             : 
      97           0 :     fd_topob_wksp( topo, "snapwm" );
      98           0 :     fd_topo_tile_t * snapwm_tile = fd_topob_tile( topo, "snapwm", "snapwm", "metric_in", ULONG_MAX, 0, 0, 0 );
      99           0 :     snapwm_tile->allow_shutdown = 1;
     100             : 
     101           0 :     fd_topob_wksp( topo, "snapwh" );
     102           0 :     fd_topo_tile_t * snapwh_tile = fd_topob_tile( topo, "snapwh", "snapwh", "metric_in", ULONG_MAX, 0, 0, 0 );
     103           0 :     snapwh_tile->allow_shutdown = 1;
     104             : 
     105           0 :     fd_topob_wksp( topo, "snapwr" );
     106           0 :     FOR(snapwr_tile_cnt) fd_topob_tile( topo, "snapwr", "snapwr", "metric_in", ULONG_MAX, 0, 0, 0 )->allow_shutdown = 1;
     107           0 :   }
     108             : 
     109           0 :   fd_topob_wksp( topo, "snapct_ld"    );
     110           0 :   fd_topob_wksp( topo, "snapld_dc"    );
     111           0 :   fd_topob_wksp( topo, "snapdc_in"    );
     112             : 
     113           0 :   fd_topob_wksp( topo, "snapin_manif" );
     114           0 :   fd_topob_wksp( topo, "snapct_repr"  );
     115             : 
     116           0 :   if( vinyl_enabled ) {
     117           0 :     fd_topob_wksp( topo, "snapin_txn");
     118           0 :     fd_topob_wksp( topo, "snapin_wm" );
     119           0 :     fd_topob_wksp( topo, "snapwm_wr" );
     120           0 :   }
     121           0 :   if( snapshot_lthash_disabled ) {
     122           0 :     if( vinyl_enabled ) {
     123           0 :       fd_topob_wksp( topo, "snapwm_ct" );
     124           0 :     } else {
     125           0 :       fd_topob_wksp( topo, "snapin_ct" );
     126           0 :     }
     127           0 :   } else {
     128           0 :     if( vinyl_enabled ) {
     129           0 :       fd_topob_wksp( topo, "snaplh"    );
     130           0 :       fd_topob_wksp( topo, "snaplv"    );
     131           0 :       FOR(snaplh_tile_cnt) fd_topob_tile( topo, "snaplh", "snaplh", "metric_in", ULONG_MAX, 0, 0, 0 )->allow_shutdown = 1;
     132           0 :       /**/                 fd_topob_tile( topo, "snaplv", "snaplv", "metric_in", ULONG_MAX, 0, 0, 0 )->allow_shutdown = 1;
     133           0 :       fd_topob_wksp( topo, "vinyl_admin" );
     134           0 :       fd_topob_wksp( topo, "snaplv_lh" );
     135           0 :       fd_topob_wksp( topo, "snaplh_lv" );
     136           0 :       fd_topob_wksp( topo, "snapwm_lv" );
     137           0 :       fd_topob_wksp( topo, "snaplv_ct" );
     138           0 :     } else {
     139           0 :       fd_topob_wksp( topo, "snapla"    );
     140           0 :       fd_topob_wksp( topo, "snapls"    );
     141           0 :       FOR(lta_tile_cnt)  fd_topob_tile( topo, "snapla", "snapla", "metric_in", ULONG_MAX, 0, 0, 0 )->allow_shutdown = 1;
     142           0 :       /**/               fd_topob_tile( topo, "snapls", "snapls", "metric_in", ULONG_MAX, 0, 0, 0 )->allow_shutdown = 1;
     143           0 :       fd_topob_wksp( topo, "snapla_ls" );
     144           0 :       fd_topob_wksp( topo, "snapin_ls" );
     145           0 :       fd_topob_wksp( topo, "snapls_ct" );
     146           0 :     }
     147           0 :   }
     148             : 
     149           0 :   fd_topob_link( topo, "snapct_ld",   "snapct_ld",     128UL,   sizeof(fd_ssctrl_init_t),       1UL );
     150           0 :   fd_topob_link( topo, "snapld_dc",   "snapld_dc",     16384UL, USHORT_MAX,                     1UL );
     151           0 :   fd_topob_link( topo, "snapdc_in",   "snapdc_in",     16384UL, USHORT_MAX,                     1UL );
     152           0 :   fd_topob_link( topo, "snapin_manif", "snapin_manif", 4UL,     sizeof(fd_snapshot_manifest_t), 1UL )->permit_no_consumers = 1;
     153           0 :   fd_topob_link( topo, "snapct_repr", "snapct_repr",   128UL,   0UL,                            1UL )->permit_no_consumers = 1;
     154             : 
     155           0 :   if( vinyl_enabled ) {
     156             :     /* snapwm needs all txn_cache data in order to verify the slot
     157             :        deltas with the slot history.  To make this possible, snapin
     158             :        uses the dcache of the snapin_txn link as the scratch memory.
     159             :        The depth of the link should match that of snapin_wm, just to
     160             :        guarantee enough mcache credits.  The mtu needs to be adjusted
     161             :        so that the total dcache size matches what snapin requires.
     162             :        Round up the mtu (ulong) size using: (...+(depth-1))/depth. */
     163           0 :     fd_topob_link( topo, "snapin_txn", "snapin_txn",   16UL,    (sizeof(fd_sstxncache_entry_t)*FD_SNAPIN_TXNCACHE_MAX_ENTRIES+15UL/*depth-1*/)/16UL/*depth*/, 1UL );
     164           0 :     fd_topob_link( topo, "snapin_wm", "snapin_wm",     16UL,    FD_SNAPWM_PAIR_BATCH_SZ_MAX,    1UL );
     165             :     /* snapwh and snapwr both use snapwm_wh's dcache.  snapwh sends
     166             :        control messages to snapwr, using snapwh_wr link, instructing
     167             :        which chunks in the dcache are ready to be consumed by snapwr. */
     168           0 :     fd_topo_link_t * snapwm_wh =
     169           0 :     fd_topob_link( topo, "snapwm_wh", "snapwm_wr",     64UL,    FD_SNAPWM_WR_MTU,               1UL );
     170           0 :     fd_topob_link( topo, "snapwh_wr", "snapwm_wr",     64UL,    0UL,                            1UL );
     171           0 :     fd_pod_insertf_ulong( topo->props, 8UL, "obj.%lu.app_sz",  snapwm_wh->dcache_obj_id );
     172           0 :   }
     173             : 
     174           0 :   if( snapshot_lthash_disabled ) {
     175           0 :     if( vinyl_enabled ) {
     176           0 :       fd_topob_link( topo, "snapwm_ct", "snapwm_ct",   128UL,   0UL,                            1UL );
     177           0 :     } else {
     178           0 :       fd_topob_link( topo, "snapin_ct", "snapin_ct",   128UL,  0UL,                             1UL );
     179           0 :     }
     180           0 :   } else {
     181           0 :     if( vinyl_enabled ) {
     182           0 :       FOR(snaplh_tile_cnt) fd_topob_link( topo, "snaplh_lv",  "snaplh_lv",    128UL,   sizeof(fd_ssctrl_hash_result_t),     1UL );
     183           0 :       /**/                 fd_topob_link( topo, "snapwm_lv",  "snapwm_lv",  32768UL, FD_SNAPWM_DUP_META_BATCH_SZ,     1UL );
     184           0 :       /**/                 fd_topob_link( topo, "snaplv_lh",  "snaplv_lh", 262144UL,       FD_SNAPLV_DUP_META_SZ, FD_SNAPLV_STEM_BURST ); /* FD_SNAPWM_DUP_META_BATCH_CNT_MAX times the depth of snapwm_lv */
     185           0 :       /**/                 fd_topob_link( topo, "snaplv_ct",  "snaplv_ct",    128UL,                         0UL,     1UL );
     186           0 :     } else {
     187           0 :       FOR(lta_tile_cnt) fd_topob_link( topo, "snapla_ls",  "snapla_ls",   128UL,  sizeof(fd_lthash_value_t),          1UL );
     188           0 :       /**/              fd_topob_link( topo, "snapin_ls",  "snapin_ls",   256UL,  sizeof(fd_snapshot_full_account_t), 1UL );
     189           0 :       /**/              fd_topob_link( topo, "snapls_ct",  "snapls_ct",   128UL,  0UL,                                1UL );
     190           0 :     }
     191           0 :   }
     192             : 
     193           0 :   if( snapshot_lthash_disabled ) {
     194           0 :     if( vinyl_enabled ) {
     195           0 :       fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapwm_ct",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     196           0 :     } else {
     197           0 :       fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapin_ct",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     198           0 :     }
     199             : 
     200           0 :   } else {
     201           0 :     if( vinyl_enabled ) {
     202           0 :       fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snaplv_ct",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     203           0 :     } else {
     204           0 :       fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapls_ct", 0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED  );
     205           0 :     }
     206           0 :   }
     207             : 
     208           0 :   fd_topob_tile_in ( topo, "snapct",  0UL, "metric_in", "snapld_dc",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     209           0 :   fd_topob_tile_out( topo, "snapct",  0UL,              "snapct_ld",    0UL                                       );
     210           0 :   fd_topob_tile_out( topo, "snapct",  0UL,              "snapct_repr",  0UL                                       );
     211           0 :   fd_topob_tile_in ( topo, "snapld",  0UL, "metric_in", "snapct_ld",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     212           0 :   fd_topob_tile_out( topo, "snapld",  0UL,              "snapld_dc",    0UL                                       );
     213           0 :   fd_topob_tile_in ( topo, "snapdc",  0UL, "metric_in", "snapld_dc",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     214           0 :   fd_topob_tile_out( topo, "snapdc",  0UL,              "snapdc_in",    0UL                                       );
     215           0 :   fd_topob_tile_in ( topo, "snapin",  0UL, "metric_in", "snapdc_in",    0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     216           0 :   fd_topob_tile_out( topo, "snapin",  0UL,              "snapin_manif", 0UL                                       );
     217             : 
     218           0 :   if( vinyl_enabled ) {
     219           0 :     fd_topob_tile_out( topo, "snapin", 0UL,              "snapin_wm", 0UL );
     220           0 :     fd_topob_tile_in ( topo, "snapwm", 0UL, "metric_in", "snapin_wm", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     221           0 :     fd_topob_tile_out( topo, "snapin", 0UL,              "snapin_txn",0UL );
     222           0 :     fd_topob_tile_in ( topo, "snapwm", 0UL, "metric_in", "snapin_txn",0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     223           0 :     fd_topob_tile_out( topo, "snapwm", 0UL,              "snapwm_wh", 0UL );
     224           0 :     fd_topob_tile_in ( topo, "snapwh", 0UL, "metric_in", "snapwm_wh", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     225           0 :     fd_topob_tile_out( topo, "snapwh", 0UL,              "snapwh_wr", 0UL );
     226             :     /* snapwh and snapwr both access snapwm_wh's dcache, avoiding a
     227             :        memcpy for every account (vinyl pair) that is being processed
     228             :        (loaded) from the snapshot. */
     229           0 :     FOR(snapwr_tile_cnt) fd_topob_tile_in ( topo, "snapwr", i, "metric_in", "snapwh_wr", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
     230           0 :     FOR(snapwr_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwr", i ) ], &topo->objs[ topo->links[ fd_topo_find_link( topo, "snapwm_wh", 0UL ) ].dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
     231           0 :   }
     232           0 :   if( snapshot_lthash_disabled ) {
     233           0 :     if( vinyl_enabled ) {
     234           0 :       /**/              fd_topob_tile_out( topo, "snapwm", 0UL,              "snapwm_ct",  0UL                                       );
     235           0 :     } else {
     236           0 :       /**/              fd_topob_tile_out( topo, "snapin", 0UL,              "snapin_ct",  0UL                                       );
     237           0 :     }
     238           0 :   } else {
     239           0 :     if( vinyl_enabled ) {
     240           0 :       FOR(snaplh_tile_cnt) fd_topob_tile_in ( topo, "snaplh", i,   "metric_in", "snapwh_wr",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     241           0 :       FOR(snaplh_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaplh", i ) ], &topo->objs[ topo->links[ fd_topo_find_link( topo, "snapwm_wh", 0UL ) ].dcache_obj_id ], FD_SHMEM_JOIN_MODE_READ_ONLY );
     242           0 :       FOR(snaplh_tile_cnt) fd_topob_tile_in ( topo, "snaplh", i,   "metric_in", "snaplv_lh",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     243           0 :       /**/                 fd_topob_tile_out( topo, "snaplv", 0UL,              "snaplv_lh",  0UL                                       );
     244           0 :       FOR(snaplh_tile_cnt) fd_topob_tile_out( topo, "snaplh", i,                "snaplh_lv",  i                                         );
     245           0 :       /**/                 fd_topob_tile_in ( topo, "snaplv", 0UL, "metric_in", "snapwm_lv",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     246           0 :       FOR(snaplh_tile_cnt) fd_topob_tile_in ( topo, "snaplv", 0UL, "metric_in", "snaplh_lv",  i,   FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     247           0 :       /**/                 fd_topob_tile_out( topo, "snaplv", 0UL,              "snaplv_ct",  0UL                                       );
     248           0 :       /**/                 fd_topob_tile_out( topo, "snapwm", 0UL,              "snapwm_lv",  0UL                                       );
     249             : 
     250           0 :       fd_topo_obj_t * vinyl_admin_obj = setup_topo_vinyl_admin( topo, "vinyl_admin" );
     251           0 :       /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwm", 0UL ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     252           0 :       FOR(snapwr_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwr", i   ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     253           0 :       /**/                 fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaplv", 0UL ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     254           0 :       FOR(snaplh_tile_cnt) fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snaplh", i   ) ], vinyl_admin_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     255           0 :       FD_TEST( fd_pod_insertf_ulong( topo->props, vinyl_admin_obj->id, "vinyl_admin" ) );
     256           0 :     } else {
     257           0 :       FOR(lta_tile_cnt) fd_topob_tile_in ( topo, "snapla", i,   "metric_in", "snapdc_in",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     258           0 :       FOR(lta_tile_cnt) fd_topob_tile_out( topo, "snapla", i,                "snapla_ls",  i                                         );
     259           0 :       /**/              fd_topob_tile_in ( topo, "snapls", 0UL, "metric_in", "snapin_ls",  0UL, FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     260           0 :       FOR(lta_tile_cnt) fd_topob_tile_in ( topo, "snapls", 0UL, "metric_in", "snapla_ls",  i,   FD_TOPOB_RELIABLE,   FD_TOPOB_POLLED );
     261           0 :       /**/              fd_topob_tile_out( topo, "snapls", 0UL,              "snapls_ct",  0UL                                       );
     262           0 :       /**/              fd_topob_tile_out( topo, "snapin", 0UL,              "snapin_ls",  0UL                                       );
     263           0 :     }
     264           0 :   }
     265             : 
     266             :   /* snapin funk / txncache access */
     267           0 :   ulong funk_obj_id;       FD_TEST( (funk_obj_id       = fd_pod_query_ulong( topo->props, "funk",       ULONG_MAX ) )!=ULONG_MAX );
     268           0 :   ulong funk_locks_obj_id; FD_TEST( (funk_locks_obj_id = fd_pod_query_ulong( topo->props, "funk_locks", ULONG_MAX ) )!=ULONG_MAX );
     269           0 :   fd_topob_tile_uses( topo, snapin_tile, &topo->objs[ funk_obj_id       ], FD_SHMEM_JOIN_MODE_READ_WRITE );
     270           0 :   fd_topob_tile_uses( topo, snapin_tile, &topo->objs[ funk_locks_obj_id ], FD_SHMEM_JOIN_MODE_READ_WRITE );
     271           0 :   fd_topob_tile_uses( topo, snapin_tile, txncache_obj,   FD_SHMEM_JOIN_MODE_READ_WRITE );
     272           0 :   snapin_tile->snapin.funk_obj_id     = funk_obj_id;
     273           0 :   snapin_tile->snapin.txncache_obj_id = txncache_obj->id;
     274           0 :   if( !config->firedancer.accounts.in_memory_only ) {
     275           0 :     ulong vinyl_map_obj_id  = fd_pod_query_ulong( topo->props, "accdb.meta_map",  ULONG_MAX ); FD_TEST( vinyl_map_obj_id !=ULONG_MAX );
     276           0 :     ulong vinyl_pool_obj_id = fd_pod_query_ulong( topo->props, "accdb.meta_pool", ULONG_MAX ); FD_TEST( vinyl_pool_obj_id!=ULONG_MAX );
     277             : 
     278           0 :     fd_topo_obj_t * vinyl_map_obj  = &topo->objs[ vinyl_map_obj_id ];
     279           0 :     fd_topo_obj_t * vinyl_pool_obj = &topo->objs[ vinyl_pool_obj_id ];
     280             : 
     281           0 :     fd_topob_tile_uses( topo, snapin_tile, vinyl_map_obj,  FD_SHMEM_JOIN_MODE_READ_WRITE );
     282           0 :     fd_topob_tile_uses( topo, snapin_tile, vinyl_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     283           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwm", 0UL ) ], vinyl_map_obj,  FD_SHMEM_JOIN_MODE_READ_WRITE );
     284           0 :     fd_topob_tile_uses( topo, &topo->tiles[ fd_topo_find_tile( topo, "snapwm", 0UL ) ], vinyl_pool_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
     285           0 :   }
     286             : 
     287           0 :   snapin_tile->snapin.max_live_slots  = config->firedancer.runtime.max_live_slots;
     288             : 
     289           0 :   for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
     290           0 :     fd_topo_tile_t * tile = &topo->tiles[ i ];
     291           0 :     fd_topo_configure_tile( tile, config );
     292           0 :   }
     293             : 
     294           0 :   fd_topob_auto_layout( topo, 0 );
     295           0 :   fd_topob_finish( topo, CALLBACKS );
     296           0 : }
     297             : 
     298             : static void
     299           0 : snapshot_load_topo1( config_t * config ) {
     300           0 :   snapshot_load_topo( config );
     301           0 : }
     302             : 
     303             : extern int * fd_log_private_shared_lock;
     304             : 
     305             : static void
     306             : snapshot_load_args( int *    pargc,
     307             :                     char *** pargv,
     308           0 :                     args_t * args ) {
     309           0 :   if( FD_UNLIKELY( fd_env_strip_cmdline_contains( pargc, pargv, "--help" ) ) ) {
     310           0 :     fputs(
     311           0 :       "\nUsage: firedancer-dev snapshot-load [GLOBAL FLAGS] [FLAGS]\n"
     312           0 :       "\n"
     313           0 :       "Global Flags:\n"
     314           0 :       "  --mainnet            Use Solana mainnet-beta defaults\n"
     315           0 :       "  --testnet            Use Solana testnet defaults\n"
     316           0 :       "  --devnet             Use Solana devnet defaults\n"
     317           0 :       "\n"
     318           0 :       "Flags:\n"
     319           0 :       "  --snapshot-dir PATH  Load/save snapshots from this directory\n"
     320           0 :       "  --offline            Do not attempt to download snapshots\n"
     321           0 :       "  --no-incremental     Disable incremental snapshot loading\n"
     322           0 :       "  --no-watch           Do not print periodic progress updates\n"
     323           0 :       "  --db <funk/vinyl>    Database engine\n"
     324           0 :       "  --db-sz <bytes>      Database size in bytes (e.g. 10e9 -> 10 GB)\n"
     325           0 :       "  --db-rec-max <num>   Database max record/account count (e.g. 10e6 -> 10M accounts)\n"
     326           0 :       "  --fsck               After loading, run database integrity checks\n"
     327           0 :       "  --lthash             After loading, recompute the account DB lthash\n"
     328           0 :       "  --accounts-hist      After loading, analyze account size distribution\n"
     329           0 :       "\n"
     330           0 :       "Vinyl database flags:\n"
     331           0 :       "  --vinyl-path <path>    Path to vinyl bstream file (overrides existing files!)\n"
     332           0 :       "  --vinyl-io <backend>   Vinyl I/O backend (default: bd)\n"
     333           0 :       "  --cache-sz <bytes>     DB cache size in bytes (e.g. 1e9 -> 1 GB)\n"
     334           0 :       "  --cache-rec-max <num>  DB cache max entry count (e.g. 1e6 -> 1M cache entries)\n"
     335           0 :       "\n"
     336           0 :       "Vinyl I/O backends:\n"
     337           0 :       "  bd  readv/writev-style single-threaded blocking I/O\n"
     338           0 :       "  mm  Memory-mapped I/O\n"
     339           0 :       "\n",
     340           0 :       stderr );
     341           0 :     exit( 0 );
     342           0 :   }
     343           0 :   memset( &args->snapshot_load, 0, sizeof(args->snapshot_load) );
     344             : 
     345           0 :   char const * snapshot_dir  = fd_env_strip_cmdline_cstr    ( pargc, pargv, "--snapshot-dir", NULL, NULL   );
     346           0 :   _Bool        offline       = fd_env_strip_cmdline_contains( pargc, pargv, "--offline"                    )!=0;
     347           0 :   _Bool        no_incremental= fd_env_strip_cmdline_contains( pargc, pargv, "--no-incremental"             )!=0;
     348           0 :   _Bool        no_watch      = fd_env_strip_cmdline_contains( pargc, pargv, "--no-watch"                   )!=0;
     349           0 :   char const * db            = fd_env_strip_cmdline_cstr    ( pargc, pargv, "--db",           NULL, "funk" );
     350           0 :   float        db_sz         = fd_env_strip_cmdline_float   ( pargc, pargv, "--db-sz",        NULL, 0.0f   );
     351           0 :   float        db_rec_max    = fd_env_strip_cmdline_float   ( pargc, pargv, "--db-rec-max",   NULL, 0.0f   );
     352           0 :   _Bool        fsck          = fd_env_strip_cmdline_contains( pargc, pargv, "--fsck"                       )!=0;
     353           0 :   _Bool        fsck_lthash   = fd_env_strip_cmdline_contains( pargc, pargv, "--fsck-lthash"                )!=0;
     354           0 :   _Bool        lthash        = fd_env_strip_cmdline_contains( pargc, pargv, "--lthash"                     )!=0;
     355           0 :   _Bool        accounts_hist = fd_env_strip_cmdline_contains( pargc, pargv, "--accounts-hist"              )!=0;
     356           0 :   char const * vinyl_path    = fd_env_strip_cmdline_cstr    ( pargc, pargv, "--vinyl-path",   NULL, NULL   );
     357           0 :   char const * vinyl_io      = fd_env_strip_cmdline_cstr    ( pargc, pargv, "--vinyl-io",     NULL, "bd"   );
     358           0 :   float        cache_sz      = fd_env_strip_cmdline_float   ( pargc, pargv, "--cache-sz",     NULL, 0.0f   );
     359           0 :   float        cache_rec_max = fd_env_strip_cmdline_float   ( pargc, pargv, "--cache-rec-max",NULL, 0.0f   );
     360             : 
     361           0 :   fd_cstr_ncpy( args->snapshot_load.snapshot_dir, snapshot_dir, sizeof(args->snapshot_load.snapshot_dir) );
     362           0 :   args->snapshot_load.fsck           = fsck;
     363           0 :   args->snapshot_load.fsck_lthash    = fsck_lthash;
     364           0 :   args->snapshot_load.lthash         = lthash;
     365           0 :   args->snapshot_load.accounts_hist  = accounts_hist;
     366           0 :   args->snapshot_load.offline        = offline;
     367           0 :   args->snapshot_load.no_incremental = no_incremental;
     368           0 :   args->snapshot_load.no_watch       = no_watch;
     369             : 
     370           0 :   if(      0==strcmp( db, "funk"  ) ) args->snapshot_load.is_vinyl = 0;
     371           0 :   else if( 0==strcmp( db, "vinyl" ) ) args->snapshot_load.is_vinyl = 1;
     372           0 :   else FD_LOG_ERR(( "invalid --db '%s' (must be 'funk' or 'vinyl')", db ));
     373             : 
     374           0 :   args->snapshot_load.db_sz         = (ulong)db_sz;
     375           0 :   args->snapshot_load.db_rec_max    = (ulong)db_rec_max;
     376           0 :   args->snapshot_load.cache_sz      = (ulong)cache_sz;
     377           0 :   args->snapshot_load.cache_rec_max = (ulong)cache_rec_max;
     378             : 
     379           0 :   fd_cstr_ncpy( args->snapshot_load.vinyl_path, vinyl_path, sizeof(args->snapshot_load.vinyl_path) );
     380             : 
     381           0 :   if( FD_UNLIKELY( strlen( vinyl_io )!=2UL ) ) FD_LOG_ERR(( "invalid --vinyl-io '%s'", vinyl_io ));
     382           0 :   fd_cstr_ncpy( args->snapshot_load.vinyl_io, vinyl_io, sizeof(args->snapshot_load.vinyl_io) );
     383           0 : }
     384             : 
     385             : static uint
     386             : fsck_funk( config_t * config,
     387           0 :            _Bool      lthash ) {
     388           0 :   uchar * props = config->topo.props;
     389           0 :   ulong funk_obj_id;  FD_TEST( (funk_obj_id  = fd_pod_query_ulong( props, "funk",       ULONG_MAX ) )!=ULONG_MAX );
     390           0 :   ulong locks_obj_id; FD_TEST( (locks_obj_id = fd_pod_query_ulong( props, "funk_locks", ULONG_MAX ) )!=ULONG_MAX );
     391           0 :   void * funk_shmem  = fd_topo_obj_laddr( &config->topo, funk_obj_id  );
     392           0 :   void * locks_shmem = fd_topo_obj_laddr( &config->topo, locks_obj_id );
     393           0 :   fd_funk_t funk[1];
     394           0 :   FD_TEST( fd_funk_join( funk, funk_shmem, locks_shmem ) );
     395           0 :   uint fsck_err = fd_accdb_fsck_funk( funk, lthash ? FD_ACCDB_FSCK_FLAGS_LTHASH : 0U );
     396           0 :   FD_TEST( fd_funk_leave( funk, NULL, NULL ) );
     397           0 :   return fsck_err;
     398           0 : }
     399             : 
     400             : static uint
     401             : fsck_vinyl( config_t * config,
     402           0 :            _Bool       lthash ) {
     403             :   /* Join meta index */
     404             : 
     405           0 :   fd_topo_t * topo = &config->topo;
     406           0 :   ulong meta_map_id  = fd_pod_query_ulong( topo->props, "accdb.meta_map",  ULONG_MAX );
     407           0 :   ulong meta_pool_id = fd_pod_query_ulong( topo->props, "accdb.meta_pool", ULONG_MAX );
     408           0 :   FD_TEST( meta_map_id!=ULONG_MAX && meta_pool_id!=ULONG_MAX );
     409           0 :   void * shmap = fd_topo_obj_laddr( topo, meta_map_id  );
     410           0 :   void * shele = fd_topo_obj_laddr( topo, meta_pool_id );
     411           0 :   fd_vinyl_meta_t meta[1];
     412           0 :   FD_TEST( fd_vinyl_meta_join( meta, shmap, shele ) );
     413             : 
     414             :   /* Join bstream */
     415             : 
     416           0 :   int dev_fd = open( config->paths.accounts, O_RDWR|O_CLOEXEC );
     417           0 :   if( FD_UNLIKELY( dev_fd<0 ) ) {
     418           0 :     FD_LOG_ERR(( "open(%s,O_RDWR|O_CLOEXEC) failed (%i-%s)",
     419           0 :                  config->paths.accounts, errno, fd_io_strerror( errno ) ));
     420           0 :   }
     421           0 :   void * mmio    = NULL;
     422           0 :   ulong  mmio_sz = 0UL;
     423           0 :   int map_err = fd_io_mmio_init( dev_fd, FD_IO_MMIO_MODE_READ_WRITE, &mmio, &mmio_sz );
     424           0 :   if( FD_UNLIKELY( map_err ) ) {
     425           0 :     FD_LOG_ERR(( "fd_io_mmio_init(%s,rw) failed (%i-%s)",
     426           0 :                  config->paths.accounts, map_err, fd_io_strerror( map_err ) ));
     427           0 :   }
     428           0 :   FD_TEST( 0==close( dev_fd ) );
     429           0 :   ulong  io_spad_max = 1UL<<20;
     430           0 :   void * io_mm       = aligned_alloc( fd_vinyl_io_mm_align(), fd_vinyl_io_mm_footprint( io_spad_max ) );
     431           0 :   FD_TEST( io_mm );
     432           0 :   fd_vinyl_io_t * io = fd_vinyl_io_mm_init( io_mm, io_spad_max, mmio, mmio_sz, 0, NULL, 0UL, 0UL );
     433           0 :   FD_TEST( io );
     434             : 
     435             :   /* Run verifier */
     436             : 
     437           0 :   uint fsck_err = fd_accdb_fsck_vinyl( io, meta, lthash ? FD_ACCDB_FSCK_FLAGS_LTHASH : 0U );
     438             : 
     439             :   /* Clean up */
     440             : 
     441           0 :   FD_TEST( fd_vinyl_io_fini( io ) );
     442           0 :   free( io_mm );
     443           0 :   fd_io_mmio_fini( mmio, mmio_sz );
     444           0 :   fd_vinyl_meta_leave( meta );
     445           0 :   return fsck_err;
     446           0 : }
     447             : 
     448             : /* ACCOUNTS_HIST_N (32) is chosen to make the histogram lightweight.
     449             :    And because accounts can have a data size in the range [0, 10MiB],
     450             :    the width of the bins increments in powers of 2.  In the future, it
     451             :    should be possible to pass this as a configuration parameter. */
     452           0 : #define ACCOUNTS_HIST_N (32)
     453             : 
     454             : struct accounts_hist {
     455             :   ulong total_cnt;
     456             :   ulong total_acc;
     457             :   ulong bin_thi[ ACCOUNTS_HIST_N ];
     458             :   ulong bin_cnt[ ACCOUNTS_HIST_N ];
     459             :   ulong bin_acc[ ACCOUNTS_HIST_N ];
     460             :   ulong bin_min[ ACCOUNTS_HIST_N ];
     461             :   ulong bin_max[ ACCOUNTS_HIST_N ];
     462             :   ulong token_cnt;
     463             : };
     464             : typedef struct accounts_hist accounts_hist_t;
     465             : 
     466             : static inline void
     467           0 : accounts_hist_reset( accounts_hist_t * hist ) {
     468           0 :   hist->total_cnt = 0UL;
     469           0 :   hist->total_acc = 0UL;
     470           0 :   for( int i=0; i < ACCOUNTS_HIST_N; i++ ) {
     471           0 :     hist->bin_thi[ i ] = fd_ulong_if( i > 0, fd_pow2( ulong, i-1 ), 0UL );
     472           0 :     hist->bin_cnt[ i ] = 0UL;
     473           0 :     hist->bin_acc[ i ] = 0UL;
     474           0 :     hist->bin_min[ i ] = ULONG_MAX;
     475           0 :     hist->bin_max[ i ] = 0UL;
     476           0 :   }
     477           0 :   hist->token_cnt = 0UL;
     478           0 : }
     479             : 
     480             : static inline void
     481             : accounts_hist_update( accounts_hist_t * hist,
     482           0 :                       ulong             account_sz ) {
     483           0 :   hist->total_cnt += 1UL;
     484           0 :   hist->total_acc += account_sz;
     485           0 :   int i=0;
     486             :   /* This allows for arbitrary thresholds - not optimized for pow2
     487             :      bins. */
     488           0 :   for( ; i < ACCOUNTS_HIST_N; i++ ) {
     489           0 :     if( FD_UNLIKELY( account_sz <= hist->bin_thi[ i ] )) {
     490           0 :       hist->bin_cnt[ i ] += 1;
     491           0 :       hist->bin_acc[ i ] += account_sz;
     492           0 :       hist->bin_min[ i ] = fd_ulong_min( hist->bin_min[ i ], account_sz );
     493           0 :       hist->bin_max[ i ] = fd_ulong_max( hist->bin_max[ i ], account_sz );
     494           0 :       break;
     495           0 :     }
     496           0 :   }
     497           0 :   FD_TEST( i < ACCOUNTS_HIST_N );
     498           0 : }
     499             : 
     500             : static inline int
     501           0 : accounts_hist_check( accounts_hist_t const * hist ) {
     502           0 :   ulong cnt = 0UL;
     503           0 :   ulong acc = 0UL;
     504           0 :   for( int i=0; i < ACCOUNTS_HIST_N; i++ ) {
     505           0 :     cnt += hist->bin_cnt[ i ];
     506           0 :     acc += hist->bin_acc[ i ];
     507           0 :   }
     508           0 :   if( cnt != hist->total_cnt ) return -1;
     509           0 :   if( acc != hist->total_acc ) return -2;
     510           0 :   return 0;
     511           0 : }
     512             : 
     513             : static void
     514           0 : accounts_hist_print( accounts_hist_t const * hist ) {
     515           0 :   double hist_total_cnt_M   = (double)hist->total_cnt / (double)1.0e6;
     516           0 :   double hist_total_cnt_GiB = (double)hist->total_acc / (double)1073741824;
     517           0 :   printf( "\n" );
     518           0 :   printf( "hist_total_cnt %16lu ( %6.1f M   )\n", hist->total_cnt, hist_total_cnt_M   );
     519           0 :   printf( "hist_total_acc %16lu ( %6.1f GiB )\n", hist->total_acc, hist_total_cnt_GiB );
     520           0 :   printf( "   bin_th_lo <  sz <=    bin_th_hi |    bin_cnt (run_sum%%) |      bin_acc (run_sum%%) |    bin_min B |    bin_max B |    bin_avg B |\n" );
     521           0 :   ulong sum_cnt = 0UL;
     522           0 :   ulong sum_acc = 0UL;
     523           0 :   for( int i=0; i < ACCOUNTS_HIST_N; i++ ) {
     524             :     /* bin thresholds */
     525           0 :     ulong hist_bin_tlo      = hist->bin_thi[ fd_int_if( i>0, i-1, i ) ];
     526           0 :     ulong hist_bin_thi      = hist->bin_thi[ i ];
     527             :     /* bin cnt */
     528           0 :     ulong hist_bin_cnt      = hist->bin_cnt[ i ];
     529           0 :     sum_cnt                += hist->bin_cnt[ i ];
     530           0 :     double sum_cnt_p        = (double)(sum_cnt * 100) / (double)hist->total_cnt;
     531           0 :     double hist_bin_cnt_K   = (double)(hist_bin_cnt) / (double)1.0e3;
     532             :     /* bin acc */
     533           0 :     ulong hist_bin_acc      = hist->bin_acc[ i ];
     534           0 :     sum_acc                += hist->bin_acc[ i ];
     535           0 :     double sum_acc_p        = (double)(sum_acc * 100) / (double)hist->total_acc;
     536           0 :     double hist_bin_acc_MiB = (double)(hist_bin_acc) / (double)1048576.0f;
     537             :     /* bin min, max, avg */
     538           0 :     ulong hist_bin_min      = fd_ulong_if( hist->bin_cnt[ i ] > 0, hist->bin_min[ i ], 0UL );
     539           0 :     ulong hist_bin_max      = hist->bin_max[ i ];
     540           0 :     ulong hist_bin_avg      = hist->bin_cnt[ i ] > 0 ? hist->bin_acc[ i ] / hist->bin_cnt[ i ] : 0UL;
     541             :     /* log */
     542           0 :     char buf[256];
     543           0 :     char * p = fd_cstr_init( buf );
     544           0 :     p = fd_cstr_append_printf( p, "%12lu %s sz <= %12lu |", hist_bin_tlo, i==0? "<=" : "< ", hist_bin_thi );
     545           0 :     p = fd_cstr_append_printf( p, " %8.1f K (%6.1f %%) |", hist_bin_cnt_K, sum_cnt_p );
     546           0 :     p = fd_cstr_append_printf( p, " %8.1f MiB (%6.1f %%) |", hist_bin_acc_MiB, sum_acc_p );
     547           0 :     p = fd_cstr_append_printf( p, " %12lu | %12lu | %12lu |", hist_bin_min, hist_bin_max, hist_bin_avg );
     548           0 :     p = fd_cstr_append_printf( p, "\n" );
     549           0 :     printf( "%s", buf );
     550           0 :   }
     551           0 :   printf( "\n" );
     552           0 : }
     553             : 
     554             : static void
     555             : accounts_hist_vinyl( accounts_hist_t * hist,
     556           0 :                      config_t *        config ) {
     557           0 :   fd_topo_t * topo = &config->topo;
     558           0 :   ulong meta_map_id  = fd_pod_query_ulong( topo->props, "accdb.meta_map",  ULONG_MAX );
     559           0 :   ulong meta_pool_id = fd_pod_query_ulong( topo->props, "accdb.meta_pool", ULONG_MAX );
     560           0 :   FD_TEST( meta_map_id!=ULONG_MAX && meta_pool_id!=ULONG_MAX );
     561           0 :   void * shmap = fd_topo_obj_laddr( topo, meta_map_id  );
     562           0 :   void * shele = fd_topo_obj_laddr( topo, meta_pool_id );
     563           0 :   fd_vinyl_meta_t meta[1];
     564           0 :   FD_TEST( fd_vinyl_meta_join( meta, shmap, shele ) );
     565             : 
     566           0 :   for( ulong ele_i=0; ele_i < fd_vinyl_meta_ele_max( meta ); ele_i++ ) {
     567           0 :     fd_vinyl_meta_ele_t const * ele = meta->ele + ele_i;
     568           0 :     if( FD_UNLIKELY( fd_vinyl_meta_private_ele_is_free( meta->ctx, ele ) ) ) continue;
     569           0 :     accounts_hist_update( hist, (ulong)ele->phdr.info.val_sz );
     570           0 :   }
     571           0 : }
     572             : 
     573             : static void
     574             : accounts_hist_funk( accounts_hist_t * hist,
     575           0 :                     config_t *        config ) {
     576           0 :   fd_topo_t * topo = &config->topo;
     577           0 :   ulong funk_obj_id;  FD_TEST( (funk_obj_id  = fd_pod_query_ulong( topo->props, "funk",       ULONG_MAX ) )!=ULONG_MAX );
     578           0 :   ulong locks_obj_id; FD_TEST( (locks_obj_id = fd_pod_query_ulong( topo->props, "funk_locks", ULONG_MAX ) )!=ULONG_MAX );
     579           0 :   FD_TEST( funk_obj_id!=ULONG_MAX );
     580           0 :   void * funk_shmem  = fd_topo_obj_laddr( topo, funk_obj_id );
     581           0 :   void * locks_shmem = fd_topo_obj_laddr( topo, locks_obj_id );
     582           0 :   fd_funk_t funk[1];
     583           0 :   FD_TEST( fd_funk_join( funk, funk_shmem, locks_shmem ) );
     584             : 
     585           0 :   fd_funk_rec_map_t const * rec_map = funk->rec_map;
     586           0 :   fd_funk_rec_t const * ele = rec_map->ele;
     587           0 :   fd_funk_rec_map_shmem_private_chain_t const * chain = fd_funk_rec_map_shmem_private_chain_const( rec_map->map, 0UL );
     588           0 :   ulong chain_cnt = fd_funk_rec_map_chain_cnt( rec_map );
     589           0 :   for( ulong chain_i=0UL; chain_i < chain_cnt; chain_i++ ) {
     590           0 :     ulong ver_cnt = chain[ chain_i ].ver_cnt;
     591           0 :     ulong ele_cnt = fd_funk_rec_map_private_vcnt_cnt( ver_cnt );
     592           0 :     ulong head_i  = fd_funk_rec_map_private_idx( chain[ chain_i ].head_cidx );
     593           0 :     ulong ele_i   = head_i;
     594           0 :     for( ulong ele_rem=ele_cnt; ele_rem; ele_rem-- ) {
     595           0 :       fd_funk_xid_key_pair_t const * pair = &ele[ ele_i ].pair;
     596           0 :       fd_funk_rec_query_t query[1];
     597           0 :       fd_funk_rec_t * rec = fd_funk_rec_query_try( funk, pair->xid, pair->key, query );
     598           0 :       FD_TEST( !!rec );
     599           0 :       fd_account_meta_t * meta = fd_funk_val( rec, funk->wksp );
     600           0 :       FD_TEST( !!meta );
     601           0 :       accounts_hist_update( hist, sizeof(fd_account_meta_t) + meta->dlen );
     602           0 :     }
     603           0 :   }
     604           0 : }
     605             : 
     606             : /* fixup_config applies command-line arguments to config, overriding
     607             :    defaults / config file */
     608             : 
     609             : static void
     610             : fixup_config( config_t *     config,
     611           0 :               args_t const * args ) {
     612           0 :   fd_topo_t * topo = &config->topo;
     613           0 :   if( args->snapshot_load.snapshot_dir[0] ) {
     614           0 :     fd_cstr_ncpy( config->paths.snapshots, args->snapshot_load.snapshot_dir, sizeof(config->paths.snapshots) );
     615           0 :   }
     616             : 
     617           0 :   if( args->snapshot_load.vinyl_path[0] ) {
     618           0 :     fd_cstr_ncpy( config->paths.accounts, args->snapshot_load.vinyl_path, sizeof(config->paths.accounts) );
     619           0 :   }
     620             : 
     621           0 :   if( args->snapshot_load.db_rec_max ) {
     622           0 :     config->firedancer.accounts.max_accounts = args->snapshot_load.db_rec_max;
     623           0 :   }
     624             : 
     625           0 :   if( args->snapshot_load.db_sz ) {
     626           0 :     config->firedancer.accounts.file_size_gib = fd_ulong_align_up( args->snapshot_load.db_sz, (1UL<<30) )>>30;
     627           0 :   }
     628             : 
     629           0 :   if( args->snapshot_load.cache_sz ) {
     630           0 :     config->firedancer.accounts.cache_size_gib = fd_ulong_align_up( args->snapshot_load.cache_sz, (1UL<<30) )>>30;
     631           0 :   }
     632             : 
     633           0 :   if( args->snapshot_load.cache_rec_max ) {
     634           0 :     config->firedancer.accounts.mean_account_footprint =
     635           0 :         (config->firedancer.accounts.cache_size_gib << 30) / args->snapshot_load.cache_rec_max;
     636           0 :   }
     637             : 
     638           0 :   if( args->snapshot_load.is_vinyl ) {
     639           0 :     config->firedancer.accounts.in_memory_only = 0;
     640             : 
     641           0 :     char const * io_mode = args->snapshot_load.vinyl_io;
     642           0 :     if(      0==strcmp( io_mode, "ur" ) ) fd_cstr_ncpy( config->firedancer.accounts.io_provider, "io_uring",  sizeof(config->firedancer.accounts.io_provider) );
     643           0 :     else if( 0==strcmp( io_mode, "bd" ) ) fd_cstr_ncpy( config->firedancer.accounts.io_provider, "portable",  sizeof(config->firedancer.accounts.io_provider) );
     644           0 :     else FD_LOG_ERR(( "unsupported --vinyl-io '%s' (valid options are 'bd' and 'ur')", io_mode ));
     645           0 :   }
     646             : 
     647           0 :   if( args->snapshot_load.offline ) {
     648           0 :     config->firedancer.snapshots.sources.gossip.allow_any      = 0;
     649           0 :     config->firedancer.snapshots.sources.gossip.allow_list_cnt = 0;
     650           0 :     config->firedancer.snapshots.sources.servers_cnt           = 0;
     651           0 :   }
     652             : 
     653           0 :   if( args->snapshot_load.no_incremental ) {
     654           0 :     config->firedancer.snapshots.incremental_snapshots = 0;
     655           0 :   }
     656             : 
     657           0 :   config->development.snapshots.disable_lthash_verification = !args->snapshot_load.lthash;
     658             : 
     659             :   /* FIXME Unfortunately, the fdctl boot procedure constructs the
     660             :            topology before parsing command-line arguments.  So, here,
     661             :            we construct the topology again (a third time ... sigh). */
     662           0 :   snapshot_load_topo( config );
     663             : 
     664           0 :   fd_topob_auto_layout( topo, 0 );
     665           0 :   fd_topob_finish( topo, CALLBACKS );
     666           0 : }
     667             : 
     668             : static void
     669             : snapshot_load_cmd_fn( args_t *   args,
     670           0 :                       config_t * config ) {
     671           0 :   fixup_config( config, args );
     672           0 :   if( FD_UNLIKELY( config->firedancer.snapshots.sources.gossip.allow_any || 0UL!=config->firedancer.snapshots.sources.gossip.allow_list_cnt ) ) {
     673           0 :     FD_LOG_ERR(( "snapshot-load command is incompatible with gossip snapshot sources" ));
     674           0 :   }
     675           0 :   _Bool watch = !args->snapshot_load.no_watch;
     676             : 
     677           0 :   fd_topo_t * topo = &config->topo;
     678             : 
     679           0 :   args_t configure_args = {
     680           0 :     .configure.command = CONFIGURE_CMD_INIT,
     681           0 :   };
     682             : 
     683           0 :   for( ulong i=0UL; STAGES[ i ]; i++ )
     684           0 :     configure_args.configure.stages[ i ] = STAGES[ i ];
     685           0 :   configure_cmd_fn( &configure_args, config );
     686             : 
     687           0 :   run_firedancer_init( config, 1, 0 );
     688             : 
     689           0 :   fd_log_private_shared_lock[ 1 ] = 0;
     690           0 :   fd_topo_join_workspaces( topo, FD_SHMEM_JOIN_MODE_READ_WRITE, FD_TOPO_CORE_DUMP_LEVEL_DISABLED );
     691           0 :   fd_topo_fill( topo );
     692             : 
     693           0 :   fd_topo_tile_t * snapct_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapct", 0UL ) ];
     694           0 :   fd_topo_tile_t * snapld_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapld", 0UL ) ];
     695           0 :   fd_topo_tile_t * snapdc_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapdc", 0UL ) ];
     696           0 :   fd_topo_tile_t * snapin_tile = &topo->tiles[ fd_topo_find_tile( topo, "snapin", 0UL ) ];
     697           0 :   ulong            snapwm_idx  =               fd_topo_find_tile( topo, "snapwm", 0UL );
     698           0 :   ulong            snapwh_idx  =               fd_topo_find_tile( topo, "snapwh", 0UL );
     699           0 :   ulong            snapwr_idx  =               fd_topo_find_tile( topo, "snapwr", 0UL );
     700           0 :   fd_topo_tile_t * snapwm_tile = snapwm_idx!=ULONG_MAX ? &topo->tiles[ snapwm_idx ] : NULL;
     701           0 :   fd_topo_tile_t * snapwh_tile = snapwh_idx!=ULONG_MAX ? &topo->tiles[ snapwh_idx ] : NULL;
     702           0 :   fd_topo_tile_t * snapwr_tile = snapwr_idx!=ULONG_MAX ? &topo->tiles[ snapwr_idx ] : NULL;
     703           0 :   ulong            snapla_idx  =               fd_topo_find_tile( topo, "snapla", 0UL );
     704           0 :   fd_topo_tile_t * snapla_tile = snapla_idx!=ULONG_MAX ? &topo->tiles[ snapla_idx ] : NULL;
     705           0 :   ulong            snapls_idx  =               fd_topo_find_tile( topo, "snapls", 0UL );
     706           0 :   fd_topo_tile_t * snapls_tile = snapls_idx!=ULONG_MAX ? &topo->tiles[ snapls_idx ] : NULL;
     707           0 :   ulong            snaplh_idx  =               fd_topo_find_tile( topo, "snaplh", 0UL );
     708           0 :   fd_topo_tile_t * snaplh_tile = snaplh_idx!=ULONG_MAX ? &topo->tiles[ snaplh_idx ] : NULL;
     709           0 :   ulong            snaplv_idx  =               fd_topo_find_tile( topo, "snaplv", 0UL );
     710           0 :   fd_topo_tile_t * snaplv_tile = snaplv_idx!=ULONG_MAX ? &topo->tiles[ snaplv_idx ] : NULL;
     711             : 
     712           0 :   double tick_per_ns = fd_tempo_tick_per_ns( NULL );
     713           0 :   double ns_per_tick = 1.0/tick_per_ns;
     714             : 
     715           0 :   long start = fd_log_wallclock();
     716           0 :   fd_topo_run_single_process( topo, 2, config->uid, config->gid, fdctl_tile_run );
     717             : 
     718           0 :   ulong volatile * const snapct_metrics = fd_metrics_tile( snapct_tile->metrics );
     719           0 :   ulong volatile * const snapld_metrics = fd_metrics_tile( snapld_tile->metrics );
     720           0 :   ulong volatile * const snapdc_metrics = fd_metrics_tile( snapdc_tile->metrics );
     721           0 :   ulong volatile * const snapin_metrics = fd_metrics_tile( snapin_tile->metrics );
     722           0 :   ulong volatile * const snapwm_metrics = snapwm_tile ? fd_metrics_tile( snapwm_tile->metrics ) : NULL;
     723           0 :   ulong volatile * const snapwh_metrics = snapwh_tile ? fd_metrics_tile( snapwh_tile->metrics ) : NULL;
     724           0 :   ulong volatile * const snapwr_metrics = snapwr_tile ? fd_metrics_tile( snapwr_tile->metrics ) : NULL;
     725           0 :   ulong volatile * const snapla_metrics = snapla_tile ? fd_metrics_tile( snapla_tile->metrics ) : NULL;
     726           0 :   ulong volatile * const snapls_metrics = snapls_tile ? fd_metrics_tile( snapls_tile->metrics ) : NULL;
     727           0 :   ulong volatile * const snaplh_metrics = snaplh_tile ? fd_metrics_tile( snaplh_tile->metrics ) : NULL;
     728           0 :   ulong volatile * const snaplv_metrics = snaplv_tile ? fd_metrics_tile( snaplv_tile->metrics ) : NULL;
     729             : 
     730           0 :   ulong total_off_old    = 0UL;
     731           0 :   ulong decomp_off_old   = 0UL;
     732           0 :   ulong vinyl_off_old    = 0UL;
     733           0 :   ulong snapld_backp_old = 0UL;
     734           0 :   ulong snapld_wait_old  = 0UL;
     735           0 :   ulong snapdc_backp_old = 0UL;
     736           0 :   ulong snapdc_wait_old  = 0UL;
     737           0 :   ulong snapin_backp_old = 0UL;
     738           0 :   ulong snapin_wait_old  = 0UL;
     739           0 :   ulong snapwm_backp_old = 0UL;
     740           0 :   ulong snapwm_wait_old  = 0UL;
     741           0 :   ulong snapwh_backp_old = 0UL;
     742           0 :   ulong snapwh_wait_old  = 0UL;
     743           0 :   ulong snapwr_wait_old  = 0UL;
     744           0 :   ulong snapla_backp_old = 0UL;
     745           0 :   ulong snapla_wait_old  = 0UL;
     746           0 :   ulong snapls_backp_old = 0UL;
     747           0 :   ulong snapls_wait_old  = 0UL;
     748           0 :   ulong snaplh_backp_old = 0UL;
     749           0 :   ulong snaplh_wait_old  = 0UL;
     750           0 :   ulong snaplv_backp_old = 0UL;
     751           0 :   ulong snaplv_wait_old  = 0UL;
     752           0 :   ulong acc_cnt_old      = 0UL;
     753             : 
     754           0 :   sleep( 1 );
     755           0 :   if( watch ) {
     756           0 :     puts( "" );
     757           0 :     puts( "Columns:" );
     758           0 :     puts( "- comp:  Compressed bandwidth"             );
     759           0 :     puts( "- raw:   Uncompressed bandwidth"           );
     760           0 :     puts( "- backp: Backpressured by downstream tile" );
     761           0 :     puts( "- stall: Waiting on upstream tile"         );
     762           0 :     puts( "- acc:   Number of accounts"               );
     763           0 :     puts( "" );
     764           0 :     fputs( "--------------------------------------------", stdout );
     765           0 :     if( snapwr_tile )      fputs( "--------------", stdout );
     766           0 :     if( snapls_tile )      fputs( "[ld],[dc],[in],[la],[ls]--------[ld],[dc],[in],[la],[ls]", stdout );
     767           0 :     else if( snaplv_tile ) fputs( "[ld],[dc],[in],[wm],[wh],[lh],[lv]--------[ld],[dc],[in],[wm],[wh],[wr],[lh],[lv]", stdout );
     768           0 :     else if( snapwr_tile ) fputs( "[ld],[dc],[in],[wm],[wh]--------[ld],[dc],[in],[wm],[wh],[wr]", stdout );
     769           0 :     else                   fputs( "[ld],[dc],[in]--------[ld],[dc],[in]", stdout );
     770           0 :     puts( "--------------" );
     771           0 :   }
     772             : 
     773           0 :   long next = start+1000L*1000L*1000L;
     774           0 :   for(;;) {
     775           0 :     ulong snapct_status = FD_VOLATILE_CONST( snapct_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
     776           0 :     ulong snapld_status = FD_VOLATILE_CONST( snapld_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
     777           0 :     ulong snapdc_status = FD_VOLATILE_CONST( snapdc_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
     778           0 :     ulong snapin_status = FD_VOLATILE_CONST( snapin_metrics[ MIDX( GAUGE, TILE, STATUS ) ] );
     779           0 :     ulong snapls_status = snapls_metrics ? FD_VOLATILE_CONST( snapls_metrics[ MIDX( GAUGE, TILE, STATUS ) ] ) : 2UL;
     780             : 
     781           0 :     if( FD_UNLIKELY( snapct_status==2UL && snapld_status==2UL && snapdc_status==2UL && snapin_status==2UL && snapls_status==2UL ) ) break;
     782             : 
     783           0 :     long cur = fd_log_wallclock();
     784           0 :     if( FD_UNLIKELY( cur<next ) ) {
     785           0 :       long sleep_nanos = fd_long_min( 1000L*1000L, next-cur );
     786           0 :       FD_TEST( !fd_sys_util_nanosleep(  (uint)(sleep_nanos/(1000L*1000L*1000L)), (uint)(sleep_nanos%(1000L*1000L*1000L)) ) );
     787           0 :       continue;
     788           0 :     }
     789             : 
     790           0 :     ulong total_off    = snapct_metrics[ MIDX( GAUGE, SNAPCT, FULL_BYTES_READ ) ] +
     791           0 :                          snapct_metrics[ MIDX( GAUGE, SNAPCT, INCREMENTAL_BYTES_READ ) ];
     792           0 :     ulong decomp_off   = snapdc_metrics[ MIDX( GAUGE, SNAPDC, FULL_DECOMPRESSED_BYTES_WRITTEN ) ] +
     793           0 :                          snapdc_metrics[ MIDX( GAUGE, SNAPDC, INCREMENTAL_DECOMPRESSED_BYTES_WRITTEN ) ];
     794           0 :     ulong vinyl_off    = snapwr_tile ? snapwr_metrics[ MIDX( GAUGE, SNAPWR, FILE_USED_BYTES ) ] : 0UL;
     795           0 :     ulong snapld_backp = snapld_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
     796           0 :     ulong snapld_wait  = snapld_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapld_backp;
     797           0 :     ulong snapdc_backp = snapdc_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
     798           0 :     ulong snapdc_wait  = snapdc_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapdc_backp;
     799           0 :     ulong snapin_backp = snapin_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
     800           0 :     ulong snapin_wait  = snapin_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapin_backp;
     801           0 :     ulong snapwm_backp = 0UL;
     802           0 :     ulong snapwm_wait  = 0UL;
     803           0 :     ulong snapwh_backp = 0UL;
     804           0 :     ulong snapwh_wait  = 0UL;
     805           0 :     ulong snapwr_backp = 0UL;
     806           0 :     ulong snapwr_wait  = 0UL;
     807           0 :     ulong snapla_backp = snapla_metrics ? snapla_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ] : 0UL;
     808           0 :     ulong snapla_wait  = snapla_metrics ? snapla_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapla_backp : 0UL;
     809           0 :     ulong snapls_backp = snapls_metrics ? snapls_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ] : 0UL;
     810           0 :     ulong snapls_wait  = snapls_metrics ? snapls_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapls_backp : 0UL;
     811           0 :     ulong snaplh_backp = snaplh_metrics ? snaplh_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ] : 0UL;
     812           0 :     ulong snaplh_wait  = snaplh_metrics ? snaplh_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snaplh_backp : 0UL;
     813           0 :     ulong snaplv_backp = snaplv_metrics ? snaplv_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ] : 0UL;
     814           0 :     ulong snaplv_wait  = snaplv_metrics ? snaplv_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snaplv_backp : 0UL;
     815           0 :     if( snapwr_tile ) {
     816           0 :       snapwm_backp     = snapwm_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
     817           0 :       snapwm_wait      = snapwm_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapwm_backp;
     818           0 :       snapwh_backp     = snapwh_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
     819           0 :       snapwh_wait      = snapwh_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapwh_backp;
     820           0 :       snapwr_backp     = snapwr_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_BACKPRESSURE_PREFRAG ) ];
     821           0 :       snapwr_wait      = snapwr_metrics[ MIDX( COUNTER, TILE, REGIME_DURATION_NANOS_CAUGHT_UP_POSTFRAG   ) ] + snapwr_backp;
     822           0 :     }
     823             : 
     824           0 :     double progress = 100.0 * (double)snapct_metrics[ MIDX( GAUGE, SNAPCT, FULL_BYTES_READ ) ] / (double)snapct_metrics[ MIDX( GAUGE, SNAPCT, FULL_BYTES_TOTAL ) ];
     825             : 
     826           0 :     ulong acc_cnt      = snapin_metrics[ MIDX( GAUGE, SNAPIN, ACCOUNTS_LOADED    ) ];
     827             : 
     828           0 :     if( watch ) {
     829           0 :       printf( "%5.1f %% comp=%4.0fMB/s snap=%4.0fMB/s",
     830           0 :               progress,
     831           0 :               (double)( total_off -total_off_old  )/1e6,
     832           0 :               (double)( decomp_off-decomp_off_old )/1e6 );
     833           0 :       if( snapwr_tile ) {
     834           0 :         printf( " vinyl=%4.0fMB/s", (double)( vinyl_off - vinyl_off_old )/1e6 );
     835           0 :       }
     836             : 
     837           0 :       printf( " backp=(%3.0f%%,%3.0f%%,%3.0f%%",
     838           0 :           ( (double)( snapld_backp-snapld_backp_old )*ns_per_tick )/1e7,
     839           0 :           ( (double)( snapdc_backp-snapdc_backp_old )*ns_per_tick )/1e7,
     840           0 :           ( (double)( snapin_backp-snapin_backp_old )*ns_per_tick )/1e7 );
     841           0 :       if( snapls_tile ) {
     842           0 :         printf( ",%3.0f%%,%3.0f%%",
     843           0 :           ( (double)( snapla_backp-snapla_backp_old )*ns_per_tick )/1e7,
     844           0 :           ( (double)( snapls_backp-snapls_backp_old )*ns_per_tick )/1e7 );
     845           0 :       }
     846           0 :       if( snapwr_tile ) {
     847           0 :         printf( ",%3.0f%%,%3.0f%%",
     848           0 :           ( (double)( snapwm_backp-snapwm_backp_old )*ns_per_tick )/1e7,
     849           0 :           ( (double)( snapwh_backp-snapwh_backp_old )*ns_per_tick )/1e7 );
     850           0 :       }
     851           0 :       if( snaplv_tile ) {
     852           0 :         printf( ",%3.0f%%,%3.0f%%",
     853           0 :           ( (double)( snaplh_backp-snaplh_backp_old )*ns_per_tick )/1e7,
     854           0 :           ( (double)( snaplv_backp-snaplv_backp_old )*ns_per_tick )/1e7 );
     855           0 :       }
     856           0 :       printf( ")" );
     857             : 
     858           0 :       printf( " busy=(%3.0f%%,%3.0f%%,%3.0f%%",
     859           0 :           100-( ( (double)( snapld_wait-snapld_wait_old )*ns_per_tick )/1e7 ),
     860           0 :           100-( ( (double)( snapdc_wait-snapdc_wait_old )*ns_per_tick )/1e7 ),
     861           0 :           100-( ( (double)( snapin_wait-snapin_wait_old )*ns_per_tick )/1e7 ) );
     862           0 :       if( snapls_tile )  {
     863           0 :         printf( ",%3.0f%%,%3.0f%%",
     864           0 :           100-( ( (double)( snapla_wait-snapla_wait_old )*ns_per_tick )/1e7 ),
     865           0 :           100-( ( (double)( snapls_wait-snapls_wait_old )*ns_per_tick )/1e7 ) );
     866           0 :       }
     867           0 :       if( snapwr_tile ) {
     868           0 :         printf( ",%3.0f%%,%3.0f%%,%3.0f%%",
     869           0 :           100-( ( (double)( snapwm_wait-snapwm_wait_old )*ns_per_tick )/1e7 ),
     870           0 :           100-( ( (double)( snapwh_wait-snapwh_wait_old )*ns_per_tick )/1e7 ),
     871           0 :           100-( ( (double)( snapwr_wait-snapwr_wait_old )*ns_per_tick )/1e7 ) );
     872           0 :       }
     873           0 :       if( snaplv_tile )  {
     874           0 :         printf( ",%3.0f%%,%3.0f%%",
     875           0 :           100-( ( (double)( snaplh_wait-snaplh_wait_old )*ns_per_tick )/1e7 ),
     876           0 :           100-( ( (double)( snaplv_wait-snaplv_wait_old )*ns_per_tick )/1e7 ) );
     877           0 :       }
     878           0 :       printf( ")" );
     879             : 
     880           0 :       printf( " acc=%4.1f M/s\n",
     881           0 :               (double)( acc_cnt-acc_cnt_old  )/1e6 );
     882           0 :       fflush( stdout );
     883           0 :     }
     884           0 :     total_off_old    = total_off;
     885           0 :     decomp_off_old   = decomp_off;
     886           0 :     vinyl_off_old    = vinyl_off;
     887           0 :     snapld_backp_old = snapld_backp;
     888           0 :     snapld_wait_old  = snapld_wait;
     889           0 :     snapdc_backp_old = snapdc_backp;
     890           0 :     snapdc_wait_old  = snapdc_wait;
     891           0 :     snapin_backp_old = snapin_backp;
     892           0 :     snapin_wait_old  = snapin_wait;
     893           0 :     snapwm_backp_old = snapwm_backp;
     894           0 :     snapwm_wait_old  = snapwm_wait;
     895           0 :     snapwh_backp_old = snapwh_backp;
     896           0 :     snapwh_wait_old  = snapwh_wait;
     897           0 :     snapwr_wait_old  = snapwr_wait;
     898           0 :     snapla_backp_old = snapla_backp;
     899           0 :     snapla_wait_old  = snapla_wait;
     900           0 :     snapls_backp_old = snapls_backp;
     901           0 :     snapls_wait_old  = snapls_wait;
     902           0 :     snaplh_backp_old = snaplh_backp;
     903           0 :     snaplh_wait_old  = snaplh_wait;
     904           0 :     snaplv_backp_old = snaplv_backp;
     905           0 :     snaplv_wait_old  = snaplv_wait;
     906           0 :     acc_cnt_old      = acc_cnt;
     907             : 
     908           0 :     next+=1000L*1000L*1000L;
     909           0 :   }
     910             : 
     911           0 :   if( args->snapshot_load.fsck ) {
     912           0 :     FD_LOG_NOTICE(( "FSCK: starting" ));
     913           0 :     uint fsck_err;
     914           0 :     if( snapwr_tile ) fsck_err = fsck_vinyl( config, args->snapshot_load.fsck_lthash );
     915           0 :     else              fsck_err = fsck_funk ( config, args->snapshot_load.fsck_lthash );
     916           0 :     if( !fsck_err ) {
     917           0 :       FD_LOG_NOTICE(( "FSCK: passed" ));
     918           0 :     } else {
     919           0 :       FD_LOG_ERR(( "FSCK: errors detected" ));
     920           0 :     }
     921           0 :   }
     922             : 
     923           0 :   if( args->snapshot_load.accounts_hist ) {
     924           0 :     accounts_hist_t hist[1];
     925           0 :     accounts_hist_reset( hist );
     926           0 :     FD_LOG_NOTICE(( "Accounts histogram: starting" ));
     927           0 :     if( snapwr_tile ) accounts_hist_vinyl( hist, config );
     928           0 :     else              accounts_hist_funk ( hist, config );
     929           0 :     FD_TEST( !accounts_hist_check( hist ) );
     930           0 :     accounts_hist_print( hist );
     931           0 :   }
     932           0 : }
     933             : 
     934             : action_t fd_action_snapshot_load = {
     935             :   .name = NAME,
     936             :   .topo = snapshot_load_topo1,
     937             :   .perm = dev_cmd_perm,
     938             :   .args = snapshot_load_args,
     939             :   .fn   = snapshot_load_cmd_fn
     940             : };

Generated by: LCOV version 1.14