LCOV - code coverage report
Current view: top level - funk - fd_funk_archive.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 115 151 76.2 %
Date: 2024-11-13 11:58:15 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "fd_funk.h"
       2             : #include <sys/types.h>
       3             : #include <sys/stat.h>
       4             : #include <fcntl.h>
       5             : #include <string.h>
       6             : #include <errno.h>
       7             : #include <unistd.h>
       8             : #include "../util/io/fd_io.h"
       9             : 
      10         600 : #define FD_ARCH_MAGIC 0x92a1235fU
      11             : 
      12             : int
      13             : fd_funk_archive( fd_funk_t *  funk,
      14         300 :                  char const * filename ) {
      15         300 :   fd_wksp_t *     wksp        = fd_funk_wksp( funk );
      16         300 :   fd_funk_rec_t * rec_map     = fd_funk_rec_map( funk, wksp );
      17         300 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
      18             : 
      19         300 :   FD_LOG_NOTICE(( "writing %s ...", filename ));
      20             : 
      21         300 :   int fd = open( filename, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
      22         300 :   if( fd == -1 ) {
      23           0 :     FD_LOG_WARNING(( "failed to open %s: %s", filename, strerror(errno) ));
      24           0 :     return FD_FUNK_ERR_SYS;
      25           0 :   }
      26             : 
      27         300 :   fd_io_buffered_ostream_t str;
      28         300 :   uchar wbuf[1<<17];
      29         300 :   fd_io_buffered_ostream_init( &str, fd, wbuf, sizeof(wbuf) );
      30         300 :   ulong tot = 0;
      31             : 
      32         300 : #define ARCH_WRITE(buf, sz) \
      33       35562 :   do {                                                                  \
      34       35562 :     int err = fd_io_buffered_ostream_write( &str, buf, sz);             \
      35       35562 :     if( err ) {                                                         \
      36           0 :       FD_LOG_WARNING(( "failed to write %s: %s", filename, fd_io_strerror(err) )); \
      37           0 :       close( fd );                                                      \
      38           0 :       unlink( filename );                                               \
      39           0 :       return FD_FUNK_ERR_SYS;                                           \
      40           0 :     }                                                                   \
      41       35562 :     tot += sz;                                                          \
      42       35562 :   } while(0)
      43             : 
      44         300 :   uint magic = FD_ARCH_MAGIC;
      45         300 :   ARCH_WRITE( &magic, sizeof(magic) );
      46         300 :   ARCH_WRITE( &partvec->num_part, sizeof(partvec->num_part) );
      47             : 
      48         300 :   for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
      49        7395 :        !fd_funk_rec_map_iter_done( rec_map, iter );
      50        7095 :        iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
      51        7095 :     fd_funk_rec_t * rec     = fd_funk_rec_map_iter_ele( rec_map, iter );
      52        7095 :     ulong           txn_idx = fd_funk_txn_idx( rec->txn_cidx );
      53        7095 :     if( fd_funk_txn_idx_is_null( txn_idx ) ) { /* This is a record from the last published transaction */
      54        7095 :       uchar type = (uchar)0xa5;
      55        7095 :       ARCH_WRITE( &type, sizeof(type) );
      56        7095 :       ARCH_WRITE( rec->pair.key, sizeof(rec->pair.key) );
      57        7095 :       ARCH_WRITE( &rec->part, sizeof(rec->part) );
      58        7095 :       ARCH_WRITE( &rec->val_sz, sizeof(rec->val_sz) );
      59        7095 :       if( rec->val_sz ) {
      60        6282 :         ARCH_WRITE( fd_wksp_laddr_fast( wksp, rec->val_gaddr ), rec->val_sz );
      61        6282 :       }
      62        7095 :     }
      63        7095 :   }
      64             : 
      65         300 :   uchar type = (uchar)0x5a;
      66         300 :   ARCH_WRITE( &type, sizeof(type) );
      67             : 
      68         300 :   int err = fd_io_buffered_ostream_flush( &str );
      69         300 :   if( err ) {
      70           0 :     FD_LOG_WARNING(( "failed to write %s: %s", filename, fd_io_strerror(err) ));
      71           0 :     close( fd );
      72           0 :     unlink( filename );
      73           0 :     return FD_FUNK_ERR_SYS;
      74           0 :   }
      75         300 :   close( fd );
      76             : 
      77         300 :   FD_LOG_NOTICE(( "wrote %lu bytes to %s", tot, filename ));
      78             : 
      79         300 :   return FD_FUNK_SUCCESS;
      80         300 : }
      81             : 
      82             : int
      83             : fd_funk_unarchive( fd_funk_t *  funk,
      84         300 :                    char const * filename ) {
      85         300 :   fd_wksp_t * wksp = fd_funk_wksp( funk );
      86         300 :   fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
      87         300 :   ulong rec_max = funk->rec_max;
      88         300 :   fd_alloc_t * alloc = fd_funk_alloc( funk, wksp );
      89             : 
      90         300 :   FD_LOG_NOTICE(( "reading %s ...", filename ));
      91             : 
      92         300 :   int fd = open( filename, O_RDONLY );
      93         300 :   if( fd == -1 ) {
      94           0 :     FD_LOG_WARNING(( "failed to open %s: %s", filename, strerror(errno) ));
      95           0 :     return FD_FUNK_ERR_SYS;
      96           0 :   }
      97             : 
      98         300 :   fd_io_buffered_istream_t str;
      99         300 :   uchar rbuf[1<<17];
     100         300 :   fd_io_buffered_istream_init( &str, fd, rbuf, sizeof(rbuf) );
     101         300 :   ulong tot = 0;
     102             : 
     103         300 : #define ARCH_READ(buf, sz)                                              \
     104       35562 :   do {                                                                  \
     105       35562 :     int err = fd_io_buffered_istream_read( &str, buf, sz);              \
     106       35562 :     if( err ) {                                                         \
     107           0 :       FD_LOG_WARNING(( "failed to read %s: %s", filename, fd_io_strerror(err) )); \
     108           0 :       close( fd );                                                      \
     109           0 :       return FD_FUNK_ERR_SYS;                                           \
     110           0 :     }                                                                   \
     111       35562 :     tot += sz;                                                          \
     112       35562 :   } while(0)
     113             : 
     114         300 :   uint magic;
     115         300 :   ARCH_READ( &magic, sizeof(magic) );
     116         300 :   if( magic != FD_ARCH_MAGIC ) {
     117           0 :     FD_LOG_WARNING(( "archive %s has wrong magic number", filename ));
     118           0 :     close( fd );
     119           0 :     return FD_FUNK_ERR_SYS;
     120           0 :   }
     121         300 :   uint num_part;
     122         300 :   ARCH_READ( &num_part, sizeof(num_part) );
     123         300 :   fd_funk_set_num_partitions( funk, num_part );
     124         300 :   fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
     125             : 
     126         300 :   uchar type;
     127         300 :   fd_funk_xid_key_pair_t pair;
     128         300 :   fd_memset( &pair, 0, sizeof(pair) );
     129         300 :   uint part;
     130         300 :   uint val_sz;
     131             : 
     132        7395 :   for(;;) {
     133        7395 :     ARCH_READ( &type, sizeof(type) );
     134        7395 :     if( type == (uchar)0x5a ) break;
     135        7095 :     switch( type ) {
     136             : 
     137        7095 :     case (uchar)0xa5: {
     138        7095 :       ARCH_READ( pair.key, sizeof(pair.key) );
     139        7095 :       ARCH_READ( &part, sizeof(part) );
     140        7095 :       ARCH_READ( &val_sz, sizeof(val_sz) );
     141             : 
     142        7095 :       if( FD_UNLIKELY( fd_funk_rec_map_is_full( rec_map ) ) ) {
     143           0 :         FD_LOG_WARNING(( "archive %s has too many records to fit in given funk", filename ));
     144           0 :         close( fd );
     145           0 :         return FD_FUNK_ERR_MEM;
     146           0 :       }
     147             : 
     148        7095 :       fd_funk_rec_t * rec     = fd_funk_rec_map_insert( rec_map, &pair );
     149        7095 :       ulong           rec_idx = (ulong)(rec - rec_map);
     150        7095 :       if( FD_UNLIKELY( rec_idx>=rec_max ) ) FD_LOG_CRIT(( "memory corruption detected (bad idx)" ));
     151             : 
     152        7095 :       ulong rec_prev_idx = funk->rec_tail_idx;
     153             : 
     154        7095 :       rec->prev_idx = rec_prev_idx;
     155        7095 :       rec->next_idx = FD_FUNK_REC_IDX_NULL;
     156        7095 :       rec->txn_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     157        7095 :       rec->tag      = 0U;
     158        7095 :       rec->flags    = 0UL;
     159             : 
     160        7095 :       int first_born = fd_funk_rec_idx_is_null( rec_prev_idx );
     161        7095 :       if( first_born ) funk->rec_head_idx               = rec_idx;
     162        6795 :       else             rec_map[ rec_prev_idx ].next_idx = rec_idx;
     163             : 
     164        7095 :       funk->rec_tail_idx = rec_idx;
     165             : 
     166        7095 :       fd_funk_val_init( rec );
     167        7095 :       if( val_sz ) {
     168        6282 :         int err;
     169        6282 :         if( !fd_funk_val_truncate( rec, val_sz, alloc, wksp, &err ) ) {
     170           0 :           FD_LOG_WARNING(( "archive %s has too much data to fit in given funk wksp", filename ));
     171           0 :           close( fd );
     172           0 :           return err;
     173           0 :         }
     174        6282 :         ARCH_READ( fd_wksp_laddr_fast( wksp, rec->val_gaddr ), val_sz );
     175        6282 :       }
     176             : 
     177        7095 :       fd_funk_part_init( rec );
     178        7095 :       if( part != FD_FUNK_PART_NULL ) {
     179        5034 :         fd_funk_part_set_intern( partvec, rec_map, rec, part );
     180        5034 :       }
     181        7095 :       break;
     182        7095 :     }
     183             : 
     184           0 :     default:
     185           0 :       FD_LOG_WARNING(( "archive %s has unknown record type", filename ));
     186           0 :       close( fd );
     187           0 :       return FD_FUNK_ERR_SYS;
     188        7095 :     }
     189        7095 :   }
     190             : 
     191         300 :   close( fd );
     192             : 
     193         300 :   FD_LOG_NOTICE(( "read %lu bytes from %s", tot, filename ));
     194             : 
     195         300 : return FD_FUNK_SUCCESS;
     196         300 : }

Generated by: LCOV version 1.14