void	op_trollback(int rb_levels)		/* rb_levels -> # of transaction levels by which we need to rollback : BYPASSOK */
{
	boolean_t	lcl_implicit_trollback = FALSE, reg_reset;
	uint4		newlevel;
	gd_region	*save_cur_region;	/* saved copy of gv_cur_region before tp_clean_up/tp_incr_clean_up modifies it */
	gd_region	*curreg;
	gv_key		*gv_orig_key_ptr;
	sgmnt_addrs	*csa;
	tp_region	*tr;
	int		tl;

	if (implicit_trollback)
	{
		/* Unlike the call to "op_trollback" from generated code, this invocation of "op_trollback" is from C runtime code.
		 * Set the global variable to FALSE right away to avoid incorrect values from persisting in case of errors
		 * down below. Before the reset of the global variable, copy it into a local variable.
		 */
		lcl_implicit_trollback = implicit_trollback;
		implicit_trollback = FALSE;
	}
	if (!dollar_tlevel)
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_TLVLZERO);
	if (0 > rb_levels)
	{
		if (dollar_tlevel < -rb_levels)
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TROLLBK2DEEP, 2, -rb_levels, dollar_tlevel);
	} else if (dollar_tlevel <= rb_levels)
		rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_INVROLLBKLVL, 2, rb_levels, dollar_tlevel);
	newlevel = (0 > rb_levels) ? dollar_tlevel + rb_levels : rb_levels;
	DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
	save_cur_region = gv_cur_region;
	GTMTRIG_ONLY(assert(tstart_trigger_depth <= gtm_trigger_depth);) /* see similar assert in op_tcommit.c for why */
	if (!newlevel)
