Line data Source code
1 : #include "fd_tower_leaves.h"
2 : #include "fd_tower.h"
3 :
4 : void *
5 : fd_tower_leaves_new( void * shmem,
6 : ulong slot_max,
7 0 : ulong seed ) {
8 :
9 0 : if( FD_UNLIKELY( !shmem ) ) {
10 0 : FD_LOG_WARNING(( "NULL mem" ));
11 0 : return NULL;
12 0 : }
13 :
14 0 : ulong footprint = fd_tower_leaves_footprint( slot_max );
15 0 : if( FD_UNLIKELY( !footprint ) ) {
16 0 : FD_LOG_WARNING(( "bad slot_max (%lu)", slot_max ));
17 0 : return NULL;
18 0 : }
19 :
20 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_tower_leaves_align() ) ) ) {
21 0 : FD_LOG_WARNING(( "misaligned mem" ));
22 0 : return NULL;
23 0 : }
24 :
25 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
26 0 : fd_tower_leaves_t * leaves = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_leaves_align(), sizeof(fd_tower_leaves_t) );
27 0 : void * map = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_leaves_map_align(), fd_tower_leaves_map_footprint ( slot_max ) );
28 0 : void * dlist = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_leaves_dlist_align(), fd_tower_leaves_dlist_footprint() );
29 0 : void * pool = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_leaves_pool_align(), fd_tower_leaves_pool_footprint( slot_max ) );
30 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_tower_leaves_align() ) == (ulong)shmem + footprint );
31 :
32 0 : leaves->map = fd_tower_leaves_map_new ( map, slot_max, seed );
33 0 : leaves->pool = fd_tower_leaves_pool_new ( pool, slot_max );
34 0 : leaves->dlist = fd_tower_leaves_dlist_new( dlist );
35 :
36 0 : FD_TEST( leaves->map );
37 0 : FD_TEST( leaves->pool );
38 0 : FD_TEST( leaves->dlist );
39 :
40 0 : return shmem;
41 0 : }
42 :
43 : fd_tower_leaves_t *
44 0 : fd_tower_leaves_join( void * shleaves ) {
45 0 : fd_tower_leaves_t * leaves = (fd_tower_leaves_t *)shleaves;
46 :
47 0 : if( FD_UNLIKELY( !leaves ) ) {
48 0 : FD_LOG_WARNING(( "NULL tower_leaves" ));
49 0 : return NULL;
50 0 : }
51 :
52 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)leaves, fd_tower_leaves_align() ) ) ) {
53 0 : FD_LOG_WARNING(( "misaligned tower_leaves" ));
54 0 : return NULL;
55 0 : }
56 :
57 0 : leaves->pool = fd_tower_leaves_pool_join ( leaves->pool );
58 0 : leaves->map = fd_tower_leaves_map_join ( leaves->map );
59 0 : leaves->dlist = fd_tower_leaves_dlist_join( leaves->dlist );
60 :
61 0 : return leaves;
62 0 : }
63 :
64 : void *
65 0 : fd_tower_leaves_leave( fd_tower_leaves_t const * leaves ) {
66 :
67 0 : if( FD_UNLIKELY( !leaves ) ) {
68 0 : FD_LOG_WARNING(( "NULL leaves" ));
69 0 : return NULL;
70 0 : }
71 :
72 0 : return (void *)leaves;
73 0 : }
74 :
75 : void *
76 0 : fd_tower_leaves_delete( void * leaves ) {
77 :
78 0 : if( FD_UNLIKELY( !leaves ) ) {
79 0 : FD_LOG_WARNING(( "NULL leaves" ));
80 0 : return NULL;
81 0 : }
82 :
83 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)leaves, fd_tower_leaves_align() ) ) ) {
84 0 : FD_LOG_WARNING(( "misaligned leaves" ));
85 0 : return NULL;
86 0 : }
87 :
88 0 : return leaves;
89 0 : }
90 :
91 : void
92 : fd_tower_leaves_upsert( fd_tower_leaves_t * leaves,
93 : ulong slot,
94 0 : ulong parent_slot ) {
95 :
96 0 : fd_tower_leaf_t * parent = fd_tower_leaves_map_ele_remove( leaves->map, &parent_slot, NULL, leaves->pool );
97 0 : if( ( FD_LIKELY( parent ) ) ) { /* optimize for one fork */
98 0 : fd_tower_leaves_dlist_ele_remove( leaves->dlist, parent, leaves->pool );
99 0 : fd_tower_leaves_pool_ele_release( leaves->pool, parent );
100 0 : }
101 0 : if( FD_UNLIKELY( fd_tower_leaves_map_ele_query( leaves->map, &slot, NULL, leaves->pool ) ) ) {
102 0 : FD_LOG_WARNING(( "[%s] slot %lu already in leaves. ignoring.", __func__, slot )); /* FIXME equivocation cases https://github.com/firedancer-io/firedancer/issues/8743 */
103 0 : }
104 0 : fd_tower_leaf_t * leaf = fd_tower_leaves_pool_ele_acquire( leaves->pool );
105 0 : leaf->slot = slot;
106 0 : fd_tower_leaves_map_ele_insert( leaves->map, leaf, leaves->pool );
107 0 : fd_tower_leaves_dlist_ele_push_tail( leaves->dlist, leaf, leaves->pool );
108 0 : }
109 :
110 : void
111 : fd_tower_leaves_remove( fd_tower_leaves_t * leaves,
112 0 : ulong slot ) {
113 :
114 0 : fd_tower_leaf_t * leaf = fd_tower_leaves_map_ele_remove( leaves->map, &slot, NULL, leaves->pool );
115 0 : if( FD_UNLIKELY( leaf ) ) {
116 0 : fd_tower_leaves_dlist_ele_remove( leaves->dlist, leaf, leaves->pool );
117 0 : fd_tower_leaves_pool_ele_release( leaves->pool, leaf );
118 0 : }
119 0 : }
|