317 lines
9.2 KiB
C
317 lines
9.2 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2010, 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"
|
|
|
|
#ifdef GTM_TRIGGER
|
|
#include "gtm_string.h"
|
|
#include "gdsroot.h" /* for gdsfhead.h */
|
|
#include "gdsbt.h" /* for gdsfhead.h */
|
|
#include "gdsfhead.h" /* For gvcst_protos.h */
|
|
#include "gvcst_protos.h"
|
|
#include "hashtab_str.h"
|
|
#include "mv_stent.h" /* for COPY_SUBS_TO_GVCURRKEY macro */
|
|
#include "gvsub2str.h" /* for COPY_SUBS_TO_GVCURRKEY */
|
|
#include "format_targ_key.h" /* for COPY_SUBS_TO_GVCURRKEY */
|
|
#include "rtnhdr.h"
|
|
#include "gv_trigger.h"
|
|
#include "trigger.h"
|
|
#include "trigger_compare_protos.h"
|
|
#include "trigger_gbl_fill_xecute_buffer.h"
|
|
#include "mvalconv.h" /* Needed for MV_FORCE_MVAL and MV_FORCE_UMVAL */
|
|
#include "op.h"
|
|
#include "nametabtyp.h"
|
|
#include "targ_alloc.h" /* for SETUP_TRIGGER_GLOBAL & SWITCH_TO_DEFAULT_REGION */
|
|
#include "gdscc.h" /* needed for tp.h */
|
|
#include "gdskill.h" /* needed for tp.h */
|
|
#include "buddy_list.h" /* needed for tp.h */
|
|
#include "hashtab_int4.h" /* needed for tp.h */
|
|
#include "filestruct.h" /* needed for jnl.h */
|
|
#include "jnl.h" /* needed for tp.h */
|
|
#include "tp.h"
|
|
|
|
GBLREF sgmnt_data_ptr_t cs_data;
|
|
GBLREF gd_addr *gd_header;
|
|
GBLREF gd_region *gv_cur_region;
|
|
GBLREF gv_key *gv_currkey;
|
|
GBLREF gv_namehead *gv_target;
|
|
|
|
LITREF mval literal_hasht;
|
|
LITREF mval literal_one;
|
|
LITREF mval literal_ten;
|
|
LITREF char *trigger_subs[];
|
|
|
|
#define NON_HASH -1
|
|
LITDEF int trig_subsc_xlate_tbl[11] =
|
|
{
|
|
NON_HASH, 1, NON_HASH, NON_HASH, 4, 5, 6, 7, NON_HASH, NON_HASH, NON_HASH
|
|
};
|
|
|
|
#define COPY_VAL_TO_INDEX_STR(SUB, PTR) \
|
|
{ \
|
|
memcpy(PTR, values[SUB], value_len[SUB]); \
|
|
PTR += value_len[SUB]; \
|
|
*PTR++ = '\0'; \
|
|
}
|
|
|
|
error_def(ERR_TRIGDEFBAD);
|
|
|
|
STATICFNDEF boolean_t compare_vals(char *trigger_val, uint4 trigger_val_len, char *key_val, uint4 key_val_len)
|
|
{
|
|
char *end_ptr;
|
|
char *k_ptr;
|
|
char *t_ptr;
|
|
|
|
if (key_val_len < trigger_val_len)
|
|
return FALSE;
|
|
end_ptr = trigger_val + trigger_val_len;
|
|
t_ptr = trigger_val;
|
|
k_ptr = key_val;
|
|
while ((end_ptr > t_ptr) && (*t_ptr == *k_ptr))
|
|
{
|
|
t_ptr++;
|
|
k_ptr++;
|
|
}
|
|
return ((end_ptr > t_ptr) && ('\0' == *k_ptr));
|
|
}
|
|
|
|
void build_kill_cmp_str(char *trigvn, int trigvn_len, char **values, uint4 *value_len, mstr *kill_key, boolean_t multi_line_xecute)
|
|
{
|
|
uint4 lcl_len;
|
|
char *ptr;
|
|
|
|
lcl_len = kill_key->len;
|
|
assert(lcl_len >= (trigvn_len + 1 + value_len[GVSUBS_SUB] + 1 + value_len[XECUTE_SUB] + 1));
|
|
ptr = kill_key->addr;
|
|
memcpy(ptr, trigvn, trigvn_len);
|
|
ptr += trigvn_len;
|
|
*ptr++ = '\0';
|
|
COPY_VAL_TO_INDEX_STR(GVSUBS_SUB, ptr);
|
|
if (!multi_line_xecute)
|
|
COPY_VAL_TO_INDEX_STR(XECUTE_SUB, ptr);
|
|
kill_key->len = INTCAST(ptr - kill_key->addr) - 1;
|
|
}
|
|
|
|
void build_set_cmp_str(char *trigvn, int trigvn_len, char **values, uint4 *value_len, mstr *set_key, boolean_t multi_line_xecute)
|
|
{
|
|
uint4 lcl_len;
|
|
char *ptr;
|
|
|
|
lcl_len = set_key->len;
|
|
assert(lcl_len >= (trigvn_len + 1 + value_len[GVSUBS_SUB] + 1 + value_len[PIECES_SUB] + 1 + value_len[DELIM_SUB] + 1
|
|
+ value_len[ZDELIM_SUB] + 1 + value_len[XECUTE_SUB] + 1));
|
|
ptr = set_key->addr;
|
|
memcpy(ptr, trigvn, trigvn_len);
|
|
ptr += trigvn_len;
|
|
*ptr++ = '\0';
|
|
COPY_VAL_TO_INDEX_STR(GVSUBS_SUB, ptr);
|
|
COPY_VAL_TO_INDEX_STR(PIECES_SUB, ptr);
|
|
COPY_VAL_TO_INDEX_STR(DELIM_SUB, ptr);
|
|
COPY_VAL_TO_INDEX_STR(ZDELIM_SUB, ptr);
|
|
if (!multi_line_xecute)
|
|
COPY_VAL_TO_INDEX_STR(XECUTE_SUB, ptr);
|
|
set_key->len = INTCAST(ptr - set_key->addr) - 1;
|
|
}
|
|
|
|
boolean_t search_trigger_hash(char *trigvn, int trigvn_len, stringkey *trigger_hash, int match_index, int *hash_indx)
|
|
{
|
|
mval collision_indx;
|
|
mval *collision_indx_ptr;
|
|
int hash_index;
|
|
mval data_val, key_val;
|
|
int4 len;
|
|
mval mv_hash;
|
|
boolean_t match, multi_record;
|
|
char *ptr;
|
|
int trig_index;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
collision_indx_ptr = &collision_indx;
|
|
MV_FORCE_UMVAL(&mv_hash, trigger_hash->hash_code);
|
|
BUILD_HASHT_SUB_MSUB_SUB_CURRKEY(LITERAL_HASHTRHASH, STR_LIT_LEN(LITERAL_HASHTRHASH), mv_hash, "", 0);
|
|
while (TRUE)
|
|
{
|
|
op_gvorder(collision_indx_ptr);
|
|
if (0 == collision_indx_ptr->str.len)
|
|
{
|
|
hash_index = 0;
|
|
match = FALSE;
|
|
break;
|
|
}
|
|
BUILD_HASHT_SUB_MSUB_MSUB_CURRKEY(LITERAL_HASHTRHASH, STR_LIT_LEN(LITERAL_HASHTRHASH), mv_hash, collision_indx);
|
|
if (!gvcst_get(&key_val))
|
|
{ /* There has to be a #TRHASH entry */
|
|
assert(FALSE);
|
|
rts_error(VARLSTCNT(8) ERR_TRIGDEFBAD, 6, trigvn_len, trigvn, LEN_AND_LIT("\"#TRHASH\""),
|
|
mv_hash.str.len, mv_hash.str.addr);
|
|
}
|
|
ptr = key_val.str.addr;
|
|
len = STRLEN(ptr);
|
|
if ((len != trigvn_len) || (0 != memcmp(trigvn, ptr, len)))
|
|
{
|
|
hash_index = 0;
|
|
match = FALSE;
|
|
break;
|
|
}
|
|
ptr += len;
|
|
assert(('\0' == *ptr) && (key_val.str.len > len));
|
|
ptr++;
|
|
A2I(ptr, key_val.str.addr + key_val.str.len, trig_index);
|
|
assert(-1 != trig_index);
|
|
if ((0 == match_index) || (match_index == trig_index))
|
|
{
|
|
hash_index = MV_FORCE_INT(collision_indx_ptr);
|
|
match = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
*hash_indx = hash_index;
|
|
return match;
|
|
}
|
|
|
|
boolean_t search_triggers(char *trigvn, int trigvn_len, char **values, uint4 *value_len, stringkey *trigger_hash, int *hash_indx,
|
|
int *trig_indx, int match_index, boolean_t doing_set)
|
|
{
|
|
mval collision_indx;
|
|
mval *collision_indx_ptr;
|
|
sgmnt_addrs *csa;
|
|
mval data_val;
|
|
mstr gbl_name;
|
|
mname_entry gvent;
|
|
gv_namehead *hasht_tree;
|
|
boolean_t have_value;
|
|
mval key_val;
|
|
int4 len;
|
|
boolean_t multi_record;
|
|
mval mv_hash;
|
|
mval mv_trig_indx;
|
|
boolean_t match;
|
|
int4 num;
|
|
char *ptr;
|
|
int4 rec_len;
|
|
int sub_indx;
|
|
mval sub_val;
|
|
uint4 trig_hash;
|
|
int trig_hash_index;
|
|
int trig_index;
|
|
char *xecute_buff;
|
|
int4 xecute_len;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
collision_indx_ptr = &collision_indx;
|
|
MV_FORCE_UMVAL(&mv_hash, trigger_hash->hash_code);
|
|
BUILD_HASHT_SUB_MSUB_SUB_CURRKEY(LITERAL_HASHTRHASH, STR_LIT_LEN(LITERAL_HASHTRHASH), mv_hash, "", 0);
|
|
xecute_buff = NULL;
|
|
while (TRUE)
|
|
{
|
|
match = TRUE;
|
|
op_gvorder(collision_indx_ptr);
|
|
if (0 == collision_indx_ptr->str.len)
|
|
{
|
|
trig_hash_index = trig_index = 0;
|
|
match = FALSE;
|
|
break;
|
|
}
|
|
BUILD_HASHT_SUB_MSUB_MSUB_CURRKEY(LITERAL_HASHTRHASH, STR_LIT_LEN(LITERAL_HASHTRHASH), mv_hash, collision_indx);
|
|
if (!gvcst_get(&key_val))
|
|
{ /* There has to be a #TRHASH entry */
|
|
assert(FALSE);
|
|
rts_error(VARLSTCNT(8) ERR_TRIGDEFBAD, 6, trigvn_len, trigvn, LEN_AND_LIT("\"#TRHASH\""),
|
|
mv_hash.str.len, mv_hash.str.addr);
|
|
}
|
|
ptr = key_val.str.addr;
|
|
len = STRLEN(ptr);
|
|
if ((len != trigvn_len) || (0 != memcmp(trigvn, ptr, len)))
|
|
{
|
|
trig_hash_index = trig_index = 0;
|
|
match = FALSE;
|
|
break;
|
|
}
|
|
ptr += len;
|
|
assert(('\0' == *ptr) && (key_val.str.len > len));
|
|
ptr++;
|
|
A2I(ptr, key_val.str.addr + key_val.str.len, trig_index);
|
|
assert(-1 != trig_index);
|
|
gbl_name.addr = trigvn;
|
|
gbl_name.len = trigvn_len;
|
|
GV_BIND_NAME_ONLY(gd_header, &gbl_name);
|
|
csa = gv_target->gd_csa;
|
|
SETUP_TRIGGER_GLOBAL;
|
|
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
|
|
MV_FORCE_MVAL(&mv_trig_indx, trig_index);
|
|
for (sub_indx = 0; sub_indx < NUM_TOTAL_SUBS; sub_indx++)
|
|
{
|
|
if (NON_HASH == trig_subsc_xlate_tbl[sub_indx])
|
|
continue;
|
|
if (!doing_set && ((DELIM_SUB == sub_indx) || (ZDELIM_SUB == sub_indx) || (PIECES_SUB == sub_indx)))
|
|
continue;
|
|
BUILD_HASHT_SUB_MSUB_SUB_CURRKEY(trigvn, trigvn_len, mv_trig_indx, trigger_subs[sub_indx],
|
|
STRLEN(trigger_subs[sub_indx]));
|
|
multi_record = FALSE;
|
|
have_value = gvcst_get(&key_val);
|
|
if (!have_value && (XECUTE_SUB == sub_indx))
|
|
{
|
|
op_gvdata(&data_val);
|
|
multi_record = (literal_ten.m[0] == data_val.m[0]) && (literal_ten.m[1] == data_val.m[1]);
|
|
}
|
|
if ((0 == value_len[sub_indx]) && !have_value && !multi_record)
|
|
continue;
|
|
if (XECUTE_SUB == sub_indx)
|
|
{
|
|
assert(NULL == xecute_buff); /* We don't want a memory leak */
|
|
xecute_buff = trigger_gbl_fill_xecute_buffer(trigvn, trigvn_len, &mv_trig_indx,
|
|
multi_record ? NULL : &key_val, &xecute_len);
|
|
if ((value_len[sub_indx] == xecute_len)
|
|
&& (0 == memcmp(values[sub_indx], xecute_buff, value_len[sub_indx])))
|
|
{
|
|
free(xecute_buff);
|
|
xecute_buff = NULL;
|
|
continue;
|
|
} else
|
|
{
|
|
free(xecute_buff);
|
|
xecute_buff = NULL;
|
|
trig_hash_index = trig_index = 0;
|
|
match = FALSE;
|
|
break;
|
|
}
|
|
} else
|
|
{
|
|
if (have_value && (value_len[sub_indx] == key_val.str.len)
|
|
&& (0 == memcmp(values[sub_indx], key_val.str.addr, value_len[sub_indx])))
|
|
continue;
|
|
else
|
|
{
|
|
trig_hash_index = trig_index = 0;
|
|
match = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
SWITCH_TO_DEFAULT_REGION;
|
|
if (!match || ((0 != match_index) && (match_index != trig_index)))
|
|
{
|
|
BUILD_HASHT_SUB_MSUB_MSUB_CURRKEY(LITERAL_HASHTRHASH, STR_LIT_LEN(LITERAL_HASHTRHASH), mv_hash,
|
|
collision_indx);
|
|
continue;
|
|
}
|
|
trig_hash_index = MV_FORCE_INT(collision_indx_ptr);
|
|
match = TRUE;
|
|
break;
|
|
}
|
|
*trig_indx = trig_index;
|
|
*hash_indx = trig_hash_index;
|
|
return match;
|
|
}
|
|
#endif /* GTM_TRIGGER */
|