Beispiel #1
0
/* returns FALSE if gv_currkey is undefined in the server end and undef_inhibit is turned OFF */
void	gvcmx_increment(mval *increment, mval *result)
{
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;
	mval		tmpmval;

	error_def(ERR_UNIMPLOP);
	error_def(ERR_TEXT);
	error_def(ERR_GVIS);

	if (!((link_info *)gv_cur_region->dyn.addr->cm_blk->usr)->server_supports_dollar_incr)
	{
		assert(dba_cm == gv_cur_region->dyn.addr->acc_meth); /* we should've covered all other access methods elsewhere */
		end = format_targ_key(buff, MAX_ZWR_KEY_SZ, gv_currkey, TRUE);
		rts_error(VARLSTCNT(14) ERR_UNIMPLOP, 0,
					ERR_TEXT, 2, LEN_AND_LIT("GT.CM server does not support $INCREMENT operation"),
					ERR_GVIS, 2, end - buff, buff,
					ERR_TEXT, 2, REG_LEN_STR(gv_cur_region));
	}
	/* gvcmz_doop() currently accepts only one argument.
	 * It serves as an input argument for SET.
	 * It serves as an output argument for GET etc.
	 * $INCR is unique in that it needs to pass the increment as input and expects the post-increment as output.
	 *
	 * In order to accomplish this without changing the gvcmz_doop() interface, we overload the one argument to
	 *	serve two purposes. It will be an input argument until the send of the message to the server and will
	 *	then serve as an output argument after the response from the server. ("result" is used for this purpose)
	 * i.e.
	 *	to serve as increment            for client --> server message
	 *	to serve as post-increment value for server --> client message
	 */
	assert(MV_IS_NUMERIC(increment));	/* op_gvincr would have forced it to be a NUMERIC */
	MV_FORCE_STR(increment);		/* convert it to a string before sending it to gvcmz_doop */
	*result = *increment;
	gvcmz_doop(CMMS_Q_INCREMENT, CMMS_R_INCREMENT, result);
}
Beispiel #2
0
void sgnl_gvundef(void)
{
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;
	error_def(ERR_GVUNDEF);

	if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
	{	end = &buff[MAX_ZWR_KEY_SZ - 1];
	}
	rts_error(VARLSTCNT(4) ERR_GVUNDEF, 2, end - &buff[0], &buff[0]);
}
Beispiel #3
0
void sgnl_gvnulsubsc(void)
{
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;

	if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
	{	end = &buff[MAX_ZWR_KEY_SZ - 1];
	}
	gv_currkey->end = 0;
	rts_error_csa(NULL, VARLSTCNT(8) ERR_NULSUBSC, 2, gv_cur_region->rname_len, &gv_cur_region->rname[0],
		ERR_GVIS, 2, end - &buff[0], &buff[0]);
}
Beispiel #4
0
void get_reference(mval *var)
{
	char	*end, *start;
	char	extnamdelim[] = "^|\"\"|";
	char	*extnamsrc, *extnamtop;
	int	maxlen;

	/* you need to return a double-quote for every single-quote. assume worst case. */
	maxlen = MAX_ZWR_KEY_SZ + (!extnam_str.len ? 0 : ((extnam_str.len * 2) + sizeof(extnamdelim)));
	if (stringpool.free + maxlen > stringpool.top)
		stp_gcol(maxlen);
	var->mvtype = MV_STR;
	start = var->str.addr = (char *)stringpool.free;
	var->str.len = 0;
	if (gv_currkey && gv_currkey->end)
	{
		if (extnam_str.len)
		{
			*start++ = extnamdelim[0];
			*start++ = extnamdelim[1];
			*start++ = extnamdelim[2];
			extnamsrc = &extnam_str.addr[0];
			extnamtop = extnamsrc + extnam_str.len;
			for ( ; extnamsrc < extnamtop; )
			{
				*start++ = *extnamsrc;
				if ('"' == *extnamsrc++)	/* caution : pointer increment side-effect */
					*start++ = '"';
			}
			*start++ = extnamdelim[3];
		}
		end = (char *)format_targ_key((unsigned char *)start, MAX_ZWR_KEY_SZ, gv_currkey, TRUE);
		if (extnam_str.len)
			/* Note: the next vertical bar overwrites the caret that
			 * was part of he original name of the global variable
			 */
			*start = extnamdelim[4];
		var->str.len = end - var->str.addr;
		stringpool.free += var->str.len;
	}
}
Beispiel #5
0
void	op_gvincr(mval *increment, mval *result)
{
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	/* If specified var name is global ^%Y*, the name is illegal to use in a SET or KILL command, only GETs are allowed */
	if ((RESERVED_NAMESPACE_LEN <= gv_currkey->end) && (0 == MEMCMP_LIT(gv_currkey->base, RESERVED_NAMESPACE)))
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_PCTYRESERVED);
	if (gv_cur_region->read_only)
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DBPRIVERR, 2, DB_LEN_STR(gv_cur_region));
	if ((TREF(gv_last_subsc_null) || TREF(gv_some_subsc_null)) && (ALWAYS != gv_cur_region->null_subs))
		sgnl_gvnulsubsc();
	assert(gv_currkey->end + 1 <= gv_cur_region->max_key_size);
	MV_FORCE_NUM(increment);
	switch (gv_cur_region->dyn.addr->acc_meth)
	{
		case dba_bg:
		case dba_mm:
			gvcst_incr(increment, result);
			break;
		case dba_cm:
			gvcmx_increment(increment, result);
			break;
		case dba_usr:
			/* $INCR not supported for DDP/USR access method */
			if (0 == (end = format_targ_key(buff, MAX_ZWR_KEY_SZ, gv_currkey, TRUE)))
				end = &buff[MAX_ZWR_KEY_SZ - 1];
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(10) ERR_UNIMPLOP, 0,
				      ERR_TEXT, 2, LEN_AND_LIT("GTCM DDP server does not support $INCREMENT"),
				      ERR_GVIS, 2, end - buff, buff,
				      ERR_TEXT, 2, REG_LEN_STR(gv_cur_region));
			break;
		default:
			assertpro(FALSE);
	}
	assert(MV_DEFINED(result));
}
Beispiel #6
0
char	*jnl2ext(char *jnl_buff, char *ext_buff)
{
    char		*curr, *val_ptr, *ptr, rectype, key_buff[sizeof(gv_key) + MAX_KEY_SZ + 7];
    jnl_record	*rec;
    gv_key		*key;
    jnl_string	*keystr;
    int		val_extr_len, val_len, rec_len;

    rec = (jnl_record *)jnl_buff;
    rectype = rec->prefix.jrec_type;
    rec_len = rec->prefix.forwptr;
    if (rec_len != REC_LEN_FROM_SUFFIX(jnl_buff, rec_len))
    {
        assert(FALSE);
        return ext_buff;
    }
    if (!IS_REPLICATED(rectype))
    {
        assert(FALSE);
        return ext_buff;
    }
    curr = ext_buff;
    if (IS_TUPD(rectype))
    {
        if (FALSE == first_tstart)
        {
            GET_SHORTP(curr, &muext_code[MUEXT_TSTART][0]);
            curr += 2;
            DELIMIT_CURR;
            MEMCPY_LIT(curr, ZERO_TIME_DELIM);
            curr += STR_LIT_LEN(ZERO_TIME_DELIM);
            curr = (char *)i2asc((uchar_ptr_t)curr, rec->jrec_kill.prefix.tn);
            DELIMIT_CURR;
            MEMCPY_LIT(curr, PIDS_DELIM);
            curr += STR_LIT_LEN(PIDS_DELIM);
            curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_kill.token_seq.jnl_seqno);
            *curr++ = '\n';
            *curr = '\0';
            first_tstart = TRUE;
        }
        num_tstarts++;
    } else if (JRT_TCOM == rectype)
    {
        num_tcommits++;
        if (num_tcommits == num_tstarts)
        {
            num_tcommits = num_tstarts = 0;
            first_tstart = FALSE;
            GET_SHORTP(curr, &muext_code[MUEXT_TCOMMIT][0]);
            curr += 2;
            DELIMIT_CURR;
            MEMCPY_LIT(curr, ZERO_TIME_DELIM);
            curr += STR_LIT_LEN(ZERO_TIME_DELIM);
            curr = (char *)i2asc((uchar_ptr_t)curr, rec->jrec_tcom.prefix.tn);
            DELIMIT_CURR;
            MEMCPY_LIT(curr, PIDS_DELIM);
            curr += STR_LIT_LEN(PIDS_DELIM);
            curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_tcom.token_seq.jnl_seqno);
            DELIMIT_CURR;
            curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_tcom.participants);
            *curr++ = '\n';
            *curr = '\0';
            return curr;
        }
        return ext_buff;
    }
    if (IS_SET(rectype))
        GET_SHORTP(curr, &muext_code[MUEXT_SET][0]);
    else if (IS_KILL(rectype))
        GET_SHORTP(curr, &muext_code[MUEXT_KILL][0]);
    else if (IS_ZKILL(rectype))
        GET_SHORTP(curr, &muext_code[MUEXT_ZKILL][0]);
    else /* if (JRT_NULL == rectype) */
    {
        assert(JRT_NULL == rectype);
        GET_SHORTP(curr, &muext_code[MUEXT_NULL][0]);
    }
    curr += 2;
    DELIMIT_CURR;
    MEMCPY_LIT(curr, ZERO_TIME_DELIM);
    curr += STR_LIT_LEN(ZERO_TIME_DELIM);
    curr = (char *)i2asc((uchar_ptr_t)curr, rec->jrec_kill.prefix.tn);
    DELIMIT_CURR;
    MEMCPY_LIT(curr, PIDS_DELIM);
    curr += STR_LIT_LEN(PIDS_DELIM);
    curr = (char *)i2ascl((uchar_ptr_t)curr, rec->jrec_kill.token_seq.jnl_seqno);
    if (rectype == JRT_NULL)
    {
        *curr++ = '\n';
        *curr='\0';
        return curr;
    }
    assert(IS_SET_KILL_ZKILL(rectype));
    DELIMIT_CURR;
    keystr = (jnl_string *)&rec->jrec_kill.mumps_node;
    ptr = (char *)ROUND_UP((uint4)key_buff, 8);
    key = (gv_key *)ptr;
    key->top = MAX_KEY_SZ;
    key->end = keystr->length;
    if (key->end > key->top)
    {
        assert(FALSE);
        return ext_buff;
    }
    memcpy(key->base, &keystr->text[0], keystr->length);
    key->base[key->end] = 0;
    curr = (char *)format_targ_key((uchar_ptr_t)curr, MAX_ZWR_KEY_SZ, key, TRUE);
    if (IS_SET(rectype))
    {
        *curr++ = '=';
        val_ptr = &keystr->text[keystr->length];
        GET_MSTR_LEN(val_len, val_ptr);
        val_ptr += sizeof(mstr_len_t);
        format2zwr((sm_uc_ptr_t)val_ptr, val_len, (uchar_ptr_t)curr, &val_extr_len);
        curr += val_extr_len;
    }
    *curr++ = '\n';
    *curr='\0';
    return curr;
}
Beispiel #7
0
bool	gtcmtr_increment(void)
{
	cm_region_list	*reg_ref;
	mval		incr_delta, post_incr;
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;
	unsigned char	*ptr, regnum;
	short		n;
	unsigned short	top, len, temp_short;
	static readonly	gds_file_id file;

	error_def(ERR_KEY2BIG);
	error_def(ERR_GVIS);
	error_def(ERR_DBPRIVERR);

	ptr = curr_entry->clb_ptr->mbf;
	assert(*ptr == CMMS_Q_INCREMENT);
	ptr++;
	GET_USHORT(len, ptr);
	ptr += SIZEOF(unsigned short);
	regnum = *ptr++;
	reg_ref = gtcm_find_region(curr_entry,regnum);
	len--; /* subtract size of regnum */
	CM_GET_GVCURRKEY(ptr, len);
	gtcm_bind_name(reg_ref->reghead, TRUE);
	if (gv_cur_region->read_only)
		rts_error(VARLSTCNT(4) ERR_DBPRIVERR, 2, DB_LEN_STR(gv_cur_region));
	if (JNL_ALLOWED(cs_addrs))
	{	/* we need to copy client's specific prc_vec into the global variable in order that the gvcst* routines
		 *	do the right job. actually we need to do this only if JNL_ENABLED(cs_addrs), but since it is not
		 *	easy to re-execute the following two assignments in case gvcst_incr's call to t_end encounters a
		 *	cdb_sc_jnlstatemod retry code, we choose the easier approach of executing the following segment
		 *	if JNL_ALLOWED(cs_addrs) is TRUE instead of checking for JNL_ENABLED(cs_addrs) to be TRUE.
		 * this approach has the overhead that we will be doing the following assignments even though JNL_ENABLED
		 * 	might not be TRUE but since the following two are just pointer copies, it is not considered a big overhead.
		 * this approach ensures that the jnl_put_jrt_pini gets the appropriate prc_vec for writing into the
		 * 	journal record in case JNL_ENABLED turns out to be TRUE in t_end time.
		 * note that the value of JNL_ALLOWED(cs_addrs) cannot be changed on the fly without obtaining standalone access
		 * 	and hence the correctness of prc_vec (whenever it turns out necessary) is guaranteed.
		 */
		originator_prc_vec = curr_entry->pvec;
		cs_addrs->jnl->pini_addr = reg_ref->pini_addr;
	}
	GET_USHORT(len, ptr);
	ptr += SIZEOF(unsigned short);
	incr_delta.mvtype = MV_STR;
	incr_delta.str.len = len;
	incr_delta.str.addr = (char *)ptr;
	if ((n = gv_currkey->end + 1) > gv_cur_region->max_key_size)
	{
		if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
			end = &buff[MAX_ZWR_KEY_SZ - 1];
		rts_error(VARLSTCNT(11) ERR_KEY2BIG, 4, n, (int4)gv_cur_region->max_key_size,
			REG_LEN_STR(gv_cur_region), 0, ERR_GVIS, 2, end - buff, buff);
	}
	MV_FORCE_NUMD(&incr_delta);
	gvcst_incr(&incr_delta, &post_incr);
	if (JNL_ALLOWED(cs_addrs))
		reg_ref->pini_addr = cs_addrs->jnl->pini_addr; /* In case journal switch occurred */
	ptr = curr_entry->clb_ptr->mbf;
	if (MV_DEFINED(&post_incr))
	{
		temp_short = (unsigned short)post_incr.str.len;
		assert((int4)temp_short == post_incr.str.len); /* ushort <- int4 assignment lossy? */
		if (curr_entry->clb_ptr->mbl < 1 +			/* msg header */
					       SIZEOF(temp_short) +	/* size of length of $INCR return value */
					       temp_short) 		/* length of $INCR return value */
		{	/* resize buffer */
			cmi_realloc_mbf(curr_entry->clb_ptr, 1 + SIZEOF(temp_short) + temp_short);
			ptr = curr_entry->clb_ptr->mbf;
		}
		*ptr++ = CMMS_R_INCREMENT;
		PUT_USHORT(ptr, temp_short);
		ptr += SIZEOF(unsigned short);
		memcpy(ptr, post_incr.str.addr, temp_short);
		ptr += temp_short;
	} else
Beispiel #8
0
boolean_t	mur_select_rec(jnl_ctl_list *jctl)
{
	boolean_t		exc_item_seen, inc_item_seen, inc_seen, wildcard_match;
	char			key_buff[MAX_KEY_SZ + 1 + SIZEOF(uint4) * 2], asc_key_buff[MAX_ZWR_KEY_SZ], *ptr;
	int			i, key_len, pat_pos, subs_pos;
	uint4			pini_addr;
	gv_key			*key;
	jnl_record		*rec;
	pini_list_struct	*plst;
	jnl_process_vector	*pv;
	enum jnl_record_type	rectype;
	long_list		*ll_ptr;
	select_list		*sl_ptr;
	jnl_string		*keystr;
	uint4			status;
	int4			pv_len, sl_len;

	assert(mur_options.selection);
	rec = jctl->reg_ctl->mur_desc->jnlrec;
	rectype = (enum jnl_record_type)rec->prefix.jrec_type;
	pini_addr = rec->prefix.pini_addr;
	key = NULL;
	if (JRT_NULL == rectype || JRT_ALIGN == rectype)
		return TRUE;
	status = mur_get_pini(jctl, pini_addr, &plst);
	if (SS_NORMAL != status)
		return TRUE;
	pv = &plst->jpv;
	if (IS_SET_KILL_ZKILL_ZTRIG(rectype))
	{	/* Translate internal format of jnl_record key to ascii */
		keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
		key = (gv_key *)key_buff;
		key->top = MAX_KEY_SZ;
		key->end = keystr->length;
		assert(key->end <= key->top);
		memcpy(key->base, &keystr->text[0], keystr->length);
		key->base[key->end] = '\0';
		key_len = INTCAST((format_targ_key((uchar_ptr_t)asc_key_buff, MAX_ZWR_KEY_SZ, key, FALSE) -
				   (unsigned char *)asc_key_buff));
	}
	/* Check this record against the various selection lists */
	if (NULL != mur_options.user)
	{
		inc_seen = inc_item_seen = exc_item_seen = FALSE;
		for (sl_ptr = mur_options.user;  NULL != sl_ptr;  sl_ptr = sl_ptr->next)
		{
			wildcard_match = FALSE;
			if (!sl_ptr->exclude)
				inc_seen = TRUE;
			if (sl_ptr->has_wildcard)
				wildcard_match = mur_do_wildcard(pv->jpv_user, sl_ptr->buff, JPV_LEN_USER, sl_ptr->len);
			if (!wildcard_match)
			{
				pv_len = real_len(JPV_LEN_USER, (uchar_ptr_t)pv->jpv_user);
				sl_len = MIN(sl_ptr->len, JPV_LEN_USER);
			}
			if (wildcard_match || (pv_len == sl_len) && (0 == memcmp(pv->jpv_user, sl_ptr->buff, sl_len)))
			{
				if (sl_ptr->exclude)
					exc_item_seen = TRUE;
				else
					inc_item_seen = TRUE;
			}
		}
		if (exc_item_seen || (inc_seen && !inc_item_seen))
			return FALSE;
	}
	if ((NULL != mur_options.global) && (NULL != key))
	{
		inc_seen = inc_item_seen = exc_item_seen = FALSE;
		for (sl_ptr = mur_options.global;  NULL != sl_ptr;  sl_ptr = sl_ptr->next)
		{
			wildcard_match = FALSE;
			if (!sl_ptr->exclude)
				inc_seen = TRUE;
			if (sl_ptr->has_wildcard)
				wildcard_match = mur_do_wildcard(asc_key_buff, sl_ptr->buff, key_len, sl_ptr->len);
			i = sl_ptr->len;
			if (sl_ptr->buff[i - 1] == ')')
				--i;
			if (wildcard_match
				|| (key_len == i) && (0 == memcmp(asc_key_buff, sl_ptr->buff, i))
				|| (key_len >  i) && (0 == memcmp(asc_key_buff, sl_ptr->buff, i))
					&& (('(' == asc_key_buff[i]) || (')' == asc_key_buff[i]) || (',' == asc_key_buff[i])))
			{
				if (sl_ptr->exclude)
					exc_item_seen = TRUE;
				else
					inc_item_seen = TRUE;
			}
		}
		if (exc_item_seen || (inc_seen && !inc_item_seen))
			return FALSE;
	}
	if (NULL != mur_options.process)
	{
		inc_seen = inc_item_seen = exc_item_seen = FALSE;
		for (sl_ptr = mur_options.process;  NULL != sl_ptr;  sl_ptr = sl_ptr->next)
		{
			wildcard_match = FALSE;
			if (!sl_ptr->exclude)
				inc_seen = TRUE;
			if (sl_ptr->has_wildcard)
				wildcard_match = mur_do_wildcard(pv->jpv_prcnam, sl_ptr->buff, JPV_LEN_PRCNAM, sl_ptr->len);
			if (!wildcard_match)
			{
				pv_len = real_len(JPV_LEN_PRCNAM, (uchar_ptr_t)pv->jpv_prcnam);
				sl_len = MIN(sl_ptr->len, JPV_LEN_PRCNAM);
			}
			if (wildcard_match || (pv_len == sl_len) && (0 == memcmp(pv->jpv_prcnam, sl_ptr->buff, sl_len)))
			{
				if (sl_ptr->exclude)
					exc_item_seen = TRUE;
				else
					inc_item_seen = TRUE;
			}
		}
		if (exc_item_seen || (inc_seen && !inc_item_seen))
			return FALSE;
	}
	if (NULL != mur_options.id)
	{
		inc_seen = inc_item_seen = exc_item_seen = FALSE;
		for (ll_ptr = mur_options.id;  NULL != ll_ptr;  ll_ptr = ll_ptr->next)
		{
			if (!ll_ptr->exclude)
				inc_seen = TRUE;
			if (ll_ptr->num == pv->jpv_pid)
			{
				if (ll_ptr->exclude)
					exc_item_seen = TRUE;
				else
					inc_item_seen = TRUE;
			}
		}
		if (exc_item_seen || (inc_seen && !inc_item_seen))
			return FALSE;
	}
	if (IS_SET_KILL_ZKILL_ZTRIG(rectype))
	{
		if (IS_SET(rectype))
			return mur_options.transaction != TRANS_KILLS;
		else
			return mur_options.transaction != TRANS_SETS;
	}
	return TRUE;
}
Beispiel #9
0
bool gtcmtr_bufflush(void)
{
	cm_region_list	*reg_ref;
	mval		v;
	short		n;
	unsigned short	num_trans, data_len;
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;
	unsigned char	*ptr, regnum, len, cc, prv;
	static readonly gds_file_id file;

	error_def(ERR_KEY2BIG);
	error_def(ERR_REC2BIG);
	error_def(ERR_GVIS);

	ptr = curr_entry->clb_ptr->mbf;
	assert(*ptr == CMMS_B_BUFFLUSH);
	ptr++;
	v.mvtype = MV_STR;
	GET_USHORT(num_trans, ptr);
	ptr += sizeof (short);
	for (; num_trans-- > 0;)
	{
		regnum = *ptr++;
		reg_ref = gtcm_find_region(curr_entry, regnum);
		len = *ptr++;
		cc = *ptr++;
		prv = *ptr++;
		assert (len + cc - 1 < gv_currkey->top);
		memcpy(&gv_currkey->base[cc], ptr, len);
		ptr += len;
		gv_currkey->end = len + cc - 1;
		gv_currkey->prev = prv;
		assert(prv < gv_currkey->end);
		if ((n = gv_currkey->end + 1) > gv_cur_region->max_key_size)
		{
			if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
				end = &buff[MAX_ZWR_KEY_SZ - 1];
			rts_error(VARLSTCNT(11) ERR_KEY2BIG, 4, n, (int4)gv_cur_region->max_key_size,
				REG_LEN_STR(gv_cur_region), 0, ERR_GVIS, 2, end - buff, buff);
		}
		gtcm_bind_name(reg_ref->reghead, TRUE);
		if (JNL_ENABLED(cs_addrs->hdr))
		{
			cs_addrs->jnl->pini_addr = reg_ref->pini_addr;
			originator_prc_vec = curr_entry->pvec;
		}
		GET_USHORT(data_len, ptr);
		ptr += sizeof(short);
		v.str.len = data_len;
		v.str.addr = (char *)ptr;
		if (n + v.str.len + sizeof(rec_hdr) > gv_cur_region->max_rec_size)
		{
			if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
				end = &buff[MAX_ZWR_KEY_SZ - 1];
			rts_error(VARLSTCNT(11) ERR_REC2BIG, 4, n + v.str.len + sizeof(rec_hdr), (int4)gv_cur_region->max_rec_size,
				REG_LEN_STR(gv_cur_region), 0, ERR_GVIS, 2, end - buff, buff);
		}
		gvcst_put(&v);
		if (JNL_ENABLED(cs_addrs->hdr))
			reg_ref->pini_addr = cs_addrs->jnl->pini_addr; /* In case  journal switch occurred */
		ptr += data_len;
	}
	ptr = curr_entry->clb_ptr->mbf;
	*ptr++ = CMMS_C_BUFFLUSH;
	curr_entry->clb_ptr->cbl = S_HDRSIZE;
	return TRUE;
}
Beispiel #10
0
void op_gvquery (mval *v)
{
	int4			size;
	unsigned char		buff[MAX_ZWR_KEY_SZ], *end, *glob_begin;
 	bool			found;
	enum db_acc_method 	acc_meth;
	unsigned char		*extnamsrc, *extnamdst, *extnamtop;
	int			maxlen;
	char			extnamdelim[] = "^|\"\"|";
	mval			val;

	/* We want to turn QUERY into QUERYGET for all types of access methods so that we can cache the value of the key returned
	 * by $QUERY. The value is very likely to be used shortly after $QUERY - Vinaya, Aug 13, 2001 */
	acc_meth = gv_cur_region->dyn.addr->acc_meth;
	if (gv_curr_subsc_null)
	{
		if (0 == gv_cur_region->std_null_coll)
			gv_currkey->base[gv_currkey->prev] = 01;
		else
		{
			gv_currkey->base[gv_currkey->end++]= 1;
			gv_currkey->base[gv_currkey->end++] = 0;
			gv_currkey->base[gv_currkey->end] = 0;
		}
	} else
	{ /* Note, gv_currkey->prev isn't changed here. We rely on this in gtcmtr_query to distinguish different forms of the key */
		gv_currkey->base[gv_currkey->end++]= 1;
		gv_currkey->base[gv_currkey->end++] = 0;
		gv_currkey->base[gv_currkey->end] = 0;
	}
	switch (acc_meth)
	{
		case dba_bg:
		case dba_mm:
			found = ((0 != gv_target->root) ? gvcst_query() : FALSE); /* global does not exist if root is 0 */
			break;
		case dba_cm:
			found = gvcmx_query(&val); /* val ignored currently - Vinaya Aug 13, 2001*/
			break;
		case dba_usr:
			found = gvusr_query(v); /* $Q result in v for dba_usr, for others, in gv_altkey */
			break;
		default:
			assert(FALSE); /* why didn't we cover all access methods? */
			found = FALSE;
			break;
	}
	v->mvtype = MV_STR;
	if (found)
	{
		if (acc_meth != dba_usr)
		{
			if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_altkey, TRUE)) == 0)
				end = &buff[MAX_ZWR_KEY_SZ - 1];
			size = (int)(end - &buff[0] - 1); /* exclude ^ */
			glob_begin = &buff[1]; /* skip ^ */
		} else
		{
			size = v->str.len - 1; /* exclude ^ */
			glob_begin = (unsigned char *)v->str.addr + 1; /* skip ^ */
		}
		/* Need to return a double-quote for every single-quote; assume worst case. */
		/* Account for ^ in both cases - extnam and no extnam */
		maxlen = size + ((0 == extnam_str.len) ? 1 : ((extnam_str.len * 2) + (int)(STR_LIT_LEN(extnamdelim))));
		if ((stringpool.top - stringpool.free) < maxlen)
		{
			v->str.len = 0; /* so stp_gcol ignores otherwise incompletely setup mval */
			stp_gcol(maxlen);
		}
		extnamdst = stringpool.free;
		*extnamdst++ = extnamdelim[0];
		if (extnam_str.len > 0)
		{
			*extnamdst++ = extnamdelim[1];
			*extnamdst++ = extnamdelim[2];
			for (extnamsrc = (unsigned char *)extnam_str.addr, extnamtop = extnamsrc + extnam_str.len;
					extnamsrc < extnamtop; )
			{
				*extnamdst++ = *extnamsrc;
				if ('"' == *extnamsrc++)	/* caution : pointer increment side-effect */
					*extnamdst++ = '"';
			}
			*extnamdst++ = extnamdelim[3];
			*extnamdst++ = extnamdelim[4];
			extnam_str.len = 0;
		}
		memcpy(extnamdst, glob_begin, size);
		v->str.len = INTCAST(extnamdst - stringpool.free + size);
		v->str.addr = (char *)stringpool.free;
		stringpool.free += v->str.len;
		assert (v->str.addr < (char *)stringpool.top && v->str.addr >= (char *)stringpool.base);
		assert (v->str.addr + v->str.len <= (char *)stringpool.top &&
			v->str.addr + v->str.len >= (char *)stringpool.base);
	} else /* !found */
		v->str.len = 0;
	return;
}
/* This routine formats and outputs journal extract records
   corresponding to M SET, KILL, ZKILL, TSTART, ZTSTART, and ZTRIGGER commands, $ZTRIGGER function (LGTRIG) and $ZTWORMHOLE */
