@@ -611,12 +611,6 @@ fd_banks_clone_from_parent( fd_banks_t * banks,
611
611
612
612
}
613
613
614
- /* If the parent bank is dead, then we also need to mark the child
615
- bank as being a dead block. */
616
- if ( FD_UNLIKELY ( parent_bank -> flags & FD_BANK_FLAGS_DEAD ) ) {
617
- new_bank -> flags |= FD_BANK_FLAGS_DEAD ;
618
- }
619
-
620
614
/* We want to copy over the fields from the parent to the child,
621
615
except for the fields which correspond to the header of the bank
622
616
struct which is used for pool and map management. We can take
@@ -652,7 +646,13 @@ fd_banks_clone_from_parent( fd_banks_t * banks,
652
646
#undef HAS_LOCK_0
653
647
#undef HAS_LOCK_1
654
648
655
- new_bank -> flags = FD_BANK_FLAGS_INIT ;
649
+ new_bank -> flags = FD_BANK_FLAGS_INIT ;
650
+ /* If the parent bank is dead, then we also need to mark the child
651
+ bank as being a dead block. */
652
+ if ( FD_UNLIKELY ( parent_bank -> flags & FD_BANK_FLAGS_DEAD ) ) {
653
+ new_bank -> flags |= FD_BANK_FLAGS_DEAD ;
654
+ }
655
+
656
656
new_bank -> refcnt = 0UL ;
657
657
658
658
/* Delta field does not need to be copied over. The dirty flag just
966
966
fd_banks_publish_prepare ( fd_banks_t * banks ,
967
967
fd_hash_t * target_block_id ,
968
968
fd_hash_t * publishable_block_id ) {
969
+ /* TODO: An optimization here is to do a single traversal of the tree
970
+ that would mark minority forks as dead while accumulating
971
+ refcnts to determine which bank is the highest publishable. */
972
+
969
973
fd_bank_t * bank_pool = fd_banks_get_bank_pool ( banks );
970
974
fd_banks_map_t * bank_map = fd_banks_get_bank_map ( banks );
971
975
@@ -993,7 +997,8 @@ fd_banks_publish_prepare( fd_banks_t * banks,
993
997
return 0 ;
994
998
}
995
999
996
- /* Mark rooted fork. */
1000
+ /* Mark every node from the target bank up through its parents to the
1001
+ root as being rooted. */
997
1002
fd_bank_t * curr = target_bank ;
998
1003
fd_bank_t * prev = NULL ;
999
1004
while ( curr ) {
@@ -1003,7 +1008,7 @@ fd_banks_publish_prepare( fd_banks_t * banks,
1003
1008
}
1004
1009
1005
1010
/* If we didn't reach the old root, target is not a descendant. */
1006
- if ( prev != root ) {
1011
+ if ( FD_UNLIKELY ( prev != root ) ) {
1007
1012
FD_LOG_CRIT (( "target block_id %s is not a descendant of root block_id %s" , FD_BASE58_ENC_32_ALLOCA ( target_block_id ), FD_BASE58_ENC_32_ALLOCA ( root_block_id ) ));
1008
1013
}
1009
1014
@@ -1021,9 +1026,11 @@ fd_banks_publish_prepare( fd_banks_t * banks,
1021
1026
}
1022
1027
1023
1028
/* For this node to be pruned, all minority forks that branch off
1024
- from it must be entirely eligible for pruning. This means
1025
- checking all children (except for the one on the rooted fork) and
1026
- their entire subtrees. */
1029
+ from it must be entirely eligible for pruning. A fork is
1030
+ eligible for pruning if there are no outstanding references to
1031
+ any of the nodes on the fork. This means checking all children
1032
+ (except for the one on the rooted fork) and their entire
1033
+ subtrees. */
1027
1034
int all_minority_forks_can_be_pruned = 1 ;
1028
1035
ulong child_idx = prune_candidate -> child_idx ;
1029
1036
while ( child_idx != fd_banks_pool_idx_null ( bank_pool ) ) {
@@ -1075,17 +1082,31 @@ fd_banks_publish_prepare( fd_banks_t * banks,
1075
1082
}
1076
1083
}
1077
1084
1078
- /* Now mark all minority forks as dead. */
1085
+ /* At this point the highest publishable bank has been identified. */
1086
+
1087
+ /* We know that the majority fork that is not getting pruned off is
1088
+ the child of the target bank. All other child/sibling nodes off of
1089
+ the other nodes that were just marked as root are minority forks
1090
+ which should be pruned off. */
1091
+ ulong target_bank_idx = fd_banks_pool_idx ( bank_pool , target_bank );
1092
+
1093
+ /* Now mark all minority forks as being dead. This involves
1094
+ traversing the tree down from the old root through its descendants
1095
+ that are marked as rooted. Any child/sibling nodes of these rooted
1096
+ nodes are minority forks which should be marked as dead. */
1097
+
1079
1098
curr = root ;
1080
1099
while ( curr && curr -> flags & FD_BANK_FLAGS_ROOTED ) {
1081
1100
fd_bank_t * rooted_child_bank = NULL ;
1082
- ulong child_idx = curr -> child_idx ;
1101
+ ulong child_idx = curr -> child_idx ;
1083
1102
while ( child_idx != fd_banks_pool_idx_null ( bank_pool ) ) {
1084
1103
fd_bank_t * sibling = fd_banks_pool_ele ( bank_pool , child_idx );
1085
1104
if ( sibling -> flags & FD_BANK_FLAGS_ROOTED ) {
1086
1105
rooted_child_bank = sibling ;
1087
- } else {
1088
- /* This is a minority fork. */
1106
+ } else if ( sibling -> parent_idx != target_bank_idx ) {
1107
+ /* This is a minority fork. Every node in the subtree should
1108
+ be marked as dead. We know that it is a minority fork
1109
+ this node is not a child of the new target root. */
1089
1110
fd_banks_subtree_mark_dead ( bank_pool , sibling );
1090
1111
}
1091
1112
child_idx = sibling -> sibling_idx ;
0 commit comments