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 22479264 : #define FD_FUNK_REC_VAL_MAX (UINT_MAX) 12 : #define FD_FUNK_VAL_ALIGN (8UL) 13 : 14 : FD_PROTOTYPES_BEGIN 15 : 16 : /* Accessors */ 17 : 18 : /* fd_funk_val_{sz,max} returns the current size of the value associated 19 : with a record and the amount of wksp allocated currently for a value. 20 : Assumes funk is a current local join. These value might change on 21 : subsequent calls if the record is resized. 22 : 0<=sz<=max<=FD_FUNK_REC_VAL_MAX. */ 23 : 24 : FD_FN_PURE static inline ulong /* Current size of the record's value in bytes */ 25 41433877 : fd_funk_val_sz( fd_funk_rec_t const * rec ) { /* Assumes pointer in caller's address space to a live funk record */ 26 41433877 : return (ulong)rec->val_sz; /* Covers the marked ERASE case too */ 27 41433877 : } 28 : 29 : FD_FN_PURE static inline ulong /* Current size of the record's value allocation in bytes */ 30 0 : fd_funk_val_max( fd_funk_rec_t const * rec ) { /* Assumes pointer in caller's address space to a live funk record */ 31 0 : return (ulong)rec->val_max; /* Covers the marked ERASE case too */ 32 0 : } 33 : 34 : /* fd_funk_val returns a pointer in the caller's address space to the 35 : current value associated with a record. fd_funk_rec_val_const is a 36 : const-correct version. There are sz bytes at the returned pointer. 37 : IMPORTANT SAFETY TIP! There are _no_ alignment guarantees on the 38 : returned value. Returns NULL if the record has a zero sz (which also 39 : covers the case where rec has been marked ERASE). max 0 implies val 40 : NULL and vice versa. Assumes no concurrent operations on rec. */ 41 : 42 : FD_FN_PURE static inline void * /* Lifetime is the lesser of rec or the value size is modified */ 43 : fd_funk_val( fd_funk_rec_t const * rec, /* Assumes pointer in caller's address space to a live funk record */ 44 60195838 : fd_wksp_t const * wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */ 45 60195838 : ulong val_gaddr = rec->val_gaddr; 46 60195838 : if( !val_gaddr ) return NULL; /* Covers the marked ERASE case too */ /* TODO: consider branchless */ 47 58250860 : return fd_wksp_laddr_fast( wksp, val_gaddr ); 48 60195838 : } 49 : 50 : FD_FN_PURE static inline void const * /* Lifetime is the lesser of rec or the value size is modified */ 51 : fd_funk_val_const( fd_funk_rec_t const * rec, /* Assumes pointer in caller's address space to a live funk record */ 52 15 : fd_wksp_t const * wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */ 53 15 : ulong val_gaddr = rec->val_gaddr; 54 15 : if( !val_gaddr ) return NULL; /* Covers the marked ERASE case too */ /* TODO: consider branchless */ 55 15 : return fd_wksp_laddr_fast( wksp, val_gaddr ); 56 15 : } 57 : 58 : /* fd_funk_val_truncate resizes a record to be new_val_sz bytes in 59 : size. 60 : 61 : This function is optimized for the user knowing the actual long term 62 : record size when they call this. 63 : 64 : Regardless of the current and new value sizes, this will 65 : always attempt to resize the record in order to minimize the amount 66 : of excess allocation used by the record. So this function should be 67 : assumed to kill any existing pointers into this record's value 68 : storage. 69 : 70 : Returns a pointer to the value memory on success and NULL on 71 : failure. If opt_err is non-NULL, on return, *opt_err will hold 72 : FD_FUNK_SUCCESS if successful or a FD_FUNK_ERR_* code on 73 : failure. Reasons for failure include FD_FUNK_ERR_INVAL (NULL 74 : rec, too large new_val_sz, rec is marked ERASE) and 75 : FD_FUNK_ERR_MEM (allocation failure, need a larger wksp). On 76 : failure, the current value is unchanged. 77 : 78 : Assumes no concurrent operations on rec. */ 79 : 80 : void * /* Returns record value on success, NULL on failure */ 81 : fd_funk_val_truncate( fd_funk_rec_t * rec, /* Assumed in caller's address space to a live funk record (NULL returns NULL) */ 82 : fd_alloc_t * alloc, /* ==fd_funk_alloc( funk, wksp ) */ 83 : fd_wksp_t * wksp, /* ==fd_funk_wksp( funk ) where funk is current local join */ 84 : ulong align, /* Must be a power of 2. 0 uses the fd_funk_alloc_malloc default alignment. */ 85 : ulong sz, /* Should be in [0,FD_FUNK_REC_VAL_MAX] (returns NULL otherwise) */ 86 : int * opt_err ); /* If non-NULL, *opt_err returns operation error code */ 87 : 88 : /* Misc */ 89 : 90 : /* fd_funk_val_init sets a record with uninitialized value metadata to 91 : the NULL value. Meant for internal use. */ 92 : 93 : static inline fd_funk_rec_t * /* Returns rec */ 94 46803822 : fd_funk_val_init( fd_funk_rec_t * rec ) { /* Assumed record in caller's address space with uninitialized value metadata */ 95 46803822 : rec->val_sz = 0U; 96 46803822 : rec->val_max = 0U; 97 46803822 : rec->val_gaddr = 0UL; 98 46803822 : return rec; 99 46803822 : } 100 : 101 : /* fd_funk_val_flush sets a record to the NULL value, discarding the 102 : current value if any. Meant for internal use. */ 103 : 104 : static inline fd_funk_rec_t * /* Returns rec */ 105 : fd_funk_val_flush( fd_funk_rec_t * rec, /* Assumed live funk record in caller's address space */ 106 : fd_alloc_t * alloc, /* ==fd_funk_alloc( funk, wksp ) */ 107 23709087 : fd_wksp_t * wksp ) { /* ==fd_funk_wksp( funk ) where funk is a current local join */ 108 23709087 : ulong val_gaddr = rec->val_gaddr; 109 23709087 : fd_funk_val_init( rec ); 110 23709087 : FD_COMPILER_MFENCE(); /* Make sure we don't double free on crash recovery */ 111 23709087 : if( val_gaddr ) fd_alloc_free( alloc, fd_wksp_laddr_fast( wksp, val_gaddr ) ); 112 23709087 : return rec; 113 23709087 : } 114 : 115 : /* fd_funk_val_verify verifies the record values. Returns 116 : FD_FUNK_SUCCESS if the values appear intact and FD_FUNK_ERR_INVAL if 117 : not (logs details). Meant to be called as part of fd_funk_verify. 118 : As such, it assumes funk is non-NULL, fd_funk_{wksp,rec_map,wksp_tag} 119 : have been verified to work and the rec_map has been verified. */ 120 : 121 : int 122 : fd_funk_val_verify( fd_funk_t * funk ); 123 : 124 : FD_PROTOTYPES_END 125 : 126 : /* TODO: Retune fd_alloc and fd_wksp for Solana record size optimized 127 : size classes and transition point to fd_wksp backing. */ 128 : 129 : #endif /* HEADER_fd_src_funk_fd_funk_val_h */