void view_arg_convert(viewtab_entry *vtp, int vtp_parm, mval *parm, viewparm *parmblk, boolean_t is_dollar_view) { static int4 first_time = TRUE; char *cptr; char *strtokptr; gd_binding *gd_map; gd_region *gd_reg_start, *r_ptr, *r_top; gvnh_reg_t *gvnh_reg; gvnh_spanreg_t *gvspan; gv_namehead *tmp_gvt; ht_ent_mname *tabent; int n, reg_index; mident_fixed lcl_buff; mname_entry gvent, lvent; mstr namestr, tmpstr; unsigned char *c, *c_top, *dst, *dst_top, global_names[1024], *nextsrc, *src, *src_top, stashed, y; switch (vtp_parm) { case VTP_NULL: if (parm != 0) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); break; case (VTP_NULL | VTP_VALUE): if (NULL == parm) { parmblk->value = (mval *)&literal_one; break; } /* caution: fall through */ case VTP_VALUE: if (NULL == parm) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); parmblk->value = parm; break; case (VTP_NULL | VTP_DBREGION): if (!is_dollar_view && ((NULL == parm) || ((1 == parm->str.len) && ('*' == *parm->str.addr)))) { parmblk->gv_ptr = NULL; break; } /* caution: fall through */ case VTP_DBREGION: if (NULL == parm) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); if (!gd_header) /* IF GD_HEADER ==0 THEN OPEN GBLDIR */ gvinit(); r_ptr = gd_header->regions; if (!parm->str.len && vtp->keycode == VTK_GVNEXT) /* "" => 1st region */ parmblk->gv_ptr = r_ptr; else { for (cptr = parm->str.addr, n = 0; n < parm->str.len; cptr++, n++) lcl_buff.c[n] = TOUPPER(*cptr); /* Region names are upper-case ASCII */ namestr.len = n; namestr.addr = &lcl_buff.c[0]; for (r_top = r_ptr + gd_header->n_regions; ; r_ptr++) { if (r_ptr >= r_top) { format2zwr((sm_uc_ptr_t)parm->str.addr, parm->str.len, global_names, &n); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOREGION,2, n, global_names); } tmpstr.len = r_ptr->rname_len; tmpstr.addr = (char *)r_ptr->rname; MSTR_CMP(tmpstr, namestr, n); if (0 == n) break; } parmblk->gv_ptr = r_ptr; } break; case VTP_DBKEY: if (NULL == parm) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); if (!parm->str.len) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTGBL, 2, parm->str.len, NULL); if (!gd_header) /* IF GD_HEADER ==0 THEN OPEN GBLDIR */ gvinit(); c = (unsigned char *)parm->str.addr; if ('^' != *c) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTGBL, 2, parm->str.len, c); c_top = c + parm->str.len; c++; /* skip initial '^' */ parmblk->str.addr = (char *)c; for ( ; (c < c_top) && ('(' != *c); c++) ; parmblk->str.len = (char *)c - parmblk->str.addr; if (MAX_MIDENT_LEN < parmblk->str.len) parmblk->str.len = MAX_MIDENT_LEN; if (!valid_mname(&parmblk->str)) { format2zwr((sm_uc_ptr_t)parm->str.addr, parm->str.len, global_names, &n); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, n, global_names); } break; case VTP_RTNAME: if (NULL == parm) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); memset(&parmblk->ident.c[0], 0, SIZEOF(parmblk->ident)); if (parm->str.len > 0) memcpy(&parmblk->ident.c[0], parm->str.addr, (parm->str.len <= MAX_MIDENT_LEN ? parm->str.len : MAX_MIDENT_LEN)); break; case VTP_NULL | VTP_DBKEYLIST: if (NULL == parm || 0 == parm->str.len) { parmblk->ni_list.gvnh_list = NULL; parmblk->ni_list.type = NOISOLATION_NULL; break; } /* caution : explicit fall through */ case VTP_DBKEYLIST: if (NULL == parm) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); if (!gd_header) gvinit(); if (first_time) { noisolation_buddy_list = (buddy_list *)malloc(SIZEOF(buddy_list)); initialize_list(noisolation_buddy_list, SIZEOF(noisolation_element), NOISOLATION_INIT_ALLOC); gvt_pending_buddy_list = (buddy_list *)malloc(SIZEOF(buddy_list)); initialize_list(gvt_pending_buddy_list, SIZEOF(gvt_container), NOISOLATION_INIT_ALLOC); first_time = FALSE; } assertpro(SIZEOF(global_names) > parm->str.len); tmpstr.len = parm->str.len; /* we need to change len and should not change parm->str, so take a copy */ tmpstr.addr = parm->str.addr; if (0 != tmpstr.len) { switch (*tmpstr.addr) { case '+' : parmblk->ni_list.type = NOISOLATION_PLUS; tmpstr.addr++; tmpstr.len--; break; case '-' : parmblk->ni_list.type = NOISOLATION_MINUS; tmpstr.addr++; tmpstr.len--; break; default : parmblk->ni_list.type = NOISOLATION_NULL; break; } if (!tmpstr.len) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, tmpstr.len, NULL); memcpy(global_names, tmpstr.addr, tmpstr.len); global_names[tmpstr.len] = '\0'; src = (unsigned char *)STRTOK_R((char *)global_names, ",", &strtokptr); REINITIALIZE_LIST(noisolation_buddy_list); /* reinitialize the noisolation buddy_list */ parmblk->ni_list.gvnh_list = NULL; for ( ; src < &global_names[tmpstr.len + 1]; src = nextsrc) { nextsrc = (unsigned char *)STRTOK_R(NULL, ",", &strtokptr); if (NULL == nextsrc) nextsrc = &global_names[tmpstr.len + 1]; if (nextsrc - src >= 2 && '^' == *src) { namestr.addr = (char *)src + 1; /* skip initial '^' */ namestr.len = INTCAST(nextsrc - src - 2); /* don't count initial ^ and trailing 0 */ if (namestr.len > MAX_MIDENT_LEN) namestr.len = MAX_MIDENT_LEN; if (valid_mname(&namestr)) { memcpy(&lcl_buff.c[0], namestr.addr, namestr.len); gvent.var_name.len = namestr.len; } else { memcpy(&lcl_buff.c[0], src, nextsrc - src - 1); format2zwr((sm_uc_ptr_t)&lcl_buff.c, nextsrc - src - 1, global_names, &n); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, n, global_names); } } else { memcpy(&lcl_buff.c[0], src, nextsrc - src - 1); format2zwr((sm_uc_ptr_t)&lcl_buff.c, nextsrc - src - 1, global_names, &n); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, n, global_names); } tmp_gvt = NULL; gvent.var_name.addr = &lcl_buff.c[0]; COMPUTE_HASH_MNAME(&gvent); if (NULL != (tabent = lookup_hashtab_mname(gd_header->tab_ptr, &gvent))) { gvnh_reg = (gvnh_reg_t *)tabent->value; assert(NULL != gvnh_reg); tmp_gvt = gvnh_reg->gvt; } else { gd_map = gv_srch_map(gd_header, gvent.var_name.addr, gvent.var_name.len, SKIP_BASEDB_OPEN_FALSE); r_ptr = gd_map->reg.addr; tmp_gvt = (gv_namehead *)targ_alloc(r_ptr->max_key_size, &gvent, r_ptr); GVNH_REG_INIT(gd_header, gd_header->tab_ptr, gd_map, tmp_gvt, r_ptr, gvnh_reg, tabent); /* In case of a global spanning multiple regions, the gvt pointer corresponding to * the region where the unsubscripted global reference maps to is stored in TWO * locations (one in gvnh_reg->gvspan->gvt_array[index] and one in gvnh_reg->gvt. * So pass in both these pointer addresses to be stored in the pending list in * case this gvt gets reallocated (due to different keysizes between gld and db). */ if (NULL == (gvspan = gvnh_reg->gvspan)) { ADD_TO_GVT_PENDING_LIST_IF_REG_NOT_OPEN(r_ptr, &gvnh_reg->gvt, NULL); } else { gd_reg_start = &gd_header->regions[0]; GET_REG_INDEX(gd_header, gd_reg_start, r_ptr, reg_index); /* the above sets "reg_index" */ assert(reg_index >= gvspan->min_reg_index); assert(reg_index <= gvspan->max_reg_index); reg_index -= gvspan->min_reg_index; ADD_TO_GVT_PENDING_LIST_IF_REG_NOT_OPEN(r_ptr, &gvspan->gvt_array[reg_index], &gvnh_reg->gvt); } } ADD_GVT_TO_VIEW_NOISOLATION_LIST(tmp_gvt, parmblk); if (!is_dollar_view && (NULL != gvnh_reg->gvspan)) { /* Global spans multiple regions. Make sure gv_targets corresponding to ALL * spanned regions are allocated so NOISOLATION status can be set in all of * them even if the corresponding regions are not open yet. Do this only for * VIEW "NOISOLATION" commands which change the noisolation characteristic. * $VIEW("NOISOLATION") only examines the characteristics and so no need to * allocate all the gv-targets in that case. Just one is enough. */ gvnh_spanreg_subs_gvt_init(gvnh_reg, gd_header, parmblk); } } } else rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWGVN, 2, tmpstr.len, tmpstr.addr); break; case VTP_LVN: if (NULL == parm) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword); if (0 < parm->str.len) { lvent.var_name.addr = parm->str.addr; lvent.var_name.len = parm->str.len; if (lvent.var_name.len > MAX_MIDENT_LEN) lvent.var_name.len = MAX_MIDENT_LEN; if (!valid_mname(&lvent.var_name)) { format2zwr((sm_uc_ptr_t)parm->str.addr, parm->str.len, global_names, &n); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWLVN, 2, n, global_names); } } else rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr); /* Now look up the name.. */ COMPUTE_HASH_MNAME(&lvent); if ((tabent = lookup_hashtab_mname(&curr_symval->h_symtab, &lvent)) && (NULL != tabent->value)) parmblk->value = (mval *)tabent->value; /* Return lv_val ptr */ else rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr); break; default: assertpro(FALSE && vtp_parm); } }
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; }