LCOV - code coverage report
Current view: top level - util/wksp - fd_wksp_io.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 120 144 83.3 %
Date: 2025-01-08 12:08:44 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include "fd_wksp_private.h"
       2             : 
       3             : #include <stdio.h>
       4             : #include <errno.h>
       5             : #include <unistd.h>
       6             : #include <fcntl.h>
       7             : 
       8             : /* fd_wksp_private_checkpt_read reads up to the leading buf_max bytes at
       9             :    path into buf.  On success, returns 0 and *_buf_sz will contain the
      10             :    number of bytes read.  Returns a fd_io_strerror compatible error code
      11             :    on failure and *_buf_sz will be unchanged (buf might have been
      12             :    clobbered). */
      13             : 
      14             : static int
      15             : fd_wksp_private_checkpt_read( char const * path,       /* Assumes valid */
      16             :                               void *       buf,        /* Assumes valid */
      17             :                               ulong        buf_max,    /* Assumes buf_max>=12 */
      18         180 :                               ulong *      _buf_sz ) { /* Assumes non-NULL */
      19             : 
      20         180 :   int fd = open( path, O_RDONLY, (mode_t)0 );
      21         180 :   if( FD_UNLIKELY( fd==-1 ) ) return errno;
      22             : 
      23         180 :   int err = fd_io_read( fd, buf, 12UL, buf_max, _buf_sz );
      24             : 
      25         180 :   if( FD_UNLIKELY( close( fd ) ) )
      26           0 :     FD_LOG_WARNING(( "close(\"%s\") failed (%i-%s); attempting to continue", path, errno, fd_io_strerror( errno ) ));
      27             : 
      28         180 :   return err;
      29         180 : }
      30             : 
      31             : int
      32             : fd_wksp_preview( char const *        path,
      33         180 :                  fd_wksp_preview_t * _opt_preview ) {
      34             : 
      35             :   /* Check input args */
      36             : 
      37         180 :   if( FD_UNLIKELY( !path ) ) return FD_WKSP_ERR_INVAL;
      38             : 
      39         180 :   fd_wksp_preview_t stack_preview[1];
      40         180 :   if( !_opt_preview ) _opt_preview = stack_preview; /* cmov */
      41             : 
      42             :   /* Read the wksp checkpt header.  165 is large enough to
      43             :      handle decoding an arbitrarily corrupted V1 header (14 worst case
      44             :      SVW encoded ulongs at 9 bytes each followed by a worst case
      45             :      non-'\0' bytes of name at 39==FD_SHMEM_NAME_MAX-1 bytes) and an
      46             :      arbitrarily corrupted V2 header (a 80 byte struct stored
      47             :      uncompressed). */
      48             : 
      49         180 :   uchar buf[ 165 ];
      50         180 :   ulong buf_sz;
      51         180 :   int   err = fd_wksp_private_checkpt_read( path, buf, 165UL, &buf_sz );
      52         180 :   if( FD_UNLIKELY( err ) ) return FD_WKSP_ERR_FAIL;
      53             : 
      54             :   /* If we read a supported valid V2 header, return the requested
      55             :      preview info */
      56             : 
      57         180 :   fd_wksp_checkpt_v2_hdr_t * v2 = (fd_wksp_checkpt_v2_hdr_t *)buf;
      58             : 
      59         180 :   ulong name_len = fd_shmem_name_len( v2->name ); /* tail reading safe */
      60             : 
      61         180 :   if( FD_LIKELY( (sizeof(fd_wksp_checkpt_v2_hdr_t)<=buf_sz                         ) &     /* header not truncated */
      62         180 :                  (v2->magic==FD_WKSP_MAGIC                                         ) &     /* with valid magic */
      63         180 :                  (v2->style==FD_WKSP_CHECKPT_STYLE_V2                              ) &     /* with valid style */
      64         180 :                  (fd_checkpt_frame_style_is_supported( v2->frame_style_compressed )) &     /* with supported compression */
      65         180 :                  (v2->reserved==0U                                                 ) &     /* with expected reserved */
      66         180 :                  (name_len>0UL                                                     ) &     /* with valid name */
      67             :                  /* ignore seed (arbitrary) */
      68         180 :                  (fd_wksp_footprint( v2->part_max, v2->data_max )>0UL              ) ) ) { /* with valid part_max / data_max */
      69         135 :     _opt_preview->style    = v2->style;
      70         135 :     _opt_preview->seed     = v2->seed;
      71         135 :     _opt_preview->part_max = v2->part_max;
      72         135 :     _opt_preview->data_max = v2->data_max;
      73         135 :     memcpy( _opt_preview->name, v2->name, name_len+1UL );
      74         135 :     return FD_WKSP_SUCCESS;
      75         135 :   }
      76             : 
      77             :   /* Otherwise, if we read a supported valid V1 header, return the
      78             :      requested preview info */
      79             : 
      80          45 :   uchar const * cur = buf;
      81             : 
      82          45 :   ulong magic;     cur = fd_ulong_svw_dec( cur, &magic     ); /* safe to tail read */
      83          45 :   ulong style_ul;  cur = fd_ulong_svw_dec( cur, &style_ul  ); /* " */
      84          45 :   ulong seed_ul;   cur = fd_ulong_svw_dec( cur, &seed_ul   ); /* " */
      85          45 :   ulong part_max;  cur = fd_ulong_svw_dec( cur, &part_max  ); /* " */
      86          45 :   ulong data_max;  cur = fd_ulong_svw_dec( cur, &data_max  ); /* " */
      87          45 :   ulong ts_ul;     cur = fd_ulong_svw_dec( cur, &ts_ul     ); /* " */
      88          45 :   ulong app_id;    cur = fd_ulong_svw_dec( cur, &app_id    ); /* " */
      89          45 :   ulong thread_id; cur = fd_ulong_svw_dec( cur, &thread_id ); /* " */
      90          45 :   ulong host_id;   cur = fd_ulong_svw_dec( cur, &host_id   ); /* " */
      91          45 :   ulong cpu_id;    cur = fd_ulong_svw_dec( cur, &cpu_id    ); /* " */
      92          45 :   ulong group_id;  cur = fd_ulong_svw_dec( cur, &group_id  ); /* " */
      93          45 :   ulong tid;       cur = fd_ulong_svw_dec( cur, &tid       ); /* " */
      94          45 :   ulong user_id;   cur = fd_ulong_svw_dec( cur, &user_id   ); /* " */
      95          45 :   /* name_len */   cur = fd_ulong_svw_dec( cur, &name_len  ); /* " */
      96             : 
      97          45 :   char  name[ FD_SHMEM_NAME_MAX ];
      98          45 :   ulong name_len_safe = fd_ulong_min( name_len, FD_SHMEM_NAME_MAX-1UL );
      99          45 :   memcpy( name, cur, name_len_safe );
     100          45 :   name[ name_len_safe ] = '\0';
     101             : 
     102          45 :   if( FD_LIKELY( (((ulong)(cur-buf))<=buf_sz                            ) &     /* header not truncated */
     103          45 :                  (magic   ==FD_WKSP_MAGIC                               ) &     /* with valid magic */
     104          45 :                  (style_ul==(ulong)FD_WKSP_CHECKPT_STYLE_V1             ) &     /* with valid style */
     105          45 :                  (seed_ul ==(ulong)(uint)seed_ul                        ) &     /* with valid seed */
     106          45 :                  (fd_wksp_footprint( part_max, data_max )>0UL           ) &     /* with valid part_max / data_max */
     107             :                  /* ignore ts_ul     (metadata) */
     108             :                  /* ignore app_id    (metadata) */
     109             :                  /* ignore thread_id (metadata) */
     110             :                  /* ignore host_id   (metadata) */
     111             :                  /* ignore cpu_id    (metadata) */
     112             :                  /* ignore group_id  (metadata) */
     113             :                  /* ignore tid_id    (metadata) */
     114             :                  /* ignore user_id   (metadata) */
     115          45 :                  ((name_len>0UL) & (fd_shmem_name_len( name )==name_len)) ) ) { /* with valid name */
     116          45 :     _opt_preview->style    = (int)style_ul;
     117          45 :     _opt_preview->seed     = (uint)seed_ul;
     118          45 :     _opt_preview->part_max = part_max;
     119          45 :     _opt_preview->data_max = data_max;
     120          45 :     memcpy( _opt_preview->name, name, name_len+1UL );
     121          45 :     return FD_WKSP_SUCCESS;
     122          45 :   }
     123             : 
     124             :   /* Otherwise, this is not a supported valid wksp checkpt header */
     125             : 
     126           0 :   return FD_WKSP_ERR_CORRUPT;
     127          45 : }
     128             : 
     129             : int
     130             : fd_wksp_checkpt_tpool( fd_tpool_t * tpool,
     131             :                        ulong        t0,
     132             :                        ulong        t1,
     133             :                        fd_wksp_t *  wksp,
     134             :                        char const * path,
     135             :                        ulong        mode,
     136             :                        int          style,
     137          72 :                        char const * uinfo ) { /* TODO: CONSIDER ALLOWING SUBSET OF TAGS */
     138             : 
     139             :   /* Check input args */
     140             : 
     141          72 :   if( FD_UNLIKELY( !wksp ) ) {
     142           0 :     FD_LOG_WARNING(( "NULL wksp" ));
     143           0 :     return FD_WKSP_ERR_INVAL;
     144           0 :   }
     145             : 
     146          72 :   if( FD_UNLIKELY( !path ) ) {
     147           0 :     FD_LOG_WARNING(( "NULL path" ));
     148           0 :     return FD_WKSP_ERR_INVAL;
     149           0 :   }
     150             : 
     151          72 :   if( FD_UNLIKELY( mode!=(ulong)(mode_t)mode ) ) {
     152          12 :     FD_LOG_WARNING(( "bad mode" ));
     153          12 :     return FD_WKSP_ERR_INVAL;
     154          12 :   }
     155             : 
     156          60 :   style = fd_int_if( !!style, style, FD_HAS_LZ4 ? FD_WKSP_CHECKPT_STYLE_V3 : FD_WKSP_CHECKPT_STYLE_V2 );
     157             : 
     158          60 :   if( FD_UNLIKELY( !uinfo ) ) uinfo = "";
     159             : 
     160          60 :   char const * binfo = fd_log_build_info;
     161          60 :   if( FD_UNLIKELY( !binfo ) ) binfo = "";
     162             : 
     163             :   /* Checkpt with the appropriate style */
     164             : 
     165          60 :   switch( style ) {
     166          12 :   case FD_WKSP_CHECKPT_STYLE_V1: return fd_wksp_private_checkpt_v1( tpool, t0, t1, wksp, path, mode, uinfo );
     167          12 :   case FD_WKSP_CHECKPT_STYLE_V2: return fd_wksp_private_checkpt_v2( tpool, t0, t1, wksp, path, mode, uinfo,
     168          12 :                                                                     FD_CHECKPT_FRAME_STYLE_RAW );
     169          24 :   case FD_WKSP_CHECKPT_STYLE_V3: return fd_wksp_private_checkpt_v2( tpool, t0, t1, wksp, path, mode, uinfo,
     170          24 :                                                                     FD_CHECKPT_FRAME_STYLE_LZ4 );
     171           0 :   break;
     172          60 :   }
     173             : 
     174          12 :   FD_LOG_WARNING(( "unsupported style" ));
     175          12 :   return FD_WKSP_ERR_INVAL;
     176          60 : }
     177             : 
     178             : int
     179             : fd_wksp_restore_tpool( fd_tpool_t * tpool,
     180             :                        ulong        t0,
     181             :                        ulong        t1,
     182             :                        fd_wksp_t *  wksp,
     183             :                        char const * path,
     184          84 :                        uint         new_seed ) {
     185             : 
     186             :   /* Check input args */
     187             : 
     188          84 :   if( FD_UNLIKELY( !wksp ) ) {
     189           0 :     FD_LOG_WARNING(( "NULL wksp" ));
     190           0 :     return FD_WKSP_ERR_INVAL;
     191           0 :   }
     192             : 
     193          84 :   if( FD_UNLIKELY( !path ) ) {
     194           0 :     FD_LOG_WARNING(( "NULL path" ));
     195           0 :     return FD_WKSP_ERR_INVAL;
     196           0 :   }
     197             : 
     198             :   /* new_seed arbitrary */
     199             : 
     200             :   /* Determine which version to use */
     201             : 
     202          84 :   fd_wksp_preview_t preview[1];
     203          84 :   int err = fd_wksp_preview( path, preview );
     204          84 :   if( FD_UNLIKELY( err ) ) {
     205           0 :     FD_LOG_WARNING(( "\"%s\" does not appear to be a supported wksp checkpt", path ));
     206           0 :     return err;
     207           0 :   }
     208             : 
     209             :   /* Restore with the appropriate version */
     210             : 
     211          84 :   switch( preview->style ) {
     212          21 :   case FD_WKSP_CHECKPT_STYLE_V1: return fd_wksp_private_restore_v1( tpool, t0, t1, wksp, path, new_seed );
     213          63 :   case FD_WKSP_CHECKPT_STYLE_V2: return fd_wksp_private_restore_v2( tpool, t0, t1, wksp, path, new_seed );
     214             :   /* note: v3 is really v2 with compressed frames */
     215           0 :   default: break; /* never get here (preview already checked) */
     216          84 :   }
     217             : 
     218           0 :   FD_LOG_WARNING(( "unsupported style" ));
     219           0 :   return FD_WKSP_ERR_CORRUPT;
     220          84 : }
     221             : 
     222             : int
     223             : fd_wksp_printf( int          fd,
     224             :                 char const * path,
     225          96 :                 int          verbose ) {
     226             : 
     227          96 :   int ret = 0;
     228         276 : # define TRAP(expr) do { int _err = (expr); if( FD_UNLIKELY( _err<0 ) ) { return _err; } ret += _err; } while(0)
     229             : 
     230          96 :   if( verbose<0 ) return ret;
     231             : 
     232          96 :   TRAP( dprintf( fd, "checkpt %s (verbose %i)\n", path, verbose ) );
     233             : 
     234          96 :   fd_wksp_preview_t preview[1];
     235          96 :   int err = fd_wksp_preview( path, preview );
     236          96 :   if( FD_UNLIKELY( err ) )
     237           0 :     TRAP( dprintf( fd, "\tinvalid or unsupported (%i-%s)\n", err, fd_wksp_strerror( err ) ) );
     238          96 :   else
     239          96 :     TRAP( dprintf( fd, "\tstyle                  %-20i\n"
     240          96 :                        "\tname                   %s\n"
     241          96 :                        "\tseed                   %-20u\n"
     242          96 :                        "\tpart_max               %-20lu\n"
     243          96 :                        "\tdata_max               %-20lu\n",
     244          96 :                        preview->style, preview->name, preview->seed, preview->part_max, preview->data_max ) );
     245             : 
     246          96 :   if( verbose<1 ) return ret;
     247             : 
     248          84 :   switch( preview->style ) {
     249          21 :   case FD_WKSP_CHECKPT_STYLE_V1: TRAP( fd_wksp_private_printf_v1( fd, path, verbose ) ); break;
     250          63 :   case FD_WKSP_CHECKPT_STYLE_V2: TRAP( fd_wksp_private_printf_v2( fd, path, verbose ) ); break;
     251             :   /* note: v3 is really v2 with compressed frames */
     252          63 :   default: /* never get here (preview already checked) */
     253           0 :     TRAP( dprintf( fd, "unsupported style" ) );
     254           0 :     break;
     255          84 :   }
     256             : 
     257          84 : # undef TRAP
     258             : 
     259          84 :   return ret;
     260          84 : }

Generated by: LCOV version 1.14