void gvzwrite_clnup(void) { gv_key *old; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; gv_cur_region = gvzwrite_block->gd_reg; change_reg(); assert(reset_gv_target == ((gv_namehead *)gvzwrite_block->old_targ)); if (NULL != gvzwrite_block->old_key) { old = (gv_key *)gvzwrite_block->old_key; memcpy(&gv_currkey->base[0], &old->base[0], old->end + 1); gv_currkey->end = old->end; gv_currkey->prev = old->prev; gd_map = gvzwrite_block->old_map; gd_map_top = gvzwrite_block->old_map_top; free(gvzwrite_block->old_key); gvzwrite_block->old_key = gvzwrite_block->old_targ = (unsigned char *)NULL; gvzwrite_block->subsc_count = 0; TREF(gv_last_subsc_null) = gvzwrite_block->gv_last_subsc_null; TREF(gv_some_subsc_null) = gvzwrite_block->gv_some_subsc_null; } RESET_GV_TARGET(DO_GVT_GVKEY_CHECK); }
void preemptive_db_clnup(int preemptive_severe) { sgmnt_addrs *csa; sgm_info *si; gd_region *r_top, *reg; gd_addr *addr_ptr; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; /* Clear "inctn_opcode" global variable now that any in-progress transaction is aborted at this point. * Not doing so would cause future calls to "t_end" to get confused and skip writing logical jnl recs * and instead incorrectly write an INCTN record (GTM-8425). */ if (bml_save_dollar_tlevel) { assert(!dollar_tlevel); dollar_tlevel = bml_save_dollar_tlevel; bml_save_dollar_tlevel = 0; } assert(!dollar_tlevel || (inctn_invalid_op == inctn_opcode) || (inctn_bmp_mark_free_gtm == inctn_opcode)); assert(dollar_tlevel || update_trans || (inctn_invalid_op == inctn_opcode)); inctn_opcode = inctn_invalid_op; if (!dollar_tlevel && update_trans) { /* It's possible we hit an error in the middle of an update, at which point we have * a valid clue and non-NULL cse. However, this causes problems for subsequent * transactions (see comment in t_begin). In particular we could end up pinning buffers * unnecessarily. So clear the cse of any histories that may have been active during the update. */ CLEAR_CSE(gv_target); if ((NULL != gv_target) && (NULL != gv_target->gd_csa)) { CLEAR_CSE(gv_target->gd_csa->dir_tree); GTMTRIG_ONLY(CLEAR_CSE(gv_target->gd_csa->hasht_tree)); } /* Resetting this is necessary to avoid blowing an assert in t_begin that it is 0 at the start of a transaction. */ update_trans = 0; } if (INVALID_GV_TARGET != reset_gv_target) { if (SUCCESS != preemptive_severe && INFO != preemptive_severe) { /* We know of a few cases in Unix where gv_target and gv_currkey could be out of sync at this point. * a) If we are inside trigger code which in turn does an update that does * reads of ^#t global and ends up in a restart. This restart would * in turn do a rts_error_csa(TPRETRY) which would invoke mdb_condition_handler * that would in turn invoke preemptive_db_clnup which invokes this macro. * In this tp restart case though, it is ok for gv_target and gv_currkey * to be out of sync because they are going to be reset by tp_clean_up anyways. * So skip the dbg-only in-sync check. * b) If we are in gvtr_init reading the ^#t global and detect an error (e.g. TRIGINVCHSET) * gv_target after the reset would be pointing to a regular global whereas gv_currkey * would be pointing to ^#t. It is ok to be out-of-sync since in this case, we expect * mdb_condition_handler to be calling us. That has code to reset gv_currkey (and * cs_addrs/cs_data etc.) to reflect gv_target (i.e. get them back in sync). * Therefore in Unix we pass SKIP_GVT_GVKEY_CHECK to skip the gvtarget/gvcurrkey out-of-sync check * in RESET_GV_TARGET. In VMS we pass DO_GVT_GVKEY_CHECK as we dont yet know of an out-of-sync situation. */ RESET_GV_TARGET(UNIX_ONLY(SKIP_GVT_GVKEY_CHECK) VMS_ONLY(DO_GVT_GVKEY_CHECK)); } } need_kip_incr = FALSE; /* in case we got an error in t_end (e.g. GBLOFLOW), dont want this global variable to get * carried over to the next non-TP transaction that this process does (e.g. inside an error trap). */ TREF(expand_prev_key) = FALSE; /* reset global (in case it is TRUE) so it does not get carried over to future operations */ if (dollar_tlevel) { for (si = first_sgm_info; si != NULL; si = si->next_sgm_info) { if (NULL != si->kip_csa) { csa = si->tp_csa; assert(si->tp_csa == si->kip_csa); PROBE_DECR_KIP(csa->hdr, csa, si->kip_csa); } } } else if (NULL != kip_csa && (NULL != kip_csa->hdr) && (NULL != kip_csa->nl)) PROBE_DECR_KIP(kip_csa->hdr, kip_csa, kip_csa); if (IS_DSE_IMAGE) { /* Release crit on any region that was obtained for the current erroring DSE operation. * Take care NOT to release crits obtained by a previous CRIT -SEIZE command. */ for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr)) { for (reg = addr_ptr->regions, r_top = reg + addr_ptr->n_regions; reg < r_top; reg++) { if (reg->open && !reg->was_open) { csa = &FILE_INFO(reg)->s_addrs; assert(csa->hold_onto_crit || !csa->dse_crit_seize_done); assert(!csa->hold_onto_crit || csa->now_crit); if (csa->now_crit && (!csa->hold_onto_crit || !csa->dse_crit_seize_done)) { rel_crit(reg); csa->hold_onto_crit = FALSE; t_abort(reg, csa); /* cancel mini-transaction if any in progress */ } } } } } }