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