Line data Source code
1 : #include "fd_epoch.h" 2 : 3 : void * 4 18 : fd_epoch_new( void * shmem, ulong voter_max ) { 5 18 : if( FD_UNLIKELY( !shmem ) ) { 6 0 : FD_LOG_WARNING(( "NULL mem" )); 7 0 : return NULL; 8 0 : } 9 : 10 18 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_epoch_align() ) ) ) { 11 0 : FD_LOG_WARNING(( "misaligned mem" )); 12 0 : return NULL; 13 0 : } 14 : 15 18 : ulong footprint = fd_epoch_footprint( voter_max ); 16 18 : if( FD_UNLIKELY( !footprint ) ) { 17 0 : FD_LOG_WARNING(( "bad mem" )); 18 0 : return NULL; 19 0 : } 20 : 21 18 : fd_wksp_t * wksp = fd_wksp_containing( shmem ); 22 18 : if( FD_UNLIKELY( !wksp ) ) { 23 0 : FD_LOG_WARNING(( "shmem must be part of a workspace" )); 24 0 : return NULL; 25 0 : } 26 : 27 18 : fd_memset( shmem, 0, footprint ); 28 18 : int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( voter_max ) ) + 2; /* fill ratio <= 0.25 */ 29 : 30 18 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 31 18 : fd_epoch_t * epoch = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_align(), sizeof(fd_epoch_t) ); 32 18 : void * epoch_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_epoch_voters_align(), fd_epoch_voters_footprint( lg_slot_cnt ) ); 33 18 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_epoch_align() ) == (ulong)shmem + footprint ); 34 : 35 18 : epoch->voters_gaddr = fd_wksp_gaddr_fast( wksp, fd_epoch_voters_join( fd_epoch_voters_new( epoch_voters, lg_slot_cnt ) ) ); 36 : 37 18 : epoch->epoch_gaddr = fd_wksp_gaddr_fast( wksp, epoch ); 38 18 : epoch->total_stake = 0UL; 39 18 : epoch->first_slot = FD_SLOT_NULL; 40 18 : epoch->last_slot = FD_SLOT_NULL; 41 : 42 18 : FD_COMPILER_MFENCE(); 43 18 : FD_VOLATILE( epoch->magic ) = FD_EPOCH_MAGIC; 44 18 : FD_COMPILER_MFENCE(); 45 : 46 18 : return shmem; 47 18 : } 48 : 49 : fd_epoch_t * 50 18 : fd_epoch_join( void * shepoch ) { 51 18 : fd_epoch_t * epoch = (fd_epoch_t *)shepoch; 52 : 53 18 : if( FD_UNLIKELY( !epoch ) ) { 54 0 : FD_LOG_WARNING(( "NULL epoch" )); 55 0 : return NULL; 56 0 : } 57 : 58 18 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)epoch, fd_epoch_align() ) ) ) { 59 0 : FD_LOG_WARNING(( "misaligned epoch" )); 60 0 : return NULL; 61 0 : } 62 : 63 18 : fd_wksp_t * wksp = fd_wksp_containing( epoch ); 64 18 : if( FD_UNLIKELY( !wksp ) ) { 65 0 : FD_LOG_WARNING(( "epoch must be part of a workspace" )); 66 0 : return NULL; 67 0 : } 68 : 69 18 : if( FD_UNLIKELY( epoch->magic!=FD_EPOCH_MAGIC ) ) { 70 0 : FD_LOG_WARNING(( "bad magic" )); 71 0 : return NULL; 72 0 : } 73 : 74 18 : return epoch; 75 18 : } 76 : 77 : void * 78 3 : fd_epoch_leave( fd_epoch_t const * epoch ) { 79 : 80 3 : if( FD_UNLIKELY( !epoch ) ) { 81 0 : FD_LOG_WARNING(( "NULL epoch" )); 82 0 : return NULL; 83 0 : } 84 : 85 3 : return (void *)epoch; 86 3 : } 87 : 88 : void * 89 3 : fd_epoch_delete( void * epoch ) { 90 : 91 3 : if( FD_UNLIKELY( !epoch ) ) { 92 0 : FD_LOG_WARNING(( "NULL epoch" )); 93 0 : return NULL; 94 0 : } 95 : 96 3 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)epoch, fd_epoch_align() ) ) ) { 97 0 : FD_LOG_WARNING(( "misaligned epoch" )); 98 0 : return NULL; 99 0 : } 100 : 101 3 : return epoch; 102 3 : } 103 : 104 : void 105 : fd_epoch_init( fd_epoch_t * epoch, 106 : ulong eah_start_slot, 107 : ulong eah_stop_slot, 108 0 : fd_vote_states_t const * vote_accounts ) { 109 : 110 0 : epoch->first_slot = eah_start_slot; 111 0 : epoch->last_slot = eah_stop_slot; 112 : 113 0 : fd_voter_t * epoch_voters = fd_epoch_voters( epoch ); 114 0 : fd_vote_states_iter_t iter_[1]; 115 0 : for( fd_vote_states_iter_t * iter = fd_vote_states_iter_init( iter_, vote_accounts ); !fd_vote_states_iter_done( iter ); fd_vote_states_iter_next( iter ) ) { 116 0 : fd_vote_state_ele_t const * vote_state = fd_vote_states_iter_ele( iter ); 117 : 118 0 : if( FD_UNLIKELY( vote_state->stake>0UL ) ) { 119 : 120 0 : #if FD_EPOCH_USE_HANDHOLDING 121 0 : FD_TEST( !fd_epoch_voters_query( epoch_voters, vote_state->vote_account, NULL ) ); 122 0 : FD_TEST( fd_epoch_voters_key_cnt( epoch_voters ) < fd_epoch_voters_key_max( epoch_voters ) ); 123 0 : #endif 124 : 125 0 : fd_voter_t * voter = fd_epoch_voters_insert( epoch_voters, vote_state->vote_account ); 126 : 127 0 : #if FD_EPOCH_USE_HANDHOLDING 128 0 : FD_TEST( 0 == memcmp( &voter->key, &vote_state->vote_account, sizeof(fd_pubkey_t) ) ); 129 0 : FD_TEST( fd_epoch_voters_query( epoch_voters, voter->key, NULL ) ); 130 0 : #endif 131 : 132 0 : voter->stake = vote_state->stake; 133 : 134 0 : voter->replay_vote.slot = FD_SLOT_NULL; 135 0 : voter->gossip_vote.slot = FD_SLOT_NULL; 136 0 : voter->rooted_vote.slot = FD_SLOT_NULL; 137 0 : } 138 0 : epoch->total_stake += vote_state->stake; 139 0 : } 140 0 : } 141 : 142 : void 143 0 : fd_epoch_fini( fd_epoch_t * epoch ) { 144 0 : fd_epoch_voters_clear( fd_epoch_voters( epoch ) ); 145 0 : epoch->total_stake = 0UL; 146 0 : }