fis-gtm/sr_port_cm/gtcmd_rundown.c

124 lines
4.1 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 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 "gtm_time.h"
#include "hashtab_mname.h"
#include "cmidef.h"
#include "cmmdef.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsblk.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "change_reg.h"
#include "gds_rundown.h"
#include "dpgbldir.h"
#include "wcs_timer_start.h"
#include "gtcmd.h"
#include "send_msg.h"
#include "targ_alloc.h"
GBLREF cm_region_head *reglist;
GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF jnl_gbls_t jgbl;
error_def(ERR_NOTALLDBRNDWN);
#ifdef VMS
GBLREF short gtcm_ast_avail;
#endif
void gtcmd_rundown(connection_struct *cnx, bool clean_exit)
{
int4 link;
cm_region_list *ptr, *last, *que_next, *que_last;
cm_region_head *region;
uint4 jnl_status;
jnl_private_control *jpc;
jnl_buffer_ptr_t jbp;
int refcnt;
boolean_t was_crit;
int4 rundown_status = EXIT_NRM; /* if gds_rundown went smoothly */
for (ptr = cnx->region_root; ptr;)
{
region = ptr->reghead;
TP_CHANGE_REG(region->reg);
jpc = cs_addrs->jnl;
if (ptr->pini_addr && clean_exit && JNL_ENABLED(cs_data) && (NOJNL != jpc->channel))
{
was_crit = cs_addrs->now_crit;
if (!was_crit)
grab_crit(gv_cur_region);
if (JNL_ENABLED(cs_data))
{
jpc->pini_addr = ptr->pini_addr;
SET_GBL_JREC_TIME; /* jnl_ensure_open/jnl_put_jrt_pfin needs this to be set */
jbp = jpc->jnl_buff;
/* Before writing to jnlfile, adjust jgbl.gbl_jrec_time if needed to maintain time order
* of jnl records. This needs to be done BEFORE the jnl_ensure_open as that could write
* journal records (if it decides to switch to a new journal file).
*/
ADJUST_GBL_JREC_TIME(jgbl, jbp);
jnl_status = jnl_ensure_open();
if (0 == jnl_status)
{
if (0 != jpc->pini_addr)
jnl_put_jrt_pfin(cs_addrs);
} else
send_msg(VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(cs_data), DB_LEN_STR(gv_cur_region));
}
if (!was_crit)
rel_crit(gv_cur_region);
}
refcnt = --region->refcnt;
/* Dont know how refcnt can become negative but in pro handle it by bypassing this region. The reason is the
* following. refcnt should have originally been a positive value. Every time this function is invoked, it would
* be decremented by one. There should have been one invocation that saw refcnt to be zero. That would have
* done the rundown of the region or if it is still in the stack the rundown is still in progress. Therefore
* it is not a good idea to try running down this region when we see refcnt to be negative (as otherwise we
* will get confused and could potentially end up with SIG-11 or ACCVIO errors). The worst case is that we
* would not have rundown the region in which case an externally issued MUPIP RUNDOWN would be enough.
*/
assert(0 <= refcnt);
if (0 == refcnt)
{ /* free up only as little as needed to facilitate structure reuse when the region is opened again */
assert(region->head.fl == region->head.bl);
VMS_ONLY(gtcm_ast_avail++);
if (JNL_ALLOWED(cs_data))
jpc->pini_addr = 0;
UNIX_ONLY(rundown_status |=) gds_rundown();
gd_ht_kill(region->reg_hash, TRUE); /* TRUE to free up the table and the gv_targets it holds too */
FREE_CSA_DIR_TREE(cs_addrs);
cm_del_gdr_ptr(gv_cur_region);
}
que_next = (cm_region_list *)((unsigned char *)ptr + ptr->regque.fl);
que_last = (cm_region_list *)((unsigned char *)ptr + ptr->regque.bl);
link = (int4)((unsigned char *)que_next - (unsigned char *)que_last);
que_last->regque.fl = link;
que_next->regque.bl = -link;
last = ptr;
ptr = ptr->next;
free(last);
}
if (EXIT_NRM != rundown_status)
rts_error(VARLSTCNT(1) ERR_NOTALLDBRNDWN);
}