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 0 : ulong seed ) {
9 :
10 0 : if( FD_UNLIKELY( !shmem ) ) {
11 0 : FD_LOG_WARNING(( "NULL mem" ));
12 0 : return NULL;
13 0 : }
14 :
15 0 : ulong footprint = fd_tower_lockos_footprint( slot_max, vtr_max );
16 0 : if( FD_UNLIKELY( !footprint ) ) {
17 0 : FD_LOG_WARNING(( "bad slot_max (%lu)", slot_max ));
18 0 : return NULL;
19 0 : }
20 :
21 0 : 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 0 : ulong interval_max = fd_ulong_pow2_up( FD_TOWER_LOCKOS_MAX*slot_max*vtr_max );
27 :
28 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
29 0 : fd_tower_lockos_t * lockos = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_tower_lockos_t), sizeof(fd_tower_lockos_t) );
30 0 : void * slot_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_slot_pool_align(), fd_tower_lockos_slot_pool_footprint( interval_max ) );
31 0 : void * slot_map = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_slot_map_align(), fd_tower_lockos_slot_map_footprint ( slot_max ) );
32 0 : void * interval_pool = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_interval_pool_align(), fd_tower_lockos_interval_pool_footprint( interval_max ) );
33 0 : void * interval_map = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_lockos_interval_map_align(), fd_tower_lockos_interval_map_footprint ( interval_max ) );
34 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_tower_lockos_align() )==(ulong)shmem + footprint );
35 :
36 0 : lockos->slot_pool = fd_tower_lockos_slot_pool_new ( slot_pool, interval_max );
37 0 : lockos->slot_map = fd_tower_lockos_slot_map_new ( slot_map, slot_max, seed );
38 0 : lockos->interval_pool = fd_tower_lockos_interval_pool_new( interval_pool, interval_max );
39 0 : lockos->interval_map = fd_tower_lockos_interval_map_new ( interval_map, interval_max, seed );
40 :
41 0 : FD_TEST( lockos->slot_map );
42 0 : FD_TEST( lockos->slot_pool );
43 0 : FD_TEST( lockos->interval_map );
44 0 : FD_TEST( lockos->interval_pool );
45 :
46 0 : return shmem;
47 0 : }
48 :
49 : fd_tower_lockos_t *
50 0 : fd_tower_lockos_join( void * shlockos ) {
51 :
52 0 : fd_tower_lockos_t * lockos = (fd_tower_lockos_t *)shlockos;
53 :
54 0 : if( FD_UNLIKELY( !lockos ) ) {
55 0 : FD_LOG_WARNING(( "NULL tower_lockos" ));
56 0 : return NULL;
57 0 : }
58 :
59 0 : 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 0 : lockos->slot_map = fd_tower_lockos_slot_map_join ( lockos->slot_map );
65 0 : lockos->slot_pool = fd_tower_lockos_slot_pool_join ( lockos->slot_pool );
66 0 : lockos->interval_map = fd_tower_lockos_interval_map_join ( lockos->interval_map );
67 0 : lockos->interval_pool = fd_tower_lockos_interval_pool_join( lockos->interval_pool );
68 :
69 0 : FD_TEST( lockos->slot_map );
70 0 : FD_TEST( lockos->slot_pool );
71 0 : FD_TEST( lockos->interval_map );
72 0 : FD_TEST( lockos->interval_pool );
73 :
74 0 : return lockos;
75 0 : }
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 0 : fd_tower_voters_t * voters ) {
109 :
110 0 : uchar __attribute__((aligned(FD_TOWER_ALIGN))) scratch[ FD_TOWER_FOOTPRINT ];
111 0 : fd_tower_t * scratch_tower = fd_tower_join( fd_tower_new( scratch ) );
112 :
113 0 : fd_tower_from_vote_acc( scratch_tower, voters->data );
114 :
115 0 : for( fd_tower_iter_t iter = fd_tower_iter_init( scratch_tower );
116 0 : !fd_tower_iter_done( scratch_tower, iter );
117 0 : iter = fd_tower_iter_next( scratch_tower, iter ) ) {
118 0 : fd_tower_t * vote = fd_tower_iter_ele( scratch_tower, iter );
119 0 : ulong interval_start = vote->slot;
120 0 : ulong interval_end = vote->slot + ( 1UL << vote->conf );
121 0 : ulong key = fd_tower_lockos_interval_key( slot, interval_end );
122 :
123 0 : if( !fd_tower_lockos_interval_map_ele_query( lockos->interval_map, &key, NULL, lockos->interval_pool ) ) {
124 0 : 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. */
125 0 : fd_tower_lockos_slot_t * slot_ele = fd_tower_lockos_slot_pool_ele_acquire( lockos->slot_pool );
126 0 : slot_ele->fork_slot = slot; /* map multi, multiple keys for the same fork_slot */
127 0 : slot_ele->interval_end = interval_end;
128 0 : FD_TEST( fd_tower_lockos_slot_map_ele_insert( lockos->slot_map, slot_ele, lockos->slot_pool ) );
129 0 : }
130 :
131 0 : FD_TEST( fd_tower_lockos_interval_pool_free( lockos->interval_pool ) );
132 0 : fd_tower_lockos_interval_t * interval = fd_tower_lockos_interval_pool_ele_acquire( lockos->interval_pool );
133 0 : interval->key = key;
134 0 : interval->addr = *addr;
135 0 : interval->start = interval_start;
136 0 : FD_TEST( fd_tower_lockos_interval_map_ele_insert( lockos->interval_map, interval, lockos->interval_pool ) );
137 0 : }
138 0 : }
139 :
140 : void
141 : fd_tower_lockos_remove( fd_tower_lockos_t * lockos,
142 0 : ulong slot ) {
143 :
144 0 : for( fd_tower_lockos_slot_t * sloti = fd_tower_lockos_slot_map_ele_remove( lockos->slot_map, &slot, NULL, lockos->slot_pool );
145 0 : sloti;
146 0 : sloti = fd_tower_lockos_slot_map_ele_remove( lockos->slot_map, &slot, NULL, lockos->slot_pool ) ) {
147 0 : ulong key = fd_tower_lockos_interval_key( slot, sloti->interval_end );
148 0 : for( fd_tower_lockos_interval_t * itrvl = fd_tower_lockos_interval_map_ele_remove( lockos->interval_map, &key, NULL, lockos->interval_pool );
149 0 : itrvl;
150 0 : itrvl = fd_tower_lockos_interval_map_ele_remove( lockos->interval_map, &key, NULL, lockos->interval_pool ) ) {
151 0 : fd_tower_lockos_interval_pool_ele_release( lockos->interval_pool, itrvl );
152 0 : }
153 0 : fd_tower_lockos_slot_pool_ele_release( lockos->slot_pool, sloti );
154 0 : }
155 0 : }
|