Beispiel #2
0
void gtm_fetch(unsigned int indxarg, ...)
#else
#error unsupported platform
#endif
{
	va_list		var;
	unsigned int 	indx;
	unsigned int 	cnt;
	stack_frame	*fp;
	ht_ent_mname	**htepp;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	assert(!process_exiting);	/* Verify that no process unwound the exit frame and continued */
	DEBUG_ONLY(DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);) /* surrounding DEBUG_ONLY needed because gdsfhead.h is
Beispiel #3
0
void gtm_fetch(unsigned int indxarg, ...)
#else
#error unsupported platform
#endif
{
	ht_ent_mname	**htepp;
	stack_frame	*fp;
	unsigned int 	cnt, indx;
	va_list		var;
#	ifdef DEBUG
	static int	als_lvval_gc_frequency, fetch_invocation;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	assert(!process_exiting);	/* Verify that no process unwound the exit frame and continued */
	assert(!TREF(expand_prev_key));	/* Verify that this global variable never stays TRUE outside of a $zprevious action */
	DEBUG_ONLY(DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);) /* surrounding DEBUG_ONLY needed because gdsfhead.h is
void gvzwr_fini(zshow_out *out, int pat)
{
	char 		m[SIZEOF(mident_fixed)];
	mval 		local, data;
	gv_key		*old;
	gvnh_reg_t	*gvnh_reg;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	if (!gv_currkey)
		gvinit();
	ESTABLISH(gvzwrite_ch);
	zwr_output = out;
	assert(INVALID_GV_TARGET == reset_gv_target);
	reset_gv_target = gv_target;
	DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
	gvzwrite_block->gd_reg = gv_cur_region;
	gvzwrite_block->old_targ = (unsigned char *)gv_target;
	old = (gv_key *)malloc(SIZEOF(gv_key) + gv_currkey->end);
	gvzwrite_block->old_key = (unsigned char *)old;
	memcpy(gvzwrite_block->old_key, gv_currkey, SIZEOF(gv_key) + gv_currkey->end);
	gvzwrite_block->gv_last_subsc_null = TREF(gv_last_subsc_null);
	gvzwrite_block->gv_some_subsc_null = TREF(gv_some_subsc_null);
	if (!pat)
	{
		local = *gvzwrite_block->pat;
		if (local.str.len)  /* New reference. Will get new gv_target.. */
		{
			gv_target = NULL;
			gv_currkey->base[0] = '\0';
			op_gvname(VARLSTCNT(1) &local);
 			op_gvdata(&data);
			if (!(MV_FORCE_INTD(&data)))
			{
				if (!undef_inhibit)
					sgnl_gvundef();
			} else
			{
				gvzwrite_block->fixed = (gvzwrite_block->fixed ? TRUE : FALSE);
				gvzwr_var(MV_FORCE_INTD(&data), 0);
			}
		} else	/* Old (naked) reference. Keep previous gv_target reference */
		{
			if (gv_currkey->prev == 0)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GVNAKED);
			gv_currkey->end = gv_currkey->prev;
			gv_currkey->base[gv_currkey->end] = 0;
			gv_currkey->prev = 0;
			/* If gvnh_reg corresponds to a spanning global, then determine
			 * gv_cur_region/gv_target/gd_targ_* variables based on updated gv_currkey.
			 */
			gvnh_reg = TREF(gd_targ_gvnh_reg);	/* set by op_gvname in previous call */
			GV_BIND_SUBSNAME_FROM_GVNH_REG_IF_GVSPAN(gvnh_reg, gd_header, gv_currkey);
			op_gvdata(&data);
			if (!(MV_FORCE_INTD(&data)))
			{
				if (!undef_inhibit)
					sgnl_gvundef();
			} else
			{
				gvzwrite_block->fixed = (gvzwrite_block->fixed ? TRUE : FALSE);
				gvzwr_var((int4)MV_FORCE_INTD(&data), 0);
			}
		}
	} else
	{
		gv_target = NULL;
		gv_currkey->base[0] = '\0';
		local.mvtype = MV_STR;
		local.str.addr = &m[0];
		local.str.len = 1;
		m[0] = '%';

		gvzwrite_block->fixed = FALSE;
		for (; ;)
		{
			op_gvname(VARLSTCNT(1) &local);
			if (do_pattern(&local, gvzwrite_block->pat))
			{
				op_gvdata(&data);
				if ((MV_FORCE_INTD(&data)))
				{
					gvzwr_var((int4)MV_FORCE_INTD(&data), 0);
				}
			}
			op_gvorder(&local);
			if (local.str.len)
			{
				assert(local.str.len <= MAX_MIDENT_LEN + 1);
				local.str.addr++;
				local.str.len--;
				memcpy(&m[0], local.str.addr, local.str.len);
				local.str.addr = &m[0];
			} else
				break;
		}
	}
	gvzwrite_clnup();	/* this routine is called by gvzwrite_ch() too */
	REVERT;
	return;
}
void	gvcst_spr_kill(void)
{
	boolean_t	spr_tpwrapped;
	boolean_t	est_first_pass;
	int		reg_index;
	gd_binding	*start_map, *end_map, *map;
	gd_region	*reg, *gd_reg_start;
	gd_addr		*addr;
	gv_namehead	*start_map_gvt;
	gvnh_reg_t	*gvnh_reg;
	trans_num	gd_targ_tn, *tn_array;
#	ifdef DEBUG
	int		save_dollar_tlevel;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	start_map = TREF(gd_targ_map);	/* set up by op_gvname/op_gvnaked/op_gvextnam done just before invoking op_gvkill */
	start_map_gvt = gv_target;	/* save gv_target corresponding to start_map so we can restore at end */
	/* Find out if the next (in terms of $order) key maps to same map as currkey. If so, no spanning activity needed */
	GVKEY_INCREMENT_ORDER(gv_currkey);
	end_map = gv_srch_map_linear(start_map, (char *)&gv_currkey->base[0], gv_currkey->end - 1);
	BACK_OFF_ONE_MAP_ENTRY_IF_EDGECASE(gv_currkey->base, gv_currkey->end - 1, end_map);
	GVKEY_UNDO_INCREMENT_ORDER(gv_currkey);
	if (start_map == end_map)
	{
		assert(gv_target == start_map_gvt);
		if (IS_OK_TO_INVOKE_GVCST_KILL(start_map_gvt))
			gvcst_kill(TRUE);
		return;
	}
	/* Do any initialization that is independent of retries BEFORE the op_tstart */
	addr = TREF(gd_targ_addr);
	assert(NULL != addr);
	gd_reg_start = &addr->regions[0];
	tn_array = TREF(gd_targ_reg_array);
	gvnh_reg = TREF(gd_targ_gvnh_reg);
	assert(NULL != gvnh_reg);
	assert(NULL != gvnh_reg->gvspan);
	/* Now that we know the keyrange maps to more than one region, go through each of them and do the kill.
	 * Since multiple regions are potentially involved, need a TP fence.
	 */
	DEBUG_ONLY(save_dollar_tlevel = dollar_tlevel);
	if (!dollar_tlevel)
	{
		spr_tpwrapped = TRUE;
		op_tstart((IMPLICIT_TSTART), TRUE, &literal_batch, 0);
		ESTABLISH_NORET(gvcst_spr_kill_ch, est_first_pass);
		GVCST_ROOT_SEARCH_AND_PREP(est_first_pass);
	} else
		spr_tpwrapped = FALSE;
	assert(gv_cur_region == start_map->reg.addr);
	DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
	/* Do any initialization that is dependent on retries AFTER the op_tstart */
	map = start_map;
	INCREMENT_GD_TARG_TN(gd_targ_tn); /* takes a copy of incremented "TREF(gd_targ_tn)" into local variable "gd_targ_tn" */
	/* Verify that initializations that happened before op_tstart are still unchanged */
	assert(addr == TREF(gd_targ_addr));
	assert(tn_array == TREF(gd_targ_reg_array));
	assert(gvnh_reg == TREF(gd_targ_gvnh_reg));
	for ( ; map <= end_map; map++)
	{
		reg = map->reg.addr;
		GET_REG_INDEX(addr, gd_reg_start, reg, reg_index);	/* sets "reg_index" */
		assert((map != start_map) || (tn_array[reg_index] != gd_targ_tn));
		assert(TREF(gd_targ_reg_array_size) > reg_index);
		if (tn_array[reg_index] == gd_targ_tn)
			continue;
		if (map != start_map)
			GV_BIND_SUBSREG(addr, reg, gvnh_reg);	/* sets gv_target/gv_cur_region/cs_addrs */
		assert(reg->open);
		if (IS_OK_TO_INVOKE_GVCST_KILL(gv_target))
			gvcst_kill(TRUE);
		tn_array[reg_index] = gd_targ_tn;
	}
	if (gv_target != start_map_gvt)
	{	/* Restore gv_cur_region/gv_target etc. */
		gv_target = start_map_gvt;
		gv_cur_region = start_map->reg.addr;
		change_reg();
	}
	DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
	if (spr_tpwrapped)
	{
		op_tcommit();
		REVERT; /* remove our condition handler */
	}
	assert(save_dollar_tlevel == dollar_tlevel);
	return;
}