Skip to content

Commit e97dd83

Browse files
txncache: add txn generation
Co-authored-by: Yufeng Zhou <yufzhou@jumptrading.com>
1 parent 90167ec commit e97dd83

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

src/flamenco/runtime/fd_txncache.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ fd_txncache_insert_txn( fd_txncache_t * tc,
205205
ulong txnhash_offset = blockcache->shmem->txnhash_offset;
206206
memcpy( txnpage->txns[ txn_idx ]->txnhash, txnhash+txnhash_offset, 20UL );
207207
txnpage->txns[ txn_idx ]->fork_id = fork_id;
208+
txnpage->txns[ txn_idx ]->generation = tc->blockcache_pool[ fork_id.val ].shmem->generation;
208209
FD_COMPILER_MFENCE();
209210

210211
ulong txn_bucket = FD_LOAD( ulong, txnhash+txnhash_offset )%tc->shmem->txn_per_slot_max;
@@ -231,6 +232,7 @@ fd_txncache_attach_child( fd_txncache_t * tc,
231232
blockcache_t * fork = &tc->blockcache_pool[ idx ];
232233
fd_txncache_fork_id_t fork_id = { .val = (ushort)idx };
233234

235+
fork->shmem->generation = tc->shmem->blockcache_generation++;
234236
fork->shmem->child_id = (fd_txncache_fork_id_t){ .val = USHORT_MAX };
235237

236238
if( FD_LIKELY( parent_fork_id.val==USHORT_MAX ) ) {
@@ -390,6 +392,13 @@ blockhash_on_fork( fd_txncache_t * tc,
390392
return NULL;
391393
}
392394

395+
static void
396+
fd_txncache_purge_stale( fd_txncache_t * tc ) {
397+
(void)tc;
398+
FD_LOG_ERR(( "txncache full, purging stale transactions" ));
399+
// TODO: Implement eviction of any txn with generation!=fork->generation
400+
}
401+
393402
void
394403
fd_txncache_insert( fd_txncache_t * tc,
395404
fd_txncache_fork_id_t fork_id,
@@ -408,7 +417,14 @@ fd_txncache_insert( fd_txncache_t * tc,
408417

409418
for(;;) {
410419
fd_txncache_txnpage_t * txnpage = fd_txncache_ensure_txnpage( tc, blockcache );
411-
FD_TEST( txnpage );
420+
if( FD_UNLIKELY( !txnpage ) ) {
421+
/* Because of sizing invariants when creating the structure, it is
422+
not typically possible to fill it, unless there are stale
423+
transactions from minority forks that were purged floating
424+
around, in which case we can purge them here and try again. */
425+
fd_txncache_purge_stale( tc );
426+
continue;
427+
}
412428

413429
int success = fd_txncache_insert_txn( tc, blockcache, txnpage, fork_id, txnhash );
414430
if( FD_LIKELY( success ) ) break;
@@ -441,7 +457,7 @@ fd_txncache_query( fd_txncache_t * tc,
441457
for( uint head=blockcache->heads[ head_hash ]; head!=UINT_MAX; head=tc->txnpages[ head/FD_TXNCACHE_TXNS_PER_PAGE ].txns[ head%FD_TXNCACHE_TXNS_PER_PAGE ]->blockcache_next ) {
442458
fd_txncache_single_txn_t * txn = tc->txnpages[ head/FD_TXNCACHE_TXNS_PER_PAGE ].txns[ head%FD_TXNCACHE_TXNS_PER_PAGE ];
443459

444-
int descends = txn->fork_id.val==fork_id.val || descends_set_test( fork->descends, txn->fork_id.val );
460+
int descends = (txn->fork_id.val==fork_id.val || descends_set_test( fork->descends, txn->fork_id.val )) && fork->shmem->generation==txn->generation;
445461
if( FD_LIKELY( descends && !memcmp( txnhash+txnhash_offset, txn->txnhash, 20UL ) ) ) {
446462
found = 1;
447463
break;

src/flamenco/runtime/fd_txncache_private.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
struct fd_txncache_single_txn {
2222
uint blockcache_next; /* Pointer to the next element in the blockcache hash chain containing this entry from the pool. */
23+
uint generation; /* The generation of the fork when this transaction was inserted. Used to
24+
determine if the transaction is still valid for a fork that might have
25+
advanced since insertion. */
2326

2427
fd_txncache_fork_id_t fork_id; /* Fork that the transaction was executed on. A transaction might be in the cache
2528
multiple times if it was executed on multiple forks. */
@@ -45,6 +48,8 @@ struct fd_txncache_blockcache_shmem {
4548
int frozen; /* If non-zero, the blockcache is frozen and should not be modified. This is used to enforce
4649
invariants on the caller of the txncache. */
4750

51+
uint generation;
52+
4853
fd_hash_t blockhash; /* The blockhash that this entry is for. */
4954
ulong txnhash_offset; /* To save memory, the Agave validator decided to truncate the hash of transactions stored in
5055
this memory to 20 bytes rather than 32 bytes. The bytes used are not the first 20 as you
@@ -125,6 +130,7 @@ struct __attribute__((aligned(FD_TXNCACHE_SHMEM_ALIGN))) fd_txncache_shmem_priva
125130
ushort txnpages_per_blockhash_max;
126131
ushort max_txnpages;
127132

133+
uint blockcache_generation; /* Incremented for every blockcache. */
128134
ushort txnpages_free_cnt; /* The number of pages in the txnpages that are not currently in use. */
129135

130136
ulong root_cnt;

src/flamenco/runtime/fd_txncache_shmem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ fd_txncache_shmem_new( void * shmem,
164164
tc->txnpages_per_blockhash_max = _max_txnpages_per_blockhash;
165165
tc->max_txnpages = _max_txnpages;
166166

167+
tc->blockcache_generation = 0U;
167168
tc->txnpages_free_cnt = _max_txnpages;
168169
ushort * txnpages_free = (ushort *)_txnpages_free;
169170
for( ushort i=0; i<_max_txnpages; i++ ) txnpages_free[ i ] = i;

0 commit comments

Comments
 (0)