fis-gtm/sr_port/dse_all.c

247 lines
6.9 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_string.h"
#include "gtm_stdio.h"
#include "util.h"
#include "cli.h"
#include "gdsroot.h"
#include "gt_timer.h"
#include "gtmmsg.h"
#if defined(UNIX)
#include "gtm_ipc.h"
#endif
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdskill.h"
#include "gdscc.h"
#include "buddy_list.h" /* needed for tp.h */
#include "hashtab_int4.h" /* needed for tp.h */
#include "tp.h"
#include "min_max.h" /* needed for init_root_gv.h */
#include "init_root_gv.h"
#include "dse.h"
#ifdef UNIX
# include "mutex.h"
#endif
#include "wcs_flu.h"
#include <signal.h> /* for VSIG_ATOMIC_T */
GBLREF VSIG_ATOMIC_T util_interrupt;
GBLREF block_id patch_curr_blk;
GBLREF gd_addr *gd_header;
GBLREF gd_region *gv_cur_region;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF short crash_count;
GBLREF uint4 process_id;
GBLREF gd_addr *original_header;
GBLREF boolean_t dse_all_dump; /* TRUE if DSE ALL -DUMP is specified */
error_def(ERR_DBRDONLY);
error_def(ERR_DSEWCINITCON);
error_def(ERR_FREEZE);
error_def(ERR_FREEZECTRL);
void dse_all(void)
{
gd_region *ptr;
tp_region *region_list, *rg, *rg_last, *rg_new; /* A handy structure for maintaining a list of regions */
int i, j;
sgmnt_addrs *old_addrs, *csa;
gd_region *old_region;
block_id old_block;
int4 stat;
boolean_t ref = FALSE;
boolean_t crit = FALSE;
boolean_t wc = FALSE;
boolean_t flush = FALSE;
boolean_t freeze = FALSE;
boolean_t nofreeze = FALSE;
boolean_t seize = FALSE;
boolean_t release = FALSE;
boolean_t dump = FALSE;
boolean_t override = FALSE;
boolean_t was_crit;
gd_addr *temp_gdaddr;
gd_binding *map;
UNIX_ONLY(char *fgets_res;)
old_addrs = cs_addrs;
old_region = gv_cur_region;
old_block = patch_curr_blk;
temp_gdaddr = gd_header;
gd_header = original_header;
if (cli_present("RENEW") == CLI_PRESENT)
{
crit = ref = wc = nofreeze = TRUE;
GET_CONFIRM_AND_HANDLE_NEG_RESPONSE;
} else
{
if (cli_present("CRITINIT") == CLI_PRESENT)
crit = TRUE;
if (cli_present("REFERENCE") == CLI_PRESENT)
ref = TRUE;
if (cli_present("WCINIT") == CLI_PRESENT)
{
GET_CONFIRM_AND_HANDLE_NEG_RESPONSE;
wc = TRUE;
}
if (cli_present("BUFFER_FLUSH") == CLI_PRESENT)
flush = TRUE;
if (cli_present("SEIZE") == CLI_PRESENT)
seize = TRUE;
if (cli_present("RELEASE") == CLI_PRESENT)
release = TRUE;
stat = cli_present("FREEZE");
if (stat == CLI_NEGATED)
nofreeze = TRUE;
else if (stat == CLI_PRESENT)
{
freeze = TRUE;
nofreeze = FALSE;
}
if (cli_present("OVERRIDE") == CLI_PRESENT)
override = TRUE;
if (cli_present("DUMP") == CLI_PRESENT)
dump = TRUE;
}
if (!dump && gv_cur_region->read_only)
rts_error(VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
region_list = NULL;
for (i = 0, ptr = gd_header->regions; i < gd_header->n_regions; i++, ptr++)
{
if (ptr->dyn.addr->acc_meth != dba_bg && ptr->dyn.addr->acc_meth != dba_mm)
{
util_out_print("Skipping region !AD: not BG or MM access",TRUE,ptr->rname_len,&ptr->rname[0]);
continue;
}
if (!ptr->open)
{
util_out_print("Skipping region !AD as it is not bound to any namespace.", TRUE,
ptr->rname_len, &ptr->rname[0]);
continue;
}
if (dump)
{
gv_cur_region = ptr;
cs_addrs = &FILE_INFO(gv_cur_region)->s_addrs;
dse_all_dump = TRUE;
dse_dmp_fhead();
assert(!dse_all_dump); /* should have been reset by "dse_dmp_fhead" */
} else
{
/* put on region list in order of ftok value so processed in same order that crits are obtained */
csa = &FILE_INFO(ptr)->s_addrs;
insert_region(ptr, &(region_list), NULL, SIZEOF(tp_region));
}
}
if (!dump)
{ /* Now run the list of regions in the sorted ftok order to execute the desired commands */
for (rg = region_list; NULL != rg; rg = rg->fPtr)
{
gv_cur_region = rg->reg;
switch(gv_cur_region->dyn.addr->acc_meth)
{
case dba_mm:
case dba_bg:
cs_addrs = &FILE_INFO(gv_cur_region)->s_addrs;
break;
default:
GTMASSERT;
}
patch_curr_blk = get_dir_root();
if (crit)
{
UNIX_ONLY(gtm_mutex_init(gv_cur_region, NUM_CRIT_ENTRY, TRUE);)
VMS_ONLY(mutex_init(cs_addrs->critical, NUM_CRIT_ENTRY, TRUE);)
cs_addrs->nl->in_crit = 0;
cs_addrs->hold_onto_crit = FALSE; /* reset this just before cs_addrs->now_crit is reset */
cs_addrs->now_crit = FALSE;
}
if (cs_addrs->critical)
crash_count = cs_addrs->critical->crashcnt;
if (freeze)
{
while (REG_ALREADY_FROZEN == region_freeze(gv_cur_region, TRUE, override, FALSE))
{
hiber_start(1000);
if (util_interrupt)
{
gtm_putmsg(VARLSTCNT(1) ERR_FREEZECTRL);
break;
}
}
if (freeze != !(cs_addrs->hdr->freeze))
util_out_print("Region !AD is now FROZEN", TRUE, REG_LEN_STR(gv_cur_region));
}
was_crit = cs_addrs->now_crit;
if (seize)
{
if (!was_crit)
grab_crit(gv_cur_region); /* no point seizing crit if WE already have it held */
cs_addrs->hold_onto_crit = TRUE; /* need to do this AFTER grab_crit */
cs_addrs->dse_crit_seize_done = TRUE;
}
if (wc)
{
if (!was_crit && !seize)
grab_crit(gv_cur_region);
DSE_WCREINIT(cs_addrs);
if (!was_crit && (!seize || release))
rel_crit(gv_cur_region);
}
if (flush)
wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH);
if (release)
{ /* user wants crit to be released unconditionally so "was_crit" not checked like everywhere else */
if (cs_addrs->now_crit)
{
cs_addrs->dse_crit_seize_done = FALSE;
cs_addrs->hold_onto_crit = FALSE; /* need to do this BEFORE rel_crit */
rel_crit(gv_cur_region);
}
else
{
assert(!cs_addrs->hold_onto_crit && !cs_addrs->dse_crit_seize_done);
util_out_print("Current process does not own the Region: !AD.",
TRUE, REG_LEN_STR(gv_cur_region));
}
}
if (nofreeze)
{
if (REG_ALREADY_FROZEN == region_freeze(gv_cur_region,FALSE, override, FALSE))
util_out_print("Region: !AD is frozen by another user, not releasing freeze",TRUE,
REG_LEN_STR(gv_cur_region));
else
util_out_print("Region !AD is now UNFROZEN", TRUE, REG_LEN_STR(gv_cur_region));
}
if (ref)
cs_addrs->nl->ref_cnt = 1;
}
}
cs_addrs = old_addrs;
gv_cur_region = old_region;
patch_curr_blk = old_block;
GET_SAVED_GDADDR(gd_header, temp_gdaddr, map, gv_cur_region);
return;
}