void	mur_extract_set(jnl_ctl_list *jctl, fi_type *fi, jnl_record *rec, pini_list_struct *plst)
{
	enum jnl_record_type	rectype;
	int			max_blen, actual, extract_len, val_extr_len, val_len;
	char			*val_ptr, *ptr, *buff;
	jnl_string		*keystr;
	boolean_t		do_format2zwr, is_ztstart;

	if (!mur_options.detail)
		extract_len = 0;
	else
		EXT_DET_COMMON_PREFIX(jctl);
	rectype = (enum jnl_record_type)rec->prefix.jrec_type;
	if (IS_FUPD_TUPD(rectype))
	{
		if (!mur_options.detail)
		{
			if (IS_TUPD(rectype))
			{
				EXT2BYTES(&muext_code[MUEXT_TSTART][0]); /* TSTART */
				is_ztstart = FALSE;
			} else /* if (IS_FUPD(rectype)) */
			{
				EXT2BYTES(&muext_code[MUEXT_ZTSTART][0]); /* ZTSTART */
				is_ztstart = TRUE;
			}
		} else
		{
			if (IS_TUPD(rectype))
			{
				strcpy(murgbl.extr_buff + extract_len, "TSTART \\");
				is_ztstart = FALSE;
			} else /* if (IS_FUPD(rectype)) */
			{
				strcpy(murgbl.extr_buff + extract_len, "ZTSTART\\");
				is_ztstart = TRUE;
			}
			extract_len = STRLEN(murgbl.extr_buff);
		}
		EXTTIME(rec->prefix.time);
		EXTQW(rec->prefix.tn);
		if (mur_options.detail)
			EXTINT(rec->prefix.checksum);
		EXTPID(plst);
		EXTQW(rec->jrec_set_kill.token_seq.jnl_seqno);
		if (!is_ztstart)
			EXT_STRM_SEQNO(rec->jrec_set_kill.strm_seqno);
		jnlext_write(fi, murgbl.extr_buff, extract_len);
	}
	/* Output the SET or KILL or ZKILL or ZTWORMHOLE or LGTRIG or ZTRIG record */
	if (!mur_options.detail)
	{
		extract_len = 0;
		if (IS_SET(rectype))
		{
			EXT2BYTES(&muext_code[MUEXT_SET][0]);
		} else if (IS_KILL(rectype))
		{
			EXT2BYTES(&muext_code[MUEXT_KILL][0]);
		} else if (IS_ZKILL(rectype))
		{
			EXT2BYTES(&muext_code[MUEXT_ZKILL][0]);
		} else if (IS_ZTWORM(rectype))
		{
			EXT2BYTES(&muext_code[MUEXT_ZTWORM][0]);
		} else if (IS_LGTRIG(rectype))
		{
			EXT2BYTES(&muext_code[MUEXT_LGTRIG][0]);
		} else if (IS_ZTRIG(rectype))
		{
			EXT2BYTES(&muext_code[MUEXT_ZTRIG][0]);
		} else
			assert(FALSE);	/* The assert will disappear in pro but not the ";" to properly terminate the else */
	} else
	{
		if (IS_FUPD_TUPD(rectype))
		{
			memcpy(murgbl.extr_buff, "                       ", 23);
			extract_len = 23;
		} else
			extract_len = STRLEN(murgbl.extr_buff);
		strcpy(murgbl.extr_buff + extract_len, "       \\");
		memcpy(murgbl.extr_buff + extract_len, jrt_label[rectype], LAB_LEN);
		extract_len += LAB_LEN;
		memcpy(murgbl.extr_buff + extract_len, LAB_TERM, LAB_TERM_SZ);
		extract_len += LAB_TERM_SZ;
	}
	EXTTIME(rec->prefix.time);
	EXTQW(rec->prefix.tn);
	if (mur_options.detail)
		EXTINT(rec->prefix.checksum);
	EXTPID(plst);
	if (IS_ZTP(rectype))
	{
		EXTQW(rec->jrec_set_kill.token_seq.token);
	} else
		EXTQW(rec->jrec_set_kill.token_seq.jnl_seqno);
	assert(IS_SET_KILL_ZKILL_ZTWORM_LGTRIG_ZTRIG(rectype));
	assert(&rec->jrec_set_kill.strm_seqno == &rec->jrec_ztworm.strm_seqno);
	assert(&rec->jrec_set_kill.strm_seqno == &rec->jrec_lgtrig.strm_seqno);
	EXT_STRM_SEQNO(rec->jrec_set_kill.strm_seqno);
	assert(&rec->jrec_set_kill.update_num == &rec->jrec_ztworm.update_num);
	assert(&rec->jrec_set_kill.update_num == &rec->jrec_lgtrig.update_num);
	EXTINT(rec->jrec_set_kill.update_num);
	do_format2zwr = FALSE;
	if (IS_SET_KILL_ZKILL_ZTRIG(rectype))
	{
		keystr = (jnl_string *)&rec->jrec_set_kill.mumps_node;
		EXTINT(keystr->nodeflags);
		buff = &murgbl.extr_buff[extract_len];
		max_blen = MIN(MAX_ZWR_KEY_SZ, murgbl.max_extr_record_length - extract_len);
		assert(MAX_ZWR_KEY_SZ == max_blen);	/* We allocated enough for key and data expansion for ZWR format */
		ptr = (char *)format_targ_key((uchar_ptr_t)buff, max_blen, gv_currkey, TRUE);
		assert(NULL != ptr);
		if (NULL != ptr)
			extract_len += (int)(ptr - &murgbl.extr_buff[extract_len]);
		if (IS_SET(rectype))
		{
			murgbl.extr_buff[extract_len++] = '=';
			val_ptr = &keystr->text[keystr->length];
			GET_MSTR_LEN(val_len, val_ptr);
			val_ptr += SIZEOF(mstr_len_t);
			do_format2zwr = TRUE;
		}
	} else if (IS_ZTWORM(rectype) || IS_LGTRIG(rectype))
	{
		assert(&rec->jrec_ztworm.ztworm_str == &rec->jrec_lgtrig.lgtrig_str);
		keystr = (jnl_string *)&rec->jrec_ztworm.ztworm_str;
		val_len = keystr->length;
		val_ptr = &keystr->text[0];
		do_format2zwr = TRUE;
	}
	if (do_format2zwr)
	{
		if (ZWR_EXP_RATIO(val_len) <= murgbl.max_extr_record_length - extract_len)
		{
			ptr = &murgbl.extr_buff[extract_len];
			format2zwr((sm_uc_ptr_t)val_ptr, val_len, (unsigned char *)ptr, &val_extr_len);
			extract_len += val_extr_len;
		} else
		{
			gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_JNLBADRECFMT,
				3, jctl->jnl_fn_len, jctl->jnl_fn, jctl->rec_offset,
				ERR_TEXT, 2, LEN_AND_LIT("Length of the record is too high for zwr format"));
			if (mur_options.verbose || mur_options.detail)
			{
				gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_MUINFOUINT4, 4,
					LEN_AND_LIT("After max expansion record length"),
					ZWR_EXP_RATIO(val_len), ZWR_EXP_RATIO(val_len));
				gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_MUINFOUINT4, 4, LEN_AND_LIT("Buffer size"),
					murgbl.max_extr_record_length - extract_len,
					murgbl.max_extr_record_length - extract_len);
			}
			assert(FALSE);
		}
	}
	murgbl.extr_buff[extract_len++] = '\\';
	jnlext_write(fi, murgbl.extr_buff, extract_len);
}
Beispiel #12
0
void gvcmz_doop(unsigned char query_code, unsigned char reply_code, mval *v)
{
	unsigned char	*ptr;
	short		len, temp_short;
	int4		status, max_reply_len;
	struct CLB	*lnk;
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;

	error_def(ERR_BADSRVRNETMSG);
	error_def(ERR_UNIMPLOP);
	error_def(ERR_TEXT);
	error_def(ERR_GVIS);

	lnk = gv_cur_region->dyn.addr->cm_blk;
	if (!((link_info *)lnk->usr)->server_supports_long_names && (PRE_V5_MAX_MIDENT_LEN < strlen((char *)gv_currkey->base)))
	{
		end = format_targ_key(buff, MAX_ZWR_KEY_SZ, gv_currkey, TRUE);
		rts_error(VARLSTCNT(14) ERR_UNIMPLOP, 0,
					ERR_TEXT, 2,
					LEN_AND_LIT("GT.CM server does not support global names longer than 8 characters"),
					ERR_GVIS, 2, end - buff, buff,
					ERR_TEXT, 2, DB_LEN_STR(gv_cur_region));
	}
	lnk->ast = 0;	/* all database queries are sync */
	lnk->cbl = 1 + /* HDR */
		   gv_currkey->end + /* key */
		   sizeof(unsigned short) + /* gv_key.top */
		   sizeof(unsigned short) + /* gv_key.end */
		   sizeof(unsigned short) + /* gv_key.prev */
		   sizeof(unsigned char) + /* gv_key.base */
		   sizeof(unsigned char) + /* regnum */
		   sizeof(unsigned short); /* size for variable len SUBSC */
	/* the current GT.CM maximum message buffer length is bounded by the size of a short which is 64K. but the
	 * calculation below of lnk->cbl and max_reply_len takes into account the fact that the value that is sent in as
	 * input or read in from the server side can be at most MAX_DBSTRLEN in size. therefore, there is a dependency
	 * that MAX_DBSTRLEN always be less than the GT.CM maximum message buffer length. to ensure this is always the
	 * case, the following assert is added so that whenever MAX_DBSTRLEN is increased, we will fail this assert
	 * and reexamine the code below.
	 */
	assert(sizeof(lnk->cbl) == 2);	/* assert it is a short. when it becomes a uint4 the assert can be removed
					 * if the macro CM_MAX_BUF_LEN (used below) is changed appropriately */
	assert(MAX_DBSTRLEN == (32 * 1024 - 1));
	if (CMMS_Q_PUT == query_code || CMMS_Q_INCREMENT == query_code)
	{
		if (CMMS_Q_INCREMENT == query_code)
		{ /* 1-byte boolean value of "undef_inhibit" passed to the server for $INCREMENT
		   although, effective V5.0-000, undef_inhibit is no longer relevant as $INCREMENT()
		   implicitly does a $GET() on the global. We keep this byte to ensure compatibility
		   with V5.0-FT01 */
			lnk->cbl++;
		}
		assert((uint4)lnk->cbl + sizeof(unsigned short) + (uint4)MAX_DBSTRLEN <= (uint4)CM_MAX_BUF_LEN);
		lnk->cbl += (sizeof(unsigned short) + v->str.len); /* VALUE + length */
	}
	if ((CMMS_Q_GET == query_code)
			|| (CMMS_Q_INCREMENT == query_code)
			|| (CMMS_Q_QUERY == query_code) && ((link_info *)lnk->usr)->query_is_queryget)
		max_reply_len = lnk->mbl + SIZEOF(unsigned short) + MAX_DBSTRLEN; /* can't predict the length of data value */
	else
		max_reply_len = lnk->mbl;
	assert(max_reply_len <= (int4)CM_MAX_BUF_LEN);
	if (stringpool.top < stringpool.free + max_reply_len)
		stp_gcol(max_reply_len);
	lnk->mbf = stringpool.free;
	ptr = lnk->mbf;
	*ptr++ = query_code;
	/* temp_short = gv_currkey->end + sizeof(gv_key) + 1; */
	temp_short = gv_currkey->end + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(char) + 1;
	CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder);
	ptr += sizeof(short);
	*ptr++ = gv_cur_region->cmx_regnum;
	CM_PUT_SHORT(ptr, gv_currkey->top, ((link_info *)(lnk->usr))->convert_byteorder);
	ptr += sizeof(short);
	CM_PUT_SHORT(ptr, gv_currkey->end, ((link_info *)(lnk->usr))->convert_byteorder);
	ptr += sizeof(short);
	CM_PUT_SHORT(ptr, gv_currkey->prev, ((link_info *)(lnk->usr))->convert_byteorder);
	ptr += sizeof(short);
	memcpy(ptr, gv_currkey->base, gv_currkey->end + 1);
	if (CMMS_Q_PUT == query_code || CMMS_Q_INCREMENT == query_code)
	{
		ptr += gv_currkey->end + 1;
		temp_short = (short)v->str.len;
		assert((int4)temp_short == v->str.len); /* short <- int4 assignment lossy? */
		CM_PUT_SHORT(ptr, temp_short, ((link_info *)(lnk->usr))->convert_byteorder);
		ptr += sizeof(short);
		memcpy(ptr,v->str.addr, v->str.len);
		if (CMMS_Q_INCREMENT == query_code)
		{ /* UNDEF flag is no longer relevant, but set the flag to ensure compatibility with V5.0-FT01 */
			assert(sizeof(undef_inhibit) == 1);
			ptr[v->str.len] = (unsigned char)undef_inhibit;
		}
	}
	status = cmi_write(lnk);
	if (CMI_ERROR(status))
	{
		((link_info *)(lnk->usr))->neterr = TRUE;
		gvcmz_error(query_code, status);
		return;
	}
	status = cmi_read(lnk);
	if (CMI_ERROR(status))
	{
		((link_info *)(lnk->usr))->neterr = TRUE;
		gvcmz_error(query_code, status);
		return;
	}
	ptr = lnk->mbf;
	if (CMMS_Q_PUT == query_code || CMMS_Q_ZWITHDRAW == query_code || CMMS_Q_KILL == query_code)
	{
		if (reply_code != *ptr)
		{
			if (*ptr != CMMS_E_ERROR)
				rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG);
			gvcmz_errmsg(lnk,FALSE);
		}
		return;
	}
	if (reply_code != *ptr)
	{
		if ((CMMS_R_UNDEF != *ptr) || ((CMMS_Q_GET != query_code) && (CMMS_Q_INCREMENT != query_code)))
		{
			if (CMMS_E_ERROR != *ptr)
				rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG);
			gvcmz_errmsg(lnk, FALSE);
		}
		if (CMMS_Q_INCREMENT == query_code)
			v->mvtype = 0;	/* set the result to be undefined */
		return;
	}
	ptr++;
	if (CMMS_R_DATA == reply_code)
	{
		CM_GET_SHORT(temp_short, ptr, ((link_info *)(lnk->usr))->convert_byteorder);
		if (1 != temp_short)
			rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG);
		ptr += sizeof(short);
		status = *ptr;	/* Temp assignment to status gets rid of compiler warning in MV_FORCE_MVAL macro */
		MV_FORCE_MVAL(v, status);
		return;
	}
	if (reply_code == CMMS_R_PREV || reply_code == CMMS_R_QUERY || reply_code == CMMS_R_ORDER)
	{
		CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder);
		ptr += sizeof(short);
		if (1 == len)
		{
			MV_FORCE_MVAL(v, 0);
		} else
		{
			if (*ptr++ != gv_cur_region->cmx_regnum)
				rts_error(VARLSTCNT(1) ERR_BADSRVRNETMSG);
			/* memcpy(gv_altkey, ptr, len - 1); */
			CM_GET_USHORT(gv_altkey->top, ptr, ((link_info *)(lnk->usr))->convert_byteorder);
			ptr += sizeof(unsigned short);
			CM_GET_USHORT(gv_altkey->end, ptr, ((link_info *)(lnk->usr))->convert_byteorder);
			ptr += sizeof(unsigned short);
			CM_GET_USHORT(gv_altkey->prev, ptr, ((link_info *)(lnk->usr))->convert_byteorder);
			ptr += sizeof(unsigned short);
			memcpy(gv_altkey->base, ptr, len - 1 - sizeof(unsigned short) - sizeof(unsigned short) -
						     sizeof(unsigned short));
			ptr += (len - 1 - sizeof(unsigned short) - sizeof(unsigned short) - sizeof(unsigned short));
			MV_FORCE_MVAL(v, 1);
		}
		if (CMMS_R_QUERY != reply_code || 1 == len || !((link_info *)lnk->usr)->query_is_queryget)
		{
			if (CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget)
				v->mvtype = 0; /* force undefined to distinguish $Q returning "" from value of QUERYGET being 0 */
			return;
		}
	}
	assert(CMMS_R_GET == reply_code
		|| CMMS_R_INCREMENT == reply_code
		|| CMMS_R_QUERY == reply_code && ((link_info *)lnk->usr)->query_is_queryget && 1 < len);
	CM_GET_SHORT(len, ptr, ((link_info *)(lnk->usr))->convert_byteorder);
	ptr += sizeof(unsigned short);
	assert(ptr >= stringpool.base && ptr + len < stringpool.top); /* incoming message is in stringpool */
	v->mvtype = MV_STR;
	v->str.len = len;
	v->str.addr = (char *)stringpool.free;	/* we don't need the reply msg anymore, can overwrite reply */
	memcpy(v->str.addr, ptr, len);		/* so that we don't leave a gaping hole in the stringpool */
	stringpool.free += len;
	return;
}
Beispiel #13
0
bool gtcmtr_put(void)
{
	cm_region_list	*reg_ref;
	mval		v;
	unsigned char	buff[MAX_ZWR_KEY_SZ], *end;
	unsigned char	*ptr, regnum;
	short		n;
	unsigned short	top, len;
	static readonly gds_file_id file;

	error_def(ERR_KEY2BIG);
	error_def(ERR_REC2BIG);
	error_def(ERR_GVIS);
	error_def(ERR_DBPRIVERR);

	ptr = curr_entry->clb_ptr->mbf;
	assert(*ptr == CMMS_Q_PUT);
	ptr++;
	GET_USHORT(len, ptr);
	ptr += SIZEOF(unsigned short);
	regnum = *ptr++;
	reg_ref = gtcm_find_region(curr_entry,regnum);
	len--; /* subtract size of regnum */
	CM_GET_GVCURRKEY(ptr, len);
	gtcm_bind_name(reg_ref->reghead, TRUE);
	if (gv_cur_region->read_only)
		rts_error(VARLSTCNT(4) ERR_DBPRIVERR, 2, DB_LEN_STR(gv_cur_region));
	if (JNL_ALLOWED(cs_addrs))
	{	/* we need to copy client's specific prc_vec into the global variable in order that the gvcst* routines
		 *	do the right job. actually we need to do this only if JNL_ENABLED(cs_addrs), but since it is not
		 *	easy to re-execute the following two assignments in case gvcst_put()'s call to t_end() encounters a
		 *	cdb_sc_jnlstatemod retry code, we choose the easier approach of executing the following segment
		 *	if JNL_ALLOWED(cs_addrs) is TRUE instead of checking for JNL_ENABLED(cs_addrs) to be TRUE.
		 * this approach has the overhead that we will be doing the following assignments even though JNL_ENABLED
		 * 	might not be TRUE but since the following two are just pointer copies, it is not considered a big overhead.
		 * this approach ensures that the jnl_put_jrt_pini() gets the appropriate prc_vec for writing into the
		 * 	journal record in case JNL_ENABLED turns out to be TRUE in t_end() time.
		 * note that the value of JNL_ALLOWED(cs_addrs) cannot be changed on the fly without obtaining standalone access
		 * 	and hence the correctness of prc_vec (whenever it turns out necessary) is guaranteed.
		 */
		originator_prc_vec = curr_entry->pvec;
		cs_addrs->jnl->pini_addr = reg_ref->pini_addr;
	}
	GET_USHORT(len, ptr);
	ptr += SIZEOF(unsigned short);
	v.mvtype = MV_STR;
	v.str.len = len;
	v.str.addr = (char *)ptr;
	if ((n = gv_currkey->end + 1) > gv_cur_region->max_key_size)
	{
		if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
			end = &buff[MAX_ZWR_KEY_SZ - 1];
		rts_error(VARLSTCNT(11) ERR_KEY2BIG, 4, n, (int4)gv_cur_region->max_key_size,
			REG_LEN_STR(gv_cur_region), 0, ERR_GVIS, 2, end - buff, buff);
	}
	if (n + v.str.len + SIZEOF(rec_hdr) > gv_cur_region->max_rec_size)
	{
		if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_currkey, TRUE)) == 0)
			end = &buff[MAX_ZWR_KEY_SZ - 1];
		rts_error(VARLSTCNT(10) ERR_REC2BIG, 4, n + v.str.len + SIZEOF(rec_hdr),
			(int4)gv_cur_region->max_rec_size, REG_LEN_STR(gv_cur_region),
			ERR_GVIS, 2, end - buff, buff);
	}
	gvcst_put(&v);
	if (JNL_ALLOWED(cs_addrs))
		reg_ref->pini_addr = cs_addrs->jnl->pini_addr; /* In case  journal switch occurred */
	ptr = curr_entry->clb_ptr->mbf;
	*ptr++ = CMMS_R_PUT;
	curr_entry->clb_ptr->cbl = S_HDRSIZE;
	return TRUE;
}