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 31839855 : fd_wksp_t * wksp /* Assumes wksp == fd_funk_wksp( funk ) */) {
6 31839855 : return (fd_funk_partvec_t *)fd_wksp_laddr_fast( wksp, funk->partvec_gaddr );
7 31839855 : }
8 :
9 : void
10 36999750 : fd_funk_part_init( fd_funk_rec_t * rec ) {
11 36999750 : rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
12 36999750 : rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
13 36999750 : rec->part = FD_FUNK_PART_NULL;
14 36999750 : }
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 2643486 : uint part) {
22 2643486 : if ( FD_UNLIKELY( part >= partvec->num_part ) )
23 0 : return FD_FUNK_ERR_INVAL;
24 :
25 2643486 : fd_funk_parthead_t * head = &partvec->heads[part];
26 :
27 2643486 : ulong prev_idx = rec->prev_part_idx;
28 2643486 : ulong next_idx = rec->next_part_idx;
29 :
30 2643486 : int prev_null = fd_funk_rec_idx_is_null( prev_idx );
31 2643486 : int next_null = fd_funk_rec_idx_is_null( next_idx );
32 :
33 2643486 : if( prev_null ) head->head_idx = next_idx;
34 1193763 : else rec_map[ prev_idx ].next_part_idx = next_idx;
35 :
36 2643486 : if( next_null ) head->tail_idx = prev_idx;
37 977226 : else rec_map[ next_idx ].prev_part_idx = prev_idx;
38 :
39 2643486 : rec->prev_part_idx = FD_FUNK_REC_IDX_NULL;
40 2643486 : rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
41 2643486 : rec->part = FD_FUNK_PART_NULL;
42 2643486 : return FD_FUNK_SUCCESS;
43 2643486 : }
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 17648316 : uint part) {
51 17648316 : if ( FD_UNLIKELY( part >= partvec->num_part ) )
52 0 : return FD_FUNK_ERR_INVAL;
53 :
54 17648316 : fd_funk_parthead_t * head = &partvec->heads[part];
55 :
56 17648316 : ulong rec_idx = (ulong)(rec - rec_map);
57 17648316 : ulong old_tail_idx = head->tail_idx;
58 17648316 : rec->prev_part_idx = old_tail_idx;
59 17648316 : head->tail_idx = rec_idx;
60 :
61 17648316 : rec->next_part_idx = FD_FUNK_REC_IDX_NULL;
62 :
63 17648316 : if ( fd_funk_rec_idx_is_null( old_tail_idx ) ) head->head_idx = rec_idx;
64 8109405 : else rec_map[old_tail_idx].next_part_idx = rec_idx;
65 :
66 17648316 : rec->part = part;
67 17648316 : return FD_FUNK_SUCCESS;
68 17648316 : }
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 12092778 : uint part) {
75 12092778 : if (part == rec->part) return FD_FUNK_SUCCESS;
76 3689325 : if ((rec->flags & FD_FUNK_REC_FLAG_ERASE)) return FD_FUNK_ERR_INVAL;
77 :
78 3689325 : int err;
79 3689325 : if (rec->part != FD_FUNK_PART_NULL) {
80 2643486 : err = fd_funk_part_remove( partvec, rec_map, rec, rec->part );
81 2643486 : if ( FD_UNLIKELY( err ) ) return err;
82 2643486 : }
83 :
84 3689325 : if (part != FD_FUNK_PART_NULL) {
85 1601154 : err = fd_funk_part_add( partvec, rec_map, rec, part );
86 1601154 : if ( FD_UNLIKELY( err ) ) return err;
87 1601154 : }
88 :
89 3689325 : return FD_FUNK_SUCCESS;
90 3689325 : }
91 :
92 : int
93 : fd_funk_part_set( fd_funk_t * funk,
94 : fd_funk_rec_t * rec,
95 2101938 : uint part) {
96 2101938 : fd_wksp_t * wksp = fd_funk_wksp( funk );
97 2101938 : return fd_funk_part_set_intern( fd_funk_get_partvec(funk, wksp),
98 2101938 : fd_funk_rec_map(funk, wksp),
99 2101938 : rec,
100 2101938 : part );
101 2101938 : }
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 : }
121 1569129 : partvec->num_part = num_part;
122 1569129 : funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
123 :
124 14122161 : for ( uint i = 0; i < num_part; ++i )
125 12553032 : partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
126 :
127 1569129 : for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
128 30712500 : !fd_funk_rec_map_iter_done( rec_map, iter );
129 29143371 : iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
130 29143371 : fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
131 29143371 : fd_funk_part_init( rec );
132 29143371 : }
133 :
134 1569129 : for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
135 30712500 : !fd_funk_rec_map_iter_done( rec_map, iter );
136 29143371 : iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
137 29143371 : fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
138 29143371 : if ( !(rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
139 20060841 : uint part = (*cb)(rec, num_part, cb_arg);
140 20060841 : if (part != FD_FUNK_PART_NULL) {
141 16047162 : int err = fd_funk_part_add( partvec, rec_map, rec, part );
142 16047162 : if ( FD_UNLIKELY( err ) ) FD_LOG_WARNING(( "error during repartition: %d", err ));
143 16047162 : }
144 20060841 : }
145 29143371 : }
146 1569129 : }
147 :
148 : void
149 3 : fd_funk_set_num_partitions( fd_funk_t * funk, uint num_part ) {
150 3 : fd_wksp_t * wksp = fd_funk_wksp( funk );
151 3 : fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
152 3 : fd_alloc_t * alloc = fd_funk_alloc( funk, wksp );
153 :
154 : /* Already have the desired number of partitions */
155 3 : if ( partvec->num_part == num_part ) {
156 0 : return;
157 0 : }
158 :
159 : /* Rebuild the header vector */
160 3 : fd_alloc_free( alloc, partvec );
161 :
162 3 : ulong tmp_max;
163 3 : partvec = (fd_funk_partvec_t *)fd_alloc_malloc_at_least( alloc, fd_funk_partvec_align(), fd_funk_partvec_footprint(num_part), &tmp_max );
164 3 : if( FD_UNLIKELY( !partvec ) ) {
165 0 : FD_LOG_ERR(( "partvec alloc failed" ));
166 0 : return;
167 0 : }
168 3 : partvec->num_part = num_part;
169 3 : funk->partvec_gaddr = fd_wksp_gaddr_fast( wksp, partvec );
170 :
171 27 : for ( uint i = 0; i < num_part; ++i ) {
172 24 : partvec->heads[i].head_idx = partvec->heads[i].tail_idx = FD_FUNK_REC_IDX_NULL;
173 24 : }
174 3 : }
175 :
176 : int
177 22275108 : fd_funk_part_verify( fd_funk_t * funk ) {
178 22275108 : fd_wksp_t * wksp = fd_funk_wksp( funk );
179 22275108 : fd_funk_partvec_t * partvec = fd_funk_get_partvec( funk, wksp );
180 22275108 : fd_funk_rec_t * rec_map = fd_funk_rec_map( funk, wksp );
181 :
182 22275108 : ulong cnt = 0;
183 124978404 : for ( uint i = 0; i < partvec->num_part; ++i ) {
184 102703296 : ulong prev = FD_FUNK_REC_IDX_NULL;
185 102703296 : ulong cur = partvec->heads[i].head_idx;
186 222981366 : while ( !fd_funk_rec_idx_is_null(cur) ) {
187 120278070 : fd_funk_rec_t * rec = rec_map + cur;
188 120278070 : if ( fd_funk_rec_map_private_unbox_tag( rec->map_next ) || (rec->flags & FD_FUNK_REC_FLAG_ERASE) ) {
189 0 : FD_LOG_WARNING(( "partition contains deleted record" ));
190 0 : return FD_FUNK_ERR_INVAL;
191 0 : }
192 120278070 : if ( rec->prev_part_idx != prev ) {
193 0 : FD_LOG_WARNING(( "prev_part_idx is wrong" ));
194 0 : return FD_FUNK_ERR_INVAL;
195 0 : }
196 120278070 : if ( rec->part != i ) {
197 0 : FD_LOG_WARNING(( "part is wrong" ));
198 0 : return FD_FUNK_ERR_INVAL;
199 0 : }
200 120278070 : prev = cur;
201 120278070 : cur = rec->next_part_idx;
202 120278070 : ++cnt;
203 120278070 : }
204 102703296 : if ( partvec->heads[i].tail_idx != prev ) {
205 0 : FD_LOG_WARNING(( "tail_idx is wrong" ));
206 0 : return FD_FUNK_ERR_INVAL;
207 0 : }
208 102703296 : }
209 :
210 22275108 : ulong cnt2 = 0;
211 22275108 : for( fd_funk_rec_map_iter_t iter = fd_funk_rec_map_iter_init( rec_map );
212 903401892 : !fd_funk_rec_map_iter_done( rec_map, iter );
213 881126784 : iter = fd_funk_rec_map_iter_next( rec_map, iter ) ) {
214 881126784 : fd_funk_rec_t * rec = fd_funk_rec_map_iter_ele( rec_map, iter );
215 881126784 : if (rec->part != FD_FUNK_PART_NULL)
216 120278070 : ++cnt2;
217 881126784 : }
218 22275108 : if ( cnt != cnt2 ) {
219 0 : FD_LOG_WARNING(( "part is wrong for some records" ));
220 0 : return FD_FUNK_ERR_INVAL;
221 0 : }
222 :
223 22275108 : return FD_FUNK_SUCCESS;
224 22275108 : }
|