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