/**************************************************************** * * * 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 #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 */