LCOV - code coverage report
Current view: top level - groove - fd_groove_volume.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 5 5 100.0 %
Date: 2025-03-20 12:08:36 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_groove_fd_groove_volume_h
       2             : #define HEADER_fd_src_groove_fd_groove_volume_h
       3             : 
       4             : #include "fd_groove_base.h" /* includes ../util/fd_util.h */
       5             : 
       6             : /* Groove data objects are stored in groove volumes.  A volume has a
       7             :    uniform size of FD_GROOVE_VOLUME_FOOTPRINT and a unique index.  A
       8             :    volume is mapped into the caller's address space starting at
       9             :    (ulong)volume0+idx*FD_GROOVE_VOLUME_FOOTPRINT where volume0 is the
      10             :    start of a region in the user's address space with enough room to
      11             :    accommodate mapping current and future volumes.  To support
      12             :    persistent and IPC usage across different applications, concurrent
      13             :    users can use different values for volume0.
      14             : 
      15             :    Volume indexing does not need to be contiguous or start at zero.
      16             :    Further, there is no theoretical limit on the number of volumes.
      17             :    Practically, the above implies that the address region footprint in
      18             :    the caller's address space is
      19             : 
      20             :      (max_idx_in_use+1)*FD_GROOVE_VOLUME_FOOTPRINT.
      21             : 
      22             :    As the FD machine model targets 64-bit address spaces, this implies a
      23             :    groove instance practically can hold at most < 2^64 B (16 EiB).
      24             :    (Note that 50 billion data objects at a worst case 10 MiB per object
      25             :    requires less than 0.5 EiB so this is not a limitation in practice.)
      26             : 
      27             :    To support commodity hardware and operating systems efficiently,
      28             :    volume0 should have at least normal page alignment and
      29             :    FD_GROOVE_VOLUME_FOOTPRINT should be a normal page multiple.  For
      30             :    highest performance on such systems, 1 GiB aligned volume0 with
      31             :    gigantic page DRAM backed volumes are recommended but this is not
      32             :    required.  E.g. it is fine for volumes to be a memory mapped file
      33             :    backed by a NVMe/SSD/RAID array.  This implementation uses a
      34             :    FD_GROOVE_VOLUME_FOOTPRINT of 1 GiB.
      35             : 
      36             :    Volumes can be backed by different technologies.  Note that while
      37             :    heterogeneous volumes are supported, this implementation does not
      38             :    treat a volume backed by fast DRAM differently from a volume backed
      39             :    by a tape drive.
      40             : 
      41             :    Empty groove volumes are stored on a lockfree stack to support adding
      42             :    / removing volumes from a groove instance dynamically without
      43             :    impacting on-going groove operations.  E.g. to increase the groove's
      44             :    capacity, create a volume at an unused index and lockfree push it
      45             :    onto the groove's empty volume stack.  To decrease capacity, pop the
      46             :    stack and reclaim the returned volume. */
      47             : 
      48             : /* FIXME: consider allowing larger volume headers (or adding a
      49             :    volume footer) to not waste ~15KiB space with pading */
      50             : 
      51             : #define FD_GROOVE_VOLUME_ALIGN     (4096UL)
      52         507 : #define FD_GROOVE_VOLUME_FOOTPRINT (1UL<<30)
      53      449592 : #define FD_GROOVE_VOLUME_MAGIC     (0xfd67007e701c3300) /* fd groove volume version 0 */
      54   136366497 : #define FD_GROOVE_VOLUME_INFO_MAX  (FD_GROOVE_BLOCK_FOOTPRINT-32UL)
      55          15 : #define FD_GROOVE_VOLUME_DATA_MAX  (FD_GROOVE_VOLUME_FOOTPRINT-FD_GROOVE_BLOCK_FOOTPRINT)
      56             : 
      57             : struct __attribute__((aligned(FD_GROOVE_VOLUME_ALIGN))) fd_groove_volume {
      58             : 
      59             :   /* This point is aligned FD_GROOVE_VOLUME_ALIGN >= FD_GROOVE_BLOCK_ALIGN */
      60             : 
      61             :   ulong magic;   /* == FD_GROOVE_VOLUME_MAGIC if volume potentially contains groove data allocations,
      62             :                     ==~FD_GROOVE_VOLUME_MAGIC if volume contains no groove data allocations,
      63             :                     other values -> not a volume */
      64             :   ulong idx;     /* Volume index (this is mapped into the user's address space at groove->volume0 + idx) */
      65             :   ulong next;    /* Managed by the groove volume pool */
      66             :   ulong info_sz; /* in [0,INFO_MAX] */
      67             : 
      68             :   /* This point is aligned 32 */
      69             : 
      70             :   uchar info[ FD_GROOVE_VOLUME_INFO_MAX ]; /* info_sz bytes of user info, bytes [info_sz,INFO_MAX) are arbitrary */
      71             : 
      72             :   /* This point is aligned FD_GROOVE_BLOCK_ALIGN */
      73             : 
      74             :   uchar data[ FD_GROOVE_VOLUME_DATA_MAX ];
      75             : };
      76             : 
      77             : typedef struct fd_groove_volume fd_groove_volume_t;
      78             : 
      79             : /* Note: given a 2^30 volume footprint, a POOL_IDX_WIDTH of 34
      80             :    supports up ~2^34 volumes for up to a ~2^64 groove data storage.
      81             :    (For the default pool index width, this could go as high as
      82             :    fd_groove_pool_max_max ~ 2^43 but it would not be possible to memory
      83             :    map such a set of volumes on 64-bit architectures.) */
      84             : 
      85             : #define POOL_NAME       fd_groove_volume_pool
      86             : #define POOL_ELE_T      fd_groove_volume_t
      87     4496757 : #define POOL_IDX_WIDTH  (34)
      88             : #define POOL_MAGIC      (0xfd67007e70190010UL) /* fd groove vol pool version 0 */
      89             : #define POOL_IMPL_STYLE 1
      90             : #include "../util/tmpl/fd_pool_para.c"
      91             : 
      92             : FD_PROTOTYPES_BEGIN
      93             : 
      94             : /* fd_groove_volume_pool_add adds the footprint sized memory region
      95             :    whose first byte is at shmem in the caller's local address space to
      96             :    the pool.  Assumes pool is a current local join, the storage to add
      97             :    is mapped into a memory region that starts and stops at a
      98             :    FD_GROOVE_VOLUME_FOOTPRINT multiple offset in the pool's address
      99             :    space, and this memory region does not conflict with any current
     100             :    groove volumes.
     101             : 
     102             :    The volume info for these will be initialized to the info_sz bytes
     103             :    pointed in the caller's local address space by info.  info_sz will
     104             :    treated as zero if info is NULL.  info_sz>FD_GROOVE_VOLUME_INFO_MAX
     105             :    will be treated as FD_GROOVE_VOLUME_INFO_MAX.  If
     106             :    info_sz<FD_GROOVE_VOLUME_INFO_MAX, any uninitialized bytes info will
     107             :    be initialized to zero.  Retains no interest in info.
     108             : 
     109             :    It is the caller's responsibility to zero / initialize any volume
     110             :    data region bytes (usually not necessary).
     111             : 
     112             :    On success, returns FD_GROOVE_SUCCESS (zero), the volumes were added
     113             :    to the pool as empty and the pool has ownership of the volumes.
     114             : 
     115             :    On failure, returns a FD_GROOVE_ERR code (negative, logs details).
     116             :    Reasons for failure include INVAL (pool is obviously not a local
     117             :    join, shmem/footprint obviously not a valid mapping ... no volumes
     118             :    added) and CORRUPT (memory corruption was detected ... if this was
     119             :    adding multiple volumes, some volumes might have been added before
     120             :    the corruption was encountered).
     121             : 
     122             :    This is safe to use concurrently, will not block the caller
     123             :    (reasonably fast O(volume_cnt) worst case) and will not block
     124             :    concurrent pool users. */
     125             : 
     126             : int
     127             : fd_groove_volume_pool_add( fd_groove_volume_pool_t * pool,
     128             :                            void *                    shmem,
     129             :                            ulong                     footprint,
     130             :                            void const *              info,
     131             :                            ulong                     info_sz );
     132             : 
     133             : /* fd_groove_volume_pool_remove removes an empty volume from the pool.
     134             :    On success, returns the location in the caller's address space of the
     135             :    removed volume (the volume will no longer be in the pool and the
     136             :    caller has ownership).  On failure, returns NULL (e.g. no volumes in
     137             :    pool were empty at some point during the call).  Logs details if
     138             :    anything wonky was detected.
     139             : 
     140             :    This is safe to use concurrently, will not block the caller
     141             :    (reasonably fast O(1) worst case) and will not block concurrent pool
     142             :    users. */
     143             : 
     144             : void *
     145             : fd_groove_volume_pool_remove( fd_groove_volume_pool_t * pool );
     146             : 
     147             : FD_PROTOTYPES_END
     148             : 
     149             : #endif /* HEADER_fd_src_groove_fd_groove_volume_h */

Generated by: LCOV version 1.14