LCOV - code coverage report
Current view: top level - vinyl/bstream - fd_vinyl_bstream.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 41 49 83.7 %
Date: 2025-12-07 04:58:33 Functions: 50 602 8.3 %

          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 direct 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 direct I/O friendly power-of-2 (i.e. a power-of-2 >=
     172             :    512).  FD_VINYL_BSTEAM_BLOCK_LG_SZ gives the log2 of this. */
     173             : 
     174   164428158 : #define FD_VINYL_BSTREAM_BLOCK_SZ    (512UL)
     175           0 : #define FD_VINYL_BSTREAM_BLOCK_LG_SZ (9)
     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    80308878 : #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 direct I/O requires our memory alignments to
     235             :    match device 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             :     uchar                   info[ FD_VINYL_BSTREAM_MOVE_INFO_MAX ]; /* move info */
     277             :     ulong                   hash_trail;
     278             :     ulong                   hash_blocks;
     279             :   } move; /* Note: a move block is immediately followed by a matching pair */
     280             : 
     281             :   struct {
     282             :     ulong                   ctl;                                    /* type PART, style RAW, sz BLOCK_SZ */
     283             :     ulong                   seq;                                    /* bstream seq num of this block */
     284             :     ulong                   seq0;                                   /* Partition starts at seq0 (at most seq, BLOCK_SZ aligned) */
     285             :     ulong                   dead_cnt;                               /* num dead blocks in this partition (for parallel recovery) */
     286             :     ulong                   move_cnt;                               /* num move blocks in this partition (for parallel recovery) */
     287             :     ulong                   info_sz;                                /* info byte size, in [0,FD_VINYL_BSTREAM_PART_INFO_MAX] */
     288             :     uchar                   info[ FD_VINYL_BSTREAM_PART_INFO_MAX ]; /* partition info */
     289             :     ulong                   hash_trail;
     290             :     ulong                   hash_blocks;
     291             :   } part;
     292             : 
     293             :   uchar zpad[ FD_VINYL_BSTREAM_BLOCK_SZ ]; /* all zeros (type, style, sz, hash_trail, hash_blocks ...) */
     294             : 
     295             :   uchar data[ FD_VINYL_BSTREAM_BLOCK_SZ ]; /* arbitrary (type, style, sz, hash_trail, hash_blocks ...) */
     296             : 
     297             : };
     298             : 
     299             : typedef union fd_vinyl_bstream_block fd_vinyl_bstream_block_t;
     300             : 
     301             : FD_PROTOTYPES_BEGIN
     302             : 
     303             : /* fd_vinyl_seq_* compare bstream sequence numbers, correctly handling
     304             :    wrap around. */
     305             : 
     306    16113000 : FD_FN_CONST static inline int fd_vinyl_seq_lt( ulong a, ulong b ) { return ((long)(a-b))< 0L; }
     307     9264228 : FD_FN_CONST static inline int fd_vinyl_seq_gt( ulong a, ulong b ) { return ((long)(a-b))> 0L; }
     308    22702188 : FD_FN_CONST static inline int fd_vinyl_seq_le( ulong a, ulong b ) { return ((long)(a-b))<=0L; }
     309     9528432 : FD_FN_CONST static inline int fd_vinyl_seq_ge( ulong a, ulong b ) { return ((long)(a-b))>=0L; }
     310     9000000 : FD_FN_CONST static inline int fd_vinyl_seq_eq( ulong a, ulong b ) { return ((long)(a-b))==0L; }
     311    11029572 : FD_FN_CONST static inline int fd_vinyl_seq_ne( ulong a, ulong b ) { return ((long)(a-b))!=0L; }
     312             : 
     313             : /* fd_vinyl_bstream_ctl return the bstream control field that encodes a
     314             :    FD_VINYL_BSTREAM_CTL_TYPE_* type, FD_VINYL_BSTREAM_CTL_STYLE_* style,
     315             :    and a byte size in [0,2^36).  fd_vinyl_bstream_ctl_* return the
     316             :    eponymous field from the given bstream ctl. */
     317             : 
     318             : FD_FN_CONST static inline ulong
     319             : fd_vinyl_bstream_ctl( int   type,
     320             :                       int   style,
     321    12000006 :                       ulong val_sz ) {
     322    12000006 :   return ((ulong)type) | (((ulong)style)<<16) | (val_sz<<28);
     323    12000006 : }
     324             : 
     325    35095158 : FD_FN_CONST static inline int   fd_vinyl_bstream_ctl_type ( ulong ctl ) { return (int)( ctl      & 65535UL); }
     326     3000012 : FD_FN_CONST static inline int   fd_vinyl_bstream_ctl_style( ulong ctl ) { return (int)((ctl>>16) &  4095UL); }
     327    38095158 : FD_FN_CONST static inline ulong fd_vinyl_bstream_ctl_sz   ( ulong ctl ) { return        ctl>>28;             }
     328             : 
     329             : /* fd_vinyl_bstream_pair_sz returns the byte footprint of a pair with a
     330             :    val_esz encoded value byte size.  Assumes val_esz in [0,2^48) which
     331             :    implies the worst case maximum encoded value size allowed is in
     332             :    [0,2^48).  Returns a positive FD_VINYL_BSTREAM_BLOCK_SZ multiple. */
     333             : 
     334             : FD_FN_CONST static inline ulong
     335    53127477 : fd_vinyl_bstream_pair_sz( ulong val_esz ) {
     336    53127477 :   return fd_ulong_align_up( sizeof(fd_vinyl_bstream_phdr_t) + val_esz + FD_VINYL_BSTREAM_FTR_SZ, FD_VINYL_BSTREAM_BLOCK_SZ );
     337    53127477 : }
     338             : 
     339             : /* fd_vinyl_bstream_hash returns a 64-bit hash of the 64-bit seed and
     340             :    the sz byte buffer buf.  Assumes buf is points to well aligned range
     341             :    of blocks stable for the duration of the call and sz is a multiple of
     342             :    FD_VINYL_BSTREAM_BLOCK_SZ.  sz 0 returns seed.  Retains no interest
     343             :    in buf. */
     344             : 
     345             : FD_FN_PURE static inline ulong
     346             : fd_vinyl_bstream_hash( ulong                            seed,
     347             :                        fd_vinyl_bstream_block_t const * buf,
     348    43653492 :                        ulong                            buf_sz ) {
     349    43653492 :   return FD_LIKELY( buf_sz ) ? fd_hash( seed, buf, buf_sz ) : seed;
     350    43653492 : }
     351             : 
     352             : /* fd_vinyl_bstream_block_hash initializes the hash fields of a bstream
     353             :    object that fits into a single block (i.e. a small val pair, sync
     354             :    block, a dead block, a move block or a part block).  block's hash
     355             :    fields and any zero padding should be zero on entry.  block's hash
     356             :    fields will be set correctly on exit.  Assumes block is valid. */
     357             : 
     358             : static inline void
     359             : fd_vinyl_bstream_block_hash( ulong                      seed,
     360     3748884 :                              fd_vinyl_bstream_block_t * block ) {
     361             : 
     362     3748884 :   ulong hash_trail  = seed;
     363     3748884 :   ulong hash_blocks = fd_vinyl_bstream_hash( hash_trail, block, FD_VINYL_BSTREAM_BLOCK_SZ );
     364             : 
     365     3748884 :   block->ftr.hash_trail  = hash_trail;
     366     3748884 :   block->ftr.hash_blocks = hash_blocks;
     367             : 
     368     3748884 : }
     369             : 
     370             : /* fd_vinyl_bstream_block_test returns FD_VINYL_SUCCESS if a bstream
     371             :    object that fits into a single bstream block (i.e. a small val pair,
     372             :    a sync block, a dead block, a move block or a part block) has valid
     373             :    data integrity hashes and FD_VINYL_ERR_CORRUPT if not.  seed is the
     374             :    bstream's data integrity seed.  Assumes block points to the valid
     375             :    stable location.  block's hash fields will be clobbered on return
     376             :    (will be zero on success). */
     377             : 
     378             : static inline int
     379             : fd_vinyl_bstream_block_test( ulong                      seed,
     380     9000006 :                              fd_vinyl_bstream_block_t * block ) {
     381             : 
     382     9000006 :   ulong hash_trail  = block->ftr.hash_trail;
     383     9000006 :   ulong hash_blocks = block->ftr.hash_blocks;
     384             : 
     385     9000006 :   block->ftr.hash_trail  = 0UL;
     386     9000006 :   block->ftr.hash_blocks = 0UL;
     387             : 
     388     9000006 :   if( FD_UNLIKELY( hash_trail                                                      != seed        ) ||
     389     9000006 :       FD_UNLIKELY( fd_vinyl_bstream_hash( seed, block, FD_VINYL_BSTREAM_BLOCK_SZ ) != hash_blocks ) )
     390     6000000 :     return FD_VINYL_ERR_CORRUPT;
     391             : 
     392     3000006 :   return FD_VINYL_SUCCESS;
     393     9000006 : }
     394             : 
     395             : /* fd_vinyl_bstream_pair_zero clears the footer region and any zero
     396             :    padding region. */
     397             : 
     398             : void
     399             : fd_vinyl_bstream_pair_zero( fd_vinyl_bstream_block_t * phdr );
     400             : 
     401             : /* fd_vinyl_bstream_pair_hash clears the footer region and any zero
     402             :    padding region of pair and then populates the hash fields
     403             :    appropriately.  seed is the bstream data integrity seed.  Assumes
     404             :    pair points to any appropriately sized and aligned memory region and
     405             :    the phdr and val fields are correctly populated (in particular,
     406             :    val_esz is set correctly). */
     407             : 
     408             : void
     409             : fd_vinyl_bstream_pair_hash( ulong                      seed,
     410             :                             fd_vinyl_bstream_block_t * phdr );
     411             : 
     412             : /* fd_vinyl_bstream_*_test returns NULL if bstream object at seq is
     413             :    well formed and an infinite lifetime human-readable cstr describing
     414             :    the issue detected if not.  The footer has been clobbered on return
     415             :    (will be zero on success).  seed is the bstream's data integrity
     416             :    seed.  Assumes pair points to a valid pair_sz footprint location.
     417             : 
     418             :    For fd_vinyl_bstream_pair_test, the pair is assumed fit within the
     419             :    the buf_sz buffer buf, not exactly fill the buffer.
     420             : 
     421             :    fd_vinyl_bstream_pair_test_fast is the same thing but omits testing
     422             :    any interior blocks for use in fast iteration.  hdr / ftr point
     423             :    locations holding the first/last block in the pair.  These should
     424             :    point to the same location if the pair fits into a single block. */
     425             : 
     426             : char const *
     427             : fd_vinyl_bstream_pair_test( ulong                      seed,
     428             :                             ulong                      seq,
     429             :                             fd_vinyl_bstream_block_t * buf,
     430             :                             ulong                      buf_sz );
     431             : 
     432             : char const *
     433             : fd_vinyl_bstream_pair_test_fast( ulong                            seed,
     434             :                                  ulong                            seq,
     435             :                                  fd_vinyl_bstream_block_t const * hdr,
     436             :                                  fd_vinyl_bstream_block_t *       ftr );
     437             : 
     438             : char const *
     439             : fd_vinyl_bstream_dead_test( ulong                      seed,
     440             :                             ulong                      seq,
     441             :                             fd_vinyl_bstream_block_t * block );
     442             : 
     443             : char const *
     444             : fd_vinyl_bstream_move_test( ulong                      seed,
     445             :                             ulong                      seq,
     446             :                             fd_vinyl_bstream_block_t * block,
     447             :                             fd_vinyl_bstream_block_t * dst );
     448             : 
     449             : char const *
     450             : fd_vinyl_bstream_part_test( ulong                      seed,
     451             :                             ulong                      seq,
     452             :                             fd_vinyl_bstream_block_t * block );
     453             : 
     454             : char const *
     455             : fd_vinyl_bstream_zpad_test( ulong                      seed,
     456             :                             ulong                      seq,
     457             :                             fd_vinyl_bstream_block_t * block );
     458             : 
     459             : /* fd_vinyl_bstream_ctl_style_cstr returns an infinite lifetime human
     460             :    readable cstr for the given style.  Return value is always non-NULL
     461             :    (if style is not a valid style, the string will be "unk").
     462             : 
     463             :    fd_cstr_to_vinyl_bstream_ctl_style returns the style corresponding to
     464             :    the given cstr.  Returns -1 if cstr does not correspond to a
     465             :    supported style. */
     466             : 
     467             : char const *
     468             : fd_vinyl_bstream_ctl_style_cstr( int style );
     469             : 
     470             : int
     471             : fd_cstr_to_vinyl_bstream_ctl_style( char const * cstr );
     472             : 
     473             : #if FD_HAS_AVX512 && defined(__AVX512DQ__)
     474             : 
     475             : /* fd_vinyl_bstream_hash_batch8 does 8 fd_vinyl_bstream_hash()
     476             :    computations in parallel.  out, buf, sz point to arrays of 8 elements
     477             :    respectively. */
     478             : 
     479             : FD_FN_PURE void
     480             : fd_vinyl_bstream_hash_batch8( ulong const *              FD_RESTRICT seed,
     481             :                               ulong *                    FD_RESTRICT out,
     482             :                               void const * FD_RESTRICT * FD_RESTRICT buf,
     483             :                               ulong const *              FD_RESTRICT sz );
     484             : 
     485             : #endif
     486             : 
     487             : FD_PROTOTYPES_END
     488             : 
     489             : #endif /* HEADER_fd_src_vinyl_bstream_fd_vinyl_bstream_h */

Generated by: LCOV version 1.14