LCOV - code coverage report
Current view: top level - funk - fd_funk.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 265 313 84.7 %
Date: 2026-03-09 05:45:24 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include "fd_funk.h"
       2             : #include "fd_funk_base.h"
       3             : #include <stdio.h>
       4             : 
       5             : ulong
       6        2340 : fd_funk_align( void ) {
       7        2340 :   return FD_FUNK_ALIGN;
       8        2340 : }
       9             : 
      10             : ulong
      11             : fd_funk_shmem_footprint( ulong txn_max,
      12         420 :                          ulong rec_max ) {
      13         420 :   if( FD_UNLIKELY( rec_max>UINT_MAX ) ) return 0UL;
      14             : 
      15         420 :   ulong l = FD_LAYOUT_INIT;
      16             : 
      17         420 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funk_shmem_t), sizeof(fd_funk_shmem_t) );
      18             : 
      19         420 :   ulong txn_chain_cnt = fd_funk_txn_map_chain_cnt_est( txn_max );
      20         420 :   l = FD_LAYOUT_APPEND( l, fd_funk_txn_map_align(), fd_funk_txn_map_footprint( txn_chain_cnt ) );
      21         420 :   l = FD_LAYOUT_APPEND( l, fd_funk_txn_pool_align(), fd_funk_txn_pool_footprint() );
      22         420 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funk_txn_t), sizeof(fd_funk_txn_t) * txn_max );
      23             : 
      24         420 :   ulong rec_chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
      25         420 :   l = FD_LAYOUT_APPEND( l, fd_funk_rec_map_align(), fd_funk_rec_map_footprint( rec_chain_cnt ) );
      26         420 :   l = FD_LAYOUT_APPEND( l, fd_funk_rec_pool_align(), fd_funk_rec_pool_footprint() );
      27         420 :   l = FD_LAYOUT_APPEND( l, alignof(fd_funk_rec_t), sizeof(fd_funk_rec_t) * rec_max );
      28             : 
      29         420 :   l = FD_LAYOUT_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      30             : 
      31         420 :   return l;
      32         420 : }
      33             : 
      34             : ulong
      35             : fd_funk_locks_footprint( ulong txn_max,
      36         210 :                          ulong rec_max ) {
      37         210 :   ulong l = FD_LAYOUT_INIT;
      38         210 :   l = FD_LAYOUT_APPEND( l, alignof(fd_rwlock_t), sizeof(fd_rwlock_t) * txn_max );
      39         210 :   l = FD_LAYOUT_APPEND( l, alignof(ulong),       sizeof(ulong)       * rec_max );
      40         210 :   return FD_LAYOUT_FINI( l, fd_funk_align() );
      41         210 : }
      42             : 
      43             : /* TODO: Consider letter user just passing a join of alloc to use,
      44             :    inferring the backing wksp and cgroup_hint from that and then
      45             :    allocating exclusively from that? */
      46             : 
      47             : void *
      48             : fd_funk_shmem_new( void * shmem,
      49             :                    ulong  wksp_tag,
      50             :                    ulong  seed,
      51             :                    ulong  txn_max,
      52         225 :                    ulong  rec_max ) {
      53         225 :   fd_funk_shmem_t * funk = shmem;
      54         225 :   fd_wksp_t *       wksp = fd_wksp_containing( funk );
      55             : 
      56         225 :   if( FD_UNLIKELY( !funk ) ) {
      57           3 :     FD_LOG_WARNING(( "NULL funk" ));
      58           3 :     return NULL;
      59           3 :   }
      60             : 
      61         222 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)funk, fd_funk_align() ) ) ) {
      62           3 :     FD_LOG_WARNING(( "misaligned funk" ));
      63           3 :     return NULL;
      64           3 :   }
      65             : 
      66         219 :   if( FD_UNLIKELY( !wksp_tag ) ) {
      67           3 :     FD_LOG_WARNING(( "bad wksp_tag" ));
      68           3 :     return NULL;
      69           3 :   }
      70             : 
      71         216 :   if( FD_UNLIKELY( !wksp ) ) {
      72           3 :     FD_LOG_WARNING(( "shmem must be part of a workspace" ));
      73           3 :     return NULL;
      74           3 :   }
      75             : 
      76         213 :   if( FD_UNLIKELY( !txn_max || txn_max>FD_FUNK_TXN_IDX_NULL ) ) { /* See note in fd_funk.h about this limit */
      77           3 :     FD_LOG_WARNING(( "txn_max too large for index compression" ));
      78           3 :     return NULL;
      79           3 :   }
      80             : 
      81         210 :   if( FD_UNLIKELY( !rec_max || rec_max>UINT_MAX ) ) {
      82           0 :     FD_LOG_WARNING(( "invalid rec_max" ));
      83           0 :     return NULL;
      84           0 :   }
      85             : 
      86         210 :   FD_SCRATCH_ALLOC_INIT( l, funk+1 );
      87             : 
      88         210 :   ulong txn_chain_cnt = fd_funk_txn_map_chain_cnt_est( txn_max );
      89         210 :   void * txn_map = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_txn_map_align(), fd_funk_txn_map_footprint( txn_chain_cnt ) );
      90         210 :   void * txn_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_txn_pool_align(), fd_funk_txn_pool_footprint() );
      91         210 :   fd_funk_txn_t * txn_ele = (fd_funk_txn_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_funk_txn_t), sizeof(fd_funk_txn_t) * txn_max );
      92             : 
      93           0 :   ulong rec_chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
      94         210 :   void * rec_map = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_rec_map_align(), fd_funk_rec_map_footprint( rec_chain_cnt ) );
      95         210 :   void * rec_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_funk_rec_pool_align(), fd_funk_rec_pool_footprint() );
      96         210 :   fd_funk_rec_t * rec_ele = (fd_funk_rec_t *)FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_funk_rec_t), sizeof(fd_funk_rec_t) * rec_max );
      97             : 
      98         210 :   void * alloc = FD_SCRATCH_ALLOC_APPEND( l, fd_alloc_align(), fd_alloc_footprint() );
      99             : 
     100         210 :   FD_TEST( _l == (ulong)funk + fd_funk_shmem_footprint( txn_max, rec_max ) );
     101             : 
     102         210 :   fd_memset( funk, 0, sizeof(fd_funk_shmem_t) );
     103             : 
     104         210 :   funk->funk_gaddr = fd_wksp_gaddr_fast( wksp, funk );
     105         210 :   funk->wksp_tag   = wksp_tag;
     106         210 :   funk->seed       = seed;
     107         210 :   funk->cycle_tag  = 3UL; /* various verify functions use tags 0-2 */
     108             : 
     109         210 :   funk->txn_map_gaddr = fd_wksp_gaddr_fast( wksp, fd_funk_txn_map_new( txn_map, txn_chain_cnt, seed ) );
     110         210 :   void * txn_pool2 = fd_funk_txn_pool_new( txn_pool );
     111         210 :   funk->txn_pool_gaddr = fd_wksp_gaddr_fast( wksp, txn_pool2 );
     112         210 :   fd_funk_txn_pool_t txn_join[1];
     113         210 :   fd_funk_txn_pool_join( txn_join, txn_pool2, txn_ele, txn_max );
     114         210 :   fd_funk_txn_pool_reset( txn_join, 0UL );
     115         210 :   funk->txn_ele_gaddr = fd_wksp_gaddr_fast( wksp, txn_ele );
     116         210 :   funk->txn_max = txn_max;
     117         210 :   funk->child_head_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     118         210 :   funk->child_tail_cidx = fd_funk_txn_cidx( FD_FUNK_TXN_IDX_NULL );
     119             : 
     120      789756 :   for( ulong i=0UL; i<txn_max; i++ ) {
     121      789546 :     txn_join->ele[ i ].state = FD_FUNK_TXN_STATE_FREE;
     122      789546 :   }
     123             : 
     124         210 :   fd_funk_txn_xid_set_root( funk->root         );
     125         210 :   fd_funk_txn_xid_set_root( funk->last_publish );
     126             : 
     127         210 :   funk->rec_map_gaddr = fd_wksp_gaddr_fast( wksp, fd_funk_rec_map_new( rec_map, rec_chain_cnt, seed ) );
     128         210 :   void * rec_pool2 = fd_funk_rec_pool_new( rec_pool );
     129         210 :   funk->rec_pool_gaddr = fd_wksp_gaddr_fast( wksp, rec_pool2 );
     130         210 :   fd_funk_rec_pool_t rec_join[1];
     131         210 :   fd_funk_rec_pool_join( rec_join, rec_pool2, rec_ele, rec_max );
     132         210 :   fd_funk_rec_pool_reset( rec_join, 0UL );
     133         210 :   funk->rec_ele_gaddr = fd_wksp_gaddr_fast( wksp, rec_ele );
     134         210 :   funk->rec_max = (uint)rec_max;
     135             : 
     136         210 :   funk->alloc_gaddr = fd_wksp_gaddr_fast( wksp, fd_alloc_join( fd_alloc_new( alloc, wksp_tag ), 0UL ) );
     137             : 
     138         210 :   FD_COMPILER_MFENCE();
     139         210 :   FD_VOLATILE( funk->magic ) = FD_FUNK_MAGIC;
     140         210 :   FD_COMPILER_MFENCE();
     141             : 
     142         210 :   return (void *)funk;
     143         210 : }
     144             : 
     145             : fd_funk_t *
     146             : fd_funk_join( fd_funk_t * ljoin,
     147             :               void *      shfunk,
     148         435 :               void *      shlocks ) {
     149         435 :   if( FD_UNLIKELY( !shfunk ) ) {
     150           3 :     FD_LOG_WARNING(( "NULL shfunk" ));
     151           3 :     return NULL;
     152           3 :   }
     153         432 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shfunk, fd_funk_align() ) ) ) {
     154           3 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     155           3 :     return NULL;
     156           3 :   }
     157         429 :   fd_wksp_t * wksp = fd_wksp_containing( shfunk );
     158         429 :   if( FD_UNLIKELY( !wksp ) ) {
     159           3 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     160           3 :     return NULL;
     161           3 :   }
     162             : 
     163         426 :   if( FD_UNLIKELY( !shlocks ) ) {
     164           0 :     FD_LOG_WARNING(( "NULL shlocks" ));
     165           0 :     return NULL;
     166           0 :   }
     167         426 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shlocks, fd_funk_align() ) ) ) {
     168           0 :     FD_LOG_WARNING(( "misaligned shlocks" ));
     169           0 :     return NULL;
     170           0 :   }
     171             : 
     172         426 :   fd_funk_shmem_t * shmem = shfunk;
     173         426 :   if( FD_UNLIKELY( shmem->magic!=FD_FUNK_MAGIC ) ) {
     174           3 :     if (shmem->magic == FD_FUNK_MAGIC+1) {
     175           0 :       FD_LOG_WARNING(( "attempted to join a funk that crashed in a critical section" ));
     176           3 :     } else {
     177           3 :       FD_LOG_WARNING(( "bad magic" ));
     178           3 :     }
     179           3 :     return NULL;
     180           3 :   }
     181             : 
     182         423 :   if( FD_UNLIKELY( !ljoin ) ) {
     183           0 :     FD_LOG_WARNING(( "NULL ljoin" ));
     184           0 :     return NULL;
     185           0 :   }
     186             : 
     187             : #ifdef FD_FUNK_WKSP_PROTECT
     188             :   fd_wksp_mprotect( wksp, 1 );
     189             : #endif
     190             : 
     191         423 :   fd_funk_t * funk = ljoin;
     192         423 :   memset( funk, 0, sizeof(fd_funk_t) );
     193             : 
     194         423 :   funk->shmem = shfunk;
     195         423 :   funk->wksp  = wksp;
     196             : 
     197         423 :   if( FD_UNLIKELY( !fd_funk_txn_pool_join( funk->txn_pool, fd_wksp_laddr( wksp, shmem->txn_pool_gaddr ), fd_wksp_laddr( wksp, shmem->txn_ele_gaddr ), shmem->txn_max ) ) ) {
     198           0 :     FD_LOG_WARNING(( "failed to join txn_pool" ));
     199           0 :     return NULL;
     200           0 :   }
     201         423 :   if( FD_UNLIKELY( !fd_funk_txn_map_join( funk->txn_map, fd_wksp_laddr( wksp, shmem->txn_map_gaddr ), fd_wksp_laddr_fast( wksp, shmem->txn_ele_gaddr ), shmem->txn_max ) ) ) {
     202           0 :     FD_LOG_WARNING(( "failed to join txn_map" ));
     203           0 :     return NULL;
     204           0 :   }
     205         423 :   if( FD_UNLIKELY( !fd_funk_rec_map_join( funk->rec_map, fd_wksp_laddr( wksp, shmem->rec_map_gaddr ), fd_wksp_laddr( wksp, shmem->rec_ele_gaddr ), shmem->rec_max ) ) ) {
     206           0 :     FD_LOG_WARNING(( "failed to join rec_map" ));
     207           0 :     return NULL;
     208           0 :   }
     209         423 :   if( FD_UNLIKELY( !fd_funk_rec_pool_join( funk->rec_pool, fd_wksp_laddr( wksp, shmem->rec_pool_gaddr ), fd_wksp_laddr_fast( wksp, shmem->rec_ele_gaddr ), shmem->rec_max ) ) ) {
     210           0 :     FD_LOG_WARNING(( "failed to join rec_pool" ));
     211           0 :     return NULL;
     212           0 :   }
     213         423 :   FD_SCRATCH_ALLOC_INIT( l2, shlocks );
     214         423 :   funk->txn_lock = FD_SCRATCH_ALLOC_APPEND( l2, alignof(fd_rwlock_t), sizeof(fd_rwlock_t) * shmem->txn_max );
     215         423 :   funk->rec_lock = FD_SCRATCH_ALLOC_APPEND( l2, alignof(ulong),       sizeof(ulong)       * shmem->rec_max );
     216           0 :   funk->alloc = fd_wksp_laddr( wksp, shmem->alloc_gaddr );
     217         423 :   if( FD_UNLIKELY( !fd_alloc_join( funk->alloc, fd_tile_idx() ) ) ) {
     218           0 :     FD_LOG_WARNING(( "failed to join funk alloc" ));
     219           0 :     return NULL;
     220           0 :   }
     221             : 
     222         423 :   return funk;
     223         423 : }
     224             : 
     225             : void *
     226             : fd_funk_locks_new( void * shlocks,
     227             :                    ulong  txn_max,
     228         210 :                    ulong  rec_max ) {
     229         210 :   if( FD_UNLIKELY( !shlocks ) ) {
     230           0 :     FD_LOG_WARNING(( "NULL shlocks" ));
     231           0 :     return NULL;
     232           0 :   }
     233         210 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shlocks, fd_funk_align() ) ) ) {
     234           0 :     FD_LOG_WARNING(( "misaligned shlocks" ));
     235           0 :     return NULL;
     236           0 :   }
     237         210 :   FD_SCRATCH_ALLOC_INIT( l, shlocks );
     238         210 :   fd_rwlock_t * txn_lock = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rwlock_t), sizeof(fd_rwlock_t) * txn_max );
     239         210 :   void *        rec_lock = FD_SCRATCH_ALLOC_APPEND( l, alignof(ulong),       sizeof(ulong)       * rec_max );
     240           0 :   memset( txn_lock, 0, sizeof(fd_rwlock_t) * txn_max );
     241         210 :   memset( rec_lock, 0, sizeof(ulong) *       rec_max );
     242         210 :   return shlocks;
     243         210 : }
     244             : 
     245             : void *
     246             : fd_funk_leave( fd_funk_t * funk,
     247             :                void **     opt_shfunk,
     248         408 :                void **     opt_shlocks ) {
     249             : 
     250         408 :   if( FD_UNLIKELY( !funk ) ) {
     251           3 :     FD_LOG_WARNING(( "NULL funk" ));
     252           3 :     if( opt_shfunk  ) *opt_shfunk  = NULL;
     253           3 :     if( opt_shlocks ) *opt_shlocks = NULL;
     254           3 :     return NULL;
     255           3 :   }
     256         405 :   void * shfunk  = funk->shmem;
     257         405 :   void * shlocks = (void *)funk->txn_lock;
     258             : 
     259         405 :   memset( funk, 0, sizeof(fd_funk_t) );
     260             : 
     261         405 :   if( opt_shfunk )  *opt_shfunk  = shfunk;
     262         405 :   if( opt_shlocks ) *opt_shlocks = shlocks;
     263         405 :   return (void *)funk;
     264         408 : }
     265             : 
     266             : void *
     267         207 : fd_funk_delete( void * shfunk ) {
     268             : 
     269         207 :   if( FD_UNLIKELY( !shfunk ) ) {
     270           3 :     FD_LOG_WARNING(( "NULL shfunk" ));
     271           3 :     return NULL;
     272           3 :   }
     273             : 
     274         204 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shfunk, fd_funk_align() ) ) ) {
     275           3 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     276           3 :     return NULL;
     277           3 :   }
     278             : 
     279         201 :   fd_wksp_t * wksp = fd_wksp_containing( shfunk );
     280         201 :   if( FD_UNLIKELY( !wksp ) ) {
     281           3 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     282           3 :     return NULL;
     283           3 :   }
     284             : 
     285         198 :   fd_funk_shmem_t * shmem = shfunk;
     286         198 :   if( FD_UNLIKELY( shmem->magic!=FD_FUNK_MAGIC ) ) {
     287           6 :     FD_LOG_WARNING(( "bad magic" ));
     288           6 :     return NULL;
     289           6 :   }
     290             : 
     291             :   /* Free all fd_alloc allocations made, individually
     292             :      (FIXME consider walking the element pool instead of the map?) */
     293             : 
     294         192 :   fd_alloc_t * alloc = fd_alloc_join( fd_wksp_laddr_fast( wksp, shmem->alloc_gaddr ), fd_tile_idx() );
     295             : 
     296         192 :   void * shmap = fd_wksp_laddr_fast( wksp, shmem->rec_map_gaddr );
     297         192 :   void * shele = fd_wksp_laddr_fast( wksp, shmem->rec_ele_gaddr );
     298         192 :   fd_funk_rec_map_t rec_map[1];
     299         192 :   if( FD_UNLIKELY( !fd_funk_rec_map_join( rec_map, shmap, shele, 0UL ) ) ) {
     300           0 :     FD_LOG_ERR(( "failed to join rec_map (corrupt funk?)" ));
     301           0 :     return NULL;
     302           0 :   }
     303         192 :   ulong chain_cnt = fd_funk_rec_map_chain_cnt( rec_map );
     304      444744 :   for( ulong chain_idx=0UL; chain_idx<chain_cnt; chain_idx++ ) {
     305      444552 :     for(
     306      444552 :         fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter( rec_map, chain_idx );
     307      445146 :         !fd_funk_rec_map_iter_done( iter );
     308      444552 :         iter = fd_funk_rec_map_iter_next( iter )
     309      444552 :     ) {
     310         594 :       fd_funk_val_flush( fd_funk_rec_map_iter_ele( iter ), alloc, wksp );
     311         594 :     }
     312      444552 :   }
     313             : 
     314         192 :   fd_funk_rec_map_leave( rec_map );
     315             : 
     316         192 :   FD_COMPILER_MFENCE();
     317         192 :   FD_VOLATILE( shmem->magic ) = 0UL;
     318         192 :   FD_COMPILER_MFENCE();
     319             : 
     320             :   /* Free the fd_alloc instance */
     321             : 
     322         192 :   fd_wksp_free_laddr( fd_alloc_delete( fd_alloc_leave( alloc ) ) );
     323             : 
     324         192 :   return shmem;
     325         192 : }
     326             : 
     327             : void
     328           9 : fd_funk_delete_fast( void * shfunk ) {
     329             : 
     330           9 :   if( FD_UNLIKELY( !shfunk ) ) {
     331           0 :     FD_LOG_WARNING(( "NULL shfunk" ));
     332           0 :   }
     333             : 
     334           9 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shfunk, fd_funk_align() ) ) ) {
     335           0 :     FD_LOG_WARNING(( "misaligned shfunk" ));
     336           0 :   }
     337             : 
     338           9 :   fd_funk_shmem_t * shmem = shfunk;
     339           9 :   if( FD_UNLIKELY( shmem->magic!=FD_FUNK_MAGIC ) ) {
     340           0 :     FD_LOG_WARNING(( "bad magic" ));
     341           0 :   }
     342             : 
     343           9 :   fd_wksp_t * wksp = fd_wksp_containing( shmem );
     344           9 :   if( FD_UNLIKELY( !wksp ) ) {
     345           0 :     FD_LOG_WARNING(( "shfunk must be part of a workspace" ));
     346           0 :   }
     347             : 
     348           9 :   ulong const tags[1] = { shmem->wksp_tag };
     349           9 :   fd_wksp_tag_free( wksp, tags, 1UL );
     350             : 
     351           9 : }
     352             : 
     353             : int
     354         243 : fd_funk_verify( fd_funk_t * join ) {
     355         243 :   fd_funk_shmem_t * funk = join->shmem;
     356             : 
     357        6318 : # define TEST(c) do {                                                                           \
     358        6318 :     if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \
     359        6318 :   } while(0)
     360             : 
     361         243 :   TEST( funk );
     362             : 
     363             :   /* Test metadata */
     364             : 
     365         243 :   TEST( funk->magic==FD_FUNK_MAGIC );
     366             : 
     367         243 :   ulong funk_gaddr = funk->funk_gaddr;
     368         243 :   TEST( funk_gaddr );
     369         243 :   fd_wksp_t * wksp = fd_funk_wksp( join );
     370         243 :   TEST( wksp );
     371         243 :   TEST( fd_wksp_laddr_fast( wksp, funk_gaddr )==(void *)funk );
     372         243 :   TEST( fd_wksp_gaddr_fast( wksp, funk       )==funk_gaddr   );
     373             : 
     374         243 :   ulong wksp_tag = fd_funk_wksp_tag( join );
     375         243 :   TEST( !!wksp_tag );
     376             : 
     377         243 :   ulong seed = funk->seed; /* seed can be anything */
     378             : 
     379         243 :   TEST( funk->cycle_tag>2UL );
     380             : 
     381             :   /* Test transaction map */
     382             : 
     383         243 :   ulong txn_max = fd_funk_txn_pool_ele_max( join->txn_pool );
     384         243 :   TEST( txn_max<=FD_FUNK_TXN_IDX_NULL );
     385             : 
     386         243 :   ulong txn_map_gaddr = funk->txn_map_gaddr;
     387         243 :   TEST( txn_map_gaddr );
     388         243 :   fd_funk_txn_map_t * txn_map = fd_funk_txn_map( join );
     389         243 :   ulong txn_chain_cnt = fd_funk_txn_map_chain_cnt_est( txn_max );
     390         243 :   TEST( txn_chain_cnt==fd_funk_txn_map_chain_cnt( txn_map ) );
     391         243 :   TEST( seed==fd_funk_txn_map_seed( txn_map ) );
     392             : 
     393         243 :   ulong child_head_idx = fd_funk_txn_idx( funk->child_head_cidx );
     394         243 :   ulong child_tail_idx = fd_funk_txn_idx( funk->child_tail_cidx );
     395             : 
     396         243 :   int null_child_head = fd_funk_txn_idx_is_null( child_head_idx );
     397         243 :   int null_child_tail = fd_funk_txn_idx_is_null( child_tail_idx );
     398             : 
     399         243 :   if( !txn_max ) TEST( null_child_head & null_child_tail );
     400         243 :   else {
     401         243 :     if( null_child_head ) TEST( null_child_tail );
     402         168 :     else                  TEST( child_head_idx<txn_max );
     403             : 
     404         243 :     if( null_child_tail ) TEST( null_child_head );
     405         168 :     else                  TEST( child_tail_idx<txn_max );
     406         243 :   }
     407             : 
     408         243 :   if( !txn_max ) TEST( fd_funk_txn_idx_is_null( child_tail_idx ) );
     409             : 
     410         243 :   fd_funk_txn_xid_t const * root = fd_funk_root( join );
     411         243 :   TEST( root ); /* Practically guaranteed */
     412         243 :   TEST( fd_funk_txn_xid_eq_root( root ) );
     413             : 
     414         243 :   fd_funk_txn_xid_t * last_publish = funk->last_publish;
     415         243 :   TEST( last_publish ); /* Practically guaranteed */
     416             :   /* (*last_publish) only be root at creation and anything but root post
     417             :      creation.  But we don't know which situation applies here so this
     418             :      could be anything. */
     419             : 
     420         243 :   TEST( !fd_funk_txn_verify( join ) );
     421             : 
     422             :   /* Test record map */
     423             : 
     424         243 :   ulong rec_max = fd_funk_rec_pool_ele_max( join->rec_pool );
     425         243 :   TEST( rec_max<=FD_FUNK_TXN_IDX_NULL );
     426             : 
     427         243 :   ulong rec_map_gaddr = funk->rec_map_gaddr;
     428         243 :   TEST( rec_map_gaddr );
     429         243 :   fd_funk_rec_map_t * rec_map = fd_funk_rec_map( join );
     430         243 :   ulong rec_chain_cnt = fd_funk_rec_map_chain_cnt_est( rec_max );
     431         243 :   TEST( rec_chain_cnt==fd_funk_rec_map_chain_cnt( rec_map ) );
     432         243 :   TEST( seed==fd_funk_rec_map_seed( rec_map ) );
     433             : 
     434         243 :   TEST( !fd_funk_rec_verify( join ) );
     435             : 
     436             :   /* Test values */
     437             : 
     438         243 :   ulong alloc_gaddr = funk->alloc_gaddr;
     439         243 :   TEST( alloc_gaddr );
     440         243 :   fd_alloc_t * alloc = fd_funk_alloc( join );
     441         243 :   TEST( alloc );
     442             : 
     443         243 :   TEST( !fd_funk_val_verify( join ) );
     444             : 
     445         243 : # undef TEST
     446             : 
     447         243 :   return FD_FUNK_SUCCESS;
     448         243 : }

Generated by: LCOV version 1.14