Line data Source code
1 : #include "fd_funk.h"
2 :
3 : fd_funk_partvec_t *
4 : fd_funk_get_partvec( fd_funk_t * funk,
5 30100329 : fd_wksp_t * wksp /* Assumes wksp == fd_funk_wksp( funk ) */) {
6 30100329 : return (fd_funk_partvec_t *)fd_wksp_laddr_fast( wksp, funk->partvec_gaddr );
7 30100329 : }
8 :
9 : void
10 27248220 : fd_funk_part_init( fd_funk_rec_t * rec ) {
11 27248220 : rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
12 27248220 : rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
13 27248220 : rec->part = FD_FUNK_PART_NULL;
14 27248220 : }
15 :
16 : /* Private function */
17 : static int
18 : fd_funk_part_remove( fd_funk_partvec_t * partvec,
19 : fd_funk_rec_t * rec_map,
20 : fd_funk_rec_t * rec,
21 3119028 : uint part) {
22 3119028 : if ( FD_UNLIKELY( part >= partvec->num_part ) )
23 0 : return FD_FUNK_ERR_INVAL;
24 :
25 3119028 : fd_funk_parthead_t * head = &partvec->heads[part];
26 :
27 3119028 : ulong prev_idx = rec->prev_part_idx;
28 3119028 : ulong next_idx = rec->next_part_idx;
29 :
30 3119028 : int prev_null = fd_funk_rec_idx_is_null( prev_idx );
31 3119028 : int next_null = fd_funk_rec_idx_is_null( next_idx );
32 :
33 3119028 : if( prev_null ) head->head_idx = next_idx;
34 1383198 : else rec_map[ prev_idx ].next_part_idx = next_idx;
35 :
36 3119028 : if( next_null ) head->tail_idx = prev_idx;
37 1201635 : else rec_map[ next_idx ].prev_part_idx = prev_idx;
38 :
39 3119028 : rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
40 3119028 : rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
41 3119028 : rec->part = FD_FUNK_PART_NULL;
42 3119028 : return FD_FUNK_SUCCESS;
43 3119028 : }
44 :
45 : /* Private function */
46 : static int
47 : fd_funk_part_add( fd_funk_partvec_t * partvec,
48 : fd_funk_rec_t * rec_map,
49 : fd_funk_rec_t * rec,
50 18127206 : uint part) {
51 18127206 : if ( FD_UNLIKELY( part >= partvec->num_part ) )
52 0 : return FD_FUNK_ERR_INVAL;
53 :
54 18127206 : fd_funk_parthead_t * head = &partvec->heads[part];
55 :
56 18127206 : ulong rec_idx = (ulong)(rec - rec_map);
57 18127206 : ulong old_tail_idx = head->tail_idx;
58 18127206 : rec->prev_part_idx = old_tail_idx;
59 18127206 : head->tail_idx = rec_idx;
60 :
61 18127206 : rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
62 :
63 18127206 : if ( fd_funk_rec_idx_is_null( old_tail_idx ) ) head->head_idx = rec_idx;
64 8453760 : else rec_map[old_tail_idx].next_part_idx = rec_idx;
65 :
66 18127206 : rec->part = part;
67 18127206 : return FD_FUNK_SUCCESS;
68 18127206 : }
69 :
70 : int
71 : fd_funk_part_set_intern( fd_funk_partvec_t * partvec,
72 : fd_funk_rec_t * rec_map,
73 : fd_funk_rec_t * rec,
74 10283355 : uint part) {
75 10283355 : if (part == rec->part) return FD_FUNK_SUCCESS;
76 4349430 : if ((rec->flags & FD_FUNK_REC_FLAG_ERASE)) return FD_FUNK_ERR_INVAL;
77 :
78 4349430 : int err;
79 4349430 : if (rec->part != FD_FUNK_PART_NULL) {
80 3119028 : err = fd_funk_part_remove( partvec, rec_map, rec, rec->part );
81 3119028 : if ( FD_UNLIKELY( err ) ) return err;
82 3119028 : }
83 :
84 4349430 : if (part != FD_FUNK_PART_NULL) {
85 2080044 : err = fd_funk_part_add( partvec, rec_map, rec, part );
86 2080044 : if ( FD_UNLIKELY( err ) ) return err;
87 2080044 : }
88 :
89 4349430 : return FD_FUNK_SUCCESS;
90 4349430 : }
91 :
92 : int
93 : fd_funk_part_set( fd_funk_t * funk,
94 : fd_funk_rec_t * rec,
95 2107938 : uint part) {
96 2107938 : fd_wksp_t * wksp = fd_funk_wksp( funk );
97 2107938 : return fd_funk_part_set_intern( fd_funk_get_partvec(funk, wksp),
98 2107938 : fd_funk_rec_map(funk, wksp),
99 2107938 : rec,
100 2107938 : part );
101 2107938 : }
102 :
103 : void
104 : fd_funk_repartition(fd_funk_t * funk,
105 : uint num_part,
106 : fd_funk_repartition_cb cb,
107 1569129 : void * cb_arg) {
108 1569129 : fd_wksp_t * wksp = fd_funk_wksp( funk );
109 1569129 : fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
110 1569129 : fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
111 1569129 : fd_alloc_t * alloc = fd_funk_alloc( funk, wksp );
112 :
113 : /* Rebuild the header vector */
114 1569129 : fd_alloc_free( alloc, partvec );
115 :
116 1569129 : ulong tmp_max;
117 1569129 : partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(num_part), &tmp_max );
118 1569129 : if( FD_UNLIKELY( !partvec ) ) {
119 0 : FD_LOG_ERR(( "partvec alloc failed" ));
120 0 : return;
121 0 : }
122 1569129 : partvec->num_part = num_part;
123 1569129 : funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
124 :
125 14122161 : for ( uint i = 0; i < num_part; ++i )
126 12553032 : partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
127 :
128 1569129 : for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
129 22338834 : !fd_funk_rec_map_iter_done( rec_map, iter );
130 20769705 : iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
131 20769705 : fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
132 20769705 : fd_funk_part_init( rec );
133 20769705 : }
134 :
135 1569129 : for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
136 22338834 : !fd_funk_rec_map_iter_done( rec_map, iter );
137 20769705 : iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
138 20769705 : fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
139 20769705 : if ( !(rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
140 20060841 : uint part = (*cb)(rec, num_part, cb_arg);
141 20060841 : if (part != FD_FUNK_PART_NULL) {
142 16047162 : int err = fd_funk_part_add( partvec, rec_map, rec, part );
143 16047162 : if ( FD_UNLIKELY( err ) ) FD_LOG_WARNING(( "error during repartition: %d", err ));
144 16047162 : }
145 20060841 : }
146 20769705 : }
147 1569129 : }
148 :
149 : void
150 306 : fd_funk_set_num_partitions( fd_funk_t * funk, uint num_part ) {
151 306 : fd_wksp_t * wksp = fd_funk_wksp( funk );
152 306 : fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
153 306 : fd_alloc_t * alloc = fd_funk_alloc( funk, wksp );
154 :
155 : /* Already have the desired number of partitions */
156 306 : if ( partvec->num_part == num_part ) {
157 0 : return;
158 0 : }
159 :
160 : /* Rebuild the header vector */
161 306 : fd_alloc_free( alloc, partvec );
162 :
163 306 : ulong tmp_max;
164 306 : partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(num_part), &tmp_max );
165 306 : if( FD_UNLIKELY( !partvec ) ) {
166 0 : FD_LOG_ERR(( "partvec alloc failed" ));
167 0 : return;
168 0 : }
169 306 : partvec->num_part = num_part;
170 306 : funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
171 :
172 2754 : for ( uint i = 0; i < num_part; ++i ) {
173 2448 : partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
174 2448 : }
175 306 : }
176 :
177 : int
178 22026408 : fd_funk_part_verify( fd_funk_t * funk ) {
179 22026408 : fd_wksp_t * wksp = fd_funk_wksp( funk );
180 22026408 : fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
181 22026408 : fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
182 :
183 22026408 : ulong cnt = 0;
184 122740104 : for ( uint i = 0; i < partvec->num_part; ++i ) {
185 100713696 : ulong prev = FD_FUNK_REC_IDX_NULL;
186 100713696 : ulong cur = partvec->heads[i].head_idx;
187 220989045 : while ( !fd_funk_rec_idx_is_null(cur) ) {
188 120275349 : fd_funk_rec_t * rec = rec_map + cur;
189 120275349 : if ( fd_funk_rec_map_private_unbox_tag( rec->map_next ) || (rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
190 0 : FD_LOG_WARNING(( "partition contains deleted record" ));
191 0 : return FD_FUNK_ERR_INVAL;
192 0 : }
193 120275349 : if ( rec->prev_part_idx != prev ) {
194 0 : FD_LOG_WARNING(( "prev_part_idx is wrong" ));
195 0 : return FD_FUNK_ERR_INVAL;
196 0 : }
197 120275349 : if ( rec->part != i ) {
198 0 : FD_LOG_WARNING(( "part is wrong" ));
199 0 : return FD_FUNK_ERR_INVAL;
200 0 : }
201 120275349 : prev = cur;
202 120275349 : cur = rec->next_part_idx;
203 120275349 : ++cnt;
204 120275349 : }
205 100713696 : if ( partvec->heads[i].tail_idx != prev ) {
206 0 : FD_LOG_WARNING(( "tail_idx is wrong" ));
207 0 : return FD_FUNK_ERR_INVAL;
208 0 : }
209 100713696 : }
210 :
211 22026408 : ulong cnt2 = 0;
212 22026408 : for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
213 606388173 : !fd_funk_rec_map_iter_done( rec_map, iter );
214 584361765 : iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
215 584361765 : fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
216 584361765 : if (rec->part != FD_FUNK_PART_NULL)
217 120275349 : ++cnt2;
218 584361765 : }
219 22026408 : if ( cnt != cnt2 ) {
220 0 : FD_LOG_WARNING(( "part is wrong for some records" ));
221 0 : return FD_FUNK_ERR_INVAL;
222 0 : }
223 :
224 22026408 : return FD_FUNK_SUCCESS;
225 22026408 : }
|