Line data Source code
1 : #include "fd_funk_private.h" 2 : 3 : void * 4 : fd_funk_val_truncate( fd_funk_rec_t * rec, 5 : fd_alloc_t * alloc, 6 : fd_wksp_t * wksp, 7 : ulong align, 8 : ulong sz, 9 1718862 : int * opt_err ) { 10 : 11 : /* Check input args */ 12 : 13 : #ifdef FD_FUNK_HANDHOLDING 14 : if( FD_UNLIKELY( (!rec) | (sz>FD_FUNK_REC_VAL_MAX) | (!alloc) | (!wksp) ) || /* NULL rec,too big,NULL alloc,NULL wksp */ 15 : FD_UNLIKELY( !fd_ulong_is_pow2( align ) & (align != 0UL) ) ) { /* Align is not a power of 2 or == 0 */ 16 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_ERR_INVAL ); 17 : return NULL; 18 : } 19 : #endif 20 : 21 1718862 : ulong val_sz = (ulong)rec->val_sz; 22 1718862 : ulong val_max = (ulong)rec->val_max; 23 : 24 1718862 : if( FD_UNLIKELY( !sz ) ) { 25 : 26 : /* User asked to truncate to 0. Flush the any existing value. */ 27 : 28 158478 : fd_funk_val_flush( rec, alloc, wksp ); 29 : 30 158478 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS ); 31 158478 : return NULL; 32 : 33 1560384 : } else if( FD_LIKELY( sz > val_max ) ) { 34 : 35 : /* User requested to increase the value size. We presume they are 36 : asking for a specific size (as opposed to bumping up the size ala 37 : append) so we don't build in extra padding to amortize the cost 38 : of future truncates. Note that new_val_sz is at least 1 at this 39 : point but val_sz / val_gaddr could be zero / zero. */ 40 : 41 1560357 : ulong val_gaddr = rec->val_gaddr; 42 1560357 : uchar * val = val_max ? fd_wksp_laddr_fast( wksp, val_gaddr ) : NULL; /* TODO: branchless */ 43 : 44 : /* NOTE: if the align is 0, we use the default alignment for 45 : fd_alloc_malloc_at_least */ 46 1560357 : ulong new_val_max; 47 1560357 : uchar * new_val = fd_alloc_malloc_at_least( alloc, align, sz, &new_val_max ); 48 1560357 : if( FD_UNLIKELY( !new_val ) ) { /* Allocation failure! */ 49 0 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_ERR_MEM ); 50 0 : return NULL; 51 0 : } 52 : 53 1560357 : if( val_sz ) fd_memcpy( new_val, val, val_sz ); /* Copy the existing value */ 54 1560357 : fd_memset( new_val + val_sz, 0, new_val_max - val_sz ); /* Clear out trailing padding to be on the safe side */ 55 : 56 1560357 : rec->val_gaddr = fd_wksp_gaddr_fast( wksp, new_val ); 57 1560357 : rec->val_sz = (uint)( sz & FD_FUNK_REC_VAL_MAX ); 58 1560357 : rec->val_max = (uint)( fd_ulong_min( new_val_max, FD_FUNK_REC_VAL_MAX ) & FD_FUNK_REC_VAL_MAX ); 59 : 60 1560357 : if( val ) fd_alloc_free( alloc, val ); /* Free the old value (if any) */ 61 : 62 1560357 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS ); 63 1560357 : return new_val; 64 : 65 1560357 : } else { 66 : 67 : /* Just set the new size */ 68 : 69 27 : rec->val_sz = (uint)( sz & FD_FUNK_REC_VAL_MAX ); 70 : 71 27 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS ); 72 27 : return (uchar *)fd_wksp_laddr_fast( wksp, rec->val_gaddr ); 73 : 74 27 : } 75 1718862 : } 76 : 77 : int 78 12 : fd_funk_val_verify( fd_funk_t * funk ) { 79 12 : fd_wksp_t * wksp = fd_funk_wksp( funk ); 80 12 : ulong wksp_tag = funk->shmem->wksp_tag; 81 : 82 : /* At this point, rec_map has been extensively verified */ 83 : 84 12 : # define TEST(c) do { \ 85 0 : if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \ 86 0 : } while(0) 87 : 88 : /* Iterate over all records in use */ 89 : 90 12 : fd_funk_all_iter_t iter[1]; 91 12 : for( fd_funk_all_iter_new( funk, iter ); !fd_funk_all_iter_done( iter ); fd_funk_all_iter_next( iter ) ) { 92 0 : fd_funk_rec_t const * rec = fd_funk_all_iter_ele_const( iter ); 93 : 94 : /* Make sure values look sane */ 95 : /* TODO: consider doing an alias analysis on allocated values? 96 : (tricky to do algo efficient in place) */ 97 : 98 0 : ulong val_sz = (ulong)rec->val_sz; 99 0 : ulong val_max = (ulong)rec->val_max; 100 0 : ulong val_gaddr = rec->val_gaddr; 101 : 102 0 : TEST( val_sz<=val_max ); 103 : 104 0 : TEST( val_max<=FD_FUNK_REC_VAL_MAX ); 105 0 : if( !val_gaddr ) TEST( !val_max ); 106 0 : else { 107 0 : TEST( (0UL<val_max) & (val_max<=FD_FUNK_REC_VAL_MAX) ); 108 0 : TEST( fd_wksp_tag( wksp, val_gaddr )==wksp_tag ); 109 0 : } 110 0 : } 111 : 112 12 : # undef TEST 113 : 114 12 : return FD_FUNK_SUCCESS; 115 12 : }