Skip to content

Commit 0caccc0

Browse files
runtime: correctly mark dead blocks
1 parent 766ee39 commit 0caccc0

File tree

3 files changed

+55
-27
lines changed

3 files changed

+55
-27
lines changed

src/discof/replay/fd_exec.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,23 +119,29 @@ fd_slice_exec_begin( fd_slice_exec_t * slice_exec_ctx,
119119
ulong slice_sz,
120120
int last_batch );
121121

122+
static inline void
123+
fd_slice_exec_skip_slice( fd_slice_exec_t * slice_exec_ctx ) {
124+
slice_exec_ctx->mblks_rem = 0UL;
125+
slice_exec_ctx->txns_rem = 0UL;
126+
}
127+
122128
static inline int
123-
fd_slice_exec_txn_ready( fd_slice_exec_t * slice_exec_ctx ) {
129+
fd_slice_exec_txn_ready( fd_slice_exec_t const * slice_exec_ctx ) {
124130
return slice_exec_ctx->txns_rem > 0UL;
125131
}
126132

127133
static inline int
128-
fd_slice_exec_microblock_ready( fd_slice_exec_t * slice_exec_ctx ) {
134+
fd_slice_exec_microblock_ready( fd_slice_exec_t const * slice_exec_ctx ) {
129135
return slice_exec_ctx->txns_rem == 0 && slice_exec_ctx->mblks_rem > 0UL;
130136
}
131137

132138
static inline int
133-
fd_slice_exec_slice_ready( fd_slice_exec_t * slice_exec_ctx ) {
139+
fd_slice_exec_slice_ready( fd_slice_exec_t const * slice_exec_ctx ) {
134140
return slice_exec_ctx->txns_rem == 0 && slice_exec_ctx->mblks_rem == 0UL;
135141
}
136142

137143
static inline int
138-
fd_slice_exec_slot_complete( fd_slice_exec_t * slice_exec_ctx ) {
144+
fd_slice_exec_slot_complete( fd_slice_exec_t const * slice_exec_ctx ) {
139145
return slice_exec_ctx->last_batch && slice_exec_ctx->mblks_rem == 0 && slice_exec_ctx->txns_rem == 0;
140146
}
141147

src/discof/replay/fd_replay_tile.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,14 @@ exec_and_handle_slice( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
17581758
}
17591759
}
17601760

1761+
if( FD_UNLIKELY( fd_banks_is_bank_dead( ctx->slot_ctx->bank ) ) ) {
1762+
/* TODO: This is a temporary hack to handle dead banks. We simply
1763+
skip the txn. This should be removed and instead be handled
1764+
by the replay dispatcher. */
1765+
FD_LOG_WARNING(( "Skipping slice because bank is dead (slot: %lu, block_id: %s)", fd_bank_slot_get( ctx->slot_ctx->bank ), FD_BASE58_ENC_32_ALLOCA( fd_bank_block_id_query( ctx->slot_ctx->bank ) ) ));
1766+
fd_slice_exec_skip_slice( &ctx->slice_exec_ctx );
1767+
}
1768+
17611769
/* At this point, we know that we have some quantity of transactions
17621770
in a microblock that we are ready to execute. */
17631771
for( int i=0; i<fd_ulong_popcnt( ctx->exec_ready_bitset ); i++ ) {
@@ -1776,13 +1784,6 @@ exec_and_handle_slice( fd_replay_tile_ctx_t * ctx, fd_stem_context_t * stem ) {
17761784
fd_txn_p_t txn_p;
17771785
fd_slice_exec_txn_parse( &ctx->slice_exec_ctx, &txn_p );
17781786

1779-
if( FD_UNLIKELY( fd_banks_is_bank_dead( ctx->slot_ctx->bank ) ) ) {
1780-
/* TODO: This is a temporary hack to handle dead banks. We simply
1781-
skip the txn. This should be removed and instead be handled
1782-
by the replay dispatcher. */
1783-
continue;
1784-
}
1785-
17861787
/* Insert or reverify invoked programs for this epoch, if needed
17871788
FIXME: this should be done during txn parsing so that we don't have to loop
17881789
over all accounts a second time. */

src/flamenco/runtime/fd_bank.c

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -611,12 +611,6 @@ fd_banks_clone_from_parent( fd_banks_t * banks,
611611

612612
}
613613

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-
620614
/* We want to copy over the fields from the parent to the child,
621615
except for the fields which correspond to the header of the bank
622616
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,
652646
#undef HAS_LOCK_0
653647
#undef HAS_LOCK_1
654648

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+
656656
new_bank->refcnt = 0UL;
657657

658658
/* Delta field does not need to be copied over. The dirty flag just
@@ -966,6 +966,10 @@ int
966966
fd_banks_publish_prepare( fd_banks_t * banks,
967967
fd_hash_t * target_block_id,
968968
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+
969973
fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
970974
fd_banks_map_t * bank_map = fd_banks_get_bank_map( banks );
971975

@@ -993,7 +997,8 @@ fd_banks_publish_prepare( fd_banks_t * banks,
993997
return 0;
994998
}
995999

996-
/* Mark rooted fork. */
1000+
/* Mark every node from the target bank up through its parents to the
1001+
root as being rooted. */
9971002
fd_bank_t * curr = target_bank;
9981003
fd_bank_t * prev = NULL;
9991004
while( curr ) {
@@ -1003,7 +1008,7 @@ fd_banks_publish_prepare( fd_banks_t * banks,
10031008
}
10041009

10051010
/* If we didn't reach the old root, target is not a descendant. */
1006-
if( prev!=root ) {
1011+
if( FD_UNLIKELY( prev!=root ) ) {
10071012
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 ) ));
10081013
}
10091014

@@ -1021,9 +1026,11 @@ fd_banks_publish_prepare( fd_banks_t * banks,
10211026
}
10221027

10231028
/* 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. */
10271034
int all_minority_forks_can_be_pruned = 1;
10281035
ulong child_idx = prune_candidate->child_idx;
10291036
while( child_idx!=fd_banks_pool_idx_null( bank_pool ) ) {
@@ -1075,17 +1082,31 @@ fd_banks_publish_prepare( fd_banks_t * banks,
10751082
}
10761083
}
10771084

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+
10791098
curr = root;
10801099
while( curr && curr->flags & FD_BANK_FLAGS_ROOTED ) {
10811100
fd_bank_t * rooted_child_bank = NULL;
1082-
ulong child_idx = curr->child_idx;
1101+
ulong child_idx = curr->child_idx;
10831102
while( child_idx!=fd_banks_pool_idx_null( bank_pool ) ) {
10841103
fd_bank_t * sibling = fd_banks_pool_ele( bank_pool, child_idx );
10851104
if( sibling->flags & FD_BANK_FLAGS_ROOTED ) {
10861105
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. */
10891110
fd_banks_subtree_mark_dead( bank_pool, sibling );
10901111
}
10911112
child_idx = sibling->sibling_idx;

0 commit comments

Comments
 (0)