LCOV - code coverage report
Current view: top level - flamenco/snapshot - fd_snapshot_main.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 261 0.0 %
Date: 2024-11-13 11:58:15 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #define FD_SCRATCH_USE_HANDHOLDING 1
       2             : #include "fd_snapshot_loader.h"
       3             : #include "fd_snapshot_http.h"
       4             : #include "fd_snapshot_restore_private.h"
       5             : #include "../runtime/fd_acc_mgr.h"
       6             : #include "../runtime/context/fd_exec_epoch_ctx.h"
       7             : #include "../runtime/context/fd_exec_slot_ctx.h"
       8             : #include "../../ballet/zstd/fd_zstd.h"
       9             : #include "../../flamenco/types/fd_types.h"
      10             : #include "../../flamenco/types/fd_types_yaml.h"
      11             : 
      12             : #include <assert.h>
      13             : #include <errno.h>
      14             : #include <fcntl.h>
      15             : #include <netdb.h>
      16             : #include <regex.h>
      17             : #include <stddef.h>
      18             : #include <stdio.h>
      19             : #include <stdlib.h>
      20             : #include <unistd.h>
      21             : #include <sys/random.h>
      22             : 
      23             : /* Snapshot restore ***************************************************/
      24             : 
      25           0 : #define OSTREAM_BUFSZ (32768UL)
      26             : 
      27             : struct fd_snapshot_dumper {
      28             :   fd_alloc_t *   alloc;
      29             :   fd_funk_t *    funk;
      30             :   fd_acc_mgr_t * acc_mgr;
      31             : 
      32             :   fd_exec_epoch_ctx_t * epoch_ctx;
      33             :   fd_exec_slot_ctx_t *  slot_ctx;
      34             : 
      35             :   int snapshot_fd;
      36             : 
      37             :   fd_snapshot_loader_t *  loader;
      38             :   fd_snapshot_restore_t * restore;
      39             : 
      40             :   int                      yaml_fd;
      41             : 
      42             :   int                      csv_fd;
      43             :   fd_io_buffered_ostream_t csv_out;
      44             :   uchar                    csv_buf[ OSTREAM_BUFSZ ];
      45             : 
      46             :   int want_manifest;
      47             :   int want_accounts;
      48             :   int has_fail;
      49             : };
      50             : 
      51             : typedef struct fd_snapshot_dumper fd_snapshot_dumper_t;
      52             : 
      53             : static fd_snapshot_dumper_t *
      54           0 : fd_snapshot_dumper_new( void * mem ) {
      55           0 :   fd_snapshot_dumper_t * dumper = mem;
      56           0 :   *dumper = (fd_snapshot_dumper_t) {
      57           0 :     .snapshot_fd = -1,
      58           0 :     .yaml_fd     = -1,
      59           0 :     .csv_fd      = -1
      60           0 :   };
      61           0 :   return dumper;
      62           0 : }
      63             : 
      64             : static void *
      65           0 : fd_snapshot_dumper_delete( fd_snapshot_dumper_t * dumper ) {
      66             : 
      67           0 :   if( dumper->loader ) {
      68           0 :     fd_snapshot_loader_delete( dumper->loader );
      69           0 :     dumper->loader = NULL;
      70           0 :   }
      71             : 
      72           0 :   if( dumper->restore ) {
      73           0 :     fd_snapshot_restore_delete( dumper->restore );
      74           0 :     dumper->restore = NULL;
      75           0 :   }
      76             : 
      77           0 :   if( dumper->slot_ctx ) {
      78           0 :     fd_exec_slot_ctx_delete( fd_exec_slot_ctx_leave( dumper->slot_ctx ) );
      79           0 :     dumper->slot_ctx = NULL;
      80           0 :   }
      81             : 
      82           0 :   if( dumper->epoch_ctx ) {
      83           0 :     fd_exec_epoch_ctx_delete( fd_exec_epoch_ctx_leave( dumper->epoch_ctx ) );
      84           0 :     dumper->epoch_ctx = NULL;
      85           0 :   }
      86             : 
      87           0 :   if( dumper->acc_mgr ) {
      88           0 :     fd_acc_mgr_delete( dumper->acc_mgr );
      89           0 :     dumper->acc_mgr = NULL;
      90           0 :   }
      91             : 
      92           0 :   if( dumper->funk ) {
      93           0 :     fd_wksp_free_laddr( fd_funk_delete( fd_funk_leave( dumper->funk ) ) );
      94           0 :     dumper->funk = NULL;
      95           0 :   }
      96             : 
      97           0 :   if( dumper->alloc ) {
      98           0 :     fd_wksp_free_laddr( fd_alloc_delete( fd_alloc_leave( dumper->alloc ) ) );
      99           0 :     dumper->alloc = NULL;
     100           0 :   }
     101             : 
     102           0 :   if( dumper->yaml_fd>=0 ) {
     103           0 :     if( FD_UNLIKELY( 0!=close( dumper->yaml_fd ) ) )
     104           0 :       FD_LOG_WARNING(( "close(%d) failed (%d-%s)", dumper->yaml_fd, errno, fd_io_strerror( errno ) ));
     105           0 :     dumper->yaml_fd = -1;
     106           0 :   }
     107             : 
     108           0 :   if( dumper->csv_fd>=0 ) {
     109           0 :     fd_io_buffered_ostream_fini( &dumper->csv_out );
     110           0 :     if( FD_UNLIKELY( 0!=close( dumper->csv_fd ) ) )
     111           0 :       FD_LOG_WARNING(( "close(%d) failed (%d-%s)", dumper->csv_fd, errno, fd_io_strerror( errno ) ));
     112           0 :     dumper->csv_fd = -1;
     113           0 :   }
     114             : 
     115           0 :   fd_memset( dumper, 0, sizeof(fd_snapshot_dumper_t) );
     116           0 :   return dumper;
     117           0 : }
     118             : 
     119             : /* fd_snapshot_dumper_on_manifest gets called when the snapshot manifest
     120             :    becomes available. */
     121             : 
     122             : static int
     123             : fd_snapshot_dumper_on_manifest( void *                 _d,
     124           0 :                                 fd_solana_manifest_t * manifest ) {
     125             : 
     126           0 :   fd_snapshot_dumper_t * d = _d;
     127           0 :   if( !d->want_manifest ) return 0;
     128           0 :   d->want_manifest = 0;
     129             : 
     130           0 :   FILE * file = fdopen( d->yaml_fd, "w" );
     131           0 :   if( FD_UNLIKELY( !file ) ) {
     132           0 :     FD_LOG_WARNING(( "fdopen(%d) failed (%d-%s)", d->yaml_fd, errno, fd_io_strerror( errno ) ));
     133           0 :     close( d->yaml_fd );
     134           0 :     d->yaml_fd  = -1;
     135           0 :     d->has_fail = 1;
     136           0 :     return errno;
     137           0 :   }
     138             : 
     139           0 :   fd_scratch_push();
     140           0 :   fd_flamenco_yaml_t * yaml = fd_flamenco_yaml_init( fd_flamenco_yaml_new( fd_scratch_alloc( fd_flamenco_yaml_align(), fd_flamenco_yaml_footprint() ) ), file );
     141           0 :   fd_solana_manifest_walk( yaml, manifest, fd_flamenco_yaml_walk, NULL, 0U );
     142           0 :   fd_flamenco_yaml_delete( yaml );
     143           0 :   fd_scratch_pop();
     144             : 
     145           0 :   int err = 0;
     146           0 :   if( FD_UNLIKELY( (err = ferror( file )) ) ) {
     147           0 :     FD_LOG_WARNING(( "Error occurred while writing manifest (%d-%s)", err, fd_io_strerror( err ) ));
     148           0 :     d->has_fail = 1;
     149           0 :   }
     150             : 
     151           0 :   fclose( file );
     152           0 :   close( d->yaml_fd );
     153           0 :   d->yaml_fd = -1;
     154           0 :   return err;
     155           0 : }
     156             : 
     157             : /* fd_snapshot_dumper_record processes a newly encountered account
     158             :    record. */
     159             : 
     160             : union fd_snapshot_csv_rec {
     161             :   char line[ 180 ];
     162             :   struct __attribute__((packed)) {
     163             :     char acct_addr[ FD_BASE58_ENCODED_32_LEN ];
     164             :     char comma1;
     165             :     char owner_addr[ FD_BASE58_ENCODED_32_LEN ];
     166             :     char comma2;
     167             :     char hash[ FD_BASE58_ENCODED_32_LEN ];
     168             :     char comma3;
     169             :     char slot[ 14 ];  /* enough for 10000 years at 400ms slot time */
     170             :     char comma4;
     171             :     char size[ 8 ];  /* can represent [0,10<<20) */
     172             :     char comma5;
     173             :     char lamports[ 20 ];  /* can represent [0,1<<64) */
     174             :     char newline;
     175             :   };
     176             : };
     177             : 
     178             : typedef union fd_snapshot_csv_rec fd_snapshot_csv_rec_t;
     179             : 
     180             : static void
     181             : fd_snapshot_dumper_record( fd_snapshot_dumper_t * d,
     182             :                            fd_funk_rec_t const *  rec,
     183           0 :                            fd_wksp_t *            wksp ) {
     184             : 
     185           0 :   uchar const *             rec_val = fd_funk_val_const( rec, wksp );
     186           0 :   fd_account_meta_t const * meta    = (fd_account_meta_t const *)rec_val;
     187             :   //uchar const *             data    = rec_val + meta->hlen;
     188             : 
     189           0 :   if( d->csv_fd>=0 ) {
     190           0 :     fd_snapshot_csv_rec_t csv_rec;
     191           0 :     fd_memset( &csv_rec, ' ', sizeof(csv_rec) );
     192             : 
     193           0 :     ulong b58sz;
     194           0 :     fd_base58_encode_32( fd_funk_key_to_acc( rec->pair.key )->uc, &b58sz, csv_rec.acct_addr );
     195           0 :     csv_rec.line[ offsetof(fd_snapshot_csv_rec_t,acct_addr)+b58sz ] = ' ';
     196           0 :     csv_rec.comma1 = ',';
     197             : 
     198           0 :     fd_base58_encode_32( meta->info.owner, &b58sz, csv_rec.owner_addr );
     199           0 :     csv_rec.line[ offsetof(fd_snapshot_csv_rec_t,owner_addr)+b58sz ] = ' ';
     200           0 :     csv_rec.comma2 = ',';
     201             : 
     202           0 :     fd_base58_encode_32( meta->hash, &b58sz, csv_rec.hash );
     203           0 :     csv_rec.line[ offsetof(fd_snapshot_csv_rec_t,hash)+b58sz ] = ' ';
     204           0 :     csv_rec.comma3 = ',';
     205             : 
     206           0 :     fd_cstr_append_ulong_as_text( csv_rec.slot, ' ', '\0', meta->dlen, 15 );
     207           0 :     csv_rec.comma4 = ',';
     208             : 
     209           0 :     fd_cstr_append_ulong_as_text( csv_rec.size, ' ', '\0', meta->dlen, 8 );
     210           0 :     csv_rec.comma5 = ',';
     211             : 
     212           0 :     fd_cstr_append_ulong_as_text( csv_rec.lamports, ' ', '\0', meta->info.lamports, 20 );
     213           0 :     csv_rec.newline = '\n';
     214             : 
     215           0 :     fd_io_buffered_ostream_write( &d->csv_out, csv_rec.line, sizeof(csv_rec.line) );
     216           0 :   }
     217           0 : }
     218             : 
     219             : /* fd_snapshot_dumper_release visits any newly appeared accounts and
     220             :    removes their records from the database. */
     221             : 
     222             : static int
     223           0 : fd_snapshot_dumper_release( fd_snapshot_dumper_t * d ) {
     224             : 
     225           0 :   fd_exec_slot_ctx_t * slot_ctx = d->slot_ctx;
     226           0 :   fd_funk_txn_t *      funk_txn = slot_ctx->funk_txn;
     227           0 :   fd_funk_txn_xid_t    txn_xid  = funk_txn->xid;
     228           0 :   fd_funk_t *          funk     = d->funk;
     229           0 :   fd_wksp_t *          wksp     = fd_funk_wksp( funk );
     230           0 :   fd_funk_rec_t *      rec_map  = fd_funk_rec_map( funk, wksp );
     231             : 
     232             :   /* Dump all the records */
     233             : 
     234           0 :   for( fd_funk_rec_t const * rec = fd_funk_txn_rec_head( funk_txn, rec_map );
     235           0 :                              rec;
     236           0 :                              rec = fd_funk_rec_next( rec, rec_map ) ) {
     237           0 :     if( FD_UNLIKELY( !fd_funk_key_is_acc( rec->pair.key ) ) ) continue;
     238           0 :     fd_snapshot_dumper_record( d, rec, wksp );
     239           0 :   }
     240             : 
     241             :   /* In order to save heap space, evict all the accounts we just
     242             :      visited.  We can do this because we know we'll never read them
     243             :      again. */
     244             : 
     245           0 :   if( FD_UNLIKELY( fd_funk_txn_cancel( funk, funk_txn, 1 )!=1UL ) )
     246           0 :     FD_LOG_ERR(( "Failed to cancel funk txn" ));  /* unreachable */
     247             : 
     248           0 :   funk_txn = fd_funk_txn_prepare( funk, NULL, &txn_xid, 1 );
     249           0 :   if( FD_UNLIKELY( !funk_txn ) )
     250           0 :     FD_LOG_ERR(( "Failed to prepare funk txn" ));  /* unreachable */
     251             : 
     252           0 :   slot_ctx->funk_txn = funk_txn;
     253           0 :   return 0;
     254           0 : }
     255             : 
     256             : /* fd_snapshot_dumper_advance polls the tar reader for data and handles
     257             :    any newly appeared accounts. */
     258             : 
     259             : static int
     260           0 : fd_snapshot_dumper_advance( fd_snapshot_dumper_t * dumper ) {
     261             : 
     262           0 :   int advance_err = fd_snapshot_loader_advance( dumper->loader );
     263           0 :   if( FD_UNLIKELY( advance_err ) ) return advance_err;
     264             : 
     265           0 :   int collect_err = fd_snapshot_dumper_release( dumper );
     266           0 :   if( FD_UNLIKELY( collect_err ) ) return collect_err;
     267             : 
     268           0 :   return 0;
     269           0 : }
     270             : 
     271             : /* fd_snapshot_dump_args_t contains the command-line arguments for the
     272             :    dump command. */
     273             : 
     274             : struct fd_snapshot_dump_args {
     275             :   char const * _page_sz;
     276             :   ulong        page_cnt;
     277             :   ulong        near_cpu;
     278             :   ulong        zstd_window_sz;
     279             :   char *       snapshot;
     280             :   char const * manifest_path;
     281             :   char const * csv_path;
     282             :   int          csv_hdr;
     283             :   ushort       http_redirs;
     284             : };
     285             : 
     286             : typedef struct fd_snapshot_dump_args fd_snapshot_dump_args_t;
     287             : 
     288             : static int
     289             : do_dump( fd_snapshot_dumper_t *    d,
     290             :          fd_snapshot_dump_args_t * args,
     291           0 :          fd_wksp_t *               wksp ) {
     292             : 
     293             :   /* Resolve snapshot source */
     294             : 
     295           0 :   fd_snapshot_src_t src[1];
     296           0 :   if( FD_UNLIKELY( !fd_snapshot_src_parse( src, args->snapshot ) ) )
     297           0 :     return EXIT_FAILURE;
     298             : 
     299             :   /* Create a heap */
     300             : 
     301           0 :   ulong const fd_alloc_tag = 41UL;
     302           0 :   d->alloc = fd_alloc_join( fd_alloc_new( fd_wksp_alloc_laddr( wksp, fd_alloc_align(), fd_alloc_footprint(), fd_alloc_tag ), fd_alloc_tag ), 0UL );
     303           0 :   if( FD_UNLIKELY( !d->alloc ) ) { FD_LOG_WARNING(( "fd_alloc_join() failed" )); return EXIT_FAILURE; }
     304             : 
     305           0 :   fd_wksp_usage_t wksp_usage[1] = {0};
     306           0 :   fd_wksp_usage( wksp, NULL, 0UL, wksp_usage );
     307             : 
     308           0 :   if( args->csv_path ) {
     309           0 :     d->csv_fd = open( args->csv_path, O_WRONLY|O_CREAT|O_TRUNC, 0644 );
     310           0 :     if( FD_UNLIKELY( d->csv_fd<0 ) ) { FD_LOG_WARNING(( "open(%s) failed (%d-%s)", args->csv_path, errno, fd_io_strerror( errno ) )); return EXIT_FAILURE; }
     311           0 :     fd_io_buffered_ostream_init( &d->csv_out, d->csv_fd, d->csv_buf, OSTREAM_BUFSZ );
     312           0 :   }
     313             : 
     314           0 :   if( args->manifest_path ) {
     315           0 :     d->yaml_fd = open( args->manifest_path, O_WRONLY|O_CREAT|O_TRUNC, 0644 );
     316           0 :     if( FD_UNLIKELY( d->yaml_fd<0 ) ) { FD_LOG_WARNING(( "open(%s) failed (%d-%s)", args->manifest_path, errno, fd_io_strerror( errno ) )); return EXIT_FAILURE; }
     317           0 :   }
     318             : 
     319             :   /* Create loader */
     320             : 
     321           0 :   d->loader = fd_snapshot_loader_new( fd_scratch_alloc( fd_snapshot_loader_align(), fd_snapshot_loader_footprint( args->zstd_window_sz ) ), args->zstd_window_sz );
     322           0 :   if( FD_UNLIKELY( !d->loader ) ) { FD_LOG_WARNING(( "Failed to create fd_snapshot_loader_t" )); return EXIT_FAILURE; }
     323             : 
     324             :   /* Create a high-quality hash seed for fd_funk */
     325             : 
     326           0 :   ulong funk_seed;
     327           0 :   if( FD_UNLIKELY( sizeof(ulong)!=getrandom( &funk_seed, sizeof(ulong), 0 ) ) )
     328           0 :     { FD_LOG_WARNING(( "getrandom() failed (%d-%s)", errno, fd_io_strerror( errno ) )); return EXIT_FAILURE; }
     329             : 
     330             :   /* Create a funk database */
     331             : 
     332           0 :   ulong const txn_max =   16UL;  /* we really only need 1 */
     333           0 :   ulong const rec_max = 1024UL;  /* we evict records as we go */
     334             : 
     335           0 :   ulong funk_tag = 42UL;
     336           0 :   d->funk = fd_funk_join( fd_funk_new( fd_wksp_alloc_laddr( wksp, fd_funk_align(), fd_funk_footprint(), funk_tag ), funk_tag, funk_seed, txn_max, rec_max ) );
     337           0 :   if( FD_UNLIKELY( !d->funk ) ) { FD_LOG_WARNING(( "Failed to create fd_funk_t" )); return EXIT_FAILURE; }
     338           0 :   fd_funk_start_write( d->funk );
     339             : 
     340             :   /* Create a new processing context */
     341             : 
     342           0 :   d->acc_mgr = fd_acc_mgr_new( fd_scratch_alloc( FD_ACC_MGR_ALIGN, FD_ACC_MGR_FOOTPRINT ), d->funk );
     343           0 :   if( FD_UNLIKELY( !d->acc_mgr ) ) { FD_LOG_WARNING(( "Failed to create fd_acc_mgr_t" )); return EXIT_FAILURE; }
     344             : 
     345           0 :   ulong const vote_acct_max = 1UL;  /* fd_snapshot doesn't retain epoch stakes */
     346           0 :   d->epoch_ctx = fd_exec_epoch_ctx_join( fd_exec_epoch_ctx_new( fd_scratch_alloc( fd_exec_epoch_ctx_align(), fd_exec_epoch_ctx_footprint( vote_acct_max ) ), vote_acct_max ) );
     347           0 :   if( FD_UNLIKELY( !d->epoch_ctx ) ) { FD_LOG_WARNING(( "Failed to create fd_exec_epoch_ctx_t" )); return EXIT_FAILURE; }
     348             : 
     349           0 :   d->slot_ctx = fd_exec_slot_ctx_join( fd_exec_slot_ctx_new( fd_scratch_alloc( FD_EXEC_SLOT_CTX_ALIGN, FD_EXEC_SLOT_CTX_FOOTPRINT ), fd_alloc_virtual( d->alloc ) ) );
     350           0 :   if( FD_UNLIKELY( !d->slot_ctx ) ) { FD_LOG_WARNING(( "Failed to create fd_exec_slot_ctx_t" )); return EXIT_FAILURE; }
     351             : 
     352           0 :   d->slot_ctx->valloc = fd_alloc_virtual( d->alloc );
     353           0 :   d->slot_ctx->acc_mgr   = d->acc_mgr;
     354           0 :   d->slot_ctx->epoch_ctx = d->epoch_ctx;
     355             : 
     356             :   /* funk_txn is destroyed automatically when deleting fd_funk_t. */
     357             : 
     358           0 :   fd_funk_txn_xid_t funk_txn_xid = { .ul = { 1UL } };
     359           0 :   fd_funk_txn_t * funk_txn = fd_funk_txn_prepare( d->funk, NULL, &funk_txn_xid, 1 );
     360           0 :   d->slot_ctx->funk_txn = funk_txn;
     361             : 
     362           0 :   void * restore_mem = fd_scratch_alloc( fd_snapshot_restore_align(), fd_snapshot_restore_footprint() );
     363           0 :   if( FD_UNLIKELY( !restore_mem ) ) FD_LOG_ERR(( "Failed to allocate restore buffer" ));  /* unreachable */
     364             : 
     365           0 :   d->restore = fd_snapshot_restore_new( restore_mem, d->acc_mgr, funk_txn, d->slot_ctx->valloc, d, fd_snapshot_dumper_on_manifest, NULL );
     366           0 :   if( FD_UNLIKELY( !d->restore ) ) { FD_LOG_WARNING(( "Failed to create fd_snapshot_restore_t" )); return EXIT_FAILURE; }
     367             : 
     368             :   /* Set up the snapshot loader */
     369             : 
     370           0 :   if( FD_UNLIKELY( !fd_snapshot_loader_init( d->loader, d->restore, src, 0UL ) ) ) {
     371           0 :     FD_LOG_WARNING(( "fd_snapshot_loader_init failed" ));
     372           0 :     return EXIT_FAILURE;
     373           0 :   }
     374             : 
     375           0 :   d->want_manifest = (!!args->manifest_path);
     376           0 :   d->want_accounts = (!!args->csv_path);
     377             : 
     378           0 :   if( FD_UNLIKELY( (!d->want_manifest) & (!d->want_accounts) ) ) {
     379           0 :     FD_LOG_NOTICE(( "Nothing to do, exiting." ));
     380           0 :     return EXIT_SUCCESS;
     381           0 :   }
     382             : 
     383           0 :   if( (d->csv_fd>=0) & (args->csv_hdr) ) {
     384           0 :     fd_snapshot_csv_rec_t csv_rec;
     385           0 :     memset( &csv_rec, ' ', sizeof(fd_snapshot_csv_rec_t) );
     386           0 :     memcpy( csv_rec.acct_addr,  "address",  strlen( "address"  ) );
     387           0 :     memcpy( csv_rec.owner_addr, "owner",    strlen( "owner"    ) );
     388           0 :     memcpy( csv_rec.hash,       "hash",     strlen( "hash"     ) );
     389           0 :     memcpy( csv_rec.slot,       "slot",     strlen( "slot"     ) );
     390           0 :     memcpy( csv_rec.size,       "size",     strlen( "size"     ) );
     391           0 :     memcpy( csv_rec.lamports,   "lamports", strlen( "lamports" ) );
     392           0 :     csv_rec.comma1  = ',';
     393           0 :     csv_rec.comma2  = ',';
     394           0 :     csv_rec.comma3  = ',';
     395           0 :     csv_rec.comma4  = ',';
     396           0 :     csv_rec.comma5  = ',';
     397           0 :     csv_rec.newline = '\n';
     398             : 
     399           0 :     if( FD_UNLIKELY( write( d->csv_fd, csv_rec.line, sizeof(fd_snapshot_csv_rec_t) )
     400           0 :                      != sizeof(fd_snapshot_csv_rec_t) ) ) {
     401           0 :       FD_LOG_WARNING(( "Failed to write CSV header (%d-%s)", errno, fd_io_strerror( errno ) ));
     402           0 :       d->has_fail = 1;
     403           0 :       return EXIT_FAILURE;
     404           0 :     }
     405           0 :   }
     406             : 
     407           0 :   for(;;) {
     408           0 :     int err = fd_snapshot_dumper_advance( d );
     409           0 :     if( err==0 )     { /* ok */ }
     410           0 :     else if( err<0 ) { /* EOF */ break; }
     411           0 :     else             { return EXIT_FAILURE; }
     412             : 
     413           0 :     if( FD_UNLIKELY( (!d->want_accounts) & (!d->want_manifest) ) )
     414           0 :       break;
     415           0 :   }
     416             : 
     417           0 :   return d->has_fail ? EXIT_FAILURE : EXIT_SUCCESS;
     418           0 : }
     419             : 
     420             : int
     421             : cmd_dump( int     argc,
     422           0 :           char ** argv ) {
     423             : 
     424           0 :   fd_snapshot_dump_args_t args[1] = {{0}};
     425           0 :   args->_page_sz       =         fd_env_strip_cmdline_cstr  ( &argc, &argv, "--page-sz",        NULL,      "gigantic" );
     426           0 :   args->page_cnt       =         fd_env_strip_cmdline_ulong ( &argc, &argv, "--page-cnt",       NULL,             3UL );
     427           0 :   args->near_cpu       =         fd_env_strip_cmdline_ulong ( &argc, &argv, "--near-cpu",       NULL, fd_log_cpu_id() );
     428           0 :   args->zstd_window_sz =         fd_env_strip_cmdline_ulong ( &argc, &argv, "--zstd-window-sz", NULL,      33554432UL );
     429           0 :   args->snapshot       = (char *)fd_env_strip_cmdline_cstr  ( &argc, &argv, "--snapshot",       NULL,            NULL );
     430           0 :   args->manifest_path  =         fd_env_strip_cmdline_cstr  ( &argc, &argv, "--manifest",       NULL,            NULL );
     431           0 :   args->csv_path       =         fd_env_strip_cmdline_cstr  ( &argc, &argv, "--csv",            NULL,            NULL );
     432           0 :   args->csv_hdr        =         fd_env_strip_cmdline_int   ( &argc, &argv, "--csv-hdr",        NULL,               1 );
     433           0 :   args->http_redirs    = (ushort)fd_env_strip_cmdline_ushort( &argc, &argv, "--http-redirs",    NULL,               5 );
     434             : 
     435           0 :   if( FD_UNLIKELY( argc!=1 ) )
     436           0 :     FD_LOG_ERR(( "Unexpected command-line arguments" ));
     437           0 :   if( FD_UNLIKELY( !args->snapshot ) )
     438           0 :     FD_LOG_ERR(( "Missing --snapshot argument" ));
     439             : 
     440           0 :   FD_LOG_NOTICE(( "Creating workspace (--page-cnt %lu, --page-sz %s)", args->page_cnt, args->_page_sz ));
     441             : 
     442             :   /* With workspace */
     443             : 
     444           0 :   fd_wksp_t * wksp = fd_wksp_new_anonymous( fd_cstr_to_shmem_page_sz( args->_page_sz ), args->page_cnt, args->near_cpu, "wksp", 0UL );
     445           0 :   if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "fd_wksp_new_anonymous() failed" ));
     446             : 
     447             :   /* With scratch */
     448             : 
     449           0 :   ulong smax = args->zstd_window_sz + (1<<29);  /* manifest plus 512 MiB headroom */
     450           0 :   FD_LOG_INFO(( "Using %.2f MiB scratch space", (double)smax/(1<<20) ));
     451           0 :   uchar * smem = fd_wksp_alloc_laddr( wksp, FD_SCRATCH_SMEM_ALIGN, smax, 1UL );
     452           0 :   if( FD_UNLIKELY( !smem ) ) FD_LOG_ERR(( "fd_wksp_alloc_laddr for scratch region of size %lu failed", smax ));
     453           0 :   ulong fmem[16];
     454           0 :   fd_scratch_attach( smem, fmem, smax, 16UL );
     455           0 :   fd_scratch_push();
     456             : 
     457             :   /* With dump context */
     458             : 
     459           0 :   fd_snapshot_dumper_t  _dumper[1];
     460           0 :   fd_snapshot_dumper_t * dumper = fd_snapshot_dumper_new( _dumper );
     461             : 
     462           0 :   int rc = do_dump( dumper, args, wksp );
     463           0 :   FD_LOG_INFO(( "Done. Cleaning up." ));
     464             : 
     465           0 :   fd_snapshot_dumper_delete( dumper );
     466             : 
     467           0 :   fd_scratch_pop();
     468           0 :   fd_scratch_detach( NULL );
     469           0 :   fd_wksp_delete_anonymous( wksp );
     470           0 :   return rc;
     471           0 : }
     472             : 
     473             : FD_IMPORT_CSTR( _help, "src/flamenco/snapshot/fd_snapshot_help.txt" );
     474             : 
     475             : __attribute__((noreturn)) static int
     476           0 : usage( int code ) {
     477           0 :   fwrite( _help, 1, _help_sz, stderr );
     478           0 :   fflush( stderr );
     479           0 :   exit( code );
     480           0 : }
     481             : 
     482             : int
     483             : main( int     argc,
     484             :       char ** argv ) {
     485             :   fd_boot( &argc, &argv );
     486             : 
     487             :   if( argc==1 ) return usage(1);
     488             :   if( 0==strcmp( argv[1], "help" ) ) return usage(0);
     489             :   for( int i=1; i<argc; i++ )
     490             :     if( 0==strcmp( argv[i], "--help" ) )
     491             :       return usage(0);
     492             : 
     493             :   argc--; argv++;
     494             :   char const * cmd = argv[0];
     495             : 
     496             :   if( 0==strcmp( cmd, "dump" ) ) {
     497             :     return cmd_dump( argc, argv );
     498             :   } else {
     499             :     fprintf( stderr, "Unknown command: %s\n", cmd );
     500             :     return usage(1);
     501             :   }
     502             : 
     503             :   fd_halt();
     504             :   return 0;
     505             : }

Generated by: LCOV version 1.14