Line data Source code
1 : #ifndef HEADER_fd_src_vinyl_bstream_fd_vinyl_bstream_h
2 : #define HEADER_fd_src_vinyl_bstream_fd_vinyl_bstream_h
3 :
4 : /* Client modifications to a vinyl key-val store are sequenced into
5 : total order by the vinyl tile and encoded into a stream of I/O
6 : friendly blocks (a "bstream"). A bstream has the strict mathematical
7 : property that a sufficient contiguous range of blocks ("the bstream's
8 : past") can be used to reconstruct the exact state of the vinyl
9 : key-val store at the bstream's "present" and then with a high
10 : probability of detecting random data corruption. Further, the
11 : bstream's past can be efficiently and continuously updated at the
12 : same time the bstream is being modified with bounded space and time
13 : overheads.
14 :
15 : To introduce concepts and give more details:
16 :
17 : - sequence space: Every byte in a bstream has a sequence number that
18 : is that byte's offset from the leading bstream byte. sequence
19 : numbers are 64-bit and wrap cyclicly (sequence wrapping is not a
20 : concern on practical timescales but the code handles it).
21 :
22 : - blocks: bstream bytes are accessed at block granularity.
23 : FD_VINYL_BSTREAM_BLOCK_SZ gives the block byte size. bstream
24 : blocks always start at FD_VINYL_BSTREAM_BLOCK_SZ multiples.
25 :
26 : - history: A bstream reader/writer maintains four block sequence
27 : numbers: seq_ancient, seq_past, seq_present, seq_future with
28 : seq_ancient <= seq_past <= seq_present <= seq_future (cyclic).
29 : These partition bstream sequence space into four regions:
30 :
31 : [seq_ancient,seq_past) (cyclic) is antiquity: these blocks have been written and forgotten (no read, no write)
32 : [seq_past, seq_present) (cyclic) is past: these blocks have been written (read only)
33 : [seq_present,seq_future) (cyclic) is present: these blocks are being written (write only)
34 : [seq_future, seq_ancient) (cyclic) is future: these blocks have not been written (no read, no write)
35 :
36 : - synchronization: The distinction between antiquity and the future
37 : is that blocks from antiquity will not be reused until the physical
38 : hardware has recorded the current location of the bstream's past.
39 :
40 : - recovery: the bstream's past is sufficient to exactly reconstruct
41 : the state of the key-val store at seq_present.
42 :
43 : - compaction: a bstream writer can cheaply prove whether or not a
44 : block is needed for recovery (blocked not needed for recovery are
45 : "garbage") and precisely track the amount of garbage in the
46 : bstream's past. The writer can use this information to decide when
47 : and how to continuously reorganize the bstream's past to yield a
48 : minimally sized past asymptotically with a bounded amount of
49 : garbage during transients ("compaction").
50 :
51 : - compression: Compaction can also statelessly re-encode the storage
52 : represetation of pairs. This will naturally compress seldom used
53 : pair data in the background while frequently used pairs will be
54 : stored uncompressed (RAW encoded) for speed.
55 :
56 : - encoding: A bstream encodes a key-val pair as follows:
57 :
58 : ----------------------------------------------------------------------- <- seq (FD_VINYL_BSTREAM_BLOCK_SZ multiple)
59 : ctl 8 type PAIR, val encoding style and val_esz ^ ^
60 : key key_sz fix sz, 8 multiple | | fd_vinyl_bstream_phdr_t
61 : val_sz 4 decoded val_sz fd_vinyl_info_t ^ | |
62 : app info INFO_SZ-4 app info v | v
63 : val val_esz encoded according to style |
64 : zero padding zpad_sz in [0,FD_VINYL_BSTREAM_BLOCK_SZ) | pair_sz (FD_VINYL_BSTREAM_BLOCK_SZ multiple)
65 : hash_trail 8 ^ |
66 : hash_blocks 8 FD_VINYL_BSTREAM_FTR_SZ v v
67 : -----------------------------------------------------------------------
68 :
69 : There is much nuance in the above:
70 :
71 : * Since sizeof(fd_vinyl_bstream_phdr_t) + FD_VINYL_BSTREAM_FTR_SZ is
72 : less than FD_VINYL_BSTREAM_BLOCK_SZ, a pair with a small enough
73 : encoded val can fit in a single block. It is not possible to
74 : encode multiple pairs in a single block though.
75 :
76 : * hash_trail covers all the pair's trailing blocks. hash_trail for
77 : a single block item is the bstream's hash seed. hash_blocks is
78 : the hash of the leading block with hash_trail as the seed.
79 :
80 : * Hashing is block oriented to create a single easily optimized
81 : case for software and hardware to target. Implementations can
82 : optimize and specialize data integrity hash functions to the case
83 : that maps a 64-bit seed and a FD_VINYL_BSTREAM_BLOCK_SZ aligned
84 : and FD_VINYL_BSTREAM_BLOCK_SZ footprint input buffer to a 64-bit
85 : output for all hashing operations.
86 :
87 : * The hashes are located at the pair end so that pairs can be
88 : streamed to storage cut-through / zero-copy style by writers with
89 : no seeking. Reading into memory can likewise be done with no
90 : intermediate copies of the pair (especially for RAW encoded
91 : pairs).
92 :
93 : * Hashing the trailing blocks and hash chaining the leading block
94 : allows updating pair metadata (e.g. renaming a pair, copying a
95 : pair, moving a pair, etc) without requiring rehashing all the
96 : data while maintaining strong data integrity protections (e.g.
97 : can detect with high probability whether the leading block has
98 : been mismatched from its trailing blocks).
99 :
100 : * Storing both hashes also allows fast high integrity bstream
101 : iteration. Specifically, iterators can fully validate small
102 : pairs and partially validate large pairs (the pair key, pair
103 : metadata and leading pair val bytes are valid and the trailing
104 : val bytes are matched to these bytes) cheaply (i.e. without
105 : needing to compute a full pair hash) with very low cost in
106 : storage or overhead on read or write.
107 :
108 : * The hashes are computed with the hash fields zeroed. The hash
109 : fields are then set when the pair is written.
110 :
111 : * This representation is cheaply relocatable (this is particularly
112 : important for compaction). For example, we could include the
113 : bstream seq in the pair header for extra redundancy (e.g. can
114 : potentially estimate bstream's past if the bstream's metadata
115 : gets corrupted) and extra data integrity checks. But then we'd
116 : have to either:
117 :
118 : - Recompute pair hashes when reorganizing the bstream's past
119 : during background compaction (which would prevent generic I/O
120 : hardware offload of bulk copies used for compaction).
121 :
122 : - Exclude seq from the block header hashing (which helps some
123 : but we'd still need to update seq in the header and thus
124 : prevent generic I/O hardware offload of bulk copies).
125 :
126 : - Keep seq constant during the compaction. This would turn seq
127 : into an indicator of when the pair was first created (or
128 : recreated if after an erase or move). Ignoring sequence wrap,
129 : this could preserve some data integrity checking (e.g. seq
130 : aligned and at or before the pair's current position) but this
131 : weakens the sync metadata redundancy benefits of including seq
132 : (can't just search for a contiguous range of well formatted
133 : blocks and use seq to get a bstream's past range estimate).
134 :
135 : - ...
136 :
137 : Instead, we go the simpler, faster and more flexible route. We
138 : omit bstream seq here from the pair. This allows pairs to be
139 : moved around in the bstream with simple bulk copies. Simpler
140 : code, more application pair metadata and faster background
141 : compaction.
142 :
143 : - control blocks: the bstream can contain control blocks to support
144 : recovery. A control block can only refer to bstream blocks before
145 : it in the bstream. Thus, they are always garbage from the point of
146 : view of compaction as they can be always be removed from the
147 : bstream's past once they are at seq_past.
148 :
149 : - zero padding: one type of control block is zero padding. These
150 : can be inserted by the bstream writer in order ensure sets of
151 : blocks are kept continguous in the underlying physical storage
152 : (e.g. making sure an encoded pair is never split across two
153 : physical volumes).
154 :
155 : - partitions: another type of control block is a partition. The
156 : bstream writer can insert partitions periodically to allow the
157 : bstream past to be quickly partitioned at object boundaries into
158 : approximately uniform slices that can be used for parallel
159 : recovery. These partitions also include the number of erases and
160 : moves that happend in the partition to aid in parallel recovery (to
161 : optionally tightly bound the size of temporary data structures at
162 : start).
163 :
164 : - hot or not: the metadata for all pairs at seq_present is always
165 : available fast O(1) to concurent vinyl users. This includes a
166 : small amount of application info (like balances, expirations, etc). */
167 :
168 : #include "../fd_vinyl_base.h"
169 :
170 : /* FD_VINYL_BSTREAM_BLOCK_SZ gives the block size in bytes of a bstream
171 : block. It is a power-of-2 of at least 128.
172 : FD_VINYL_BSTEAM_BLOCK_LG_SZ gives the log2 of this. */
173 :
174 291675882 : #define FD_VINYL_BSTREAM_BLOCK_SZ (128UL)
175 0 : #define FD_VINYL_BSTREAM_BLOCK_LG_SZ (7)
176 :
177 : /* A FD_VINYL_BSTREAM_CTL_TYPE_* specifies how to interpret the next
178 : range of blocks in the bstream. A FD_VINYL_BSTREAM_CTL_STYLE_*
179 : specifies the encoding style for that range of blocks (e.g. whether
180 : or not a pair is compressed). We use a 16-bit and a 12-bit
181 : non-compact encoding respectively for these so that simple data
182 : corruption errors can be detected without doing more expensive
183 : validation first. This leaves 36 bits for ctl sz, limiting a pair's
184 : encoded val size to be in [0,2^36). The LZ4 API inexplicably uses
185 : signed 32-bit ints for buffer sizes so an encoded / decode value size
186 : is further limited to be in [0,LZ4_MAX_INPUT_SIZE) (where
187 : LZ4_MAX_INPUT_SIZE is a little under 2^31). */
188 :
189 3000000 : #define FD_VINYL_BSTREAM_CTL_TYPE_PAIR ((int)(0x9a17)) /* "pair" */
190 18 : #define FD_VINYL_BSTREAM_CTL_TYPE_SYNC ((int)(0x512c)) /* "sync" */
191 0 : #define FD_VINYL_BSTREAM_CTL_TYPE_DEAD ((int)(0xdead)) /* "dead" */
192 0 : #define FD_VINYL_BSTREAM_CTL_TYPE_MOVE ((int)(0x30c3)) /* "move" */
193 0 : #define FD_VINYL_BSTREAM_CTL_TYPE_PART ((int)(0xd121)) /* "divi"der */
194 0 : #define FD_VINYL_BSTREAM_CTL_TYPE_ZPAD (0) /* (must be zero) */
195 :
196 9000006 : #define FD_VINYL_BSTREAM_CTL_STYLE_RAW ((int)0x7a3) /* "raw" */
197 6 : #define FD_VINYL_BSTREAM_CTL_STYLE_LZ4 ((int)0x124) /* "lz4" */
198 :
199 : /* A fd_vinyl_bstream_phdr_t gives the layout of bstream pair header
200 : (e.g. ctl, type PAIR, val encoding style, val encoding size, key,
201 : decoded val size and other application info). */
202 :
203 : struct fd_vinyl_bstream_phdr {
204 : ulong ctl;
205 : fd_vinyl_key_t key;
206 : fd_vinyl_info_t info;
207 : };
208 :
209 : typedef struct fd_vinyl_bstream_phdr fd_vinyl_bstream_phdr_t;
210 :
211 : /* FD_VINYL_BSTREAM_FTR_SZ gives the number of bytes in a bstream
212 : object footer. */
213 :
214 135493134 : #define FD_VINYL_BSTREAM_FTR_SZ (2UL*sizeof(ulong))
215 :
216 : /* If pair val byte size is greater than
217 : FD_VINYL_BSTREAM_LZ4_VAL_THRESH, it is considered worth trying to
218 : encode with lz4 compression (if lz4 compression is enabled). The
219 : default below is such that, even if the val smaller than this
220 : compressed to 0 bytes, it would still require one block of bstream
221 : space. (FIXME: make this dynamically run time configured?) */
222 :
223 : #define FD_VINYL_BSTREAM_LZ4_VAL_THRESH (FD_VINYL_BSTREAM_BLOCK_SZ - sizeof(fd_vinyl_bstream_phdr_t) - FD_VINYL_BSTREAM_FTR_SZ)
224 :
225 : /* FD_VINYL_BSTREAM_*_INFO_MAX give the max app info bytes that can be
226 : stashed in the eponymous control block. */
227 :
228 18 : #define FD_VINYL_BSTREAM_SYNC_INFO_MAX (FD_VINYL_BSTREAM_BLOCK_SZ - 6UL*sizeof(ulong))
229 0 : #define FD_VINYL_BSTREAM_DEAD_INFO_MAX (FD_VINYL_BSTREAM_BLOCK_SZ - 5UL*sizeof(ulong) - sizeof(fd_vinyl_bstream_phdr_t))
230 0 : #define FD_VINYL_BSTREAM_MOVE_INFO_MAX (FD_VINYL_BSTREAM_BLOCK_SZ - 5UL*sizeof(ulong) - sizeof(fd_vinyl_bstream_phdr_t) - sizeof(fd_vinyl_key_t))
231 0 : #define FD_VINYL_BSTREAM_PART_INFO_MAX (FD_VINYL_BSTREAM_BLOCK_SZ - 8UL*sizeof(ulong))
232 :
233 : /* A fd_vinyl_bstream_block gives the binary layouts for various types
234 : of blocks. Note that I/O acceleration may require our memory
235 : alignments to match our I/O alignments. Hence is this aligned
236 : FD_VINYL_BSTREAM_BLOCK_SZ in memory too. */
237 :
238 : union __attribute__((aligned(FD_VINYL_BSTREAM_BLOCK_SZ))) fd_vinyl_bstream_block {
239 :
240 : ulong ctl;
241 :
242 : fd_vinyl_bstream_phdr_t phdr; /* type PAIR, style *, sz pair val encoded sz */
243 :
244 : struct {
245 : uchar _[ FD_VINYL_BSTREAM_BLOCK_SZ - FD_VINYL_BSTREAM_FTR_SZ ];
246 : ulong hash_trail;
247 : ulong hash_blocks;
248 : } ftr;
249 :
250 : struct {
251 : ulong ctl; /* type SYNC, style 0 (ABI version), sz VAL_MAX */
252 : ulong seq_past; /* recover using blocks [seq_past,seq_present) */
253 : ulong seq_present; /* these are FD_VINYL_BSTREAM_BLOCK_SZ multiples */
254 : ulong info_sz; /* info byte size, in [0,FD_VINYL_BSTREAM_SYNC_INFO_MAX]. */
255 : uchar info[ FD_VINYL_BSTREAM_SYNC_INFO_MAX ]; /* sync info */
256 : ulong hash_trail; /* establishes bstream's hash seed */
257 : ulong hash_blocks;
258 : } sync; /* Note: this is located "outside" the bstream */
259 :
260 : struct {
261 : ulong ctl; /* type DEAD, style RAW, sz BLOCK_SZ */
262 : ulong seq; /* bstream seq num of this block */
263 : fd_vinyl_bstream_phdr_t phdr; /* pair header of the key getting erased */
264 : ulong info_sz; /* info byte size, in [0,FD_VINYL_BSTREAM_DEAD_INFO_MAX] */
265 : uchar info[ FD_VINYL_BSTREAM_DEAD_INFO_MAX ]; /* dead info */
266 : ulong hash_trail;
267 : ulong hash_blocks;
268 : } dead;
269 :
270 : struct {
271 : ulong ctl; /* type MOVE, style RAW, sz BLOCK_SZ */
272 : ulong seq; /* bstream seq num of this block */
273 : fd_vinyl_bstream_phdr_t src; /* src pair header */
274 : fd_vinyl_key_t dst; /* pair src.key renamed to pair dst or replaced pair dst */
275 : ulong info_sz; /* info byte size, in [0,FD_VINYL_BSTREAM_MOVE_INFO_MAX] */
276 : # if 0 /* Note: with BLOCK_SZ==128, MOVE_INFO_MAX=0 so there's no move.info field due to language limitations */
277 : uchar info[ FD_VINYL_BSTREAM_MOVE_INFO_MAX ]; /* move info */
278 : # endif
279 : ulong hash_trail;
280 : ulong hash_blocks;
281 : } move; /* Note: a move block is immediately followed by a matching pair */
282 :
283 : struct {
284 : ulong ctl; /* type PART, style RAW, sz BLOCK_SZ */
285 : ulong seq; /* bstream seq num of this block */
286 : ulong seq0; /* Partition starts at seq0 (at most seq, BLOCK_SZ aligned) */
287 : ulong dead_cnt; /* num dead blocks in this partition (for parallel recovery) */
288 : ulong move_cnt; /* num move blocks in this partition (for parallel recovery) */
289 : ulong info_sz; /* info byte size, in [0,FD_VINYL_BSTREAM_PART_INFO_MAX] */
290 : uchar info[ FD_VINYL_BSTREAM_PART_INFO_MAX ]; /* partition info */
291 : ulong hash_trail;
292 : ulong hash_blocks;
293 : } part;
294 :
295 : uchar zpad[ FD_VINYL_BSTREAM_BLOCK_SZ ]; /* all zeros (type, style, sz, hash_trail, hash_blocks ...) */
296 :
297 : uchar data[ FD_VINYL_BSTREAM_BLOCK_SZ ]; /* arbitrary (type, style, sz, hash_trail, hash_blocks ...) */
298 :
299 : };
300 :
301 : typedef union fd_vinyl_bstream_block fd_vinyl_bstream_block_t;
302 :
303 : FD_PROTOTYPES_BEGIN
304 :
305 : /* fd_vinyl_seq_* compare bstream sequence numbers, correctly handling
306 : wrap around. */
307 :
308 16447536 : FD_FN_CONST static inline int fd_vinyl_seq_lt( ulong a, ulong b ) { return ((long)(a-b))< 0L; }
309 9213480 : FD_FN_CONST static inline int fd_vinyl_seq_gt( ulong a, ulong b ) { return ((long)(a-b))> 0L; }
310 23045172 : FD_FN_CONST static inline int fd_vinyl_seq_le( ulong a, ulong b ) { return ((long)(a-b))<=0L; }
311 9426936 : FD_FN_CONST static inline int fd_vinyl_seq_ge( ulong a, ulong b ) { return ((long)(a-b))>=0L; }
312 9000000 : FD_FN_CONST static inline int fd_vinyl_seq_eq( ulong a, ulong b ) { return ((long)(a-b))==0L; }
313 10976892 : FD_FN_CONST static inline int fd_vinyl_seq_ne( ulong a, ulong b ) { return ((long)(a-b))!=0L; }
314 :
315 : /* fd_vinyl_bstream_ctl return the bstream control field that encodes a
316 : FD_VINYL_BSTREAM_CTL_TYPE_* type, FD_VINYL_BSTREAM_CTL_STYLE_* style,
317 : and a byte size in [0,2^36). fd_vinyl_bstream_ctl_* return the
318 : eponymous field from the given bstream ctl. */
319 :
320 : FD_FN_CONST static inline ulong
321 : fd_vinyl_bstream_ctl( int type,
322 : int style,
323 12000006 : ulong val_sz ) {
324 12000006 : return ((ulong)type) | (((ulong)style)<<16) | (val_sz<<28);
325 12000006 : }
326 :
327 35450319 : FD_FN_CONST static inline int fd_vinyl_bstream_ctl_type ( ulong ctl ) { return (int)( ctl & 65535UL); }
328 3000012 : FD_FN_CONST static inline int fd_vinyl_bstream_ctl_style( ulong ctl ) { return (int)((ctl>>16) & 4095UL); }
329 38450319 : FD_FN_CONST static inline ulong fd_vinyl_bstream_ctl_sz ( ulong ctl ) { return ctl>>28; }
330 :
331 : /* fd_vinyl_bstream_pair_sz returns the byte footprint of a pair with a
332 : val_esz encoded value byte size. Assumes val_esz in [0,2^48) which
333 : implies the worst case maximum encoded value size allowed is in
334 : [0,2^48). Returns a positive FD_VINYL_BSTREAM_BLOCK_SZ multiple. */
335 :
336 : FD_FN_CONST static inline ulong
337 71548440 : fd_vinyl_bstream_pair_sz( ulong val_esz ) {
338 71548440 : return fd_ulong_align_up( sizeof(fd_vinyl_bstream_phdr_t) + val_esz + FD_VINYL_BSTREAM_FTR_SZ, FD_VINYL_BSTREAM_BLOCK_SZ );
339 71548440 : }
340 :
341 : /* fd_vinyl_bstream_hash returns a 64-bit hash of the 64-bit seed and
342 : the sz byte buffer buf. Assumes buf is points to well aligned range
343 : of blocks stable for the duration of the call and sz is a multiple of
344 : FD_VINYL_BSTREAM_BLOCK_SZ. sz 0 returns seed. Retains no interest
345 : in buf. */
346 :
347 : FD_FN_PURE static inline ulong
348 : fd_vinyl_bstream_hash( ulong seed,
349 : fd_vinyl_bstream_block_t const * buf,
350 43298280 : ulong buf_sz ) {
351 43298280 : return FD_LIKELY( buf_sz ) ? fd_hash( seed, buf, buf_sz ) : seed;
352 43298280 : }
353 :
354 : /* fd_vinyl_bstream_block_hash initializes the hash fields of a bstream
355 : object that fits into a single block (i.e. a small val pair, sync
356 : block, a dead block, a move block or a part block). block's hash
357 : fields and any zero padding should be zero on entry. block's hash
358 : fields will be set correctly on exit. Assumes block is valid. */
359 :
360 : static inline void
361 : fd_vinyl_bstream_block_hash( ulong seed,
362 3748326 : fd_vinyl_bstream_block_t * block ) {
363 :
364 3748326 : ulong hash_trail = seed;
365 3748326 : ulong hash_blocks = fd_vinyl_bstream_hash( hash_trail, block, FD_VINYL_BSTREAM_BLOCK_SZ );
366 :
367 3748326 : block->ftr.hash_trail = hash_trail;
368 3748326 : block->ftr.hash_blocks = hash_blocks;
369 :
370 3748326 : }
371 :
372 : /* fd_vinyl_bstream_block_test returns FD_VINYL_SUCCESS if a bstream
373 : object that fits into a single bstream block (i.e. a small val pair,
374 : a sync block, a dead block, a move block or a part block) has valid
375 : data integrity hashes and FD_VINYL_ERR_CORRUPT if not. seed is the
376 : bstream's data integrity seed. Assumes block points to the valid
377 : stable location. block's hash fields will be clobbered on return
378 : (will be zero on success). */
379 :
380 : static inline int
381 : fd_vinyl_bstream_block_test( ulong seed,
382 9000006 : fd_vinyl_bstream_block_t * block ) {
383 :
384 9000006 : ulong hash_trail = block->ftr.hash_trail;
385 9000006 : ulong hash_blocks = block->ftr.hash_blocks;
386 :
387 9000006 : block->ftr.hash_trail = 0UL;
388 9000006 : block->ftr.hash_blocks = 0UL;
389 :
390 9000006 : if( FD_UNLIKELY( hash_trail != seed ) ||
391 9000006 : FD_UNLIKELY( fd_vinyl_bstream_hash( seed, block, FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_blocks ) )
392 6000000 : return FD_VINYL_ERR_CORRUPT;
393 :
394 3000006 : return FD_VINYL_SUCCESS;
395 9000006 : }
396 :
397 : /* fd_vinyl_bstream_pair_zero clears the footer region and any zero
398 : padding region. */
399 :
400 : void
401 : fd_vinyl_bstream_pair_zero( fd_vinyl_bstream_block_t * phdr );
402 :
403 : /* fd_vinyl_bstream_pair_hash clears the footer region and any zero
404 : padding region of pair and then populates the hash fields
405 : appropriately. seed is the bstream data integrity seed. Assumes
406 : pair points to any appropriately sized and aligned memory region and
407 : the phdr and val fields are correctly populated (in particular,
408 : val_esz is set correctly). */
409 :
410 : void
411 : fd_vinyl_bstream_pair_hash( ulong seed,
412 : fd_vinyl_bstream_block_t * phdr );
413 :
414 : /* fd_vinyl_bstream_*_test returns NULL if bstream object at seq is
415 : well formed and an infinite lifetime human-readable cstr describing
416 : the issue detected if not. The footer has been clobbered on return
417 : (will be zero on success). seed is the bstream's data integrity
418 : seed. Assumes pair points to a valid pair_sz footprint location.
419 :
420 : For fd_vinyl_bstream_pair_test, the pair is assumed fit within the
421 : the buf_sz buffer buf, not exactly fill the buffer.
422 :
423 : fd_vinyl_bstream_pair_test_fast is the same thing but omits testing
424 : any interior blocks for use in fast iteration. hdr / ftr point
425 : locations holding the first/last block in the pair. These should
426 : point to the same location if the pair fits into a single block. */
427 :
428 : char const *
429 : fd_vinyl_bstream_pair_test( ulong seed,
430 : ulong seq,
431 : fd_vinyl_bstream_block_t * buf,
432 : ulong buf_sz );
433 :
434 : char const *
435 : fd_vinyl_bstream_pair_test_fast( ulong seed,
436 : ulong seq,
437 : fd_vinyl_bstream_block_t const * hdr,
438 : fd_vinyl_bstream_block_t * ftr );
439 :
440 : char const *
441 : fd_vinyl_bstream_dead_test( ulong seed,
442 : ulong seq,
443 : fd_vinyl_bstream_block_t * block );
444 :
445 : char const *
446 : fd_vinyl_bstream_move_test( ulong seed,
447 : ulong seq,
448 : fd_vinyl_bstream_block_t * block,
449 : fd_vinyl_bstream_block_t * dst );
450 :
451 : char const *
452 : fd_vinyl_bstream_part_test( ulong seed,
453 : ulong seq,
454 : fd_vinyl_bstream_block_t * block );
455 :
456 : char const *
457 : fd_vinyl_bstream_zpad_test( ulong seed,
458 : ulong seq,
459 : fd_vinyl_bstream_block_t * block );
460 :
461 : /* fd_vinyl_bstream_ctl_style_cstr returns an infinite lifetime human
462 : readable cstr for the given style. Return value is always non-NULL
463 : (if style is not a valid style, the string will be "unk").
464 :
465 : fd_cstr_to_vinyl_bstream_ctl_style returns the style corresponding to
466 : the given cstr. Returns -1 if cstr does not correspond to a
467 : supported style. */
468 :
469 : char const *
470 : fd_vinyl_bstream_ctl_style_cstr( int style );
471 :
472 : int
473 : fd_cstr_to_vinyl_bstream_ctl_style( char const * cstr );
474 :
475 : #if FD_HAS_AVX512 && defined(__AVX512DQ__)
476 :
477 : /* fd_vinyl_bstream_hash_batch8 does 8 fd_vinyl_bstream_hash()
478 : computations in parallel. out, buf, sz point to arrays of 8 elements
479 : respectively. */
480 :
481 : FD_FN_PURE void
482 : fd_vinyl_bstream_hash_batch8( ulong const * FD_RESTRICT seed,
483 : ulong * FD_RESTRICT out,
484 : void const * FD_RESTRICT * FD_RESTRICT buf,
485 : ulong const * FD_RESTRICT sz );
486 :
487 : #endif
488 :
489 : FD_PROTOTYPES_END
490 :
491 : #endif /* HEADER_fd_src_vinyl_bstream_fd_vinyl_bstream_h */
|