LCOV - code coverage report
Current view: top level - vinyl/meta - fd_vinyl_meta.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 53 55 96.4 %
Date: 2025-12-07 04:58:33 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "fd_vinyl_meta.h"
       2             : 
       3             : #define MAP_NAME                  fd_vinyl_meta
       4    50956248 : #define MAP_ELE_T                 fd_vinyl_meta_ele_t
       5             : #define MAP_KEY_T                 fd_vinyl_key_t
       6     1997640 : #define MAP_KEY                   phdr.key
       7             : #define MAP_KEY_EQ(k0,k1)         fd_vinyl_key_eq( (k0), (k1) )
       8             : #define MAP_KEY_HASH(key,seed)    fd_vinyl_key_memo( (seed), (key) )
       9             : #define MAP_MEMOIZE               1
      10     3061716 : #define MAP_MEMO                  memo
      11             : #define MAP_KEY_EQ_IS_SLOW        1
      12             : #define MAP_ELE_IS_FREE(ctx,ele)  (!(ele)->phdr.ctl)
      13             : #define MAP_ELE_FREE(ctx,ele)     do { (ele)->phdr.ctl = 0UL; } while(0)
      14             : #define MAP_ELE_MOVE(ctx,dst,src) do { fd_vinyl_meta_ele_t * _src = (src); *(dst) = *_src; _src->phdr.ctl = 0UL; } while(0)
      15             : #define MAP_IMPL_STYLE            2
      16             : #include "../../util/tmpl/fd_map_slot_para.c"
      17             : 
      18             : int
      19             : fd_vinyl_meta_query_fast( fd_vinyl_meta_ele_t const * ele0,
      20             :                           ulong                       ele_max,
      21             :                           fd_vinyl_key_t const *      key,
      22             :                           ulong                       memo,
      23    22503069 :                           ulong *                     _ele_idx ) {
      24             : 
      25    22503069 :   ulong ele_idx = memo & (ele_max-1UL);
      26             : 
      27    22503069 :   int err = FD_VINYL_ERR_CORRUPT;
      28             : 
      29    22503069 :   ulong rem;
      30             : 
      31    27842088 :   for( rem=ele_max; rem; rem-- ) { /* guarantee finite termination in face of corruption */
      32    27842088 :     fd_vinyl_meta_ele_t const * ele = ele0 + ele_idx;
      33             : 
      34    27842088 :     if( FD_UNLIKELY( !ele->phdr.ctl ) ) { /* not found */
      35     7502265 :       *_ele_idx = ele_idx;
      36     7502265 :       err       = FD_VINYL_ERR_KEY;
      37     7502265 :       break;
      38     7502265 :     }
      39             : 
      40    20339823 :     if( FD_LIKELY( ele->memo==memo ) && FD_LIKELY( fd_vinyl_key_eq( &ele->phdr.key, key ) ) ) { /* found */
      41    15000804 :       *_ele_idx = ele_idx;
      42    15000804 :       err       = FD_VINYL_SUCCESS;
      43    15000804 :       break;
      44    15000804 :    }
      45             : 
      46     5339019 :     ele_idx = (ele_idx+1UL) & (ele_max-1UL); /* collision, try next slot */
      47     5339019 :   }
      48             : 
      49    22503069 :   FD_CRIT( rem, "corruption detected" );
      50             : 
      51    22503069 :   return err;
      52    22503069 : }
      53             : 
      54             : #include "../line/fd_vinyl_line.h" /* FIXME: gross (maybe make line below meta in the API hierarchy?) */
      55             : 
      56             : void
      57             : fd_vinyl_meta_remove_fast( fd_vinyl_meta_ele_t * ele0,
      58             :                            ulong                 ele_max,
      59             :                            ulong *               lock,
      60             :                            int                   lock_shift,
      61             :                            fd_vinyl_line_t *     line,
      62             :                            ulong                 line_cnt,
      63     3750531 :                            ulong                 ele_idx ) {
      64             : 
      65             :   /* At this point, we know:
      66             : 
      67             :      - nobody will lock any elements behind our back (single writer)
      68             :      - no elements are locked (not in a prepare)
      69             :      - there is at least one unoccupied element in the meta (pair_max < ele_max)
      70             :      - there is at least one   occupied element in the meta (ele_idx)
      71             :      - (thus ele_max is at least 2)
      72             : 
      73             :      When we remove element ele_idx, we might need to move elements in
      74             :      the cyclic contiguously occupied range starting at ele_idx toward
      75             :      ele_idx (but not before ele_idx) to keep their probe sequences
      76             :      intact.  This can interfere with lockfree non-blocking concurrent
      77             :      reads whose probe sequences overlap this range.
      78             : 
      79             :      Thus, we determine the set of contiguously occupied elements
      80             :      starting at ele_idx, determine the range of corresponding locks and
      81             :      lock them before we remove ele_idx to protect concurrent readers.
      82             :      If the map is not overfilled, contig_cnt is O(1) elements.
      83             : 
      84             :      If the ele is currently cached, we also need to update the
      85             :      underlying line to it points to the moved location. */
      86             : 
      87     3750531 :   ulong contig_cnt;
      88             : 
      89     5829162 :   for( contig_cnt=1UL; contig_cnt<ele_max; contig_cnt++ )
      90     5829162 :     if( FD_LIKELY( !ele0[ (ele_idx + contig_cnt) & (ele_max-1UL) ].phdr.ctl ) ) break;
      91             : 
      92     3750531 :   FD_CRIT( contig_cnt<ele_max, "corruption detected" );
      93             : 
      94             :   /* At this point, contig_cnt is in [1,ele_max) and meta elements
      95             :      [ele_idx,ele_idx+contig_cnt) (cyclic) are the contiguously occupied
      96             :      elements starting at ele_idx.  Determine the set of locks that
      97             :      cover this set. */
      98             : 
      99     3750531 :   ulong lock_lo  =  ele_idx                     >> lock_shift;        /* lock that covers first element (wrapped) */
     100     3750531 :   ulong lock_hi  = (ele_idx + contig_cnt - 1UL) >> lock_shift;        /* lock that covers last  element (unwrapped) */
     101     3750531 :   ulong lock_max =  ele_max                     >> lock_shift;        /* max locks */
     102     3750531 :   ulong lock_cnt = fd_ulong_min( lock_hi - lock_lo + 1UL, lock_max ); /* num locks required */
     103             : 
     104             :   /* Lock the range */
     105             : 
     106     8020473 :   for( ulong idx=0UL; idx<lock_cnt; idx++ ) fd_vinyl_meta_lock_update_fast( lock + ((lock_lo + idx) & (lock_max-1UL)), 1L );
     107             : 
     108             :   /* At this point, we are clear to remove ele_idx.  Make a hole at
     109             :      ele_idx and then iterate over the contig_cnt-1 remaining cyclically
     110             :      contiguously occupied elements, repairing broken probe sequences as
     111             :      we go.  Since we already learned how many contiguous elements there
     112             :      are (from the above locking), we can simplify the iteration
     113             :      slightly over a standard remove. */
     114             : 
     115     3750531 :   ele0[ ele_idx ].phdr.ctl = 0UL;
     116             : 
     117     3750531 :   ulong hole_idx = ele_idx;
     118             : 
     119     5829162 :   for( ulong rem=contig_cnt-1UL; rem; rem-- ) {
     120     2078631 :     ele_idx = (ele_idx+1UL) & (ele_max-1UL);
     121             : 
     122             :     /* At this point, meta elements before hole_idx (cyclic) have intact
     123             :        probe sequences, meta element hole_idx is unoccupied, meta
     124             :        elements (hole_idx,ele_idx) (cyclic) are occupied with intact
     125             :        probe sequences and meta elements [ele_idx,ele_idx+rem) (cyclic)
     126             :        are occupied but might have broken probe sequences due to the
     127             :        hole.
     128             : 
     129             :        If a probe looking for the key at ele_idx does not start its
     130             :        probe in (hole_idx,ele_idx] (cyclic), probing will fail
     131             :        erroneously due to the hole.  In this case, we move ele_idx to
     132             :        hole_idx to restore the probe sequence for the key at ele_idx,
     133             :        making a new hole at ele_idx.  As the probe sequences following
     134             :        the new hole could still be broken, we continue repairing probe
     135             :        sequences for elements following the new hole. */
     136             : 
     137     2078631 :     ulong start_idx = ele0[ ele_idx ].memo & (ele_max-1UL);
     138             : 
     139     2078631 :     if( !( ((hole_idx<start_idx) & (start_idx<=ele_idx)                       ) |
     140     2078631 :            ((hole_idx>ele_idx) & ((hole_idx<start_idx) | (start_idx<=ele_idx))) ) ) {
     141             : 
     142      673278 :       ulong line_idx = ele0[ ele_idx ].line_idx;
     143      673278 :       if( FD_LIKELY( line_idx<line_cnt ) ) {
     144           0 :         FD_CRIT( line[ line_idx ].ele_idx==ele_idx, "corruption detected" );
     145           0 :         line[ line_idx ].ele_idx = hole_idx;
     146      673278 :       } else {
     147      673278 :         FD_CRIT( line_idx==ULONG_MAX, "corruption detected" );
     148      673278 :       }
     149             : 
     150      673278 :       ele0[ hole_idx ] = ele0[ ele_idx ];
     151      673278 :       ele0[ ele_idx ].phdr.ctl = 0UL;
     152             : 
     153      673278 :       hole_idx = ele_idx;
     154             : 
     155      673278 :     }
     156     2078631 :   }
     157             : 
     158             :   /* Unlock the range */
     159             : 
     160     8020473 :   for( ulong idx=0UL; idx<lock_cnt; idx++ ) fd_vinyl_meta_lock_update_fast( lock + ((lock_lo + idx) & (lock_max-1UL)), 1L );
     161     3750531 : }

Generated by: LCOV version 1.14