@@ -396,130 +396,52 @@ fd_funk_rec_cancel( fd_funk_t * funk,
396396 fd_funk_rec_pool_release ( funk -> rec_pool , prepare -> rec , 1 );
397397}
398398
399- static void
400- fd_funk_rec_txn_publish ( fd_funk_t * funk ,
401- fd_funk_rec_prepare_t * prepare ) {
402- fd_funk_rec_t * rec = prepare -> rec ;
403- uint * rec_head_idx = prepare -> rec_head_idx ;
404- uint * rec_tail_idx = prepare -> rec_tail_idx ;
405-
406- uint rec_prev_idx ;
407- uint rec_idx = (uint )( rec - funk -> rec_pool -> ele );
408- rec_prev_idx = * rec_tail_idx ;
409- * rec_tail_idx = rec_idx ;
410- rec -> prev_idx = rec_prev_idx ;
411- rec -> next_idx = FD_FUNK_REC_IDX_NULL ;
412- if ( fd_funk_rec_idx_is_null ( rec_prev_idx ) ) {
413- * rec_head_idx = rec_idx ;
414- } else {
415- funk -> rec_pool -> ele [ rec_prev_idx ].next_idx = rec_idx ;
416- }
417-
418- if ( FD_UNLIKELY ( fd_funk_rec_map_txn_insert ( funk -> rec_map , rec ) ) ) {
419- FD_LOG_CRIT (( "fd_funk_rec_map_insert failed" ));
420- }
421- }
422-
423- void
399+ int
424400fd_funk_rec_insert_para ( fd_funk_t * funk ,
425401 fd_funk_txn_xid_t const * xid ,
426- fd_funk_rec_key_t const * key ) {
402+ fd_funk_rec_key_t const * key ,
403+ ulong val_align ,
404+ ulong val_sz ,
405+ void * val ) {
406+ if ( FD_UNLIKELY ( !funk ) ) FD_LOG_ERR (( "NULL funk" ));
407+ if ( FD_UNLIKELY ( !xid ) ) FD_LOG_ERR (( "NULL xid" ));
408+ if ( FD_UNLIKELY ( !key ) ) FD_LOG_ERR (( "NULL key" ));
409+ if ( FD_UNLIKELY ( !val && val_sz ) ) FD_LOG_ERR (( "NULL val" ));
427410
428- /* TODO: There is probably a cleaner way to allocate the txn memory. */
429-
430- /* See the header comment for why the max is 2. */
431- #define MAX_TXN_KEY_CNT (2UL)
432- uchar txn_mem [ fd_funk_rec_map_txn_footprint ( MAX_TXN_KEY_CNT ) ] __attribute__((aligned (alignof(fd_funk_rec_map_txn_t ))));
433-
434- /* First, we will do a global query to find a version of the record
435- from either the current transaction or one of its ancestors. */
436-
437- fd_funk_rec_t const * rec_glob = NULL ;
438- fd_funk_txn_xid_t txn_glob [1 ] = {0 };
411+ fd_funk_xid_key_pair_t pair [1 ];
412+ fd_funk_rec_key_set_pair ( pair , xid , key );
439413
440414 for (;;) {
441- fd_funk_rec_query_t query_glob [1 ];
442- fd_funk_txn_t const * found_txn = NULL ;
443- rec_glob = fd_funk_rec_query_try_global ( funk , xid , key , & found_txn , query_glob );
444- if ( found_txn ) fd_funk_txn_xid_copy ( txn_glob , & found_txn -> xid );
445- else fd_funk_txn_xid_copy ( txn_glob , fd_funk_last_publish ( funk ) );
446-
447- /* If the record exists and already exists in the specified funk
448- txn, we can return successfully.
449-
450- TODO: This should probably also check that the record has a large
451- enough size, i.e. rec_glob >= min_sz. */
452- if ( rec_glob && fd_funk_txn_xid_eq ( txn_glob , xid ) ) {
453- return ;
415+ /* See if the record already exists. */
416+ fd_funk_rec_query_t query [1 ];
417+ int err = fd_funk_rec_map_query_try ( funk -> rec_map , pair , NULL , query , 0 );
418+ if ( err == FD_MAP_SUCCESS ) {
419+ fd_funk_rec_t * rec = fd_funk_rec_map_query_ele ( query );
420+ /* Set the value of the record */
421+ if ( !fd_funk_val_truncate ( rec , fd_funk_alloc ( funk ), fd_funk_wksp ( funk ), val_align , val_sz , & err ) ) {
422+ FD_LOG_ERR (( "fd_funk_val_truncate() failed (out of memory?)" ));
423+ return err ;
424+ }
425+ memcpy ( fd_funk_val ( rec , fd_funk_wksp ( funk ) ), val , val_sz );
426+ return FD_FUNK_SUCCESS ;
454427 }
455428
456- if ( rec_glob && fd_funk_rec_query_test ( query_glob )== FD_FUNK_SUCCESS ) {
457- break ;
429+ /* The record doesn't exist. Create it. */
430+ fd_funk_rec_prepare_t prepare [1 ];
431+ fd_funk_rec_t * rec = fd_funk_rec_prepare ( funk , xid , key , prepare , & err );
432+ if ( FD_UNLIKELY ( !rec ) ) {
433+ FD_LOG_CRIT (( "fd_funk_rec_prepare returned err=%d" , err ));
434+ return err ;
458435 }
459- }
460-
461- /* At this point, we need to atomically clone the record and copy
462- in the contents of the global record. We at most will be trying to
463- create a txn with two record keys. If the key exists in some
464- ancestor txn, than we need to add the ancestor key to the txn. We
465- will always need to add the current key to the txn. */
466- /* TODO: Turn key_max into a const. */
467-
468- fd_funk_rec_map_txn_t * map_txn = fd_funk_rec_map_txn_init ( txn_mem , funk -> rec_map , MAX_TXN_KEY_CNT );
469-
470- fd_funk_xid_key_pair_t pair [1 ];
471- fd_funk_rec_key_set_pair ( pair , xid , key );
472-
473- fd_funk_rec_map_txn_add ( map_txn , pair , 1 );
474-
475- fd_funk_xid_key_pair_t pair_glob [1 ];
476- if ( rec_glob ) {
477- fd_funk_rec_key_set_pair ( pair_glob , txn_glob , key );
478- fd_funk_rec_map_txn_add ( map_txn , pair_glob , 1 );
479- }
480-
481- /* Now that the keys are in the txn, we can try to start the
482- transaction on the record_map. */
483-
484- int err = fd_funk_rec_map_txn_try ( map_txn , FD_MAP_FLAG_BLOCKING );
485- if ( FD_UNLIKELY ( err != FD_MAP_SUCCESS ) ) {
486- FD_LOG_CRIT (( "fd_funk_rec_map_txn_try returned err %d" , err ));
487- }
488-
489- /* We are now in a txn try with a lock on both record keys. */
490-
491- /* First we need to make sure that the record hasn't been created yet. */
492- fd_funk_rec_map_query_t query [1 ];
493- err = fd_funk_rec_map_txn_query ( funk -> rec_map , pair , NULL , query , FD_MAP_FLAG_BLOCKING );
494- if ( FD_UNLIKELY ( err == FD_MAP_SUCCESS ) ) {
495- /* The key has been inserted. We need to gracefully exit the txn. */
496- err = fd_funk_rec_map_txn_test ( map_txn );
497- if ( FD_UNLIKELY ( err != FD_MAP_SUCCESS ) ) {
498- FD_LOG_CRIT (( "fd_funk_rec_map_txn_test returned err %d" , err ));
436+ /* Set the value of the record */
437+ if ( !fd_funk_val_truncate ( rec , fd_funk_alloc ( funk ), fd_funk_wksp ( funk ), val_align , val_sz , & err ) ) {
438+ FD_LOG_ERR (( "fd_funk_val_truncate() failed (out of memory?)" ));
439+ return err ;
499440 }
500- fd_funk_rec_map_txn_fini ( map_txn );
501- return ;
502- }
503-
504- /* If we are at this point, we know for certain that the record hasn't
505- been created yet. We will copy in the record from the global txn
506- (if one exists). */
507-
508- fd_funk_rec_prepare_t prepare [1 ];
509- fd_funk_rec_prepare ( funk , xid , key , prepare , & err );
510- if ( FD_UNLIKELY ( err ) ) {
511- FD_LOG_CRIT (( "fd_funk_rec_prepare returned err=%d" , err ));
512- }
513- fd_funk_rec_txn_publish ( funk , prepare );
514-
515- err = fd_funk_rec_map_txn_test ( map_txn );
516- if ( FD_UNLIKELY ( err != FD_MAP_SUCCESS ) ) {
517- FD_LOG_CRIT (( "fd_funk_rec_map_txn_test returned err %d" , err ));
441+ memcpy ( fd_funk_val ( rec , fd_funk_wksp ( funk ) ), val , val_sz );
442+ fd_funk_rec_publish ( funk , prepare );
443+ return FD_FUNK_SUCCESS ;
518444 }
519-
520- fd_funk_rec_map_txn_fini ( map_txn );
521-
522- #undef MAX_TXN_KEY_CNT
523445}
524446
525447fd_funk_rec_t *
0 commit comments