fis-gtm/sr_port/mupip_integ.c

819 lines
28 KiB
C
Raw Normal View History

/****************************************************************
* *
* 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 "stp_parms.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "error.h"
#include "cli.h"
#include "iosp.h"
#include "gdscc.h"
#include "gdskill.h"
#include "filestruct.h"
#include "jnl.h"
#include "buddy_list.h" /* needed for tp.h */
#include "hashtab_int4.h" /* needed for tp.h */
#include "tp.h"
#include "mu_int_maps.h"
#include "util.h"
#include "mupipbckup.h"
#include "dbfilop.h"
#include "targ_alloc.h"
#include "mupip_exit.h"
#ifdef UNIX
#include "ipcrmid.h"
#include "db_ipcs_reset.h"
#endif
#include "mu_getlst.h"
#include "mu_outofband_setup.h"
#include "mupip_integ.h"
#include "gtmmsg.h"
#include "collseq.h"
#ifdef GTM_SNAPSHOT
#include "db_snapshot.h"
#endif
#include "mupint.h"
#include "mu_gv_cur_reg_init.h"
#define DUMMY_GLOBAL_VARIABLE "%D%DUMMY_VARIABLE"
#define DUMMY_GLOBAL_VARIABLE_LEN SIZEOF(DUMMY_GLOBAL_VARIABLE)
#define MAX_UTIL_LEN 80
#define APPROX_ALL_ERRORS 1000000
#define DEFAULT_ERR_LIMIT 10
#define DEFAULT_ADJACENCY 10
#define PERCENT_FACTOR 100
#define PERCENT_DECIMAL_SCALE 100000
#define PERCENT_SCALE_FACTOR 1000
#define LEAVE_BLOCKS_ALONE 0x0FFFFFFFFUL
#define TEXT1 " is incorrect, should be "
#define TEXT2 "!/Largest transaction number found in database was "
#define TEXT3 "Current transaction number is "
#define MSG1 "!/!/WARNING: Transaction number reset complete on all active blocks. Please do a DATABASE BACKUP before proceeding"
/* The QWPERCENTCALC calculates the percent used compatibly with the code fragment below.
* The size is no longer int_size but is now a qw_num, so the QW macros are now used to
* do the calculation.
*
* leftpt = (int_size * PERCENT_FACTOR) / (int_blks * blk_size);
* rightpt = (int_size * PERCENT_DECIMAL_SCALE) / (int_blks * blk_size) - (leftpt * PERCENT_SCALE_FACTOR);
*/
#define QWPERCENTCALC(lpt, rpt, qwint_size, int_blks, blk_size) \
{ \
qw_num tmp; \
size_t rem; \
\
if (int_blks) \
{ \
QWMULBYDW(tmp, (qwint_size), PERCENT_DECIMAL_SCALE); \
QWDIVIDEBYDW(tmp, (int_blks), tmp, rem); \
QWDIVIDEBYDW(tmp, (blk_size), tmp, rem); \
QWDIVIDEBYDW(tmp, PERCENT_SCALE_FACTOR, tmp, rpt); \
DWASSIGNQW((lpt), tmp); \
} else \
{ \
(lpt) = 0; \
(rpt) = 0; \
} \
}
GBLDEF unsigned char mu_int_root_level;
GBLDEF int4 mu_int_adj[MAX_BT_DEPTH + 1];
GBLDEF uint4 mu_int_errknt;
GBLDEF uint4 mu_int_blks[MAX_BT_DEPTH + 1];
GBLDEF uint4 mu_int_offset[MAX_BT_DEPTH + 1];
GBLDEF uint4 mu_int_recs[MAX_BT_DEPTH + 1];
GBLDEF qw_num mu_int_size[MAX_BT_DEPTH + 1];
GBLDEF int disp_map_errors;
GBLDEF int disp_maxkey_errors;
GBLDEF int disp_trans_errors;
GBLDEF int maxkey_errors = 0;
GBLDEF int muint_adj;
GBLDEF int mu_int_plen;
GBLDEF int mu_map_errs;
GBLDEF int trans_errors = 0;
GBLDEF boolean_t block = FALSE;
GBLDEF boolean_t muint_fast = FALSE;
GBLDEF boolean_t master_dir;
GBLDEF boolean_t muint_key = FALSE;
GBLDEF boolean_t muint_subsc = FALSE;
GBLDEF boolean_t mu_int_err_ranges;
GBLDEF boolean_t tn_reset_specified; /* use this to avoid recomputing cli_present("TN_RESET") in the loop */
GBLDEF boolean_t tn_reset_this_reg;
GBLDEF block_id mu_int_adj_prev[MAX_BT_DEPTH + 1];
GBLDEF block_id mu_int_path[MAX_BT_DEPTH + 1];
GBLDEF global_list *trees_tail;
GBLDEF global_list *trees;
GBLDEF sgmnt_data mu_int_data;
GBLDEF unsigned char *mu_int_master;
GBLDEF trans_num largest_tn;
GBLDEF int4 mu_int_blks_to_upgrd;
GBLDEF span_node_integ *sndata;
/* The following global variable is used to store the encryption information for the current database. The
* variable is initialized in mu_int_init(mupip integ -file <file.dat>) and mu_int_reg(mupip integ -reg <reg_name>). */
GTMCRYPT_ONLY(
GBLDEF gtmcrypt_key_t mu_int_encrypt_key_handle;
)
GBLREF bool mu_ctrly_occurred;
GBLREF bool mu_ctrlc_occurred;
GBLREF bool error_mupip;
GBLREF short crash_count;
GBLREF gd_region *gv_cur_region;
GBLREF gv_namehead *gv_target;
GBLREF gv_key *gv_altkey;
GBLREF gv_key *gv_currkey;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF tp_region *grlist;
GBLREF bool region;
GBLREF boolean_t debug_mupip;
GBLDEF boolean_t ointeg_this_reg;
GTM_SNAPSHOT_ONLY(
GBLDEF util_snapshot_ptr_t util_ss_ptr;
GBLDEF boolean_t preserve_snapshot;
GBLDEF boolean_t online_specified;
)
error_def(ERR_CTRLC);
error_def(ERR_CTRLY);
error_def(ERR_DBBTUFIXED);
error_def(ERR_DBBTUWRNG);
error_def(ERR_DBNOREGION);
error_def(ERR_DBRBNLBMN);
error_def(ERR_DBRBNNEG);
error_def(ERR_DBRBNTOOLRG);
error_def(ERR_DBRDONLY);
error_def(ERR_DBTNLTCTN);
error_def(ERR_DBTNRESETINC);
error_def(ERR_DBTNRESET);
error_def(ERR_INTEGERRS);
error_def(ERR_MUNOACTION);
error_def(ERR_MUNOFINISH);
error_def(ERR_MUPCLIERR);
error_def(ERR_DBSPANGLOINCMP);
error_def(ERR_DBSPANCHUNKORD);
void mupip_integ(void)
{
boolean_t full, muint_all_index_blocks;
boolean_t update_filehdr, update_header_tn;
char *temp, util_buff[MAX_UTIL_LEN];
unsigned char dummy;
unsigned char key_buff[2048];
short iosb[4];
unsigned short keylen;
unsigned int blocks_free = LEAVE_BLOCKS_ALONE;
int idx, leftpt, rightpt, total_errors, util_len;
uint4 cli_status;
block_id dir_root, mu_index_adj, mu_data_adj, muint_block;
uint4 prev_errknt, mu_dir_blks, mu_dir_recs, mu_data_blks, mu_data_recs, mu_index_blks, mu_index_recs;
qw_num mu_dir_size, mu_index_size, mu_data_size;
tp_region *rptr;
file_control *fc;
boolean_t retvalue_mu_int_reg, online_integ = FALSE, region_was_frozen;
GTM_SNAPSHOT_ONLY(
char ss_filename[GTM_PATH_MAX];
unsigned short ss_file_len = GTM_PATH_MAX;
)
sgmnt_data_ptr_t csd;
span_node_integ span_node_data;
sndata = &span_node_data;
sndata->sn_cnt = 0;
sndata->sn_blk_cnt = 0;
sndata->sn_type = SN_NOT;
error_mupip = FALSE;
if (NULL == gv_target)
gv_target = (gv_namehead *)targ_alloc(DUMMY_GLOBAL_VARIABLE_LEN, NULL, NULL);
if (CLI_PRESENT == (cli_status = cli_present("MAXKEYSIZE")))
{
assert(SIZEOF(disp_maxkey_errors) == SIZEOF(int4));
if (0 == cli_get_int("MAXKEYSIZE", (int4 *)&disp_maxkey_errors))
mupip_exit(ERR_MUPCLIERR);
if (disp_maxkey_errors < 1)
disp_maxkey_errors = 1;
} else if (CLI_NEGATED == cli_status)
disp_maxkey_errors = APPROX_ALL_ERRORS;
else
disp_maxkey_errors = DEFAULT_ERR_LIMIT;
if (CLI_PRESENT == (cli_status = cli_present("TRANSACTION")))
{
assert(SIZEOF(disp_trans_errors) == SIZEOF(int4));
if (0 == cli_get_int("TRANSACTION", (int4 *)&disp_trans_errors))
mupip_exit(ERR_MUPCLIERR);
if (disp_trans_errors < 1)
disp_trans_errors = 1;
} else if (CLI_NEGATED == cli_status)
disp_trans_errors = APPROX_ALL_ERRORS;
else
disp_trans_errors = DEFAULT_ERR_LIMIT;
if (CLI_PRESENT == (cli_status = cli_present("MAP")))
{
assert(SIZEOF(disp_map_errors) == SIZEOF(int4));
if (0 == cli_get_int("MAP", (int4 *)&disp_map_errors))
mupip_exit(ERR_MUPCLIERR);
if (disp_map_errors < 1)
disp_map_errors = 1;
} else if (CLI_NEGATED == cli_status)
disp_map_errors = APPROX_ALL_ERRORS;
else
disp_map_errors = DEFAULT_ERR_LIMIT;
if (CLI_PRESENT == cli_present("ADJACENCY"))
{
assert(SIZEOF(muint_adj) == SIZEOF(int4));
if (0 == cli_get_int("ADJACENCY", (int4 *)&muint_adj))
mupip_exit(ERR_MUPCLIERR);
} else
muint_adj = DEFAULT_ADJACENCY;
if (CLI_PRESENT == cli_present("BRIEF"))
full = FALSE;
else if (CLI_PRESENT == cli_present("FULL"))
full = TRUE;
else
full = FALSE;
if (CLI_PRESENT == cli_present("FAST"))
muint_fast = TRUE;
else
muint_fast = FALSE;
/* DBG qualifier prints extra debug messages while waiting for KIP in region freeze */
debug_mupip = (CLI_PRESENT == cli_present("DBG"));
GTM_SNAPSHOT_ONLY(online_specified = (CLI_PRESENT == cli_present("ONLINE"));)
# ifdef GTM_SNAPSHOT
if (online_specified)
{ /* if MUPIP INTEG -ONLINE -ANALYZE=<filename> is given then display details about the snapshot file
* and do early return
*/
if (cli_get_str("ANALYZE", ss_filename, &ss_file_len))
{
ss_anal_shdw_file(ss_filename, ss_file_len);
return;
}
}
# endif
if ((CLI_PRESENT == cli_present("REGION")) GTM_SNAPSHOT_ONLY(|| online_specified))
{
gvinit(); /* side effect: initializes gv_altkey (used by code below) & gv_currkey (not used by below code) */
region = TRUE;
mu_getlst("WHAT", SIZEOF(tp_region));
if (!grlist)
{
error_mupip = TRUE;
mu_int_errknt++;
mu_int_err(ERR_DBNOREGION, 0, 0, 0, 0, 0, 0, 0);
mupip_exit(ERR_MUNOACTION);
}
rptr = grlist;
} else
GVKEY_INIT(gv_altkey, DBKEYSIZE(MAX_KEY_SZ)); /* used by code below */
GTM_SNAPSHOT_ONLY(online_integ = ((TRUE != cli_negated("ONLINE")) && region)); /* Default option for INTEG is -ONLINE */
GTM_SNAPSHOT_ONLY(preserve_snapshot = (CLI_PRESENT == cli_present("PRESERVE"))); /* Should snapshot file be preserved ? */
GTM_SNAPSHOT_ONLY(assert(!online_integ || (region && !tn_reset_specified)));
if (CLI_PRESENT == cli_present("SUBSCRIPT"))
{
keylen = SIZEOF(key_buff);
if (0 == cli_get_str("SUBSCRIPT", (char *)key_buff, &keylen))
mupip_exit(ERR_MUPCLIERR);
if (FALSE == mu_int_getkey(key_buff, keylen))
mupip_exit(ERR_MUPCLIERR);
assert(muint_key); /* or else "mu_int_getkey" call above would have returned FALSE */
disp_map_errors = 0;
}
if (CLI_PRESENT == cli_present("BLOCK"))
{
if (0 == cli_get_hex("BLOCK", (uint4 *)&muint_block))
mupip_exit(SS_NORMAL);
block = TRUE;
disp_map_errors = 0;
master_dir = FALSE;
}
muint_all_index_blocks = !(block || muint_key);
mu_int_master = malloc(MASTER_MAP_SIZE_MAX);
tn_reset_specified = (CLI_PRESENT == cli_present("TN_RESET"));
mu_outofband_setup();
UNIX_ONLY(ESTABLISH(mu_int_ch);)
if (region)
{
if (online_integ)
{
# ifdef GTM_SNAPSHOT
/* The below structure members will be assigned in ss_initiate done in mu_int_reg.
* No free required as will be gone when process dies
*/
util_ss_ptr = malloc(SIZEOF(util_snapshot_t));
util_ss_ptr->header = &mu_int_data;
util_ss_ptr->master_map = mu_int_master;
util_ss_ptr->native_size = 0;
# endif
}
else /* Establish the condition handler ONLY if ONLINE INTEG was not requested */
ESTABLISH(mu_freeze_ch);
}
for (total_errors = mu_int_errknt = 0; ; total_errors += mu_int_errknt, mu_int_errknt = 0)
{
if (mu_ctrly_occurred || mu_ctrlc_occurred)
break;
if (region)
{
assert(NULL != rptr);
if (!mupfndfil(rptr->reg, NULL))
{
mu_int_errknt++;
rptr = rptr->fPtr;
if (NULL == rptr)
break;
continue;
}
}
QWASSIGNDW(mu_dir_size, 0);
QWASSIGNDW(mu_index_size, 0);
QWASSIGNDW(mu_data_size, 0);
mu_index_adj = mu_data_adj = 0;
mu_dir_blks = mu_dir_recs = 0;
mu_data_blks = mu_data_recs = 0;
mu_index_blks = mu_index_recs = 0;
mu_int_err_ranges = (CLI_NEGATED != cli_present("KEYRANGES"));
mu_int_root_level = (unsigned char)-1;
mu_map_errs = 0, prev_errknt = 0, largest_tn = 0;
mu_int_blks_to_upgrd = 0;
for (idx = 0; idx <= MAX_BT_DEPTH; idx++)
{
QWASSIGNDW(mu_int_size[idx], 0);
mu_int_blks[idx] = mu_int_recs[idx] = 0;
}
mu_int_path[0] = 0;
mu_int_offset[0] = 0;
mu_int_plen = 1;
memset(mu_int_adj, 0, SIZEOF(mu_int_adj));
if (region)
{
util_out_print("!/!/Integ of region !AD", TRUE, REG_LEN_STR(rptr->reg));
ointeg_this_reg = online_integ;
mu_int_reg(rptr->reg, &retvalue_mu_int_reg);
region_was_frozen = !ointeg_this_reg;
if (TRUE != retvalue_mu_int_reg)
{
rptr = rptr->fPtr;
if (NULL == rptr)
break;
continue;
}
/* If the region was frozen (INTEG -REG -NOONLINE) then use cs_addrs->hdr for verification of
* blks_to_upgrd, free blocks calculation. Otherwise (ONLINE INTEG) then use mu_int_data for
* the verification.
*/
if (region_was_frozen)
csd = cs_addrs->hdr;
else
csd = &mu_int_data;
} else
{
region_was_frozen = FALSE; /* For INTEG -FILE, region is not frozen as we would have standalone access */
if (FALSE == mu_int_init())
mupip_exit(ERR_INTEGERRS);
/* Since we have standalone access, there is no need for cs_addrs->hdr. So, use mu_int_data for
* verifications
*/
csd = &mu_int_data;
}
trees_tail = trees = (global_list *)malloc(SIZEOF(global_list));
memset(trees, 0, SIZEOF(global_list));
trees->root = dir_root = get_dir_root();
master_dir = TRUE;
trees_tail->nct = 0;
trees_tail->act = 0;
trees_tail->ver = 0;
tn_reset_this_reg = update_header_tn = FALSE;
if (tn_reset_specified)
{
if (gv_cur_region->read_only)
{
gtm_putmsg(VARLSTCNT(4) ERR_DBRDONLY, 2, gv_cur_region->dyn.addr->fname_len,
gv_cur_region->dyn.addr->fname);
mu_int_errknt++;
mu_int_err(ERR_DBTNRESET, 0, 0, 0, 0, 0, 0, 0);
mu_int_errknt-=2;
/* is this error supposed to update error count, or leave it ( then mu_int_errknt-- instead)*/
mu_int_plen++; /* continuing, so compensate for mu_int_err decrement */
} else
tn_reset_this_reg = update_header_tn = TRUE;
}
if (block)
{
master_dir = FALSE;
trees->root = muint_block;
}
for (trees->link = 0; ; master_dir = FALSE, temp = (char*)trees, trees = trees->link, free(temp))
{
if (mu_ctrly_occurred || mu_ctrlc_occurred)
{
if (region_was_frozen)
{
region_freeze(rptr->reg, FALSE, FALSE, FALSE);
if (!rptr->reg->read_only)
{
fc = gv_cur_region->dyn.addr->file_cntl;
fc->op = FC_WRITE;
fc->op_buff = (unsigned char *)FILE_INFO(rptr->reg)->s_addrs.hdr;
fc->op_len = ROUND_UP(SIZEOF(sgmnt_data), DISK_BLOCK_SIZE);
fc->op_pos = 1;
dbfilop(fc);
}
}
gtm_putmsg(VARLSTCNT(1) mu_ctrly_occurred ? ERR_CTRLY : ERR_CTRLC);
mupip_exit(ERR_MUNOFINISH);
}
if (!trees)
break;
mu_int_path[0] = trees->root;
if (trees->root < 0)
{
mu_int_err(ERR_DBRBNNEG, 0, 0, 0, 0, 0, 0, mu_int_root_level);
continue;
}
if (trees->root >= mu_int_data.trans_hist.total_blks)
{
mu_int_err(ERR_DBRBNTOOLRG, 0, 0, 0, 0, 0, 0,
mu_int_root_level);
continue;
}
if (0 == (trees->root % mu_int_data.bplmap))
{
mu_int_err(ERR_DBRBNLBMN, 0, 0, 0, 0, 0, 0, mu_int_root_level);
continue;
}
mu_int_plen = 0;
memset(mu_int_adj_prev, 0, SIZEOF(mu_int_adj_prev));
gv_target->nct = trees->nct;
gv_target->act = trees->act;
gv_target->ver = trees->ver;
gv_altkey->prev = 0;
assert(trees->keysize == strlen(trees->key));
gv_altkey->end = trees->keysize;
assert(gv_altkey->end + 2 <= gv_altkey->top);
memcpy(gv_altkey->base, trees->key, gv_altkey->end);
gv_altkey->base[gv_altkey->end++] = '\0';
gv_altkey->base[gv_altkey->end] = '\0';
if (gv_target->act)
act_in_gvt();
if (mu_int_blk(trees->root, MAX_BT_DEPTH, TRUE, gv_altkey->base, gv_altkey->end, &dummy, 0, 0))
{
/* We are done with the INTEG CHECK for the current GVT, but if the spanning node INTEG
* check is not finished, either of the following two are occurred.
*/
if (SPAN_NODE == sndata->sn_type)
{ /* ERROR 1: There is discontinuity in the spanning node blocks;
* adjacent spanning block is missing.
*/
mu_int_plen = mu_int_root_level + 1;
mu_int_err(ERR_DBSPANGLOINCMP, TRUE, FALSE, sndata->span_node_buf, sndata->key_len,
&dummy, 0, 0);
sndata->sn_blk_cnt += sndata->span_blk_cnt;
mu_int_plen = 0;
sndata->sn_type = SN_NOT;
}
if (2 == sndata->sn_type)
{ /* ERROR 2: Spanning-node-block occurred in the middle of non-spanning block */
mu_int_plen = mu_int_root_level + 1;
mu_int_err(ERR_DBSPANCHUNKORD, TRUE, FALSE, sndata->span_node_buf, sndata->key_len,
&dummy, 0, 0);
sndata->sn_blk_cnt += sndata->span_blk_cnt;
mu_int_plen = 0;
mu_int_plen = 0;
sndata->sn_type = SN_NOT;
}
if (full)
{
if (trees->root == dir_root)
util_out_print("!/Directory tree", TRUE);
else
util_out_print("!/Global variable ^!AD", TRUE, LEN_AND_STR(trees->key));
if (mu_int_errknt > prev_errknt)
{
if (trees->root == dir_root)
util_out_print("Total error count for directory tree: !UL",
TRUE, mu_int_errknt - prev_errknt);
else
util_out_print("Total error count for global !AD: !UL.",
TRUE, LEN_AND_STR(trees->key), mu_int_errknt - prev_errknt);
prev_errknt = mu_int_errknt;
}
util_out_print("Level Blocks Records % Used Adjacent", TRUE);
for (idx = mu_int_root_level; idx >= 0; idx--)
{
if ((0 == idx) && muint_fast && (trees->root != dir_root))
util_out_print("!5UL !12UL NA NA NA", TRUE,
idx, mu_int_blks[idx]);
else
{
QWPERCENTCALC(leftpt, rightpt, mu_int_size[idx], mu_int_blks[idx],
mu_int_data.blk_size);
if (trees->root != dir_root)
{
util_out_print("!5UL !12UL !12UL !8UL.!3ZL !12UL",
TRUE, idx, mu_int_blks[idx], mu_int_recs[idx],
leftpt, rightpt, mu_int_adj[idx]);
} else
util_out_print("!5UL !12UL !12UL !8UL.!3ZL NA",
TRUE, idx, mu_int_blks[idx], mu_int_recs[idx],
leftpt, rightpt);
}
}
}
if (dir_root == trees->root)
{
for (idx = mu_int_root_level; idx >= 0; idx--)
{
mu_dir_blks += mu_int_blks[idx];
QWINCRBY(mu_dir_size, mu_int_size[idx]);
mu_dir_recs += mu_int_recs[idx];
QWASSIGNDW(mu_int_size[idx], 0);
mu_int_adj[0] = mu_int_blks[idx] = mu_int_recs[idx] = 0;
}
} else
{
for (idx = mu_int_root_level; idx > 0; idx--)
{
mu_index_blks += mu_int_blks[idx];
QWINCRBY(mu_index_size, mu_int_size[idx]);
mu_index_recs += mu_int_recs[idx];
mu_index_adj += mu_int_adj[idx];
QWASSIGNDW(mu_int_size[idx], 0);
mu_int_adj[idx] = mu_int_blks[idx] = mu_int_recs[idx] = 0;
}
mu_data_blks += mu_int_blks[0];
mu_data_adj += mu_int_adj[0];
QWINCRBY(mu_data_size, mu_int_size[0]);
mu_data_recs += mu_int_recs[0];
QWASSIGNDW(mu_int_size[0], 0);
mu_int_adj[0] = mu_int_blks[0] = mu_int_recs[0] = 0;
}
} else if (update_header_tn)
{
update_header_tn = FALSE;
mu_int_err(ERR_DBTNRESETINC, 0, 0, 0, 0, 0, 0, 0);
mu_int_plen++; /* continuing, so compensate for mu_int_err decrement */
mu_int_errknt--; /* if this error is not supposed to increment the error count */
}
}
if (muint_all_index_blocks)
{
mu_int_maps();
if (! mu_int_errknt)
{
blocks_free = mu_int_data.trans_hist.total_blks -
(mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap -
mu_data_blks - mu_index_blks - mu_dir_blks;
/* If ONLINE INTEG, then cs_addrs->hdr->trans_hist.free_blocks can no longer be expected to remain
* the same as it was during the time INTEG started as updates are allowed when ONLINE INTEG is
* in progress and hence use mu_int_data.trans_hist.free_blocks as it is the copy of the file header
* right when ONLINE INTEG starts.
*/
if (csd->trans_hist.free_blocks != blocks_free)
{
if (gv_cur_region->read_only)
mu_int_errknt++;
util_len = SIZEOF("!/Free blocks counter in file header: ") - 1;
memcpy(util_buff, "!/Free blocks counter in file header: ", util_len);
util_len += i2hex_nofill(csd->trans_hist.free_blocks, (uchar_ptr_t)&util_buff[util_len], 8);
MEMCPY_LIT(&util_buff[util_len], TEXT1);
util_len += SIZEOF(TEXT1) - 1;
util_len += i2hex_nofill(blocks_free, (uchar_ptr_t)&util_buff[util_len], 8);
util_buff[util_len] = 0;
util_out_print(util_buff, TRUE);
} else
blocks_free = LEAVE_BLOCKS_ALONE;
}
if (!muint_fast && (mu_int_blks_to_upgrd != csd->blks_to_upgrd))
{
gtm_putmsg(VARLSTCNT(4) ERR_DBBTUWRNG, 2, mu_int_blks_to_upgrd, csd->blks_to_upgrd);
if (gv_cur_region->read_only || mu_int_errknt)
mu_int_errknt++;
else
gtm_putmsg(VARLSTCNT(1) ERR_DBBTUFIXED);
}
if (((0 != mu_int_data.kill_in_prog) || (0 != mu_int_data.abandoned_kills)) && (!mu_map_errs) && !region
&& !gv_cur_region->read_only)
{
assert(mu_int_errknt > 0);
mu_int_errknt--;
}
}
if (muint_fast)
{
if (mu_int_errknt)
util_out_print("!/Total error count from fast integ: !UL.", TRUE, mu_int_errknt);
else
util_out_print("!/No errors detected by fast integ.", TRUE);
} else
{
if (mu_int_errknt)
util_out_print("!/Total error count from integ: !UL.", TRUE, mu_int_errknt);
else
util_out_print("!/No errors detected by integ.", TRUE);
}
util_out_print("!/Type Blocks Records % Used Adjacent!/", TRUE);
QWPERCENTCALC(leftpt, rightpt, mu_dir_size, mu_dir_blks, mu_int_data.blk_size);
util_out_print("Directory !8UL !12UL !8UL.!3ZL NA", TRUE, mu_dir_blks, mu_dir_recs,
leftpt, rightpt);
QWPERCENTCALC(leftpt, rightpt, mu_index_size, mu_index_blks, mu_int_data.blk_size);
util_out_print("Index !12UL !12UL !8UL.!3ZL !12UL", TRUE, mu_index_blks, mu_index_recs, leftpt, rightpt,
mu_index_adj);
if (muint_fast)
util_out_print("Data !12UL NA NA NA", TRUE, mu_data_blks);
else
{
QWPERCENTCALC(leftpt, rightpt, mu_data_size, mu_data_blks, mu_int_data.blk_size);
util_out_print("Data !12UL !12UL !8UL.!3ZL !12UL", TRUE, mu_data_blks, mu_data_recs,
leftpt, rightpt, mu_data_adj);
}
if ((FALSE == block) && (FALSE == muint_key))
util_out_print("Free !12UL NA NA NA", TRUE,
mu_int_data.trans_hist.total_blks -
(mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap -
mu_data_blks - mu_index_blks - mu_dir_blks);
if (muint_fast)
{
util_out_print("Total !12UL NA NA !12UL", TRUE,
mu_int_data.trans_hist.total_blks -
(mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap,
mu_data_adj + mu_index_adj);
} else
{
util_out_print("Total !12UL !12UL NA !12UL", TRUE,
mu_int_data.trans_hist.total_blks -
(mu_int_data.trans_hist.total_blks + mu_int_data.bplmap - 1) / mu_int_data.bplmap,
mu_dir_recs + mu_index_recs + mu_data_recs, mu_data_adj + mu_index_adj);
}
if(sndata->sn_cnt)
{
util_out_print("[Spanning Nodes:!UL ; Blocks:!UL]", TRUE, sndata->sn_cnt, sndata->sn_blk_cnt);
/*[span_node:<no of span-node in DB>; blks: <total number of spanning blocks used by all span-node>]*/
}
if (largest_tn)
{
mu_int_err(ERR_DBTNLTCTN, 0, 0, 0, 0, 0, 0, 0);
mu_int_plen--;
mu_int_errknt--;
if (trans_errors > disp_trans_errors)
{
util_out_print("Maximum number of transaction number errors to display: !UL, was exceeded",
TRUE, disp_trans_errors);
util_out_print("!UL transaction number errors encountered.", TRUE, trans_errors);
}
MEMCPY_LIT(util_buff, TEXT2);
util_len = SIZEOF(TEXT2) - 1;
util_len += i2hexl_nofill(largest_tn, (uchar_ptr_t)&util_buff[util_len], 16);
util_buff[util_len] = 0;
util_out_print(util_buff, TRUE);
MEMCPY_LIT(util_buff, TEXT3);
util_len = SIZEOF(TEXT3) - 1;
util_len += i2hexl_nofill(mu_int_data.trans_hist.curr_tn, (uchar_ptr_t)&util_buff[util_len], 16);
util_buff[util_len] = 0;
util_out_print(util_buff, TRUE);
}
if (maxkey_errors > disp_maxkey_errors)
{
util_out_print("Maximum number of keys too large errors to display: !UL, was exceeded",
TRUE, disp_maxkey_errors);
util_out_print("!UL keys too large errors encountered.", TRUE, maxkey_errors);
}
if (region)
{
/* Below logic updates the database file header in the shared memory with values calculated
* by INTEG during it's course of tree traversal and writes it to disk. If ONLINE INTEG is
* in progress, then these values could legally be out-of-date and hence avoid writing the header if
* ONLINE INTEG is in progress.
*/
if (!gv_cur_region->read_only && !ointeg_this_reg)
{
if (LEAVE_BLOCKS_ALONE != blocks_free)
csd->trans_hist.free_blocks = blocks_free;
if (!mu_int_errknt && muint_all_index_blocks && !muint_fast)
{
if (mu_int_blks_to_upgrd != csd->blks_to_upgrd)
csd->blks_to_upgrd = mu_int_blks_to_upgrd;
}
csd->span_node_absent = (sndata->sn_cnt) ? FALSE : TRUE;
csd->maxkeysz_assured = (maxkey_errors) ? FALSE : TRUE;
region_freeze(gv_cur_region, FALSE, FALSE, FALSE);
fc = gv_cur_region->dyn.addr->file_cntl;
fc->op = FC_WRITE;
fc->op_buff = (unsigned char *)FILE_INFO(gv_cur_region)->s_addrs.hdr;
fc->op_len = ROUND_UP(SIZEOF(sgmnt_data), DISK_BLOCK_SIZE);
fc->op_pos = 1;
dbfilop(fc);
}
else if (region_was_frozen)
{
/* If online_integ, then database is not frozen, so no need to unfreeze. */
region_freeze(gv_cur_region, FALSE, FALSE, FALSE);
}
# ifdef GTM_SNAPSHOT
else
{
assert(SNAPSHOTS_IN_PROG(cs_addrs));
assert(NULL != cs_addrs->ss_ctx);
ss_release(&cs_addrs->ss_ctx);
CLEAR_SNAPSHOTS_IN_PROG(cs_addrs);
}
# endif
rptr = rptr->fPtr;
if (NULL == rptr)
break;
} else if (!gv_cur_region->read_only)
{
assert(!online_integ);
update_filehdr = FALSE;
if (muint_all_index_blocks)
{
if ((0 == mu_map_errs) && ((0 != mu_int_data.kill_in_prog) || (0 != mu_int_data.abandoned_kills)))
{
mu_int_data.abandoned_kills = 0;
mu_int_data.kill_in_prog = 0;
update_filehdr = TRUE;
}
if ((LEAVE_BLOCKS_ALONE != blocks_free) && (mu_int_data.trans_hist.free_blocks != blocks_free))
{
mu_int_data.trans_hist.free_blocks = blocks_free;
update_filehdr = TRUE;
}
if (!mu_int_errknt && !muint_fast)
{
if (mu_int_blks_to_upgrd != mu_int_data.blks_to_upgrd)
{
mu_int_data.blks_to_upgrd = mu_int_blks_to_upgrd;
update_filehdr = TRUE;
}
}
}
if (update_header_tn)
{
mu_int_data.trans_hist.early_tn = 2;
mu_int_data.trans_hist.curr_tn = 1;
/* curr_tn = 1 + 1 is done (instead of = 2) so as to use INCREMENT_CURR_TN macro.
* this way all places that update db curr_tn are easily obtained by searching for the macro.
* Reason for setting the transaction number to 2 (instead of 1) is so as to let a BACKUP in
* all forms to proceed, which earlier used to error out on seeing the database transaction
* number as 1.
*/
INCREMENT_CURR_TN(&mu_int_data);
/* Reset all last backup transaction numbers to 1. */
mu_int_data.last_inc_backup = 1;
mu_int_data.last_com_backup = 1;
mu_int_data.last_rec_backup = 1;
mu_int_data.last_inc_bkup_last_blk = 0;
mu_int_data.last_com_bkup_last_blk = 0;
mu_int_data.last_rec_bkup_last_blk = 0;
update_filehdr = TRUE;
util_out_print(MSG1, TRUE);
}
if (FALSE != update_filehdr)
{
fc = gv_cur_region->dyn.addr->file_cntl;
fc->op = FC_WRITE;
fc->op_buff = (unsigned char *)&mu_int_data;
fc->op_len = ROUND_UP(SIZEOF(sgmnt_data), DISK_BLOCK_SIZE);
fc->op_pos = 1;
dbfilop(fc);
fc->op = FC_CLOSE;
dbfilop(fc);
}
break;
} else
break;
}
# ifdef UNIX
if (!region)
{
db_ipcs_reset(gv_cur_region);
mu_gv_cur_reg_free(); /* mu_gv_cur_reg_init done in mu_int_init() */
REVERT;
}
# endif
total_errors += mu_int_errknt;
if (error_mupip)
total_errors++;
if (mu_ctrly_occurred || mu_ctrlc_occurred)
{
gtm_putmsg(VARLSTCNT(1) mu_ctrly_occurred ? ERR_CTRLY : ERR_CTRLC);
mupip_exit(ERR_MUNOFINISH);
}
if (0 != total_errors)
mupip_exit(ERR_INTEGERRS);
mupip_exit(SS_NORMAL);
}