@@ -1074,13 +1074,13 @@ fd_forest_publish( fd_forest_t * forest, ulong new_root_slot ) {
10741074#define SLOT_INSERT 1
10751075
10761076int
1077- fd_forest_evict ( fd_forest_t * forest , ulong new_slot , ulong parent_slot ) {
1077+ fd_forest_evict ( fd_forest_t * forest , ulong new_slot , ulong parent_slot ) {
10781078 FD_LOG_NOTICE (( "fd_forest_eviction_time" ));
10791079 fd_forest_ancestry_t * ancestry = fd_forest_ancestry ( forest );
10801080 fd_forest_frontier_t * frontier = fd_forest_frontier ( forest );
10811081 fd_forest_subtlist_t * subtlist = fd_forest_subtlist ( forest );
1082+ fd_forest_orphaned_t * orphaned = fd_forest_orphaned ( forest );
10821083 fd_forest_blk_t * pool = fd_forest_pool ( forest );
1083- ulong null = fd_forest_pool_idx_null ( pool );
10841084
10851085
10861086 int has_orphans = !fd_forest_subtlist_is_empty ( subtlist , pool );
@@ -1089,42 +1089,50 @@ fd_forest_evict( fd_forest_t * forest, ulong new_slot, ulong parent_slot ) {
10891089 /* During regular operation there's usually no orphans, but if eviction
10901090 is called then it's likely we have orphans. */
10911091 if ( FD_LIKELY ( has_orphans ) ) {
1092+
10921093 /* We'll keep it if it's older than all of our orphans, or if it's
10931094 parent is part of the main tree. */
1094-
1095- ulong evict_orphan_slot = ULONG_MAX ; /* best orphan candidate for eviction is the newest subtree. */
1095+ fd_forest_blk_t * evict_orphan = NULL ; /* best orphan candidate for eviction is the newest subtree. */
10961096 for ( fd_forest_subtlist_iter_t iter = fd_forest_subtlist_iter_fwd_init ( subtlist , pool );
10971097 !fd_forest_subtlist_iter_done ( iter , subtlist , pool );
10981098 iter = fd_forest_subtlist_iter_fwd_next ( iter , subtlist , pool ) ) {
10991099 fd_forest_blk_t * ele = fd_forest_subtlist_iter_ele ( iter , subtlist , pool );
1100- if ( FD_LIKELY ( evict_orphan_slot == ULONG_MAX ) ) evict_orphan_slot = ele -> slot ;
1101- else evict_orphan_slot = fd_ulong_max ( evict_orphan_slot , ele -> slot );
1100+ if ( FD_LIKELY ( evict_orphan == NULL ) ) evict_orphan = ele ;
1101+ else evict_orphan = fd_ptr_if ( evict_orphan -> slot < ele -> slot , ele , evict_orphan );
1102+ }
11021103
1104+ for ( fd_forest_orphaned_iter_t iter = fd_forest_orphaned_iter_init ( orphaned , pool );
1105+ !fd_forest_orphaned_iter_done ( iter , orphaned , pool );
1106+ iter = fd_forest_orphaned_iter_next ( iter , orphaned , pool ) ) {
1107+ fd_forest_blk_t * ele = fd_forest_orphaned_iter_ele ( iter , orphaned , pool );
1108+ evict_orphan = fd_ptr_if ( evict_orphan -> slot < ele -> slot , ele , evict_orphan );
11031109 }
1104- /* We are connecting to the main tree. Nuke the orphan. */
1110+ /* Now we have the max of all subtrees and orphans. This is our best candidate for eviction. */
1111+
1112+ /* If are connecting to the main tree. Nuke the best candidate orphan. */
11051113 if ( fd_forest_ancestry_ele_query ( ancestry , & parent_slot , NULL , pool ) ||
11061114 fd_forest_frontier_ele_query ( frontier , & parent_slot , NULL , pool ) ) {
1107- // evict_orphan_slot
1108-
1115+ subtrees_orphaned_remove ( forest , evict_orphan -> slot );
1116+ requests_remove ( forest , fd_forest_orphreqs ( forest ), fd_forest_orphlist ( forest ), & forest -> orphiter , fd_forest_pool_idx ( pool , evict_orphan ) );
1117+ fd_forest_pool_ele_release ( pool , evict_orphan );
11091118 return SLOT_INSERT ;
11101119 }
11111120
1112-
1113- /* We ourselves are an orphan. Should we evict something else or just evict ourselves?
1121+ /* The new slot an orphan. Should we evict the candidate orphan or insert ourselves?
11141122 We'll keep it if it's older than all of our orphans */
1115- for ( fd_forest_subtlist_iter_t iter = fd_forest_subtlist_iter_fwd_init ( subtlist , pool );
1116- !fd_forest_subtlist_iter_done ( iter , subtlist , pool );
1117- iter = fd_forest_subtlist_iter_fwd_next ( iter , subtlist , pool ) ) {
1118- fd_forest_blk_t * ele = fd_forest_subtlist_iter_ele ( iter , subtlist , pool );
1119- if ( FD_LIKELY ( new_slot > ele -> slot ) ) {
1120- return SLOT_IGNORE ;
1121- }
1123+
1124+ if ( evict_orphan -> slot < new_slot ) {
1125+ return SLOT_IGNORE ;
1126+ } else {
1127+ subtrees_orphaned_remove ( forest , evict_orphan -> slot );
1128+ requests_remove ( forest , fd_forest_orphreqs ( forest ), fd_forest_orphlist ( forest ), & forest -> orphiter , fd_forest_pool_idx ( pool , evict_orphan ) );
1129+ fd_forest_pool_ele_release ( pool , evict_orphan );
1130+ return SLOT_INSERT ;
11221131 }
11231132
1124- // choose something to evict from orphans
1125- return SLOT_INSERT ;
11261133 } else {
1127- /* Have no orphans. */
1134+ /* Have no orphans. Considering the most extreme case where someone
1135+ has DoSed us with 10000 slots that chain to the root. */
11281136
11291137 if ( FD_LIKELY ( parent_exists ) ) {
11301138 /* Parent exists. This slot chains to the main tree. From oldest to newest,
@@ -1158,18 +1166,16 @@ fd_forest_evict( fd_forest_t * forest, ulong new_slot, ulong parent_slot ) {
11581166 else return SLOT_IGNORE ;
11591167 } else {
11601168 /* evict slot found. EVICT IT. */
1161-
1169+ fd_forest_blk_t * evict_ele = fd_forest_frontier_ele_remove ( frontier , & evict_slot , NULL , pool );
1170+ requests_remove ( forest , fd_forest_requests ( forest ), fd_forest_reqslist ( forest ), & forest -> iter , fd_forest_pool_idx ( pool , evict_ele ) );
1171+ fd_forest_pool_ele_release ( pool , evict_ele );
11621172 return SLOT_INSERT ;
11631173 }
11641174 } else {
11651175 /* Parent does not exist. This new slot would've been added as an orphan. */
11661176 return SLOT_IGNORE ;
11671177 }
11681178 }
1169-
1170-
1171-
1172-
11731179}
11741180
11751181ulong
0 commit comments