fis-gtm/sr_port/gvincr_compute_post_incr.c

93 lines
3.7 KiB
C

/****************************************************************
* *
* Copyright 2004, 2012 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_string.h"
#include "cdb_sc.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "gdskill.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsblk.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "gdscc.h"
#include "min_max.h" /* needed for gdsblkops.h */
#include "gdsblkops.h"
#include "jnl.h"
#include "copy.h"
#include "op.h" /* for op_add prototype */
#define GVINCR_PRE_INCR_MIN_BUFFLEN MAX_NUM_SIZE /* starting size of the malloced buffer to store pre_increment value */
/* since the increment will mostly be a number, start with MAX_NUM_SIZE */
static char *gvincr_pre_incr_buff; /* buffer to hold the pre-$INCR string value before converting to numeric */
static int gvincr_pre_incr_bufflen = 0; /* length of the currently allocated buffer, updated if expansion occurs */
GBLREF mval *post_incr_mval;
GBLREF gv_key *gv_currkey;
GBLREF mval increment_delta_mval; /* mval holding the increment value, set by op_gvincr */
GBLREF unsigned int t_tries;
/* compute post_incr_mval from the current value of gv_currkey that was just now searched down the tree */
enum cdb_sc gvincr_compute_post_incr(srch_blk_status *bh)
{
int4 cur_blk_size;
sm_uc_ptr_t buffaddr;
rec_hdr_ptr_t rp;
unsigned short rec_size;
int4 target_key_size, data_len;
uint4 gvincr_malloc_len;
mval pre_incr_mval;
int tmp_cmpc;
buffaddr = bh->buffaddr;
cur_blk_size = ((blk_hdr_ptr_t)buffaddr)->bsiz;
rp = (rec_hdr_ptr_t)(buffaddr + bh->curr_rec.offset);
GET_USHORT(rec_size, &rp->rsiz);
target_key_size = bh->curr_rec.match;
assert(target_key_size == gv_currkey->end + 1);
data_len = rec_size + EVAL_CMPC(rp) - SIZEOF(rec_hdr) - target_key_size;
if ((0 > data_len) || (((sm_uc_ptr_t)rp + rec_size) > ((sm_uc_ptr_t)buffaddr + cur_blk_size)))
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_rmisalign;
}
if (data_len > gvincr_pre_incr_bufflen)
{
if (NULL != gvincr_pre_incr_buff)
free(gvincr_pre_incr_buff);
gvincr_malloc_len = (data_len > GVINCR_PRE_INCR_MIN_BUFFLEN) ? data_len
: GVINCR_PRE_INCR_MIN_BUFFLEN;
gvincr_pre_incr_buff = (char *)malloc(gvincr_malloc_len);
gvincr_pre_incr_bufflen = gvincr_malloc_len;
}
/* malloced buffer is used for pre_incr_mval instead of stringpool because this is memory that is
* inherently used only by $INCREMENT and is needed only during the lifetime of the increment.
* keeping it in the stringpool causes it to stay until the next garbage collection which adds
* to unnecessary overheads.
*/
pre_incr_mval.mvtype = MV_STR;
pre_incr_mval.str.addr = (char *)gvincr_pre_incr_buff;
pre_incr_mval.str.len = data_len;
memcpy(pre_incr_mval.str.addr, (sm_uc_ptr_t)rp + rec_size - data_len, data_len);
op_add(&pre_incr_mval, &increment_delta_mval, post_incr_mval);
assert(MV_IS_NUMERIC(post_incr_mval));
/* "post_incr_mval" is of numeric type, convert it to a string type so it can be used by the caller to set "value" */
MV_FORCE_STR(post_incr_mval); /* will use stringpool to store string representation */
/* "post_incr_mval" is a copy of the mval pointer passed to "op_gvincr" and hence is on the M-stack
* and therefore is known to the garbage collector (stp_gcol). hence it is ok for it to use the stringpool
*/
return cdb_sc_normal;
}