Line data Source code
1 : #include "fd_tower_lockos.h"
2 : #include "fd_tower.h"
3 :
4 : void *
5 : fd_tower_lockos_new( void * shmem,
6 : ulong slot_max,
7 : ulong vtr_max,
8 15 : ulong seed ) {
9 :
10 15 : if( FD_UNLIKELY( !shmem ) ) {
11 0 : FD_LOG_WARNING(( "NULL mem" ));
12 0 : return NULL;
13 0 : }
14 :
15 15 : ulong footprint = fd_tower_lockos_footprint( slot_max, vtr_max );
16 15 : if( FD_UNLIKELY( !footprint ) ) {
17 0 : FD_LOG_WARNING(( "bad slot_max (%lu)", slot_max ));
18 0 : return NULL;
19 0 : }
20 :
21 15 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_tower_lockos_align() ) ) ) {
22 0 : FD_LOG_WARNING(( "misaligned mem" ));
23 0 : return NULL;
24 0 : }
25 :
26 15 : ulong interval_max = fd_ulong_pow2_up( FD_TOWER_LOCKOS_MAX*slot_max*vtr_max );
27 :
28 15 : FD_SCRATCH_ALLOC_INIT( l, shmem );
29 15 : fd_tower_lockos_t * lockos = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_tower_lockos_t), sizeof(fd_tower_lockos_t) );
30 15 : void * slot_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_slot_pool_align(), fd_tower_lockos_slot_pool_footprint( interval_max ) );
31 15 : void * slot_map = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_slot_map_align(), fd_tower_lockos_slot_map_footprint ( slot_max ) );
32 15 : void * interval_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_interval_pool_align(), fd_tower_lockos_interval_pool_footprint( interval_max ) );
33 15 : void * interval_map = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_interval_map_align(), fd_tower_lockos_interval_map_footprint ( interval_max ) );
34 15 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_tower_lockos_align() )==(ulong)shmem + footprint );
35 :
36 15 : lockos->slot_pool = fd_tower_lockos_slot_pool_new ( slot_pool, interval_max );
37 15 : lockos->slot_map = fd_tower_lockos_slot_map_new ( slot_map, slot_max, seed );
38 15 : lockos->interval_pool = fd_tower_lockos_interval_pool_new( interval_pool, interval_max );
39 15 : lockos->interval_map = fd_tower_lockos_interval_map_new ( interval_map, interval_max, seed );
40 :
41 15 : FD_TEST( lockos->slot_map );
42 15 : FD_TEST( lockos->slot_pool );
43 15 : FD_TEST( lockos->interval_map );
44 15 : FD_TEST( lockos->interval_pool );
45 :
46 15 : return shmem;
47 15 : }
48 :
49 : fd_tower_lockos_t *
50 15 : fd_tower_lockos_join( void * shlockos ) {
51 :
52 15 : fd_tower_lockos_t * lockos = (fd_tower_lockos_t *)shlockos;
53 :
54 15 : if( FD_UNLIKELY( !lockos ) ) {
55 0 : FD_LOG_WARNING(( "NULL tower_lockos" ));
56 0 : return NULL;
57 0 : }
58 :
59 15 : if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)lockos, fd_tower_lockos_align() ) ) ) {
60 0 : FD_LOG_WARNING(( "misaligned tower_lockos" ));
61 0 : return NULL;
62 0 : }
63 :
64 15 : lockos->slot_map = fd_tower_lockos_slot_map_join ( lockos->slot_map );
65 15 : lockos->slot_pool = fd_tower_lockos_slot_pool_join ( lockos->slot_pool );
66 15 : lockos->interval_map = fd_tower_lockos_interval_map_join ( lockos->interval_map );
67 15 : lockos->interval_pool = fd_tower_lockos_interval_pool_join( lockos->interval_pool );
68 :
69 15 : FD_TEST( lockos->slot_map );
70 15 : FD_TEST( lockos->slot_pool );
71 15 : FD_TEST( lockos->interval_map );
72 15 : FD_TEST( lockos->interval_pool );
73 :
74 15 : return lockos;
75 15 : }
76 :
77 : void *
78 0 : fd_tower_lockos_leave( fd_tower_lockos_t const * lockos ) {
79 :
80 0 : if( FD_UNLIKELY( !lockos ) ) {
81 0 : FD_LOG_WARNING(( "NULL lockos" ));
82 0 : return NULL;
83 0 : }
84 :
85 0 : return (void *)lockos;
86 0 : }
87 :
88 : void *
89 0 : fd_tower_lockos_delete( void * lockos ) {
90 :
91 0 : if( FD_UNLIKELY( !lockos ) ) {
92 0 : FD_LOG_WARNING(( "NULL lockos" ));
93 0 : return NULL;
94 0 : }
95 :
96 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)lockos, fd_tower_lockos_align() ) ) ) {
97 0 : FD_LOG_WARNING(( "misaligned lockos" ));
98 0 : return NULL;
99 0 : }
100 :
101 0 : return lockos;
102 0 : }
103 :
104 : void
105 : fd_tower_lockos_insert( fd_tower_lockos_t * lockos,
106 : ulong slot,
107 : fd_hash_t const * addr,
108 138 : fd_tower_voters_t * voters ) {
109 :
110 138 : for( fd_tower_iter_t iter = fd_tower_iter_init( voters->tower );
111 276 : !fd_tower_iter_done( voters->tower, iter );
112 138 : iter = fd_tower_iter_next( voters->tower, iter ) ) {
113 138 : fd_tower_vote_t const * vote = fd_tower_iter_ele_const( voters->tower, iter );
114 138 : ulong interval_start = vote->slot;
115 138 : ulong interval_end = vote->slot + ( 1UL << vote->conf );
116 138 : ulong key = fd_tower_lockos_interval_key( slot, interval_end );
117 :
118 138 : if( !fd_tower_lockos_interval_map_ele_query( lockos->interval_map, &key, NULL, lockos->interval_pool ) ) {
119 129 : FD_TEST( fd_tower_lockos_slot_pool_free( lockos->slot_pool ) ); /* [slot, interval_end] is a new vote interval. guaranteed to have space because we size slot pool to max voters * max slots. */
120 129 : fd_tower_lockos_slot_t * slot_ele = fd_tower_lockos_slot_pool_ele_acquire( lockos->slot_pool );
121 129 : slot_ele->fork_slot = slot; /* map multi, multiple keys for the same fork_slot */
122 129 : slot_ele->interval_end = interval_end;
123 129 : FD_TEST( fd_tower_lockos_slot_map_ele_insert( lockos->slot_map, slot_ele, lockos->slot_pool ) );
124 129 : }
125 :
126 138 : FD_TEST( fd_tower_lockos_interval_pool_free( lockos->interval_pool ) );
127 138 : fd_tower_lockos_interval_t * interval = fd_tower_lockos_interval_pool_ele_acquire( lockos->interval_pool );
128 138 : interval->key = key;
129 138 : interval->addr = *addr;
130 138 : interval->start = interval_start;
131 138 : FD_TEST( fd_tower_lockos_interval_map_ele_insert( lockos->interval_map, interval, lockos->interval_pool ) );
132 138 : }
133 138 : }
134 :
135 : void
136 : fd_tower_lockos_remove( fd_tower_lockos_t * lockos,
137 12 : ulong slot ) {
138 :
139 12 : for( fd_tower_lockos_slot_t * sloti = fd_tower_lockos_slot_map_ele_remove( lockos->slot_map, &slot, NULL, lockos->slot_pool );
140 114 : sloti;
141 102 : sloti = fd_tower_lockos_slot_map_ele_remove( lockos->slot_map, &slot, NULL, lockos->slot_pool ) ) {
142 102 : ulong key = fd_tower_lockos_interval_key( slot, sloti->interval_end );
143 102 : for( fd_tower_lockos_interval_t * itrvl = fd_tower_lockos_interval_map_ele_remove( lockos->interval_map, &key, NULL, lockos->interval_pool );
144 204 : itrvl;
145 102 : itrvl = fd_tower_lockos_interval_map_ele_remove( lockos->interval_map, &key, NULL, lockos->interval_pool ) ) {
146 102 : fd_tower_lockos_interval_pool_ele_release( lockos->interval_pool, itrvl );
147 102 : }
148 102 : fd_tower_lockos_slot_pool_ele_release( lockos->slot_pool, sloti );
149 102 : }
150 12 : }
|