Line data Source code
1 : #ifndef HEADER_fd_src_funk_fd_funk_val_h 2 : #define HEADER_fd_src_funk_fd_funk_val_h 3 : 4 : /* This provides APIs for managing funk record values. It is generally 5 : not meant to be included directly. Use fd_funk.h instead. */ 6 : 7 : #include "fd_funk_rec.h" /* Includes fd_funk_txn.h, fd_funk_base.h */ 8 : 9 : /* FD_FUNK_REC_VAL_MAX is the maximum size of a record value. */ 10 : 11 7305801 : #define FD_FUNK_REC_VAL_MAX ((1UL<<28)-1UL) 12 : #define FD_FUNK_VAL_ALIGN (8UL) 13 : 14 53352372 : #define FD_FUNK_VAL_SHRINK_FREE_THRESHOLD (512UL<<10) /* 512 KiB */ 15 : 16 : FD_PROTOTYPES_BEGIN 17 : 18 : /* Accessors */ 19 : 20 : /* fd_funk_val_{sz,max} returns the current size of the value associated 21 : with a record and the amount of wksp allocated currently for a value. 22 : Assumes funk is a current local join. These value might change on 23 : subsequent calls if the record is resized. 24 : 0<=sz<=max<=FD_FUNK_REC_VAL_MAX. */ 25 : 26 : FD_FN_PURE static inline ulong /* Current size of the record's value in bytes */ 27 0 : fd_funk_val_sz( fd_funk_rec_t const * rec ) { /* Assumes pointer in caller's address space to a live funk record */ 28 0 : return (ulong)rec->val_sz; /* Covers the marked ERASE case too */ 29 0 : } 30 : 31 : FD_FN_PURE static inline ulong /* Current size of the record's value allocation in bytes */ 32 0 : fd_funk_val_max( fd_funk_rec_t const * rec ) { /* Assumes pointer in caller's address space to a live funk record */ 33 0 : return (ulong)rec->val_max; /* Covers the marked ERASE case too */ 34 0 : } 35 : 36 : /* fd_funk_val returns a pointer in the caller's address space to the 37 : current value associated with a record. fd_funk_rec_val_const is a 38 : const-correct version. There are sz bytes at the returned pointer. 39 : IMPORTANT SAFETY TIP! There are _no_ alignment guarantees on the 40 : returned value. Returns NULL if the record has a zero sz (which also 41 : covers the case where rec has been marked ERASE). max 0 implies val 42 : NULL and vice versa. Assumes no concurrent operations on rec. */ 43 : 44 : FD_FN_PURE static inline void * /* Lifetime is the lesser of rec or the value size is modified */ 45 : fd_funk_val( fd_funk_rec_t const * rec, /* Assumes pointer in caller's address space to a live funk record */ 46 3601971 : fd_wksp_t const * wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */ 47 3601971 : ulong val_gaddr = rec->val_gaddr; 48 3601971 : if( !val_gaddr ) return NULL; /* Covers the marked ERASE case too */ /* TODO: consider branchless */ 49 3601971 : return fd_wksp_laddr_fast( wksp, val_gaddr ); 50 3601971 : } 51 : 52 : FD_FN_PURE static inline void const * /* Lifetime is the lesser of rec or the value size is modified */ 53 : fd_funk_val_const( fd_funk_rec_t const * rec, /* Assumes pointer in caller's address space to a live funk record */ 54 48 : fd_wksp_t const * wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */ 55 48 : ulong val_gaddr = rec->val_gaddr; 56 48 : if( !val_gaddr ) return NULL; /* Covers the marked ERASE case too */ /* TODO: consider branchless */ 57 48 : return fd_wksp_laddr_fast( wksp, val_gaddr ); 58 48 : } 59 : 60 : FD_FN_CONST static inline int 61 : fd_funk_val_shrink_compacts( ulong sz, 62 54641670 : ulong val_max ) { 63 54641670 : return (sz<val_max) && 64 54641670 : ( ( (5UL*sz)<(4UL*val_max) ) | 65 28180401 : ( (val_max-sz)>FD_FUNK_VAL_SHRINK_FREE_THRESHOLD ) ); 66 54641670 : } 67 : 68 : /* fd_funk_val_truncate resizes a record to be new_val_sz bytes in 69 : size. Invalidates val_gaddr. 70 : 71 : If the requested size is larger than the current allocation, this 72 : reallocates the record. If the requested size is smaller than the 73 : current allocation, reallocates if fd_funk_val_shrink_compacts()==1. 74 : 75 : Returns a pointer to the value memory on success and NULL on 76 : failure. If opt_err is non-NULL, on return, *opt_err will hold 77 : FD_FUNK_SUCCESS if successful or a FD_FUNK_ERR_* code on 78 : failure. Reasons for failure include FD_FUNK_ERR_INVAL (NULL 79 : rec, too large new_val_sz, rec is marked ERASE) and 80 : FD_FUNK_ERR_MEM (allocation failure, need a larger wksp). On 81 : failure, the current value is unchanged. 82 : 83 : Assumes no concurrent operations on rec. */ 84 : 85 : void * /* Returns record value on success, NULL on failure */ 86 : fd_funk_val_truncate( fd_funk_rec_t * rec, /* Assumed in caller's address space to a live funk record (NULL returns NULL) */ 87 : fd_alloc_t * alloc, /* ==fd_funk_alloc( funk, wksp ) */ 88 : fd_wksp_t * wksp, /* ==fd_funk_wksp( funk ) where funk is current local join */ 89 : ulong align, /* Must be a power of 2. 0 uses the fd_funk_alloc_malloc default alignment. */ 90 : ulong sz, /* Should be in [0,FD_FUNK_REC_VAL_MAX] (returns NULL otherwise) */ 91 : int * opt_err ); /* If non-NULL, *opt_err returns operation error code */ 92 : 93 : /* Misc */ 94 : 95 : /* fd_funk_val_init sets a record with uninitialized value metadata to 96 : the NULL value. Meant for internal use. */ 97 : 98 : static inline fd_funk_rec_t * /* Returns rec */ 99 2648448 : fd_funk_val_init( fd_funk_rec_t * rec ) { /* Assumed record in caller's address space with uninitialized value metadata */ 100 2648448 : rec->val_sz = 0U; 101 2648448 : rec->val_max = 0U; 102 2648448 : rec->val_gaddr = 0UL; 103 2648448 : return rec; 104 2648448 : } 105 : 106 : /* fd_funk_val_flush sets a record to the NULL value, discarding the 107 : current value if any. Meant for internal use. */ 108 : 109 : static inline fd_funk_rec_t * /* Returns rec */ 110 : fd_funk_val_flush( fd_funk_rec_t * rec, /* Assumed live funk record in caller's address space */ 111 : fd_alloc_t * alloc, /* ==fd_funk_alloc( funk, wksp ) */ 112 1371480 : fd_wksp_t * wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */ 113 1371480 : ulong val_gaddr = rec->val_gaddr; 114 1371480 : fd_funk_val_init( rec ); 115 1371480 : FD_COMPILER_MFENCE(); /* Make sure we don't double free on crash recovery */ 116 1371480 : if( val_gaddr ) fd_alloc_free( alloc, fd_wksp_laddr_fast( wksp, val_gaddr ) ); 117 1371480 : return rec; 118 1371480 : } 119 : 120 : /* fd_funk_val_verify verifies the record values. Returns 121 : FD_FUNK_SUCCESS if the values appear intact and FD_FUNK_ERR_INVAL if 122 : not (logs details). Meant to be called as part of fd_funk_verify. 123 : As such, it assumes funk is non-NULL, fd_funk_{wksp,rec_map,wksp_tag} 124 : have been verified to work and the rec_map has been verified. */ 125 : 126 : int 127 : fd_funk_val_verify( fd_funk_t * funk ); 128 : 129 : FD_PROTOTYPES_END 130 : 131 : /* TODO: Retune fd_alloc and fd_wksp for Solana record size optimized 132 : size classes and transition point to fd_wksp backing. */ 133 : 134 : #endif /* HEADER_fd_src_funk_fd_funk_val_h */