fis-gtm/sr_port/desired_db_format_set.c

191 lines
6.4 KiB
C

/****************************************************************
* *
* Copyright 2005, 2011 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 "gtm_string.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "gdscc.h"
#include "gdskill.h"
#include "jnl.h"
#include "iosp.h" /* for SS_NORMAL */
#include "util.h"
/* Prototypes */
#include "gtmmsg.h" /* for gtm_putmsg prototype */
#include "desired_db_format_set.h"
#include "send_msg.h" /* for send_msg */
#include "wcs_phase2_commit_wait.h"
#define WCS_PHASE2_COMMIT_WAIT_LIT "wcb_phase2_commit_wait"
LITREF char *gtm_dbversion_table[];
GBLREF inctn_opcode_t inctn_opcode;
GBLREF jnl_gbls_t jgbl;
GBLREF uint4 process_id;
GBLREF inctn_detail_t inctn_detail; /* holds detail to fill in to inctn jnl record */
/* input parameter "command_name" is a string that is either "MUPIP REORG UPGRADE/DOWNGRADE" or "MUPIP SET VERSION" */
int4 desired_db_format_set(gd_region *reg, enum db_ver new_db_format, char *command_name)
{
boolean_t was_crit;
char *db_fmt_str;
char *wcblocked_ptr;
int4 status;
uint4 jnl_status;
inctn_opcode_t save_inctn_opcode;
sgmnt_addrs *csa;
sgmnt_data_ptr_t csd;
trans_num curr_tn;
jnl_private_control *jpc;
jnl_buffer_ptr_t jbp;
error_def(ERR_COMMITWAITSTUCK);
error_def(ERR_DBDSRDFMTCHNG);
error_def(ERR_MMNODYNDWNGRD);
error_def(ERR_MUDWNGRDTN);
error_def(ERR_MUNOACTION);
error_def(ERR_WCBLOCKED);
error_def(ERR_CRYPTNOV4);
error_def(ERR_SNAPSHOTNOV4);
assert(reg->open);
csa = &FILE_INFO(reg)->s_addrs;
csd = csa->hdr;
GTMCRYPT_ONLY(
/* We don't allow databases to be encrypted if the version is V4 */
if (csd->is_encrypted && (GDSV4 == new_db_format))
{
gtm_putmsg(VARLSTCNT(4) ERR_CRYPTNOV4, 2, DB_LEN_STR(reg));
return ERR_CRYPTNOV4;
}
)
GTM_SNAPSHOT_ONLY(
/* We don't allow databases to be downgraded when snapshots are in progress */
if (SNAPSHOTS_IN_PROG(csa->nl) && (GDSV4 == new_db_format))
{
gtm_putmsg(VARLSTCNT(5) ERR_SNAPSHOTNOV4, 3, csa->nl->num_snapshots_in_effect, DB_LEN_STR(reg));
return ERR_SNAPSHOTNOV4;
}
)
was_crit = csa->now_crit;
if (FALSE == was_crit)
grab_crit(reg);
/* if MM and desired_db_format is not V5, gvcst_init would have issued MMNODYNDWNGRD error. assert that. */
assert(dba_bg == csd->acc_meth || (dba_mm == csd->acc_meth) && (GDSV5 == csd->desired_db_format));
if (csd->desired_db_format == new_db_format)
{ /* no change in db_format. fix max_tn_warn if necessary and return right away. */
status = ERR_MUNOACTION;
assert(csd->trans_hist.curr_tn <= csd->max_tn);
if ((GDSV4 == new_db_format) && (MAX_TN_V4 < csd->max_tn))
{ /* reset max_tn to MAX_TN_V4 only if V4 format and the new value will still be greater than curr_tn */
if (MAX_TN_V4 >= csd->trans_hist.curr_tn)
{
csd->max_tn = MAX_TN_V4;
/* since max_tn changed above, max_tn_warn might also need to correspondingly change */
SET_TN_WARN(csd, csd->max_tn_warn);
} else
GTMASSERT; /* out-of-design state where curr_tn > MAX_TN_V4 in GDSV4 */
}
if (FALSE == was_crit)
rel_crit(reg);
return status;
}
if (dba_mm == csd->acc_meth)
{
status = ERR_MMNODYNDWNGRD;
gtm_putmsg(VARLSTCNT(4) status, 2, REG_LEN_STR(reg));
if (FALSE == was_crit)
rel_crit(reg);
return status;
}
/* check if curr_tn is too high to downgrade */
curr_tn = csd->trans_hist.curr_tn;
if ((GDSV4 == new_db_format) && (MAX_TN_V4 <= curr_tn))
{
status = ERR_MUDWNGRDTN;
gtm_putmsg(VARLSTCNT(5) status, 3, &curr_tn, DB_LEN_STR(reg));
if (FALSE == was_crit)
rel_crit(reg);
return status;
}
/* Wait for concurrent phase2 commits to complete before switching the desired db format */
if (csa->nl->wcs_phase2_commit_pidcnt && !wcs_phase2_commit_wait(csa, NULL))
{ /* Set wc_blocked so next process to get crit will trigger cache-recovery */
SET_TRACEABLE_VAR(csd->wc_blocked, TRUE);
wcblocked_ptr = WCS_PHASE2_COMMIT_WAIT_LIT;
send_msg(VARLSTCNT(8) ERR_WCBLOCKED, 6, LEN_AND_STR(wcblocked_ptr),
process_id, &csd->trans_hist.curr_tn, DB_LEN_STR(reg));
status = ERR_COMMITWAITSTUCK;
gtm_putmsg(VARLSTCNT(7) status, 5, process_id, 1, csa->nl->wcs_phase2_commit_pidcnt, DB_LEN_STR(reg));
if (FALSE == was_crit)
rel_crit(reg);
return status;
}
if (JNL_ENABLED(csd))
{
SET_GBL_JREC_TIME; /* needed for jnl_ensure_open, jnl_put_jrt_pini and jnl_write_aimg_rec */
jpc = csa->jnl;
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)
{
save_inctn_opcode = inctn_opcode;
inctn_opcode = inctn_db_format_change;
inctn_detail.blks2upgrd_struct.blks_to_upgrd_delta = csd->blks_to_upgrd;
if (0 == jpc->pini_addr)
jnl_put_jrt_pini(csa);
jnl_write_inctn_rec(csa);
inctn_opcode = save_inctn_opcode;
} else
gtm_putmsg(VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(reg));
}
csd->desired_db_format = new_db_format;
csd->fully_upgraded = FALSE;
csd->desired_db_format_tn = curr_tn;
switch(new_db_format)
{
case GDSV4:
csd->max_tn = MAX_TN_V4;
break;
case GDSV5:
csd->max_tn = MAX_TN_V5;
break;
default:
GTMASSERT;
}
SET_TN_WARN(csd, csd->max_tn_warn); /* if max_tn changed above, max_tn_warn also needs a corresponding change */
assert(curr_tn < csd->max_tn); /* ensure CHECK_TN macro below will not issue TNTOOLARGE rts_error */
CHECK_TN(csa, csd, curr_tn); /* can issue rts_error TNTOOLARGE */
/* increment csd->trans_hist.curr_tn */
assert(csd->trans_hist.early_tn == csd->trans_hist.curr_tn);
csd->trans_hist.early_tn = csd->trans_hist.curr_tn + 1;
INCREMENT_CURR_TN(csd);
if (FALSE == was_crit)
rel_crit(reg);
status = SS_NORMAL;
send_msg(VARLSTCNT(11) ERR_DBDSRDFMTCHNG, 9, DB_LEN_STR(reg), LEN_AND_STR(gtm_dbversion_table[new_db_format]),
LEN_AND_STR(command_name), process_id, process_id, &curr_tn);
return status;
}