LCOV - code coverage report
Current view: top level - util/wksp - fd_wksp_restore_v1.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 246 305 80.7 %
Date: 2026-09-17 04:28:31 Functions: 4 4 100.0 %

          Line data    Source code
       1             : #include "fd_wksp_private.h"
       2             : #include "../tpool/fd_tpool.h"
       3             : 
       4             : #include <stdio.h>
       5             : #include <errno.h>
       6             : #include <unistd.h>
       7             : #include <fcntl.h>
       8             : #include <sys/stat.h>
       9             : 
      10             : /* fd_wksp_private_restore_ulong restores a ulong from the stream in.
      11             :    Returns 0 on success and, on return, *_val will contain the restored
      12             :    val.  Returns non-zero on failure (will be an errno compat error
      13             :    code) and, on failure, *_val will be zero.  This will implicitly read
      14             :    ahead for future restores. */
      15             : 
      16             : static int
      17             : fd_wksp_private_restore_v1_ulong( fd_io_buffered_istream_t * in,
      18         981 :                                   ulong *                    _val ) {
      19         981 :   ulong         csz;
      20         981 :   uchar const * buf;
      21         981 :   uchar         _buf[9UL];
      22             : 
      23             :   /* Read the encoded val */
      24             : 
      25         981 :   ulong peek_sz = fd_io_buffered_istream_peek_sz( in );
      26             : 
      27         981 :   if( FD_LIKELY( peek_sz>=9UL ) ) { /* encoded val already prefetched */
      28         906 :     buf = fd_io_buffered_istream_peek( in );
      29         906 :     csz = fd_ulong_svw_dec_sz( buf );
      30         906 :     fd_io_buffered_istream_seek( in, csz );
      31         906 :   } else { /* encoded val not guaranteed prefetched (this will also implicitly prefetch for future restores) */
      32          75 :     int err;
      33          75 :     err = fd_io_buffered_istream_read( in, _buf,     1UL     ); if( FD_UNLIKELY( err ) ) { *_val = 0UL; return err; }
      34          75 :     csz = fd_ulong_svw_dec_sz( _buf );
      35          75 :     err = fd_io_buffered_istream_read( in, _buf+1UL, csz-1UL ); if( FD_UNLIKELY( err ) ) { *_val = 0UL; return err; }
      36          75 :     buf = _buf;
      37          75 :   }
      38             : 
      39             :   /* Decode encoded val */
      40             : 
      41         981 :   *_val = fd_ulong_svw_dec_fixed( buf, csz );
      42         981 :   return 0;
      43         981 : }
      44             : 
      45             : /* fd_wksp_private_restore_buf restores a variable length buffer buf of
      46             :    maximum size buf_max from the stream in.  Returns 0 on success and,
      47             :    on success, buf will contain the buffer and *_buf_sz will contain the
      48             :    buffer's size (will be in [0,buf_max]).  Returns non-zero on failure
      49             :    (will be an errno compat error code) and, on failure, buf will be
      50             :    clobbered and *_buf_sz will be zero.  This will implicitly read ahead
      51             :    for future restores.  Zero buf_max is fine (and NULL buf is fine if
      52             :    buf_max is zero). */
      53             : 
      54             : static int
      55             : fd_wksp_private_restore_v1_buf( fd_io_buffered_istream_t * in,
      56             :                                 void *                     buf,
      57             :                                 ulong                      buf_max,
      58         378 :                                 ulong *                    _buf_sz ) {
      59             : 
      60             :   /* Restore buf_sz */
      61             : 
      62         378 :   ulong buf_sz;
      63         378 :   int   err = fd_wksp_private_restore_v1_ulong( in, &buf_sz );
      64         378 :   if( FD_UNLIKELY( (!!err) | (buf_sz>buf_max) ) ) { /* I/O error, unexpected EOF, or buf_max too small */
      65           0 :     if( !!err ) err = EPROTO; /* cmov */
      66           0 :     *_buf_sz = 0UL;
      67           0 :     return err;
      68           0 :   }
      69             : 
      70             :   /* Restore buf */
      71             : 
      72         378 :   err = fd_io_buffered_istream_read( in, buf, buf_sz );
      73         378 :   *_buf_sz = fd_ulong_if( !err, buf_sz, 0UL );
      74         378 :   return err;
      75         378 : }
      76             : 
      77         603 : #define RESTORE_ULONG(v) do {                                \
      78         603 :     err = fd_wksp_private_restore_v1_ulong( restore, &v );   \
      79         603 :     if( FD_UNLIKELY( err ) ) { err_info = #v; goto io_err; } \
      80         603 :   } while(0)
      81             : 
      82             : /* Note: on success, v_len==strlen( v ) and will be in [0,max).  Assumes
      83             :    max is positive. */
      84             : 
      85         378 : #define RESTORE_CSTR(v,max) do {                                              \
      86         378 :     err = fd_wksp_private_restore_v1_buf( restore, v, (max)-1UL, &v##_len );  \
      87         378 :     if( FD_UNLIKELY( err ) ) { err_info = #v; goto io_err; }                  \
      88         378 :     v[v##_len] = '\0'; /* v##_len in [0,max) at this point */                 \
      89         378 :     if( FD_UNLIKELY( strlen( v )!=v##_len ) ) { err_info = #v; goto io_err; } \
      90         378 :   } while(0)
      91             : 
      92             : #define RBUF_ALIGN     (4096UL)
      93          42 : #define RBUF_FOOTPRINT (65536UL)
      94             : 
      95             : int
      96             : fd_wksp_private_restore_v1( fd_tpool_t * tpool,
      97             :                             ulong        t0,
      98             :                             ulong        t1,
      99             :                             fd_wksp_t *  wksp,
     100             :                             char const * path,
     101          21 :                             uint         new_seed ) {
     102          21 :   (void)tpool; (void)t0; (void)t1; /* Note: Thread parallel v1 checkpoint not supported */
     103             : 
     104          21 :   FD_LOG_INFO(( "Restore checkpt \"%s\" into wksp \"%s\" (seed %u)", path, wksp->name, new_seed ));
     105             : 
     106          21 :   int fd = open( path, O_RDONLY, (mode_t)0 );
     107          21 :   if( FD_UNLIKELY( fd==-1 ) ) {
     108           0 :     FD_LOG_WARNING(( "open(\"%s\",O_RDONLY,0) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
     109           0 :     return FD_WKSP_ERR_FAIL;
     110           0 :   }
     111             : 
     112          21 :   uchar                    rbuf[ RBUF_FOOTPRINT ] __attribute__((aligned( RBUF_ALIGN )));
     113          21 :   fd_io_buffered_istream_t restore[1];
     114          21 :   fd_io_buffered_istream_init( restore, fd, rbuf, RBUF_FOOTPRINT );
     115             : 
     116          21 :   int err;
     117             : 
     118          21 :   err = fd_wksp_private_lock( wksp ); if( FD_UNLIKELY( err ) ) goto fini; /* logs details */
     119             : 
     120          21 :   ulong                     wksp_part_max = wksp->part_max;
     121          21 :   ulong                     wksp_data_max = wksp->data_max;
     122          21 :   ulong                     wksp_data_lo  = wksp->gaddr_lo;
     123          21 :   ulong                     wksp_data_hi  = wksp->gaddr_hi;
     124          21 :   fd_wksp_private_pinfo_t * wksp_pinfo    = fd_wksp_private_pinfo( wksp );
     125          21 :   int                       wksp_dirty    = 0;
     126             : 
     127          21 :   char const * err_info;
     128             : 
     129         114 : # define RESTORE_TEST(c) do { if( FD_UNLIKELY( !(c) ) ) { err_info = #c; goto stream_err; } } while(0)
     130             : 
     131          21 :   ulong orig_part_max;
     132          21 :   ulong orig_data_max;
     133             : 
     134          21 :   {
     135          21 :     FD_LOG_INFO(( "Restore header (v1)" ));
     136             : 
     137          21 :     ulong magic;     RESTORE_ULONG( magic     );
     138          21 :     ulong style_ul;  RESTORE_ULONG( style_ul  );
     139          21 :     ulong seed_ul;   RESTORE_ULONG( seed_ul   );
     140          21 :     ulong part_max;  RESTORE_ULONG( part_max  );
     141          21 :     ulong data_max;  RESTORE_ULONG( data_max  );
     142          21 :     ulong ts_ul;     RESTORE_ULONG( ts_ul     ); /* considered metadata */
     143          21 :     ulong app_id;    RESTORE_ULONG( app_id    ); /* " */
     144          21 :     ulong thread_id; RESTORE_ULONG( thread_id ); /* " */
     145          21 :     ulong host_id;   RESTORE_ULONG( host_id   ); /* " */
     146          21 :     ulong cpu_id;    RESTORE_ULONG( cpu_id    ); /* " */
     147          21 :     ulong group_id;  RESTORE_ULONG( group_id  ); /* " */
     148          21 :     ulong tid;       RESTORE_ULONG( tid       ); /* " */
     149          21 :     ulong user_id;   RESTORE_ULONG( user_id   ); /* " */
     150             : 
     151          21 :     char name[ FD_SHMEM_NAME_MAX ]; ulong name_len; RESTORE_CSTR( name, FD_SHMEM_NAME_MAX );
     152             : 
     153          21 :     RESTORE_TEST( magic==FD_WKSP_MAGIC                                   );
     154          21 :     RESTORE_TEST( style_ul==(ulong)FD_WKSP_CHECKPT_STYLE_V1              );
     155          21 :     RESTORE_TEST( seed_ul==(ulong)(uint)seed_ul                          );
     156          21 :     RESTORE_TEST( fd_wksp_footprint( part_max, data_max )>0UL            );
     157          21 :     RESTORE_TEST( (name_len>0UL) & (fd_shmem_name_len( name )==name_len) );
     158             : 
     159          21 :     FD_LOG_INFO(( "Restore metadata (v1)" ));
     160             : 
     161          21 :     char ts_cstr[ FD_LOG_WALLCLOCK_CSTR_BUF_SZ ];
     162          21 :     fd_log_wallclock_cstr( (long)ts_ul, ts_cstr );
     163             : 
     164          21 :     char app   [ FD_LOG_NAME_MAX              ]; ulong app_len;    RESTORE_CSTR( app,    FD_LOG_NAME_MAX              );
     165          21 :     char thread[ FD_LOG_NAME_MAX              ]; ulong thread_len; RESTORE_CSTR( thread, FD_LOG_NAME_MAX              );
     166          21 :     char host  [ FD_LOG_NAME_MAX              ]; ulong host_len;   RESTORE_CSTR( host,   FD_LOG_NAME_MAX              );
     167          21 :     char cpu   [ FD_LOG_NAME_MAX              ]; ulong cpu_len;    RESTORE_CSTR( cpu,    FD_LOG_NAME_MAX              );
     168          21 :     char group [ FD_LOG_NAME_MAX              ]; ulong group_len;  RESTORE_CSTR( group,  FD_LOG_NAME_MAX              );
     169          21 :     char user  [ FD_LOG_NAME_MAX              ]; ulong user_len;   RESTORE_CSTR( user,   FD_LOG_NAME_MAX              );
     170          21 :     char binfo [ FD_WKSP_CHECKPT_V1_BINFO_MAX ]; ulong binfo_len;  RESTORE_CSTR( binfo,  FD_WKSP_CHECKPT_V1_BINFO_MAX );
     171          21 :     char uinfo [ FD_WKSP_CHECKPT_V1_UINFO_MAX ]; ulong uinfo_len;  RESTORE_CSTR( uinfo,  FD_WKSP_CHECKPT_V1_UINFO_MAX );
     172             : 
     173             :     /* Note: this mirrors v2 */
     174             : 
     175          21 :     FD_LOG_INFO(( "\n"
     176          21 :                   "\tstyle                  %-20i\n"       /* verbose 0 info */
     177          21 :                   "\tname                   %s\n"
     178          21 :                   "\tseed                   %-20u\n"
     179          21 :                   "\tpart_max               %-20lu\n"
     180          21 :                   "\tdata_max               %-20lu\n"
     181          21 :                   "\tmagic                  %016lx\n"      /* verbose 1 info */
     182          21 :                   "\twallclock              %-20li (%s)\n"
     183          21 :                   "\tapp                    %-20lu (%s)\n"
     184          21 :                   "\tthread                 %-20lu (%s)\n"
     185          21 :                   "\thost                   %-20lu (%s)\n"
     186          21 :                   "\tcpu                    %-20lu (%s)\n"
     187          21 :                   "\tgroup                  %-20lu (%s)\n"
     188          21 :                   "\ttid                    %-20lu\n"
     189          21 :                   "\tuser                   %-20lu (%s)\n"
     190          21 :                   "\tbinfo\n\t\t%s\n"                     /* verbose 2 info */
     191          21 :                   "\tuinfo\n\t\t%s",
     192          21 :                   (int)style_ul, name, (uint)seed_ul, part_max, data_max,
     193          21 :                   magic, (long)ts_ul, ts_cstr,
     194          21 :                   app_id,    app,
     195          21 :                   thread_id, thread,
     196          21 :                   host_id,   host,
     197          21 :                   cpu_id,    cpu,
     198          21 :                   group_id,  group,
     199          21 :                   tid,
     200          21 :                   user_id,   user,
     201          21 :                   binfo,
     202          21 :                   uinfo ));
     203             : 
     204          21 :     orig_part_max = part_max;
     205          21 :     orig_data_max = data_max;
     206          21 :   }
     207             : 
     208          21 :   FD_LOG_INFO(( "Restore allocations" ));
     209             : 
     210          21 :   ulong orig_data_lo  = fd_wksp_private_data_off( orig_part_max );
     211          21 :   ulong orig_data_hi  = orig_data_lo + orig_data_max;
     212          21 :   ulong wksp_part_cnt = 0UL;
     213             : 
     214          30 :   for(;;) {
     215             : 
     216             :     /* Restore the allocation header */
     217             : 
     218          30 :     ulong tag;      RESTORE_ULONG( tag      ); if( FD_UNLIKELY( !tag ) ) break; /* Optimize for lots of partitions */
     219           9 :     ulong gaddr_lo; RESTORE_ULONG( gaddr_lo );
     220           9 :     ulong sz;       RESTORE_ULONG( sz       );
     221             : 
     222           9 :     ulong gaddr_hi = gaddr_lo + sz;
     223             : 
     224           9 :     RESTORE_TEST( (orig_data_lo<=gaddr_lo) & (gaddr_lo<gaddr_hi) & (gaddr_hi<=orig_data_hi) );
     225             : 
     226           9 :     if( FD_UNLIKELY( wksp_part_cnt>=wksp_part_max ) ) {
     227           0 :       FD_LOG_WARNING(( "Restore \"%s\" to wksp \"%s\" failed because too few wksp partitions (part_max checkpt %lu, wksp %lu)",
     228           0 :                        path, wksp->name, orig_part_max, wksp_part_max ));
     229           0 :       goto unlock;
     230           0 :     }
     231             : 
     232           9 :     if( FD_UNLIKELY( !((wksp_data_lo<=gaddr_lo) & (gaddr_hi<=wksp_data_hi)) ) ) {
     233           0 :       FD_LOG_WARNING(( "Restore \"%s\" to wksp \"%s\" failed because checkpt partition [0x%016lx,0x%016lx) tag %lu "
     234           0 :                        "does not fit into wksp data region [0x%016lx,0x%016lx) (data_max checkpt %lu, wksp %lu)",
     235           0 :                        path, wksp->name, gaddr_lo, gaddr_hi, tag, wksp_data_lo, wksp_data_hi, orig_data_max, wksp_data_max ));
     236           0 :       goto unlock;
     237           0 :     }
     238             : 
     239             :     /* Restore the allocation payload into the wksp and record this
     240             :        allocation in the wksp */
     241             : 
     242           9 :     wksp_dirty = 1;
     243             : 
     244             :     #if FD_HAS_DEEPASAN
     245             :     /* The destination can be poisoned free space, so unpoison it before
     246             :        restoring into it (the rebuild below syncs the final state). */
     247             :     fd_asan_unpoison( fd_wksp_laddr_fast( wksp, gaddr_lo ), sz );
     248             :     #endif
     249             : 
     250           9 :     err = fd_io_buffered_istream_read( restore, fd_wksp_laddr_fast( wksp, gaddr_lo ), sz );
     251           9 :     if( FD_UNLIKELY( err ) ) {
     252           0 :       FD_LOG_WARNING(( "Restore \"%s\" to wksp \"%s\" failed because of I/O error (%i-%s)",
     253           0 :                        path, wksp->name, err, fd_io_strerror( err ) ));
     254           0 :       goto unlock;
     255           0 :     }
     256             : 
     257           9 :     wksp_pinfo[ wksp_part_cnt ].gaddr_lo = gaddr_lo;
     258           9 :     wksp_pinfo[ wksp_part_cnt ].gaddr_hi = gaddr_hi;
     259           9 :     wksp_pinfo[ wksp_part_cnt ].tag      = tag;
     260           9 :     wksp_part_cnt++;
     261           9 :   }
     262             : 
     263          21 :   FD_LOG_INFO(( "Rebuilding wksp with restored allocations" ));
     264             : 
     265          21 :   wksp_dirty = 1;
     266             : 
     267      343740 :   for( ulong i=wksp_part_cnt; i<wksp_part_max; i++ ) wksp_pinfo[ i ].tag = 0UL; /* Remove all remaining old allocations */
     268          21 :   err = fd_wksp_rebuild( wksp, new_seed ); /* logs details */
     269          21 :   if( FD_UNLIKELY( err ) ) { /* wksp dirty */
     270           0 :     FD_LOG_WARNING(( "Restore \"%s\" to wksp \"%s\" failed because of rebuild error", path, wksp->name ));
     271           0 :     goto unlock;
     272           0 :   }
     273             : 
     274             :   #if FD_HAS_DEEPASAN
     275             :   fd_wksp_private_asan_sync( wksp ); /* old allocations are gone now */
     276             :   #endif
     277             : 
     278          21 :   wksp_dirty = 0;
     279             : 
     280          21 :   FD_LOG_INFO(( "Restore successful" ));
     281             : 
     282             :   /* err = 0 at this point */
     283             : 
     284          21 : unlock: /* note: wksp locked at this point */
     285             : 
     286             :   /* If wksp is not clean, reset it to get it back to a clean state */
     287             : 
     288          21 :   if( wksp_dirty ) {
     289           0 :     FD_LOG_WARNING(( "wksp \"%s\" dirty; attempting to reset it and continue", wksp->name ));
     290           0 :     for( ulong i=0UL; i<wksp_part_max; i++ ) wksp_pinfo[ i ].tag = 0UL;
     291           0 :     fd_wksp_rebuild( wksp, new_seed ); /* logs details */
     292             :     #if FD_HAS_DEEPASAN
     293             :     fd_wksp_private_asan_sync( wksp ); /* everything is free now */
     294             :     #endif
     295           0 :     err = FD_WKSP_ERR_CORRUPT;
     296           0 :   }
     297             : 
     298          21 :   fd_wksp_private_unlock( wksp );
     299             : 
     300          21 : fini: /* Note: wksp unlocked at this point */
     301             : 
     302          21 :   fd_io_buffered_istream_fini( restore );
     303             : 
     304          21 :   if( FD_UNLIKELY( close( fd ) ) )
     305           0 :     FD_LOG_WARNING(( "close(\"%s\") failed (%i-%s); attempting to continue", path, errno, fd_io_strerror( errno ) ));
     306             : 
     307          21 :   return err;
     308             : 
     309           0 : io_err: /* Note: wksp locked at this point */
     310             : 
     311           0 :   FD_LOG_WARNING(( "Restore \"%s\" to wksp \"%s\" failed (%s) due to I/O error (%i-%s)",
     312           0 :                    path, wksp->name, err_info, err, fd_io_strerror( err ) ));
     313           0 :   err = FD_WKSP_ERR_FAIL;
     314             : 
     315           0 :   goto unlock;
     316             : 
     317           0 : stream_err: /* Note: wksp locked at this point */
     318             : 
     319           0 :   FD_LOG_WARNING(( "Restore \"%s\" to wksp \"%s\" failed due to checkpt format error (%s)", path, wksp->name, err_info ));
     320           0 :   err = FD_WKSP_ERR_FAIL;
     321             : 
     322           0 :   goto unlock;
     323             : 
     324          21 : # undef RESTORE_TEST
     325          21 : }
     326             : 
     327             : int
     328             : fd_wksp_private_printf_v1( int          out,
     329             :                            char const * path,
     330          21 :                            int          verbose ) {
     331             : 
     332          54 : # define TRAP(x)         do { err = (x); if( FD_UNLIKELY( err<0 ) ) { ret = err; goto done; } ret += err; } while(0)
     333         105 : # define RESTORE_TEST(c) do { if( FD_UNLIKELY( !(c) ) ) { err_info = #c; goto stream_err; } } while(0)
     334             : 
     335          21 :   int                        fd      = -1;
     336          21 :   fd_io_buffered_istream_t * restore = NULL;
     337          21 :   int                        ret     = 0;
     338          21 :   int                        err;
     339          21 :   char const *               err_info;
     340          21 :   uchar                      rbuf[ RBUF_FOOTPRINT ] __attribute__((aligned( RBUF_ALIGN )));
     341          21 :   fd_io_buffered_istream_t   _restore[1];
     342             : 
     343          21 :   fd = open( path, O_RDONLY, (mode_t)0 );
     344          21 :   if( FD_UNLIKELY( fd==-1 ) ) TRAP( dprintf( out, "\topen(O_RDONLY) failed (%i-%s)\n", errno, fd_io_strerror( errno ) ) );
     345             : 
     346          21 :   restore = fd_io_buffered_istream_init( _restore, fd, rbuf, RBUF_FOOTPRINT );
     347             : 
     348             :   /* Print the header and metadata (note: fd_wksp_private_printf
     349             :      already printed the preview info and verbose is at least 1) */
     350             : 
     351          21 :   ulong orig_part_max;
     352          21 :   ulong orig_data_max;
     353             : 
     354          21 :   {
     355          21 :     ulong magic;     RESTORE_ULONG( magic     );
     356          21 :     ulong style_ul;  RESTORE_ULONG( style_ul  );
     357          21 :     ulong seed_ul;   RESTORE_ULONG( seed_ul   );
     358          21 :     ulong part_max;  RESTORE_ULONG( part_max  );
     359          21 :     ulong data_max;  RESTORE_ULONG( data_max  );
     360          21 :     ulong ts_ul;     RESTORE_ULONG( ts_ul     ); /* considered metadata */
     361          21 :     ulong app_id;    RESTORE_ULONG( app_id    ); /* " */
     362          21 :     ulong thread_id; RESTORE_ULONG( thread_id ); /* " */
     363          21 :     ulong host_id;   RESTORE_ULONG( host_id   ); /* " */
     364          21 :     ulong cpu_id;    RESTORE_ULONG( cpu_id    ); /* " */
     365          21 :     ulong group_id;  RESTORE_ULONG( group_id  ); /* " */
     366          21 :     ulong tid;       RESTORE_ULONG( tid       ); /* " */
     367          21 :     ulong user_id;   RESTORE_ULONG( user_id   ); /* " */
     368             : 
     369          21 :     char name[ FD_SHMEM_NAME_MAX ]; ulong name_len; RESTORE_CSTR( name, FD_SHMEM_NAME_MAX );
     370             : 
     371          21 :     RESTORE_TEST( magic==FD_WKSP_MAGIC                                   );
     372          21 :     RESTORE_TEST( style_ul==(ulong)FD_WKSP_CHECKPT_STYLE_V1              );
     373          21 :     RESTORE_TEST( seed_ul==(ulong)(uint)seed_ul                          );
     374          21 :     RESTORE_TEST( fd_wksp_footprint( part_max, data_max )>0UL            );
     375          21 :     RESTORE_TEST( (name_len>0UL) & (fd_shmem_name_len( name )==name_len) );
     376             : 
     377          21 :     char app   [ FD_LOG_NAME_MAX              ]; ulong app_len;    RESTORE_CSTR( app,    FD_LOG_NAME_MAX              );
     378          21 :     char thread[ FD_LOG_NAME_MAX              ]; ulong thread_len; RESTORE_CSTR( thread, FD_LOG_NAME_MAX              );
     379          21 :     char host  [ FD_LOG_NAME_MAX              ]; ulong host_len;   RESTORE_CSTR( host,   FD_LOG_NAME_MAX              );
     380          21 :     char cpu   [ FD_LOG_NAME_MAX              ]; ulong cpu_len;    RESTORE_CSTR( cpu,    FD_LOG_NAME_MAX              );
     381          21 :     char group [ FD_LOG_NAME_MAX              ]; ulong group_len;  RESTORE_CSTR( group,  FD_LOG_NAME_MAX              );
     382          21 :     char user  [ FD_LOG_NAME_MAX              ]; ulong user_len;   RESTORE_CSTR( user,   FD_LOG_NAME_MAX              );
     383          21 :     char binfo [ FD_WKSP_CHECKPT_V1_BINFO_MAX ]; ulong binfo_len;  RESTORE_CSTR( binfo,  FD_WKSP_CHECKPT_V1_BINFO_MAX );
     384          21 :     char uinfo [ FD_WKSP_CHECKPT_V1_UINFO_MAX ]; ulong uinfo_len;  RESTORE_CSTR( uinfo,  FD_WKSP_CHECKPT_V1_UINFO_MAX );
     385             : 
     386          21 :     char ts_cstr[ FD_LOG_WALLCLOCK_CSTR_BUF_SZ ];
     387          21 :     fd_log_wallclock_cstr( (long)ts_ul, ts_cstr );
     388             : 
     389             :     /* Note: this mirrors v2 printf */
     390             : 
     391          21 :     if( verbose>=1 )
     392          21 :       TRAP( dprintf( out,
     393             :                    //"\tstyle                  %-20i\n"        /* verbose 0 info (already printed) */
     394             :                    //"\tname                   %s\n"
     395             :                    //"\tseed                   %-20u\n"
     396             :                    //"\tpart_max               %-20lu\n"
     397             :                    //"\tdata_max               %-20lu\n"
     398          21 :                      "\tmagic                  %016lx\n"       /* verbose 1 info */
     399          21 :                      "\twallclock              %-20li (%s)\n"
     400          21 :                      "\tapp                    %-20lu (%s)\n"
     401          21 :                      "\tthread                 %-20lu (%s)\n"
     402          21 :                      "\thost                   %-20lu (%s)\n"
     403          21 :                      "\tcpu                    %-20lu (%s)\n"
     404          21 :                      "\tgroup                  %-20lu (%s)\n"
     405          21 :                      "\ttid                    %-20lu\n"
     406          21 :                      "\tuser                   %-20lu (%s)\n",
     407          21 :                      magic,
     408          21 :                      (long)ts_ul, ts_cstr,
     409          21 :                      app_id,      app,
     410          21 :                      thread_id,   thread,
     411          21 :                      host_id,     host,
     412          21 :                      cpu_id,      cpu,
     413          21 :                      group_id,    group,
     414          21 :                      tid,
     415          21 :                      user_id,     user ) );
     416          21 :     if( verbose>=2 )
     417          18 :       TRAP( dprintf( out, "\tbinfo\n\t\t%s\n"
     418          21 :                           "\tuinfo\n\t\t%s\n", binfo, uinfo ) ); /* verbose 2 info */
     419             : 
     420          21 :     orig_part_max = part_max;
     421          21 :     orig_data_max = data_max;
     422          21 :   }
     423             : 
     424          21 :   if( verbose>=3 ) {
     425             : 
     426           9 :     ulong orig_data_lo = fd_wksp_private_data_off( orig_part_max );
     427           9 :     ulong orig_data_hi = orig_data_lo + orig_data_max;
     428             : 
     429           9 :     ulong alloc_tot = 0UL;
     430           9 :     ulong alloc_cnt = 0UL;
     431           9 :     ulong alloc_big = 0UL;
     432             : 
     433           9 :     if( verbose>=4 ) TRAP( dprintf( out, "\tgaddr          [0x%016lx,0x%016lx)\n", orig_data_lo, orig_data_hi ) );
     434             : 
     435           9 :     for(;;) {
     436             : 
     437             :       /* Print partition metadata */
     438             : 
     439           9 :       ulong tag;      RESTORE_ULONG( tag      ); if( !tag ) break; /* no more partitions */
     440           0 :       ulong gaddr_lo; RESTORE_ULONG( gaddr_lo );
     441           0 :       ulong sz;       RESTORE_ULONG( sz       );
     442             : 
     443           0 :       ulong gaddr_hi = gaddr_lo + sz;
     444             : 
     445           0 :       RESTORE_TEST( (orig_data_lo<=gaddr_lo) & (gaddr_lo<gaddr_hi) & (gaddr_hi<=orig_data_hi) );
     446             : 
     447           0 :       if( verbose>=4 ) TRAP( dprintf( out, "\tpartition      [0x%016lx,0x%016lx) sz %20lu tag %20lu\n", gaddr_lo, gaddr_hi, sz, tag ) );
     448             : 
     449           0 :       alloc_cnt += 1UL;
     450           0 :       alloc_tot += sz;
     451           0 :       alloc_big  = fd_ulong_max( alloc_big, sz );
     452             : 
     453             :       /* Skip partition data (TODO: add verbose 5 for pretty printing
     454             :          the raw partition data too). */
     455             : 
     456           0 :       int err = fd_io_buffered_istream_skip( restore, sz );
     457           0 :       if( FD_UNLIKELY( err ) ) { err_info = "partition data"; goto io_err; }
     458           0 :     }
     459             : 
     460           9 :     TRAP( dprintf( out, "\t%20lu bytes used (%20lu blocks, largest %20lu bytes)\n"
     461           9 :                         "\t%20lu bytes free (%20s blocks, largest %20s bytes)\n"
     462           9 :                         "\t%20lu errors detected\n"
     463           9 :                         , alloc_tot, alloc_cnt, alloc_big, orig_data_max-alloc_tot, "-", "-", 0UL /* no err if we got here */ ) );
     464             : 
     465           9 :   }
     466             : 
     467          21 : done:
     468          21 :   if( FD_LIKELY( restore ) ) fd_io_buffered_istream_fini( restore );
     469          21 :   if( FD_LIKELY( fd!=-1  ) ) close( fd ); /* TODO: Consider trapping (but we might be in a dprintf err) */
     470          21 :   return ret;
     471             : 
     472           0 : io_err:
     473           0 :   if( err<0 ) TRAP( dprintf( out, "\tFAIL: io: %s (unexpected end of file)\n", err_info ) );
     474           0 :   else        TRAP( dprintf( out, "\tFAIL: io: %s (%i-%s)\n", err_info, err, fd_io_strerror( err ) ) );
     475           0 :   goto done;
     476             : 
     477           0 : stream_err:
     478           0 :   TRAP( dprintf( fd, "\tFAIL: stream: %s\n", err_info ) );
     479           0 :   goto done;
     480             : 
     481           0 : # undef RESTORE_TEST
     482           0 : # undef TRAP
     483           0 : }
     484             : 
     485             : #undef RBUF_FOOTPRINT
     486             : #undef RBUF_ALIGN
     487             : 
     488             : #undef RESTORE_CSTR
     489             : #undef RESTORE_ULONG

Generated by: LCOV version 1.14