Line data Source code
1 : #include "fd_txncache_writer.h" 2 : #include "../../flamenco/runtime/fd_txncache_private.h" 3 : #include "../../util/fd_util.h" 4 : 5 : /* Mirror of blockcache_t and fd_txncache_private from fd_txncache.c. 6 : Needed to access the page index array and txnpages. */ 7 : 8 : struct fd_txncache_writer_blockcache { 9 : fd_txncache_blockcache_shmem_t * shmem; 10 : uint * heads; 11 : ushort * pages; 12 : descends_set_t * descends; 13 : }; 14 : 15 : typedef struct fd_txncache_writer_blockcache fd_txncache_writer_blockcache_t; 16 : 17 : struct fd_txncache_writer_tc { 18 : fd_txncache_shmem_t * shmem; 19 : fd_txncache_blockcache_shmem_t * blockcache_shmem_pool; 20 : fd_txncache_writer_blockcache_t * blockcache_pool; 21 : blockhash_map_t * blockhash_map; 22 : ushort * txnpages_free; 23 : fd_txncache_txnpage_t * txnpages; 24 : }; 25 : 26 : typedef struct fd_txncache_writer_tc fd_txncache_writer_tc_t; 27 : 28 12 : #define STATE_HEADER 1 29 48 : #define STATE_BLOCKHASH 2 30 36 : #define STATE_TXNS 3 31 12 : #define STATE_DONE 4 32 6 : #define STATE_INIT STATE_HEADER 33 : 34 : static int 35 : txncache_txn_on_snapshot_root( fd_txncache_writer_tc_t const * tc, 36 : ulong snapshot_root_idx, 37 90 : fd_txncache_single_txn_t const * txn ) { 38 90 : if( FD_UNLIKELY( snapshot_root_idx>=tc->shmem->active_slots_max ) ) return 0; 39 90 : if( FD_UNLIKELY( txn->fork_id.val>=tc->shmem->active_slots_max ) ) return 0; 40 : 41 90 : fd_txncache_blockcache_shmem_t const * txn_fork = &tc->blockcache_shmem_pool[ txn->fork_id.val ]; 42 90 : if( FD_UNLIKELY( txn_fork->frozen<0 || txn_fork->generation!=txn->generation ) ) return 0; 43 : 44 90 : return txn->fork_id.val==snapshot_root_idx || 45 90 : descends_set_test( tc->blockcache_pool[ snapshot_root_idx ].descends, txn->fork_id.val ); 46 90 : } 47 : 48 : static ulong 49 : txncache_count_txns( fd_txncache_writer_tc_t const * tc, 50 : ulong snapshot_root_idx, 51 24 : ulong bc_idx ) { 52 24 : fd_txncache_blockcache_shmem_t const * bc_shmem = &tc->blockcache_shmem_pool[ bc_idx ]; 53 24 : fd_txncache_writer_blockcache_t const * bc = &tc->blockcache_pool[ bc_idx ]; 54 24 : ulong cnt = 0UL; 55 48 : for( ushort p=0; p<bc_shmem->pages_cnt; p++ ) { 56 24 : fd_txncache_txnpage_t const * page = &tc->txnpages[ bc->pages[ p ] ]; 57 24 : ulong txns_in_page = FD_TXNCACHE_TXNS_PER_PAGE - (ulong)page->free; 58 72 : for( ulong t=0UL; t<txns_in_page; t++ ) { 59 48 : fd_txncache_single_txn_t const * txn = page->txns[ t ]; 60 48 : if( FD_LIKELY( txncache_txn_on_snapshot_root( tc, snapshot_root_idx, txn ) ) ) cnt++; 61 48 : } 62 24 : } 63 24 : return cnt; 64 24 : } 65 : 66 : fd_txncache_writer_t * 67 : fd_txncache_writer_init( fd_txncache_writer_t * writer, 68 : fd_txncache_t * tc, 69 6 : ulong slot ) { 70 6 : fd_txncache_writer_tc_t const * ltc = (fd_txncache_writer_tc_t const *)tc; 71 6 : writer->state = STATE_INIT; 72 6 : writer->tc = tc; 73 6 : writer->slot = slot; 74 6 : writer->snapshot_root_idx = root_slist_is_empty( ltc->shmem->root_ll, ltc->blockcache_shmem_pool ) ? 75 6 : ULONG_MAX : 76 6 : root_slist_idx_peek_tail( ltc->shmem->root_ll, ltc->blockcache_shmem_pool ); 77 6 : writer->root_iter = root_slist_iter_init( ltc->shmem->root_ll, ltc->blockcache_shmem_pool ); 78 6 : writer->page_idx = 0UL; 79 6 : writer->txn_idx = 0UL; 80 6 : writer->txns_in_page = 0UL; 81 6 : return writer; 82 6 : } 83 : 84 : /* Size estimate */ 85 : 86 : #define ENCODE_FN static ulong txncache_estimate( fd_txncache_writer_t * enc ) 87 27 : #define PREP ulong sz = 0UL; 88 84 : #define PUSH_VAL(t,n) do { sz += sizeof(t); (void)(n); } while(0) 89 24 : #define RET_EXPR sz 90 : #include "fd_txncache_encoder.c" 91 : 92 : ulong 93 : fd_txncache_writer_serialized_sz( fd_txncache_t * tc, 94 3 : ulong slot ) { 95 3 : fd_txncache_writer_t writer[1]; 96 3 : fd_txncache_writer_init( writer, tc, slot ); 97 3 : ulong sz = 0UL; 98 27 : for(;;) { 99 27 : ulong chunk = txncache_estimate( writer ); 100 27 : if( FD_UNLIKELY( !chunk ) ) break; 101 24 : sz += chunk; 102 24 : } 103 3 : return sz; 104 3 : } 105 : 106 : /* Actual encoder */ 107 : 108 : __attribute__((cold,noreturn,unused)) 109 : static void fail( fd_txncache_writer_t const * enc, 110 : ulong buf_sz, 111 0 : ulong line_nr ) { 112 0 : FD_LOG_ERR(( "buffer overflow (state=%u, buf_sz=%lu, line_nr=%lu)", enc->state, buf_sz, line_nr )); 113 0 : } 114 : 115 : #define ENCODE_FN \ 116 : ulong \ 117 : fd_txncache_writer_serialize( fd_txncache_writer_t * enc, \ 118 : uchar out_buf[ FD_TXNCACHE_WRITER_BUF_MIN ], \ 119 : ulong buf_sz ) 120 : #define PREP \ 121 27 : uchar * p = out_buf; \ 122 27 : uchar * p1 __attribute__((unused)) = out_buf+buf_sz; 123 : #define PUSH_VAL( t, n ) \ 124 84 : FD_STORE( t, __extension__({ \ 125 84 : if( FD_UNLIKELY( p+sizeof(t) > p1 ) ) fail( enc, buf_sz, __LINE__ ); \ 126 84 : uchar * ret = p; \ 127 84 : p += sizeof(t); \ 128 84 : ret; \ 129 84 : }), (n) ) 130 24 : #define RET_EXPR (ulong)( p - out_buf ) 131 : #include "fd_txncache_encoder.c"