Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_accdb_fd_vinyl_req_pool_h
2 : #define HEADER_fd_src_flamenco_accdb_fd_vinyl_req_pool_h
3 :
4 : /* fd_vinyl_req_pool.h provides a simple allocation policy for vinyl
5 : request metadata, and a shared memory persistent object class for
6 : convenience.
7 :
8 : This exists because metadata is not stored in-line with the shared
9 : memory request queue. Instead, the request queue holds pointers to
10 : request batches stored in another shared memory workspace.
11 :
12 : ┌───────────────┐ ┌────────────────┐ ┌───────────────┐
13 : │ vinyl_rq │ │ vinyl_req_pool │ │ vinyl_data │
14 : ├───────────────┤ ├────────────────┤ │ │
15 : │ │ │ │ ┌──┼►┌───────────┐ │
16 : │ request batch │ │ │ │ │ │ account │ │
17 : │ │ │ │ │ │ │ data │ │
18 : │ request batch ┼─┬──┼► key 0 │ │ │ │ │ │
19 : │ ... │ │ │ key 1 │ │ │ │ │ │
20 : └───────────────┘ │ │ key ... │ │ │ └───────────┘ │
21 : │ │ │ │ │ │
22 : └──┼► val_gaddr 0 ──┼─┘ │ │
23 : │ val_gaddr 1 ──┼─┐ │ │
24 : │ val_gaddr ... │ └──┼►┌───────────┐ │
25 : │ │ │ │ account │ │
26 : │ │ │ │ data │ │
27 : │ │ │ └───────────┘ │
28 : └────────────────┘ └───────────────┘
29 :
30 : The above figure illustrates the relationship between vinyl_rq and
31 : record data values. Note that the vinyl tile need not be aware of
32 : the vinyl_req_pool allocator. */
33 :
34 : #include "../../vinyl/rq/fd_vinyl_rq.h"
35 : #include "../../vinyl/cq/fd_vinyl_cq.h"
36 :
37 : /* fd_vinyl_req_pool_t stores request metadata batches.
38 :
39 : It is sized by two parameters: batch_max, the max number of request
40 : batches. And batch_key_max, the max number of keys in each request
41 : batch.
42 :
43 : Should not be declared locally (construct via fd_vinyl_req_pool_new).
44 :
45 : The req_pool itself is not safe to share across threads. However,
46 : the _gaddr() values returned are safe to share. */
47 :
48 : struct fd_vinyl_req_pool {
49 : ulong magic;
50 : fd_wksp_t * wksp;
51 : ulong batch_key_max;
52 : ulong batch_max;
53 : ulong * free;
54 : ulong free_cnt;
55 : ulong * used; /* bit set */
56 :
57 : ulong key_off;
58 : ulong val_gaddr_off;
59 : ulong err_off;
60 : ulong comp_off;
61 :
62 : /* ... variable size data follows ...*/
63 : };
64 :
65 : typedef struct fd_vinyl_req_pool fd_vinyl_req_pool_t;
66 :
67 0 : #define FD_VINYL_REQ_POOL_MAGIC (0x7ecb0aa4a4730117UL) /* magic */
68 0 : #define FD_VINYL_REQ_POOL_ALIGN (128UL) /* double cache line */
69 :
70 : FD_PROTOTYPES_BEGIN
71 :
72 : /* fd_vinyl_req_pool_{align,footprint} describe a memory region suitable
73 : to hold a vinyl_req_pool object. If any footprint params are
74 : invalid, footprint silently returns 0UL.
75 : Footprint scales like O(batch_max*batch_key_max). */
76 :
77 : ulong
78 : fd_vinyl_req_pool_align( void );
79 :
80 : ulong
81 : fd_vinyl_req_pool_footprint( ulong batch_max,
82 : ulong batch_key_max );
83 :
84 : /* fd_vinyl_req_pool_new formats the memory region as a vinyl_req_pool
85 : object. shmem is assumed to be in a wksp. Returns the newly created
86 : object on success. On failure logs warning and returns NULL.
87 :
88 : Reasons for failure are: NULL shmem, misaligned shmem, invalid
89 : params, shmem not in a wksp. */
90 :
91 : void *
92 : fd_vinyl_req_pool_new( void * shmem,
93 : ulong batch_max,
94 : ulong batch_key_max );
95 :
96 : /* fd_vinyl_req_pool_join joins the caller to a vinyl_req_pool object in
97 : shared memory. Only one join should be active at a time. */
98 :
99 : fd_vinyl_req_pool_t *
100 : fd_vinyl_req_pool_join( void * shmem );
101 :
102 : /* fd_vinyl_req_pool_leave detaches the caller from a vinyl_req_pool
103 : object. (Currently a no-op, provided for readability) */
104 :
105 : void *
106 : fd_vinyl_req_pool_leave( fd_vinyl_req_pool_t * pool );
107 :
108 : /* fd_vinyl_req_pool_delete destroys a vinyl_req_pool object and returns
109 : the backing memory region back to the caller. On failure logs
110 : warning and returns NULL. */
111 :
112 : void *
113 : fd_vinyl_req_pool_delete( void * shmem );
114 :
115 : /* fd_vinyl_req_{batch_max,batch_req_max} return parameters of an
116 : existing object. */
117 :
118 : static inline ulong
119 0 : fd_vinyl_req_batch_max( fd_vinyl_req_pool_t * pool ) {
120 0 : return pool->batch_max;
121 0 : }
122 :
123 : static inline ulong
124 0 : fd_vinyl_req_batch_key_max( fd_vinyl_req_pool_t * pool ) {
125 0 : return pool->batch_key_max;
126 0 : }
127 :
128 : /* fd_vinyl_req_pool_free_batch_cnt returns the number of free batches. */
129 :
130 : static inline ulong
131 0 : fd_vinyl_req_pool_free_batch_cnt( fd_vinyl_req_pool_t * pool ) {
132 0 : return pool->free_cnt;
133 0 : }
134 :
135 : /* fd_vinyl_req_pool_acquire opens a new request batch. Returns the
136 : index of the newly required batch. Panics with FD_LOG_CRIT if no
137 : batches are free. */
138 :
139 : ulong
140 : fd_vinyl_req_pool_acquire( fd_vinyl_req_pool_t * pool );
141 :
142 : /* fd_vinyl_req_pool_release frees a request batch. Panics with
143 : FD_LOG_CRIT if this is an invalid free. */
144 :
145 : void
146 : fd_vinyl_req_pool_release( fd_vinyl_req_pool_t * pool,
147 : ulong batch_idx );
148 :
149 : /* fd_vinyl_req_batch_key returns a pointer to the array of keys for a
150 : request batch. */
151 :
152 : static inline fd_vinyl_key_t *
153 : fd_vinyl_req_batch_key( fd_vinyl_req_pool_t * pool,
154 0 : ulong batch_idx ) {
155 0 : fd_vinyl_key_t * key0 = (fd_vinyl_key_t *)( (ulong)pool + pool->key_off );
156 0 : return key0 + (batch_idx * pool->batch_key_max);
157 0 : }
158 :
159 : /* fd_vinyl_req_batch_key_gaddr returns the 'key_gaddr' paramter for a
160 : request batch. */
161 :
162 : static inline ulong
163 : fd_vinyl_req_batch_key_gaddr( fd_vinyl_req_pool_t * pool,
164 0 : ulong batch_idx ) {
165 0 : return fd_wksp_gaddr_fast( pool->wksp, fd_vinyl_req_batch_key( pool, batch_idx ) );
166 0 : }
167 :
168 : /* fd_vinyl_req_batch_val_gaddr returns a pointer to the array of
169 : val_gaddr values for a request batch. */
170 :
171 : static inline ulong *
172 : fd_vinyl_req_batch_val_gaddr( fd_vinyl_req_pool_t * pool,
173 0 : ulong batch_idx ) {
174 0 : ulong * val_gaddr0 = (ulong *)( (ulong)pool + pool->val_gaddr_off );
175 0 : return val_gaddr0 + (batch_idx * pool->batch_key_max);
176 0 : }
177 :
178 : /* fd_vinyl_req_batch_val_gaddr_gaddr returns the 'val_gaddr_gaddr'
179 : parameter for a request batch. */
180 :
181 : static inline ulong
182 : fd_vinyl_req_batch_val_gaddr_gaddr( fd_vinyl_req_pool_t * pool,
183 0 : ulong batch_idx ) {
184 0 : return fd_wksp_gaddr_fast( pool->wksp, fd_vinyl_req_batch_val_gaddr( pool, batch_idx ) );
185 0 : }
186 :
187 : /* fd_vinyl_req_batch_err returns a pointer to the error codes for a
188 : request batch. */
189 :
190 : static inline schar *
191 : fd_vinyl_req_batch_err( fd_vinyl_req_pool_t * pool,
192 0 : ulong batch_idx ) {
193 0 : schar * err0 = (schar *)( (ulong)pool + pool->err_off );
194 0 : return err0 + (batch_idx * pool->batch_key_max);
195 0 : }
196 :
197 : /* fd_vinyl_req_batch_err_gaddr returns the 'err_gaddr' parameter for a
198 : request batch. */
199 :
200 : static inline ulong
201 : fd_vinyl_req_batch_err_gaddr( fd_vinyl_req_pool_t * pool,
202 0 : ulong batch_idx ) {
203 0 : return fd_wksp_gaddr_fast( pool->wksp, fd_vinyl_req_batch_err( pool, batch_idx ) );
204 0 : }
205 :
206 : /* fd_vinyl_req_batch_comp returns a pointer to the array of completion
207 : objects for a request batch. */
208 :
209 : static inline fd_vinyl_comp_t *
210 : fd_vinyl_req_batch_comp( fd_vinyl_req_pool_t * pool,
211 0 : ulong batch_idx ) {
212 0 : fd_vinyl_comp_t * comp0 = (fd_vinyl_comp_t *)( (ulong)pool + pool->comp_off );
213 0 : return comp0 + (batch_idx * pool->batch_key_max);
214 0 : }
215 :
216 : /* fd_vinyl_req_batch_comp_gaddr returns the 'comp_gaddr' parameter for
217 : a request batch. */
218 :
219 : static inline ulong
220 : fd_vinyl_req_batch_comp_gaddr( fd_vinyl_req_pool_t * pool,
221 0 : ulong batch_idx ) {
222 0 : return fd_wksp_gaddr_fast( pool->wksp, fd_vinyl_req_batch_comp( pool, batch_idx ) );
223 0 : }
224 :
225 : /* fd_vinyl_rq_send_batch is syntax sugar for fd_vinyl_rq_send with a
226 : req_pool-provided request batch. */
227 :
228 : static inline void
229 : fd_vinyl_req_send_batch( fd_vinyl_rq_t * rq,
230 : fd_vinyl_req_pool_t * req_pool,
231 : ulong req_id,
232 : ulong link_id,
233 : int type,
234 : ulong flags,
235 : ulong batch_idx,
236 : ulong batch_cnt,
237 0 : ulong val_max ) {
238 0 : ulong key_gaddr = fd_vinyl_req_batch_key_gaddr ( req_pool, batch_idx );
239 0 : ulong val_gaddr_gaddr = fd_vinyl_req_batch_val_gaddr_gaddr( req_pool, batch_idx );
240 0 : ulong err_gaddr = fd_vinyl_req_batch_err_gaddr ( req_pool, batch_idx );
241 0 : ulong comp_gaddr = fd_vinyl_req_batch_comp_gaddr ( req_pool, batch_idx );
242 0 : fd_vinyl_rq_send( rq, req_id, link_id, type, flags, batch_cnt, val_max, key_gaddr, val_gaddr_gaddr, err_gaddr, comp_gaddr );
243 0 : }
244 :
245 : FD_PROTOTYPES_END
246 :
247 : #endif /* HEADER_fd_src_flamenco_accdb_fd_vinyl_req_pool_h */
|