Line data Source code
1 : #ifndef HEADER_fd_src_vinyl_data_fd_vinyl_data_h
2 : #define HEADER_fd_src_vinyl_data_fd_vinyl_data_h
3 :
4 : /* fd_vinyl_data provides a data structure suitable for in-memory
5 : caching extremely of large amounts of variable sized pairs in memory.
6 : The memory layouts are such that cached pairs can be zero copy
7 : lockfree operated on by multiple threads in other address spaces and
8 : async direct I/O hardware concurrently.
9 :
10 : Note that, though pairs are cached in a shared memory region, this is
11 : not a persistent or concurrent datastructure. Specifically, only the
12 : vinyl tile can allocate or free objects from it and then can do only
13 : sequentially.
14 :
15 : Notes:
16 :
17 : - The shared memory region is divided into a fixed number of fixed
18 : sized volumes (similar to fd_groove).
19 : - Volumes flexibly store data objects.
20 : - Volumes not in use are stored on a free volume stack.
21 : - The size of a data object is determined by the object's size class.
22 : - A data object can either be an allocation (i.e. a cached pair val
23 : that fits in that object's sizeclass) or a superblock (a collection
24 : of smaller data objects from the same sizeclass).
25 :
26 : The algorithms that manage the allocations are virtually identical to
27 : fd_groove and fd_alloc. But they have been simplified, customized
28 : and optimized for this use case (e.g. minimal need for address
29 : translation, no need for atomic operations, no need for concurrency
30 : group optimizations, no need to layout cache for concurrent access,
31 : much more fine grained size classes for minimal data store overheads,
32 : etc). This also does extensive (and compile time configurable)
33 : memory data integrity continuously to help catch memory corruption
34 : (either due to hardware failures, buggy usage or malicious usage).
35 :
36 : I/O alignment requirements quantize the data cache footprint of a
37 : val_sz pair to BLOCK_SZ+align_up(pair_sz(val_sz),BLOCK_SZ). This
38 : unavoidable quantization dominates allocation footprint efficiency
39 : for the smallest values (e.g. a val_sz 1 pair will occupy 2 blocks
40 : for the I/O alignment requirements and metadata). This is negligible
41 : for large pairs (e.g. ~0.0024% for a VAL_MAX ~ 10 MiB val).
42 :
43 : Rounding an allocation to the smallest compatible size class adds no
44 : additional overhead for smallest sizes (every possible quantization
45 : of a val_sz less then ~4-8 KiB has a dedicated sizeclass). For
46 : object sizes << VAL_MAX, the worst case overhead is better than ~2%.
47 : For the object sizes ~ VAL_MAX, if the volume size is ~O(1) VAL_MAX,
48 : volume divisibility starts to impact this overhead. It still less
49 : than ~20% for the current config (and such sizes should be rare in
50 : the practical usage). This effect can eliminated by using volume
51 : sizes much larger than VAL_MAX (at the expense of creating a deeper
52 : sizeclass nesting).
53 :
54 : The packing of objects into nested superblocks also incurs a small
55 : amount of additional overhead. The smallest footprint object (2
56 : blocks or 256B) will be in a leaf superblock with 64 objects. The
57 : leaf superblock overhead (128B) amortized over these 64 objects is
58 : thus 2 bytes per object. This leaf superblock will be nested in a
59 : larger superblock with 2 leaf superblocks. With 128B additional
60 : overhead amortized over 128 objects, this yields 1 more byte overhead
61 : per object. And so forth. For this sizeclass, the overall
62 : superblock overhead converges to <~4 bytes per object absolute or
63 : <~1.5% relative. This is a rough relative upper bound for all
64 : sizeclasses. Specifically, for leaf superblocks with less than 64
65 : objects, there is more absolute superblock overhead per object but
66 : the object itself is large enough to compensate. And for objects in
67 : large superblocks, the objects more than large enough to compensate.
68 :
69 : The allocator will also implicitly adaptively preallocate space for
70 : frequently used sizeclasses to speed up allocations. For
71 : asymptotically large data caches relative to the worst case object
72 : sizes, the amount of preallocation is very small.
73 :
74 : TL;DR Allocator footprint overhead is the unavoidable BLOCK_SZ
75 : quantization plus a couple percent typically. */
76 :
77 : #include "../io/fd_vinyl_io.h"
78 :
79 : /* fd_vinyl_data_szc **************************************************/
80 :
81 : struct __attribute__((aligned(8))) fd_vinyl_data_szc_cfg {
82 : uint val_max; /* max pair val byte size that can be stored in an object in this size class.
83 : The object is aligned in memory with FD_VINYL_BSTREAM_BLOCK_SZ alignment and with a footprint of:
84 : FD_VINYL_BSTREAM_BLOCK_SZ + sizeof(fd_vinyl_bstream_phdr_t) + val_max + FD_VINYL_BSTREAM_FTR_SZ
85 : The footprint is a FD_VINYL_BSTREAM_BLOCK_SZ multiple. */
86 : ushort obj_cnt; /* ==num objects in the containing superblock, in [2,64] */
87 : ushort parent_szc; /* size class of the superblock that contains objects of this size class,
88 : FD_VINYL_DATA_SZC_CNT indicates superblocks for objects of this size class fill an entire volume,
89 : (the superblock footprint is FD_VINYL_BSTREAM_BLOCK_SZ + obj_cnt*obj_footprint) */
90 : };
91 :
92 : typedef struct fd_vinyl_data_szc_cfg fd_vinyl_data_szc_cfg_t;
93 :
94 : FD_PROTOTYPES_BEGIN
95 :
96 : /* fd_vinyl_data_szc_cfg describes the sizeclasses used by the data
97 : cache. Indexed [0,FD_VINYL_DATA_SZC_CNT). */
98 :
99 69603471 : #define FD_VINYL_DATA_SZC_CNT (327UL)
100 :
101 : extern fd_vinyl_data_szc_cfg_t const fd_vinyl_data_szc_cfg[ FD_VINYL_DATA_SZC_CNT ];
102 :
103 : /* fd_vinyl_data_szc_obj_footprint returns the in-memory footprint for
104 : an object with the given size class.
105 :
106 : fd_vinyl_data_szc_val_max returns the largest pair val that can be
107 : cached in an object with the given size class. Assumes szc is in
108 : [O,FD_VINYL_DATA_SZC_CNT). Return will be in
109 : [0,cfg(SZC_CNT-1).val_max].
110 :
111 : fd_vinyl_data_szc returns the tightest fitting size class that can
112 : cache a pair val with a maximum size of val_max. Assumes val_max is
113 : in [0,szc.cfg(SZC_CNT-1.val_max]. Return will be in
114 : [0,FD_VINYL_DATA_SZC_CNT). The returned size class is typically able
115 : to hold a val_max ~1-2% larger than the given val_max.
116 :
117 : Note that the size classes are configured such that, given val_sz in
118 : [0,FD_VINYL_VAL_MAX]:
119 :
120 : fd_vinyl_data_szc_val_max( fd_vinyl_data_szc( val_sz ) ) <= FD_VINYL_VAL_MAX.
121 :
122 : where equality is achieved when val_sz==FD_VINYL_VAL_MAX.
123 :
124 : FIXME: should these be FD_FN_CONST (szc_cfg is const)? */
125 :
126 : FD_FN_PURE static inline ulong
127 60943713 : fd_vinyl_data_szc_obj_footprint( ulong szc ) {
128 60943713 : return FD_VINYL_BSTREAM_BLOCK_SZ +
129 60943713 : sizeof(fd_vinyl_bstream_phdr_t) + (ulong)fd_vinyl_data_szc_cfg[ szc ].val_max + FD_VINYL_BSTREAM_FTR_SZ;
130 60943713 : }
131 :
132 : FD_FN_PURE static inline ulong
133 42099069 : fd_vinyl_data_szc_val_max( ulong szc ) {
134 42099069 : return (ulong)fd_vinyl_data_szc_cfg[ szc ].val_max;
135 42099069 : }
136 :
137 : FD_FN_PURE static inline ulong
138 51117102 : fd_vinyl_data_szc( ulong val_max ) {
139 :
140 51117102 : ulong l = 0UL;
141 51117102 : ulong h = FD_VINYL_DATA_SZC_CNT-1UL;
142 :
143 511171020 : for( ulong rem=9UL; rem; rem-- ) { /* Update if FD_VINYL_DATA_SZC_CNT changed */
144 :
145 : /* At this point, szc in [0,l) aren't suitable, szc in [h,CNT) are
146 : suitable and szc in [l,h) are untested. See fd_alloc for more
147 : detail on using fixed count loop. */
148 :
149 460053918 : ulong m = (l+h) >> 1;
150 460053918 : int c = (((ulong)fd_vinyl_data_szc_cfg[ m ].val_max) >= val_max);
151 460053918 : l = fd_ulong_if( c, l, m+1UL );
152 460053918 : h = fd_ulong_if( c, m, h );
153 :
154 460053918 : }
155 :
156 51117102 : return l;
157 51117102 : }
158 :
159 : FD_PROTOTYPES_END
160 :
161 : /* fd_vinyl_data_obj **************************************************/
162 :
163 7899 : #define FD_VINYL_DATA_OBJ_TYPE_FREEVOL (0xf7eef7eef7eef7eeUL) /* free, object is a free volume */
164 15071136 : #define FD_VINYL_DATA_OBJ_TYPE_ALLOC (0xa11ca11ca11ca11cUL) /* allc, object is an allocation */
165 3760572 : #define FD_VINYL_DATA_OBJ_TYPE_SUPERBLOCK (0x59e759e759e759e7UL) /* sper, object is a superblock */
166 :
167 : #define FD_VINYL_DATA_OBJ_GUARD_SZ (FD_VINYL_BSTREAM_BLOCK_SZ - sizeof(fd_vinyl_io_rd_t) - 8UL*sizeof(ulong))
168 :
169 : struct fd_vinyl_data_obj;
170 : typedef struct fd_vinyl_data_obj fd_vinyl_data_obj_t;
171 :
172 : struct __attribute__((aligned(FD_VINYL_BSTREAM_BLOCK_SZ))) fd_vinyl_data_obj {
173 :
174 : /* type gives the object type. A FD_VINYL_DATA_OBJ_TYPE_*.
175 :
176 : For type SUPERBLOCK objects, child_szc gives the size class of the
177 : objects contained in this superblock. In
178 : [0,FD_VINYL_DATA_SZC_CNT). Ignored for other types of objects.
179 :
180 : For type SUPERBLOCK and type ALLOC objects, szc gives the size
181 : class of the object. In [0,FD_VINYL_DATA_SZC_CNT]. Values less
182 : then SZC_CNT indicate an object contained in a superblock. Equal
183 : to SZC_CNT indicates an object that fills an entire volume. For
184 : other types of objects, ignored.
185 :
186 : For objects contained in a parent superblock, idx gives the index
187 : of the object in its parent, in [0,szc.obj_cnt). For objects that
188 : fill an entire volume, idx gives the data volume index, in
189 : [0,vol_cnt).
190 :
191 : For type SUPERBLOCK objects, free_blocks gives a bit field
192 : identifying which blocks are free. Ignored for other types of
193 : objects.
194 :
195 : For inactive type SUPERBLOCK objects, next_off gives the byte
196 : offset from laddr0 of the next inactive superblock and 0UL if no
197 : more inactive superblocks. next_off is ignored in other
198 : circumstances (but see note about pending I/O ops). Note that this
199 : implies laddr0 must less than the local address of vol (such that
200 : data gaddr==0 never points to an object). Note also that, if
201 : laddr0 is 0, next_off will be just a pointer in the local address
202 : space.
203 :
204 : Note that I/O acceleration may require memory alignment and I/O
205 : device alignment to match. So we need to put all the object
206 : allocator data its own block. This can leave a lot of extra space.
207 : We put this space up front in the block to that it can act as a
208 : guard region for whatever preceeds it (applications could even use
209 : this guard region to stash extra info but this is not recommended
210 : because of false sharing conflicts in might induce between
211 : different threads using adjacent in memory objects). Likewise,
212 : because we have all this space from block quantization, we don't
213 : try to be hyperefficient with the packing (like we do for, say,
214 : fd_alloc). */
215 :
216 : # if 0 /* Note: with BLOCK_SZ==128, GUARD_SZ=0 so there's no guard field due to language limitations */
217 : uchar guard[ FD_VINYL_DATA_OBJ_GUARD_SZ ];
218 : # endif
219 :
220 : /* rd on its own cache line */
221 :
222 : fd_vinyl_io_rd_t rd[1]; /* rd: ctx is element idx */
223 :
224 : /* allocator metadata on its own cache line */
225 :
226 : ulong unused[1]; /* unused space */
227 : schar * rd_err; /* rd: client req_err (or dummy location if no client req_err) */
228 : short rd_active; /* rd: is a read in progess on this obj */
229 : ushort _unused; /* unused space */
230 : ushort szc; /* data: allocation size class */
231 : ushort child_szc; /* data: (superblock) contains allocations of this sizeclass */
232 : ulong line_idx; /* vinyl line_idx that is responsible for this object, in [0,line_cnt), ignored if not type alloc */
233 : ulong type; /* data: allocation type (alloc or superblock) */
234 : ulong idx; /* data: (alloc or superblock) index of this allocation in its parent superblock, (vol) vol idx */
235 : ulong free_blocks; /* data: (superblock) bit field free allocations */
236 : ulong next_off; /* data: (inactive superblock) pointer to next inactive superblock or 0 last */
237 :
238 : /* This point is FD_VINYL_BSTREAM_BLOCK_SZ aligned */
239 :
240 : /* Space for sizeof(fd_vinyl_bstream_phdr_t) + fd_vinyl_data_szc_cfg[szc].val_max + FD_VINYL_BSTREAM_FTR_SZ
241 :
242 : Note that is is a FD_VINYL_BSTREAM_BLOCK_SZ multiple so that the
243 : entire region starting from phdr can submitted zero copy for
244 : streaming to hardware async direct I/O friendly. */
245 :
246 : /* This point is FD_VINYL_BSTREAM_BLOCK_SZ aligned */
247 :
248 : /* There is an implied FD_VINYL_DATA_OBJ_GUARD_SZ region here as per
249 : note above. It is not considered part of _this_ data_obj_t though. */
250 :
251 : };
252 :
253 : FD_PROTOTYPES_BEGIN
254 :
255 : /* fd_vinyl_data_obj_* returns a pointer to the eponymous field in
256 : the given data object. Assumes obj is valid. Returns value for
257 : fd_vinyl_data_obj_phdr will be FD_VINYL_BSTREAM_BLOCK_SZ aligned.
258 : fd_vinyl_data_* mirror the above but they take the value region as
259 : input. */
260 :
261 : FD_FN_CONST static inline fd_vinyl_bstream_phdr_t *
262 3000000 : fd_vinyl_data_obj_phdr( fd_vinyl_data_obj_t const * obj ) {
263 3000000 : return (fd_vinyl_bstream_phdr_t *)((ulong)obj + sizeof(fd_vinyl_data_obj_t));
264 3000000 : }
265 :
266 : FD_FN_CONST static inline fd_vinyl_key_t *
267 3000000 : fd_vinyl_data_obj_key( fd_vinyl_data_obj_t const * obj ) {
268 3000000 : return (fd_vinyl_key_t *)((ulong)obj + sizeof(fd_vinyl_data_obj_t) + sizeof(ulong));
269 3000000 : }
270 :
271 : FD_FN_CONST static inline fd_vinyl_info_t *
272 6000000 : fd_vinyl_data_obj_info( fd_vinyl_data_obj_t const * obj ) {
273 6000000 : return (fd_vinyl_info_t *)((ulong)obj + sizeof(fd_vinyl_data_obj_t) + sizeof(ulong) + sizeof(fd_vinyl_key_t));
274 6000000 : }
275 :
276 : FD_FN_CONST static inline void *
277 3000000 : fd_vinyl_data_obj_val( fd_vinyl_data_obj_t const * obj ) {
278 3000000 : return (void *)((ulong)obj + sizeof(fd_vinyl_data_obj_t) + sizeof(fd_vinyl_bstream_phdr_t));
279 3000000 : }
280 :
281 : FD_FN_PURE static inline ulong
282 3000000 : fd_vinyl_data_obj_val_sz( fd_vinyl_data_obj_t const * obj ) {
283 3000000 : return (ulong)fd_vinyl_data_obj_info( obj )->val_sz;
284 3000000 : }
285 :
286 : FD_FN_PURE static inline ulong
287 3000000 : fd_vinyl_data_obj_val_max( fd_vinyl_data_obj_t const * obj ) {
288 3000000 : return fd_vinyl_data_szc_val_max( (ulong)obj->szc );
289 3000000 : }
290 :
291 : FD_FN_CONST static inline fd_vinyl_data_obj_t *
292 6000000 : fd_vinyl_data_obj( void const * val ) {
293 6000000 : return (fd_vinyl_data_obj_t *)((ulong)val - sizeof(fd_vinyl_bstream_phdr_t) - sizeof(fd_vinyl_data_obj_t));
294 6000000 : }
295 :
296 : FD_FN_CONST static inline fd_vinyl_bstream_phdr_t *
297 3000000 : fd_vinyl_data_phdr( void const * val ) {
298 3000000 : return (fd_vinyl_bstream_phdr_t *)((ulong)val - sizeof(fd_vinyl_bstream_phdr_t));
299 3000000 : }
300 :
301 : FD_FN_CONST static inline fd_vinyl_key_t *
302 3000000 : fd_vinyl_data_key( void const * val ) {
303 3000000 : return (fd_vinyl_key_t *)((ulong)val - sizeof(fd_vinyl_info_t) - sizeof(fd_vinyl_key_t));
304 3000000 : }
305 :
306 : FD_FN_CONST static inline fd_vinyl_info_t *
307 6000000 : fd_vinyl_data_info( void const * val ) {
308 6000000 : return (fd_vinyl_info_t *)((ulong)val - sizeof(fd_vinyl_info_t));
309 6000000 : }
310 :
311 : FD_FN_PURE static inline ulong
312 3000000 : fd_vinyl_data_val_sz( void const * val ) {
313 3000000 : return (ulong)fd_vinyl_data_info( val )->val_sz;
314 3000000 : }
315 :
316 : FD_FN_PURE static inline ulong
317 3000000 : fd_vinyl_data_val_max( void const * val ) {
318 3000000 : return fd_vinyl_data_szc_val_max( (ulong)fd_vinyl_data_obj( val )->szc );
319 3000000 : }
320 :
321 : FD_PROTOTYPES_END
322 :
323 : /* fd_vinyl_data_vol **************************************************/
324 :
325 45793758 : #define FD_VINYL_DATA_VOL_FOOTPRINT (34078592UL) /* autogenerated */
326 :
327 : struct fd_vinyl_data_vol {
328 : fd_vinyl_data_obj_t obj[1];
329 : uchar data[ FD_VINYL_DATA_VOL_FOOTPRINT - sizeof(fd_vinyl_data_obj_t) ];
330 : };
331 :
332 : typedef struct fd_vinyl_data_vol fd_vinyl_data_vol_t;
333 :
334 : /* fd_vinyl_data ******************************************************/
335 :
336 : #define FD_VINYL_DATA_ALIGN (128UL)
337 : #define FD_VINYL_DATA_FOOTPRINT sizeof(fd_vinyl_data_t)
338 :
339 : struct __attribute((aligned(FD_VINYL_DATA_ALIGN))) fd_vinyl_data {
340 : void * shmem; /* Raw shared memory region */
341 : ulong shmem_sz; /* Raw shared memory region size */
342 : void * laddr0; /* Location where gaddr 0 points in the local address space
343 : (FD_VINYL_BSTREAM_BLOCK_SZ aligned) */
344 : fd_vinyl_data_vol_t * vol; /* Vols, indexed [0,vol_cnt), in raw shared memory region */
345 : ulong vol_cnt; /* Num vols, in [0,FD_VINYL_DATA_VOL_MAX) */
346 : ulong vol_idx_free; /* Idx of first free volume if in [0,vol_cnt), no free volumes o.w. */
347 : struct {
348 : fd_vinyl_data_obj_t * active; /* active superblock for this size class */
349 : fd_vinyl_data_obj_t * inactive_top; /* top of the inactive superblock stack for this size class */
350 : } superblock[ FD_VINYL_DATA_SZC_CNT ];
351 : };
352 :
353 : typedef struct fd_vinyl_data fd_vinyl_data_t;
354 :
355 : FD_PROTOTYPES_BEGIN
356 :
357 : /* fd_vinyl_data_{align,footprint} return the alignment and footprint
358 : needed for a local memory region to hold the state of a data cache.
359 : align will be a power of 2 and footprint will be a multiple of align.
360 : Matches FD_VINYL_DATA_{ALIGN,FOOTPRINT}. */
361 :
362 : FD_FN_CONST ulong fd_vinyl_data_align ( void );
363 : FD_FN_CONST ulong fd_vinyl_data_footprint( void );
364 :
365 : /* fd_vinyl_data_init formats a suitable local memory region lmem and an
366 : arbitrary shared memory region shmem with byte size shmem_sz as a
367 : vinyl data cache. laddr0 gives the location in the caller's local
368 : address space that corresponds to data object global address 0. It
369 : should be FD_VINYL_BSTREAM_BLOCK_SZ aligned and before shmem. E.g.
370 : laddr0==NULL could be used when the data objects aren't shared with
371 : threads in different processes while laddr0==wksp could be used for
372 : data objects that are shared and backed by a wksp.
373 :
374 : IMPORTANT SAFETY TIP! This does _not_ do the initial formatting of
375 : the shmem region into free data volumes (e.g. the caller can use the
376 : data shmem region as a scratch during thread parallel resume and then
377 : format it appropriately). The caller is responsible for calling
378 : fd_vinyl_data_reset before using data as an object store.
379 :
380 : Returns a handle to the data cache on success (data cache owns the
381 : memory regions) and NULL on failure (bad lmem, bad shmem, too small
382 : size ... logs details, no ownership changes). */
383 :
384 : fd_vinyl_data_t *
385 : fd_vinyl_data_init( void * lmem,
386 : void * shmem,
387 : ulong shmem_sz,
388 : void * laddr0 );
389 :
390 : /* fd_vinyl_data_fini stops using lmem and shmem as a data cache.
391 : Returns lmem on success and NULL on failure (logs details). */
392 :
393 : void *
394 : fd_vinyl_data_fini( fd_vinyl_data_t * data );
395 :
396 : /* fd_vinyl_data_{laddr0,shmem,shmem_sz} return the address translation
397 : and shared memory region used by the data cache. */
398 :
399 3 : FD_FN_PURE static inline void * fd_vinyl_data_laddr0 ( fd_vinyl_data_t const * data ) { return (void *)data->laddr0; }
400 3 : FD_FN_PURE static inline void * fd_vinyl_data_shmem ( fd_vinyl_data_t const * data ) { return (void *)data->shmem; }
401 3 : FD_FN_PURE static inline ulong fd_vinyl_data_shmem_sz( fd_vinyl_data_t const * data ) { return data->shmem_sz; }
402 :
403 : /* fd_vinyl_data_is_valid_obj returns 1 if laddr appears to point to
404 : a valid data object and 0 if not. vol points to data volume 0 in the
405 : local address space and vol_cnt is the number of data volumes. */
406 :
407 : FD_FN_PURE static inline int
408 : fd_vinyl_data_is_valid_obj( void const * laddr,
409 : fd_vinyl_data_vol_t const * vol,
410 44950959 : ulong vol_cnt ) {
411 :
412 44950959 : ulong vol_idx = ((ulong)laddr - (ulong)vol) / FD_VINYL_DATA_VOL_FOOTPRINT;
413 :
414 44950959 : if( FD_UNLIKELY( !( ((ulong)vol<=(ulong)laddr) &
415 44950959 : (vol_idx<vol_cnt) &
416 44950959 : fd_ulong_is_aligned( (ulong)laddr, FD_VINYL_BSTREAM_BLOCK_SZ ) ) ) ) return 0;
417 :
418 : /* At this point, laddr seems to be properly aligned and in volume
419 : vol_idx. We are safe to read the type and sizeclass. */
420 :
421 44950959 : fd_vinyl_data_obj_t const * obj = (fd_vinyl_data_obj_t const *)laddr;
422 44950959 : ulong szc = (ulong)obj->szc;
423 :
424 44950959 : if( FD_UNLIKELY( !((obj->type==FD_VINYL_DATA_OBJ_TYPE_ALLOC) & (szc<FD_VINYL_DATA_SZC_CNT)) ) ) return 0;
425 :
426 : /* At this point, laddr seems to contain an allocation of sizeclass
427 : szc. Make sure the object idx seems to be valid and the object is
428 : contained entirely within volume vol_idx. */
429 :
430 30000000 : ulong end = (ulong)laddr + fd_vinyl_data_szc_obj_footprint( szc );
431 :
432 30000000 : if( FD_UNLIKELY( !((obj->idx<(ulong)fd_vinyl_data_szc_cfg[ szc ].obj_cnt) & (end<=(ulong)&vol[vol_idx+1UL])) ) ) return 0;
433 :
434 30000000 : return 1;
435 30000000 : }
436 :
437 : /* fd_vinyl_data_alloc acquires an object of sizeclass szc from the data
438 : cache. Returns a pointer to the object on success and NULL if there
439 : is no space available in the data. Will FD_LOG_CRIT if anything
440 : wonky is detected (bad, memory corruption, etc). */
441 :
442 : fd_vinyl_data_obj_t *
443 : fd_vinyl_data_alloc( fd_vinyl_data_t * data,
444 : ulong szc );
445 :
446 : /* fd_vinyl_data_free releases obj to the data cache. This cannot fail
447 : from the caller's perspective. Will FD_LOG_CRIT if anything wonky is
448 : detected (bad args, memory corruption, etc). */
449 :
450 : void
451 : fd_vinyl_data_free( fd_vinyl_data_t * data,
452 : fd_vinyl_data_obj_t * obj );
453 :
454 : /* fd_vinyl_data_reset uses the caller and tpool threads (t0,t1) to free
455 : all objects from the data cache. level zero/non-zero indicates to do
456 : soft/hard reset. In a hard reset, the shmem region is zero'd before
457 : formatting it into a set of free data volumes. This cannot fail from
458 : the caller's perspective. Assumes tpool threads (t0,t1) are
459 : available for dispatch. Retains no interest in tpool and tpool
460 : threads (t0,t1) will be available for dispatch on return. */
461 :
462 : void
463 : fd_vinyl_data_reset( fd_tpool_t * tpool, ulong t0, ulong t1, int level,
464 : fd_vinyl_data_t * data );
465 :
466 : /* fd_vinyl_data_verify returns FD_VINYL_SUCCESS (0) if the given data
467 : appears to be a valid vinyl data and FD_VINYL_ERR_CORRUPT (negative)
468 : otherwise (logs details). This only verifies the vinyl data's state
469 : and superblock heirarchy are intact. It does not test any of the
470 : allocations for correctness (but could given access to the bstream,
471 : line and/or meta). */
472 :
473 : FD_FN_PURE int
474 : fd_vinyl_data_verify( fd_vinyl_data_t const * data );
475 :
476 : FD_PROTOTYPES_END
477 :
478 : #endif /* HEADER_fd_src_vinyl_data_fd_vinyl_data_h */
|