191 lines
6.4 KiB
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;
|
|
}
|