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 4285395 : 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 4285395 : ulong val_sz = (ulong)rec->val_sz; 22 4285395 : ulong val_max = (ulong)rec->val_max; 23 : 24 4285395 : if( FD_UNLIKELY( !sz ) ) { 25 : 26 : /* User asked to truncate to 0. Flush the any existing value. */ 27 : 28 0 : fd_funk_val_flush( rec, alloc, wksp ); 29 : 30 0 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS ); 31 0 : return NULL; 32 : 33 4285395 : } else if( FD_LIKELY( (sz > val_max) | fd_funk_val_shrink_compacts( sz, val_max ) ) ) { 34 : 35 1277010 : ulong val_gaddr = rec->val_gaddr; 36 1277010 : uchar * val = val_max ? fd_wksp_laddr_fast( wksp, val_gaddr ) : NULL; /* TODO: branchless */ 37 : 38 : /* NOTE: if the align is 0, we use the default alignment for 39 : fd_alloc_malloc_at_least */ 40 1277010 : ulong new_val_max; 41 1277010 : uchar * new_val = fd_alloc_malloc_at_least( alloc, align, sz, &new_val_max ); 42 1277010 : if( FD_UNLIKELY( !new_val ) ) { /* Allocation failure! */ 43 0 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_ERR_MEM ); 44 0 : return NULL; 45 0 : } 46 : 47 1277010 : ulong copy_sz = fd_ulong_min( val_sz, sz ); 48 1277010 : if( copy_sz ) fd_memcpy( new_val, val, copy_sz ); /* Copy the existing value */ 49 1277010 : fd_memset( new_val + copy_sz, 0, new_val_max - copy_sz ); /* Clear out trailing padding to be on the safe side */ 50 : 51 1277010 : rec->val_gaddr = fd_wksp_gaddr_fast( wksp, new_val ); 52 1277010 : rec->val_sz = (uint)( sz & FD_FUNK_REC_VAL_MAX ); 53 1277010 : rec->val_max = (uint)( fd_ulong_min( new_val_max, FD_FUNK_REC_VAL_MAX ) & FD_FUNK_REC_VAL_MAX ); 54 : 55 1277010 : if( val ) fd_alloc_free( alloc, val ); /* Free the old value (if any) */ 56 : 57 1277010 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS ); 58 1277010 : return new_val; 59 : 60 3008385 : } else { 61 : 62 : /* Just set the new size */ 63 : 64 3008385 : rec->val_sz = (uint)( sz & FD_FUNK_REC_VAL_MAX ); 65 : 66 3008385 : fd_int_store_if( !!opt_err, opt_err, FD_FUNK_SUCCESS ); 67 3008385 : return (uchar *)fd_wksp_laddr_fast( wksp, rec->val_gaddr ); 68 : 69 3008385 : } 70 4285395 : } 71 : 72 : int 73 201 : fd_funk_val_verify( fd_funk_t * funk ) { 74 201 : fd_wksp_t * wksp = fd_funk_wksp( funk ); 75 201 : ulong wksp_tag = funk->shmem->wksp_tag; 76 : 77 : /* At this point, rec_map has been extensively verified */ 78 : 79 53172 : # define TEST(c) do { \ 80 53172 : if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return FD_FUNK_ERR_INVAL; } \ 81 53172 : } while(0) 82 : 83 : /* Iterate over all records in use */ 84 : 85 201 : fd_funk_all_iter_t iter[1]; 86 13494 : for( fd_funk_all_iter_new( funk, iter ); !fd_funk_all_iter_done( iter ); fd_funk_all_iter_next( iter ) ) { 87 13293 : fd_funk_rec_t const * rec = fd_funk_all_iter_ele_const( iter ); 88 : 89 : /* Make sure values look sane */ 90 : /* TODO: consider doing an alias analysis on allocated values? 91 : (tricky to do algo efficient in place) */ 92 : 93 13293 : ulong val_sz = (ulong)rec->val_sz; 94 13293 : ulong val_max = (ulong)rec->val_max; 95 13293 : ulong val_gaddr = rec->val_gaddr; 96 : 97 13293 : TEST( val_sz<=val_max ); 98 : 99 13293 : TEST( val_max<=FD_FUNK_REC_VAL_MAX ); 100 13293 : if( !val_gaddr ) TEST( !val_max ); 101 13293 : else { 102 13293 : TEST( (0UL<val_max) & (val_max<=FD_FUNK_REC_VAL_MAX) ); 103 13293 : TEST( fd_wksp_tag( wksp, val_gaddr )==wksp_tag ); 104 13293 : } 105 13293 : } 106 : 107 201 : # undef TEST 108 : 109 201 : return FD_FUNK_SUCCESS; 110 201 : }