LCOV - code coverage report
Current view: top level - discof/store - fd_store.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 110 143 76.9 %
Date: 2025-08-01 05:13:22 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "fd_store.h"
       2             : #include "../../flamenco/fd_flamenco_base.h"
       3             : 
       4             : void *
       5           3 : fd_store_new( void * shmem, ulong fec_max, ulong seed ) {
       6             : 
       7           3 :   if( FD_UNLIKELY( !shmem ) ) {
       8           0 :     FD_LOG_WARNING(( "NULL mem" ));
       9           0 :     return NULL;
      10           0 :   }
      11             : 
      12           3 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_store_align() ) ) ) {
      13           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      14           0 :     return NULL;
      15           0 :   }
      16             : 
      17           3 :   ulong footprint = fd_store_footprint( fec_max );
      18           3 :   if( FD_UNLIKELY( !footprint ) ) {
      19           0 :     FD_LOG_WARNING(( "bad fec_max (%lu)", fec_max ));
      20           0 :     return NULL;
      21           0 :   }
      22             : 
      23           3 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
      24           3 :   if( FD_UNLIKELY( !wksp ) ) {
      25           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
      26           0 :     return NULL;
      27           0 :   }
      28             : 
      29           3 :   fd_memset( shmem, 0, footprint );
      30             : 
      31           3 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      32           3 :   fd_store_t * store = FD_SCRATCH_ALLOC_APPEND( l, fd_store_align(),      sizeof( fd_store_t )               );
      33           3 :   void *       pool  = FD_SCRATCH_ALLOC_APPEND( l, fd_store_pool_align(), fd_store_pool_footprint( fec_max ) );
      34           3 :   void *       map   = FD_SCRATCH_ALLOC_APPEND( l, fd_store_map_align(),  fd_store_map_footprint ( fec_max ) );
      35           3 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_store_align() ) == (ulong)shmem + footprint );
      36             : 
      37           3 :   store->seed        = seed;
      38           3 :   store->root        = ULONG_MAX;
      39           3 :   store->store_gaddr = fd_wksp_gaddr_fast( wksp, store                                                         );
      40           3 :   store->pool_gaddr  = fd_wksp_gaddr_fast( wksp, fd_store_pool_join( fd_store_pool_new( pool, fec_max      ) ) );
      41           3 :   store->map_gaddr   = fd_wksp_gaddr_fast( wksp, fd_store_map_join ( fd_store_map_new ( map, fec_max, seed ) ) );
      42             : 
      43           3 :   FD_COMPILER_MFENCE();
      44           3 :   FD_VOLATILE( store->magic ) = FD_STORE_MAGIC;
      45           3 :   FD_COMPILER_MFENCE();
      46             : 
      47           3 :   return shmem;
      48           3 : }
      49             : 
      50             : fd_store_t *
      51           3 : fd_store_join( void * shstore ) {
      52           3 :   fd_store_t * store = (fd_store_t *)shstore;
      53             : 
      54           3 :   if( FD_UNLIKELY( !store ) ) {
      55           0 :     FD_LOG_WARNING(( "NULL store" ));
      56           0 :     return NULL;
      57           0 :   }
      58             : 
      59           3 :   if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)store, fd_store_align() ) ) ) {
      60           0 :     FD_LOG_WARNING(( "misaligned store" ));
      61           0 :     return NULL;
      62           0 :   }
      63             : 
      64           3 :   fd_wksp_t * wksp = fd_wksp_containing( store );
      65           3 :   if( FD_UNLIKELY( !wksp ) ) {
      66           0 :     FD_LOG_WARNING(( "store must be part of a workspace" ));
      67           0 :     return NULL;
      68           0 :   }
      69             : 
      70           3 :   if( FD_UNLIKELY( store->magic!=FD_STORE_MAGIC ) ) {
      71           0 :     FD_LOG_WARNING(( "bad magic" ));
      72           0 :     return NULL;
      73           0 :   }
      74             : 
      75           3 :   return store;
      76           3 : }
      77             : 
      78             : void *
      79           3 : fd_store_leave( fd_store_t const * store ) {
      80             : 
      81           3 :   if( FD_UNLIKELY( !store ) ) {
      82           0 :     FD_LOG_WARNING(( "NULL store" ));
      83           0 :     return NULL;
      84           0 :   }
      85             : 
      86           3 :   return (void *)store;
      87           3 : }
      88             : 
      89             : void *
      90           3 : fd_store_delete( void * store ) {
      91             : 
      92           3 :   if( FD_UNLIKELY( !store ) ) {
      93           0 :     FD_LOG_WARNING(( "NULL store" ));
      94           0 :     return NULL;
      95           0 :   }
      96             : 
      97           3 :   if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)store, fd_store_align() ) ) ) {
      98           0 :     FD_LOG_WARNING(( "misaligned store" ));
      99           0 :     return NULL;
     100           0 :   }
     101             : 
     102           3 :   return store;
     103           3 : }
     104             : 
     105             : fd_store_fec_t *
     106             : fd_store_insert( fd_store_t * store,
     107             :                  fd_hash_t  * merkle_root,
     108             :                  uchar      * data,
     109          21 :                  ulong        data_sz ) {
     110             : 
     111             : # if FD_STORE_USE_HANDHOLDING /* FIXME eviction? max bound guaranteed for worst-case? */
     112          21 :   if( FD_UNLIKELY( !fd_store_pool_free( fd_store_pool( store ) ) ) ) { FD_LOG_WARNING(( "store full"                                                              )); return NULL; }
     113          21 :   if( FD_UNLIKELY( data_sz > FD_STORE_DATA_MAX                   ) ) { FD_LOG_WARNING(( "data_sz %lu > FD_STORE_DATA_MAX", data_sz                                )); return NULL; }
     114          21 :   if( FD_UNLIKELY( fd_store_query_const( store, merkle_root )    ) ) { FD_LOG_WARNING(( "merkle root %s already in store", FD_BASE58_ENC_32_ALLOCA( merkle_root ) )); return NULL; }
     115          21 : # endif
     116             : 
     117          21 :   fd_store_fec_t * pool = fd_store_pool( store );
     118          21 :   ulong            null = fd_store_pool_idx_null( pool );
     119          21 :   fd_store_fec_t * fec  = fd_store_pool_ele_acquire( pool );
     120          21 :   fec->key              = *merkle_root;
     121          21 :   fec->next             = null;
     122          21 :   fec->parent           = null;
     123          21 :   fec->child            = null;
     124          21 :   fec->sibling          = null;
     125          21 :   fec->data_sz          = data_sz;
     126          21 :   memcpy( fec->data, data, data_sz );
     127          21 :   fd_store_map_ele_insert( fd_store_map( store ), fec, fd_store_pool( store ) );
     128          21 :   if( FD_UNLIKELY( store->root == null ) ) store->root = fd_store_pool_idx( pool, fec );
     129          21 :   return fec;
     130          21 : }
     131             : 
     132             : fd_store_fec_t *
     133          18 : fd_store_link( fd_store_t * store, fd_hash_t * merkle_root, fd_hash_t * chained_merkle_root ) {
     134             : 
     135          18 : # if FD_STORE_USE_HANDHOLDING
     136          18 :   if( FD_UNLIKELY( !fd_store_query_const( store, merkle_root         ) ) ) { FD_LOG_WARNING(( "missing merkle root %s",         FD_BASE58_ENC_32_ALLOCA( merkle_root         ) ) ); return NULL; }
     137          18 :   if( FD_UNLIKELY( !fd_store_query_const( store, chained_merkle_root ) ) ) { FD_LOG_WARNING(( "missing chained merkle root %s", FD_BASE58_ENC_32_ALLOCA( chained_merkle_root ) ) ); return NULL; }
     138          18 : # endif
     139             : 
     140          18 :   fd_store_map_t * map    = fd_store_map( store );
     141          18 :   fd_store_fec_t * pool   = fd_store_pool( store );
     142          18 :   ulong            null   = fd_store_pool_idx_null( pool );
     143          18 :   fd_store_fec_t * parent = fd_store_map_ele_query( map, chained_merkle_root, NULL, pool );
     144          18 :   fd_store_fec_t * child  = fd_store_map_ele_query( map, merkle_root, NULL, pool );
     145             : 
     146          18 :   child->parent = fd_store_pool_idx( pool, parent );
     147          18 :   if( FD_LIKELY( parent->child == null ) ) {
     148          15 :     parent->child = fd_store_pool_idx( pool, child ); /* set as left-child. */
     149          15 :   } else {
     150           3 :     fd_store_fec_t * curr = fd_store_pool_ele( pool, parent->child );
     151           3 :     while( curr->sibling != null ) curr = fd_store_pool_ele( pool, curr->sibling );
     152           3 :     curr->sibling = fd_store_pool_idx( pool, child ); /* set as right-sibling. */
     153           3 :   }
     154          18 :   return child;
     155          18 : }
     156             : 
     157             : fd_store_fec_t *
     158             : fd_store_publish( fd_store_t  * store,
     159           3 :                   fd_hash_t   * merkle_root ) {
     160             : 
     161           3 :   fd_store_map_t * map  = fd_store_map( store );
     162           3 :   fd_store_fec_t * pool = fd_store_pool( store );
     163           3 :   ulong            null = fd_store_pool_idx_null( pool );
     164           3 :   fd_store_fec_t * oldr = fd_store_root( store );
     165           3 :   fd_store_fec_t * newr = fd_store_map_ele_query( map, merkle_root, NULL, pool );
     166             : 
     167           3 : # if FD_STORE_USE_HANDHOLDING
     168           3 :   if( FD_UNLIKELY( !newr ) ) { FD_LOG_WARNING(( "merkle root %s not found", FD_BASE58_ENC_32_ALLOCA( merkle_root ) )); return NULL; }
     169           3 : # endif
     170             : 
     171             :   /* First, remove the previous root, and push it as the first element
     172             :      of the BFS queue. */
     173             : 
     174           3 :   fd_store_fec_t * head = fd_store_map_ele_remove( map, &oldr->key, NULL, pool );
     175           3 :   head->next            = null; /* clear map next */
     176           3 :   fd_store_fec_t * tail = head; /* tail of BFS queue */
     177             : 
     178             :   /* Second, BFS down the tree, pruning all of root's ancestors and also
     179             :      any descendants of those ancestors. */
     180             : 
     181          18 :   while( FD_LIKELY( head ) ) {
     182          15 :     fd_store_fec_t * child = fd_store_pool_ele( pool, head->child );          /* left-child */
     183          30 :     while( FD_LIKELY( child ) ) {                                             /* iterate over children */
     184          15 :       if( FD_LIKELY( child != newr ) ) {                                      /* stop at new root */
     185          12 :         tail->next = fd_store_map_idx_remove( map, &child->key, null, pool ); /* remove node from map to reuse `.next` */
     186          12 :         tail       = fd_store_pool_ele( pool, tail->next );                   /* push onto BFS queue (so descendants can be pruned) */
     187          12 :         tail->next = null;                                                    /* clear map next */
     188          12 :       }
     189          15 :       child = fd_store_pool_ele( pool, child->sibling ); /* right-sibling */
     190          15 :     }
     191          15 :     fd_store_fec_t * next = fd_store_pool_ele( pool, head->next ); /* pophead */
     192          15 :     fd_store_pool_ele_release( pool, head );                       /* release */
     193          15 :     head = next;                                                   /* advance */
     194          15 :   }
     195           3 :   newr->parent = null;                            /* unlink old root */
     196           3 :   store->root  = fd_store_pool_idx( pool, newr ); /* replace with new root */
     197           3 :   return newr;
     198           3 : }

Generated by: LCOV version 1.14