fis-gtm/sr_port/op_xkill.c

129 lines
4.5 KiB
C

/****************************************************************
* *
* Copyright 2001, 2011 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 <stdarg.h>
#include "gtm_string.h"
#include "lv_val.h"
#include "op.h"
GBLREF symval *curr_symval;
GBLREF lv_val *active_lv;
GBLREF uint4 lvtaskcycle;
GBLREF boolean_t gtm_stdxkill;
void op_xkill(UNIX_ONLY_COMMA(int n) mval *lvname_arg, ...)
{
va_list var;
VMS_ONLY(int n;)
DEBUG_ONLY(int vcnt;)
lv_val *lv;
mval *lvname;
mname_entry lvent;
ht_ent_mname *tabent, *top;
boolean_t lcl_stdxkill;
error_def(ERR_XKILLCNTEXC);
active_lv = (lv_val *)NULL; /* if we get here, subscript set was successful. clear active_lv to avoid later
cleanup problems */
/* GTM supports two methods for exclusive kill that affect the way aliases and pass-by-reference (PBR) parameters are
* treated when used in an exclusive kill.
* - M Standard - An alias or PBR var specified in an xkill list while its aliases are NOT in the list is killed.
* - GTM alternate - In the same situation, the aliases are NOT killed.
*
* The differences in processing of these two xkill modes are small but distinct. We will loop through the var list in
* both cases but in the M Standard variant, we will mark the hash table entry as not to be killed in the lower kill loop
* while in the GTM variant, we will mark the lv_val instead.
*/
lcl_stdxkill = gtm_stdxkill;
VAR_START(var, lvname_arg);
VMS_ONLY(va_count(n);)
lvname = lvname_arg;
assert(0 < n);
/* In debug mode we want to make sure the elements we mark to not be deleted are the ONLY
* elements that don't get deleted. The lvtaskcycle value, which is guaranteed to never be 0
* (once it has been incremented via macro), is an excellent way to get a fairly unique way of
* marking the hte. If we get positive marks that are NOT this value, we need to figure out why.
*/
# ifdef DEBUG
vcnt = 0;
INCR_LVTASKCYCLE; /* Needed for both debug of MSTD version or to mark lv_vals */
# else
if (!lcl_stdxkill)
{
INCR_LVTASKCYCLE; /* Needed to mark lv_vals */
}
# endif
for (; 0 < n;)
{
MV_FORCE_STR(lvname);
if (lvname->str.len)
{ /* convert mval to var_tabent and see if it is in the symbol table */
if (lvname->str.len > MAX_MIDENT_LEN)
lvname->str.len = MAX_MIDENT_LEN;
lvent.var_name.len = lvname->str.len;
lvent.var_name.addr = lvname->str.addr;
COMPUTE_HASH_MNAME(&lvent);
if (tabent = lookup_hashtab_mname(&curr_symval->h_symtab, &lvent))
{ /* save info about the variable */
lv = (lv_val *)tabent->value;
assert(lv);
assert(LV_IS_BASE_VAR(lv));
assert(HTENT_VALID_MNAME(tabent, lv_val, lv));
if (lcl_stdxkill)
{ /* M Standard xkill variant - mark the hash table entry so it is not deleted */
assert(!tabent->key.marked);
tabent->key.marked = PRO_ONLY(TRUE) DEBUG_ONLY(lvtaskcycle);
DEBUG_ONLY(vcnt++);
} else
{ /* GTM xkill variant - mark the lvval so it is not deleted for ANY variant */
DEBUG_ONLY(if (lv->stats.lvtaskcycle != lvtaskcycle) vcnt++;);
lv->stats.lvtaskcycle = lvtaskcycle;
}
}
}
if (0 < --n)
lvname = va_arg(var, mval *);
else
break;
}
va_end(var);
/* Perform "op_killall" processing except on those hash table entries we have marked */
for (tabent = curr_symval->h_symtab.base, top = tabent + curr_symval->h_symtab.size; tabent < top; tabent++)
{
if (HTENT_VALID_MNAME(tabent, lv_val, lv))
{
assert(LV_IS_BASE_VAR(lv));
if (lcl_stdxkill)
{ /* M Standard variant - delete this var if hashtab entry not marked (delete by name) */
if (!tabent->key.marked)
lv_kill(lv, DOTPSAVE_TRUE, DO_SUBTREE_TRUE);
else
{ /* If marked, unmark it and reduce debug count to verify array was as we expected it */
assert(tabent->key.marked == lvtaskcycle);
tabent->key.marked = FALSE;
DEBUG_ONLY(vcnt--);
}
} else
{ /* GTM variant - delete var if lv_val is not marked (delete by value) */
if (lv->stats.lvtaskcycle != lvtaskcycle)
lv_kill(lv, DOTPSAVE_TRUE, DO_SUBTREE_TRUE);
/* Note there is no (easy) way to maintain the debug vcnt in this variant */
}
}
}
assert(!lcl_stdxkill || (0 == vcnt)); /* Verify we found the same number as we marked but only for M-Standard variant */
}