@@ -357,8 +357,10 @@ static int
357357fd_progcache_push ( fd_progcache_t * cache ,
358358 fd_funk_txn_t * txn ,
359359 fd_funk_rec_t * rec ,
360- void const * prog_addr ) {
360+ void const * prog_addr ,
361+ fd_funk_rec_t * * dup_rec ) {
361362 fd_funk_t * funk = cache -> funk ;
363+ * dup_rec = NULL ;
362364
363365 /* Phase 1: Determine record's xid-key pair */
364366
@@ -385,21 +387,32 @@ fd_progcache_push( fd_progcache_t * cache,
385387 FD_LOG_CRIT (( "Failed to insert progcache record: canont lock funk rec map chain: %i-%s" , txn_err , fd_map_strerror ( txn_err ) ));
386388 }
387389
388- /* Phase 3: Atomically add record to funk txn's record list */
390+ /* Phase 3: Check if record exists */
389391
390- int insert_err = fd_funk_rec_map_txn_insert ( funk -> rec_map , rec );
391- if ( FD_UNLIKELY ( insert_err == FD_MAP_ERR_KEY ) ) {
392+ fd_funk_rec_map_query_t query [1 ];
393+ int query_err = fd_funk_rec_map_txn_query ( funk -> rec_map , & rec -> pair , NULL , query , 0 );
394+ if ( FD_UNLIKELY ( query_err == FD_MAP_SUCCESS ) ) {
392395 fd_funk_rec_map_txn_test ( map_txn );
393396 fd_funk_rec_map_txn_fini ( map_txn );
397+ * dup_rec = query -> ele ;
394398 return 0 ; /* another thread was faster */
399+ } else if ( FD_UNLIKELY ( query_err != FD_MAP_ERR_KEY ) ) {
400+ FD_LOG_CRIT (( "fd_funk_rec_map_txn_query failed: %i-%s" , query_err , fd_map_strerror ( query_err ) ));
401+ }
402+
403+ /* Phase 4: Insert new record */
404+
405+ int insert_err = fd_funk_rec_map_txn_insert ( funk -> rec_map , rec );
406+ if ( FD_UNLIKELY ( insert_err != FD_MAP_SUCCESS ) ) {
407+ FD_LOG_CRIT (( "fd_funk_rec_map_txn_insert failed: %i-%s" , insert_err , fd_map_strerror ( insert_err ) ));
395408 }
396409
397410 /* At this point, another thread could aggressively evict this entry.
398411 But this entry is not yet present in rec_map! This is why we hold
399412 a lock on the rec_map chain -- the rec_map_remove executed by the
400413 eviction will be sequenced after completion of phase 5. */
401414
402- /* Phase 4 : Insert rec into rec_map */
415+ /* Phase 5 : Insert rec into rec_map */
403416
404417 if ( txn ) {
405418 fd_funk_rec_push_tail ( funk -> rec_pool -> ele ,
@@ -408,7 +421,7 @@ fd_progcache_push( fd_progcache_t * cache,
408421 & txn -> rec_tail_idx );
409422 }
410423
411- /* Phase 5 : Finish rec_map transaction */
424+ /* Phase 6 : Finish rec_map transaction */
412425
413426 int test_err = fd_funk_rec_map_txn_test ( map_txn );
414427 if ( FD_UNLIKELY ( test_err != FD_MAP_SUCCESS ) ) FD_LOG_CRIT (( "fd_funk_rec_map_txn_test failed: %i-%s" , test_err , fd_map_strerror ( test_err ) ));
@@ -577,7 +590,8 @@ fd_progcache_insert( fd_progcache_t * cache,
577590
578591 /* Publish cache entry to funk index */
579592
580- int push_ok = fd_progcache_push ( cache , txn , funk_rec , prog_addr );
593+ fd_funk_rec_t * dup_rec = NULL ;
594+ int push_ok = fd_progcache_push ( cache , txn , funk_rec , prog_addr , & dup_rec );
581595
582596 /* Done modifying transaction */
583597
@@ -588,12 +602,11 @@ fd_progcache_insert( fd_progcache_t * cache,
588602 EVICTED AFTER PEEK? */
589603
590604 if ( !push_ok ) {
591- fd_progcache_rec_t const * other = fd_progcache_peek ( cache , load_xid , prog_addr , env -> epoch_slot0 );
592- if ( FD_UNLIKELY ( !other ) ) {
593- FD_LOG_CRIT (( "fd_progcache_push/fd_progcache_peek data race detected" ));
594- }
605+ FD_TEST ( dup_rec );
606+ fd_funk_val_flush ( funk_rec , funk -> alloc , funk -> wksp );
607+ fd_funk_rec_pool_release ( funk -> rec_pool , funk_rec , 1 );
595608 cache -> metrics -> dup_insert_cnt ++ ;
596- return other ;
609+ return fd_funk_val_const ( dup_rec , funk -> wksp ) ;
597610 }
598611
599612 cache -> metrics -> fill_cnt ++ ;
@@ -681,7 +694,8 @@ fd_progcache_invalidate( fd_progcache_t * cache,
681694
682695 /* Publish cache entry to funk index */
683696
684- int push_ok = fd_progcache_push ( cache , txn , funk_rec , prog_addr );
697+ fd_funk_rec_t * dup_rec = NULL ;
698+ int push_ok = fd_progcache_push ( cache , txn , funk_rec , prog_addr , & dup_rec );
685699
686700 /* Done modifying transaction */
687701
@@ -692,12 +706,11 @@ fd_progcache_invalidate( fd_progcache_t * cache,
692706 EVICTED AFTER PEEK? */
693707
694708 if ( !push_ok ) {
695- fd_progcache_rec_t const * other = fd_progcache_peek_exact ( cache , xid , prog_addr );
696- if ( FD_UNLIKELY ( !other ) ) {
697- FD_LOG_CRIT (( "fd_progcache_push/fd_progcache_peek data race detected" ));
698- }
709+ FD_TEST ( dup_rec );
710+ fd_funk_val_flush ( funk_rec , funk -> alloc , funk -> wksp );
711+ fd_funk_rec_pool_release ( funk -> rec_pool , funk_rec , 1 );
699712 cache -> metrics -> dup_insert_cnt ++ ;
700- return other ;
713+ return fd_funk_val_const ( dup_rec , funk -> wksp ) ;
701714 }
702715
703716 cache -> metrics -> invalidate_cnt ++ ;
0 commit comments