LCOV - code coverage report
Current view: top level - disco/store - fd_store.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 189 0.0 %
Date: 2026-03-19 18:19:27 Functions: 0 14 0.0 %

          Line data    Source code
       1             : #include "fd_store.h"
       2             : 
       3           0 : #define BLOCKING 1
       4             : 
       5             : static inline fd_store_map_t *
       6           0 : map_laddr( fd_store_t * store ) {
       7           0 :   return fd_wksp_laddr_fast( fd_store_wksp( store ), store->map_gaddr );
       8           0 : }
       9             : 
      10             : static inline fd_store_pool_t
      11           0 : pool_ljoin( fd_store_t const * store ) {
      12           0 :   return (fd_store_pool_t){
      13           0 :       .pool    = fd_wksp_laddr_fast( fd_store_wksp( store ), store->pool_mem_gaddr ),
      14           0 :       .ele     = fd_wksp_laddr_fast( fd_store_wksp( store ), store->pool_ele_gaddr ),
      15           0 :       .ele_max = store->fec_max };
      16           0 : }
      17             : 
      18             : static inline fd_store_fec_t *
      19           0 : pool_laddr( fd_store_t * store ) {
      20           0 :   fd_store_pool_t pool = pool_ljoin( store );
      21           0 :   return pool.ele;
      22           0 : }
      23             : 
      24             : void *
      25           0 : fd_store_new( void * shmem, ulong fec_max, ulong part_cnt ) {
      26             : 
      27           0 :   if( FD_UNLIKELY( part_cnt==0UL ) ) {
      28           0 :     FD_LOG_WARNING(( "part_cnt must be non-zero" ));
      29           0 :     return NULL;
      30           0 :   }
      31             : 
      32           0 :   if( FD_UNLIKELY( !shmem ) ) {
      33           0 :     FD_LOG_WARNING(( "NULL mem" ));
      34           0 :     return NULL;
      35           0 :   }
      36             : 
      37           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_store_align() ) ) ) {
      38           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      39           0 :     return NULL;
      40           0 :   }
      41             : 
      42           0 :   ulong footprint = fd_store_footprint( fec_max );
      43           0 :   if( FD_UNLIKELY( !footprint ) ) {
      44           0 :     FD_LOG_WARNING(( "bad fec_max (%lu)", fec_max ));
      45           0 :     return NULL;
      46           0 :   }
      47             : 
      48           0 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
      49           0 :   if( FD_UNLIKELY( !wksp ) ) {
      50           0 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
      51           0 :     return NULL;
      52           0 :   }
      53             : 
      54             :   /* This seed value is very important. We have fec_max chains in the
      55             :      map, which means the size of each partition of buckets should be
      56             :      fec_max / part_cnt. When inserting into the map, we use the
      57             :      partition_slot_cnt as the seed, so that the modified hash function
      58             :      can use the seed/partition_slot_cnt to hash the key into the
      59             :      correct partition. */
      60             : 
      61           0 :   ulong part_slot_cnt = fec_max / part_cnt;
      62           0 :   ulong seed          = part_slot_cnt;
      63             : 
      64           0 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      65           0 :   fd_store_t * store  = FD_SCRATCH_ALLOC_APPEND( l, fd_store_align(),        sizeof(fd_store_t)                 );
      66           0 :   void *       map    = FD_SCRATCH_ALLOC_APPEND( l, fd_store_map_align(),    fd_store_map_footprint ( fec_max ) );
      67           0 :   void *       shpool = FD_SCRATCH_ALLOC_APPEND( l, fd_store_pool_align(),   fd_store_pool_footprint()          );
      68           0 :   void *       shele  = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_store_fec_t), sizeof(fd_store_fec_t)*fec_max     );
      69           0 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_store_align() )==(ulong)shmem + footprint );
      70             : 
      71           0 :   fd_memset( store, 0, sizeof(fd_store_t) );
      72           0 :   store->store_gaddr    = fd_wksp_gaddr_fast( wksp, store  );
      73           0 :   store->pool_mem_gaddr = fd_wksp_gaddr_fast( wksp, shpool );
      74           0 :   store->pool_ele_gaddr = fd_wksp_gaddr_fast( wksp, shele  );
      75           0 :   store->map_gaddr      = fd_wksp_gaddr_fast( wksp, fd_store_map_join( fd_store_map_new ( map, fec_max, seed ) ) );
      76             : 
      77           0 :   store->part_cnt = part_cnt;
      78           0 :   store->fec_max  = fec_max;
      79             : 
      80           0 :   fd_store_pool_t pool = pool_ljoin( store );
      81           0 :   if( FD_UNLIKELY( !fd_store_pool_new( shpool ) ) ) {
      82           0 :     FD_LOG_WARNING(( "fd_store_pool_new failed" ));
      83           0 :     return NULL;
      84           0 :   }
      85           0 :   fd_store_pool_reset( &pool, 0 );
      86             : 
      87           0 :   FD_COMPILER_MFENCE();
      88           0 :   FD_VOLATILE( store->magic ) = FD_STORE_MAGIC;
      89           0 :   FD_COMPILER_MFENCE();
      90             : 
      91           0 :   return shmem;
      92           0 : }
      93             : 
      94             : fd_store_t *
      95           0 : fd_store_join( void * shstore ) {
      96             : 
      97           0 :   if( FD_UNLIKELY( !shstore ) ) {
      98           0 :     FD_LOG_WARNING(( "NULL store" ));
      99           0 :     return NULL;
     100           0 :   }
     101             : 
     102           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)shstore, fd_store_align() ) ) ) {
     103           0 :     FD_LOG_WARNING(( "misaligned store" ));
     104           0 :     return NULL;
     105           0 :   }
     106             : 
     107           0 :   fd_wksp_t * wksp = fd_wksp_containing( shstore );
     108           0 :   if( FD_UNLIKELY( !wksp ) ) {
     109           0 :     FD_LOG_WARNING(( "store must be part of a workspace" ));
     110           0 :     return NULL;
     111           0 :   }
     112             : 
     113           0 :   fd_store_t * store = (fd_store_t *)shstore;
     114           0 :   if( FD_UNLIKELY( store->magic!=FD_STORE_MAGIC ) ) {
     115           0 :     FD_LOG_WARNING(( "bad magic" ));
     116           0 :     return NULL;
     117           0 :   }
     118             : 
     119           0 :   return store;
     120           0 : }
     121             : 
     122             : void *
     123           0 : fd_store_leave( fd_store_t const * store ) {
     124             : 
     125           0 :   if( FD_UNLIKELY( !store ) ) {
     126           0 :     FD_LOG_WARNING(( "NULL store" ));
     127           0 :     return NULL;
     128           0 :   }
     129             : 
     130           0 :   return (void *)store;
     131           0 : }
     132             : 
     133             : void *
     134           0 : fd_store_delete( void * shstore ) {
     135             : 
     136           0 :   if( FD_UNLIKELY( !shstore ) ) {
     137           0 :     FD_LOG_WARNING(( "NULL store" ));
     138           0 :     return NULL;
     139           0 :   }
     140             : 
     141           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)shstore, fd_store_align() ) ) ) {
     142           0 :     FD_LOG_WARNING(( "misaligned store" ));
     143           0 :     return NULL;
     144           0 :   }
     145             : 
     146           0 :   fd_store_t * store = (fd_store_t *)shstore;
     147           0 :   if( FD_UNLIKELY( store->magic!=FD_STORE_MAGIC ) ) {
     148           0 :     FD_LOG_WARNING(( "bad magic" ));
     149           0 :     return NULL;
     150           0 :   }
     151             : 
     152           0 :   FD_COMPILER_MFENCE();
     153           0 :   FD_VOLATILE( store->magic ) = 0UL;
     154           0 :   FD_COMPILER_MFENCE();
     155             : 
     156           0 :   return shstore;
     157           0 : }
     158             : 
     159             : fd_store_fec_t *
     160             : fd_store_query( fd_store_t       * store,
     161           0 :                 fd_hash_t  const * merkle_root ) {
     162             : 
     163           0 :   fd_store_pool_t pool = pool_ljoin( store );
     164           0 :   ulong           null = fd_store_pool_idx_null();
     165           0 :   for( uint part_idx = 0; part_idx < store->part_cnt; part_idx++ ) {
     166           0 :     fd_store_key_t   key = { *merkle_root, part_idx };
     167           0 :     ulong            idx = fd_store_map_idx_query_const( map_laddr( store ), &key, null, pool_laddr( store ) );
     168           0 :     fd_store_fec_t * fec = fd_store_pool_ele( &pool, idx );
     169           0 :     if( FD_LIKELY( fec ) ) return fec;
     170           0 :   }
     171           0 :   return NULL;
     172           0 : }
     173             : 
     174             : fd_store_fec_t *
     175             : fd_store_insert( fd_store_t * store,
     176             :                  ulong        part_idx,
     177           0 :                  fd_hash_t  * merkle_root ) {
     178             : 
     179           0 :   fd_store_pool_t pool = pool_ljoin( store );
     180           0 :   ulong           null = fd_store_pool_idx_null();
     181             : 
     182           0 :   for( ulong part_idx = 0; part_idx < store->part_cnt; part_idx++ ) {
     183           0 :     fd_store_key_t key = { *merkle_root, part_idx };
     184           0 :     ulong          idx = null;
     185             : 
     186           0 :     FD_STORE_SLOCK_BEGIN( store ) {
     187           0 :       idx = fd_store_map_idx_query_const( map_laddr( store ), &key, null, pool_laddr( store ) );
     188           0 :     } FD_STORE_SLOCK_END;
     189             : 
     190           0 :     fd_store_fec_t * fec = fd_store_pool_ele( &pool, idx );
     191           0 :     if( FD_UNLIKELY( fec ) ) return fec;
     192           0 :   }
     193             : 
     194           0 :   int err; fd_store_fec_t * fec = fd_store_pool_acquire( &pool, NULL, BLOCKING, &err );
     195           0 :   if( FD_UNLIKELY( err!=FD_POOL_SUCCESS ) ) FD_LOG_CRIT(( "store pool: %s", fd_store_pool_strerror( err ) ));
     196           0 :   fec->key.merkle_root = *merkle_root;
     197           0 :   fec->key.part_idx    = part_idx;
     198           0 :   fec->cmr             = (fd_hash_t){ 0 };
     199           0 :   fec->next            = null;
     200           0 :   fec->data_sz         = 0UL;
     201             : 
     202           0 :   FD_STORE_SLOCK_BEGIN( store ) {
     203           0 :     fd_store_map_ele_insert( map_laddr( store ), fec, pool_laddr( store ) );
     204           0 :   } FD_STORE_SLOCK_END;
     205             : 
     206           0 :   return fec;
     207           0 : }
     208             : 
     209             : void
     210             : fd_store_remove( fd_store_t      * store,
     211           0 :                  fd_hash_t const * merkle_root ) {
     212             : 
     213           0 :   fd_store_pool_t pool = pool_ljoin( store );
     214           0 :   for( uint part_idx = 0; part_idx < store->part_cnt; part_idx++ ) {
     215           0 :     fd_store_key_t   key = { *merkle_root, part_idx };
     216           0 :     fd_store_fec_t * fec = NULL;
     217             : 
     218           0 :     FD_STORE_XLOCK_BEGIN( store ) {
     219           0 :       fec = fd_store_map_ele_remove( map_laddr( store ), &key, NULL, pool_laddr( store ) );
     220           0 :     } FD_STORE_XLOCK_END;
     221           0 :     if( FD_UNLIKELY( !fec ) ) continue;
     222             : 
     223           0 :     int err = fd_store_pool_release( &pool, fec, BLOCKING );
     224           0 :     if( FD_UNLIKELY( err!=FD_POOL_SUCCESS ) ) FD_LOG_CRIT(( "store pool: %s", fd_store_pool_strerror( err ) ));
     225           0 :     return;
     226           0 :   }
     227             : 
     228           0 :   FD_BASE58_ENCODE_32_BYTES( merkle_root->uc, _merkle_root );
     229           0 :   FD_LOG_WARNING(( "key not found %s", _merkle_root ));
     230           0 : }
     231             : 
     232             : int
     233           0 : fd_store_verify( fd_store_t * store ) {
     234             : 
     235           0 :   fd_store_map_t * map  = map_laddr( store );
     236           0 :   fd_store_fec_t * fec0 = pool_laddr( store );
     237             : 
     238           0 :   ulong part_sz = store->fec_max / store->part_cnt;
     239           0 :   if( part_sz != map->seed ) {
     240           0 :     FD_LOG_WARNING(( "part_sz (%lu) != map->seed (%lu)", part_sz, map->seed ));
     241           0 :     return -1;
     242           0 :   }
     243             : 
     244             :   /* Iterate the map and check slots are partitioned correctly. */
     245             : 
     246           0 :   for( fd_store_map_iter_t iter = fd_store_map_iter_init(       map, fec0 );
     247           0 :                                  !fd_store_map_iter_done( iter, map, fec0 );
     248           0 :                            iter = fd_store_map_iter_next( iter, map, fec0 ) ) {
     249           0 :     fd_store_fec_t const * fec = fd_store_map_iter_ele_const( iter, map, fec0 );
     250           0 :     if( FD_UNLIKELY( !fec ) ) {
     251           0 :       FD_LOG_WARNING(( "NULL ele" ));
     252           0 :       return -1;
     253           0 :     }
     254           0 :     ulong chain_idx = fd_store_map_private_chain_idx( &fec->key, map->seed, map->chain_cnt );
     255           0 :     ulong k         = fec->key.part_idx;
     256           0 :     ulong n         = part_sz;
     257           0 :     if( FD_UNLIKELY( chain_idx < k * n || chain_idx >= (k + 1) * n ) ) { /* chain_idx in [k*n, (k+1)*n) */
     258           0 :       FD_LOG_WARNING(( "chain_idx %lu not in range [%lu, %lu)", chain_idx, k * n, (k + 1) * n ) );
     259           0 :       return -1;
     260           0 :     }
     261           0 :   }
     262           0 :   fd_store_pool_t pool = pool_ljoin( store );
     263           0 :   if( FD_UNLIKELY( fd_store_pool_verify( &pool )==-1 ) ) return -1;
     264           0 :   return fd_store_map_verify( map, store->fec_max, fec0 );
     265           0 : }

Generated by: LCOV version 1.14