fis-gtm/sr_port/mupip_upgrade.c

348 lines
13 KiB
C

/****************************************************************
* *
* Copyright 2005, 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. *
* *
****************************************************************/
/* mupip_upgrade.c: Driver program to upgrade one of the following.
* 1) V4.x database files (max of 64M blocks) to V5.0 format (will still support a max of 64M blocks)
* 2) Mastermap of pre-V5.3-004 V5.x database files (max of 128M blocks) to support a new max of 224M blocks
*/
#include "mdef.h"
#ifdef UNIX
#include "gtm_stat.h"
#include "gtm_fcntl.h"
#include "gtm_unistd.h"
#include "eintr_wrappers.h"
#include "gtm_stdlib.h"
#else
#include <descrip.h>
#include <fab.h>
#include <ssdef.h>
#include <rms.h>
#include <iodef.h>
#include <efndef.h>
#endif
#include "gtm_string.h"
#ifdef __MVS__
#include "gtm_zos_io.h"
#endif
#include "gtmio.h"
#include "iosp.h"
#include "gdsroot.h"
#include "v15_gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "v15_gdsbt.h"
#include "gdsfhead.h"
#include "v15_gdsfhead.h"
#include "filestruct.h"
#include "v15_filestruct.h"
#include "gdsblk.h"
#include "jnl.h" /* For fd_type */
#include "error.h"
#include "util.h"
#include "gtmmsg.h"
#include "cli.h"
#include "repl_sp.h"
#include "mupip_exit.h"
#include "mupip_upgrade.h"
#include "mu_upgrd_dngrd_hdr.h"
#include "mu_upgrd_dngrd_confirmed.h"
#include "mu_outofband_setup.h"
#include "gdsbml.h"
#include "anticipatory_freeze.h"
#ifdef UNIX
#include "mu_all_version_standalone.h"
#endif
LITREF char gtm_release_name[];
LITREF int4 gtm_release_name_len;
UNIX_ONLY(static sem_info *sem_inf;)
UNIX_ONLY(static void mupip_upgrade_cleanup(void);)
error_def(ERR_BADDBVER);
error_def(ERR_DBFILOPERR);
error_def(ERR_DBMAXREC2BIG);
error_def(ERR_DBMINRESBYTES);
error_def(ERR_DBNOTGDS);
error_def(ERR_DBOPNERR);
error_def(ERR_DBPREMATEOF);
error_def(ERR_DBRDONLY);
error_def(ERR_PREMATEOF);
error_def(ERR_MUINFOUINT4);
error_def(ERR_MUINFOUINT8);
error_def(ERR_MUNODBNAME);
error_def(ERR_MUNOUPGRD);
error_def(ERR_MUPGRDSUCC);
error_def(ERR_MUSTANDALONE);
error_def(ERR_MUUPGRDNRDY);
error_def(ERR_SYSCALL);
error_def(ERR_TEXT);
ZOS_ONLY(error_def(ERR_BADTAG);)
void mupip_upgrade(void)
{
char db_fn[MAX_FN_LEN + 1];
unsigned short db_fn_len; /* cli_get_str expects short */
fd_type channel;
int save_errno, v15_csd_size, max_max_rec_size;
int fstat_res;
int4 status, rc;
uint4 status2;
off_t v15_file_size;
v15_sgmnt_data v15_csd;
sgmnt_data csd;
#ifdef UNIX
struct stat stat_buf;
unsigned char new_v5_master_map[MASTER_MAP_SIZE_DFLT - MASTER_MAP_SIZE_V5_OLD];
#elif defined(VMS)
struct FAB mupfab;
struct XABFHC xabfhc;
#endif
ZOS_ONLY(int realfiletag;)
DEBUG_ONLY(int norm_vbn;)
unsigned char new_master_map[MASTER_MAP_SIZE_V4];
/* Structure checks .. */
#ifndef __ia64
assert((24 * 1024) == SIZEOF(v15_sgmnt_data)); /* Verify V4 file header hasn't suddenly increased for some odd reason */
#endif
UNIX_ONLY(sem_inf = (sem_info *)malloc(SIZEOF(sem_info) * FTOK_ID_CNT);
memset(sem_inf, 0, SIZEOF(sem_info) * FTOK_ID_CNT);
atexit(mupip_upgrade_cleanup));
db_fn_len = SIZEOF(db_fn);
if (!cli_get_str("FILE", db_fn, &db_fn_len))
rts_error(VARLSTCNT(1) ERR_MUNODBNAME);
db_fn[db_fn_len] = '\0'; /* Null terminate */
if (!mu_upgrd_dngrd_confirmed())
{
gtm_putmsg(VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_LIT("Upgrade canceled by user"));
mupip_exit(ERR_MUNOUPGRD);
}
gtm_putmsg(VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_LIT("Mupip upgrade started"));
UNIX_ONLY(mu_all_version_get_standalone(db_fn, sem_inf));
mu_outofband_setup(); /* Will ignore user interrupts. Note that now the
* elapsed time for this is order of milliseconds */
/* ??? Should we set this just before DB_DO_FILE_WRITE to have smallest time window of ignoring signal? */
#ifdef VMS
mupfab = cc$rms_fab;
mupfab.fab$l_fna = db_fn;
mupfab.fab$b_fns = db_fn_len;
mupfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD ;
mupfab.fab$l_fop = FAB$M_UFO;
xabfhc = cc$rms_xabfhc;
mupfab.fab$l_xab = &xabfhc;
status = sys$open(&mupfab);
if (0 == (status & 1))
{
if (RMS$_FLK == status)
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_MUSTANDALONE, ERROR), 2, db_fn_len, db_fn);
else
gtm_putmsg(VARLSTCNT(6) ERR_DBOPNERR, 2, db_fn_len, db_fn, status, mupfab.fab$l_stv);
mupip_exit(ERR_MUNOUPGRD);
}
channel = mupfab.fab$l_stv;
v15_file_size = xabfhc.xab$l_ebk;
#else
if (FD_INVALID == (channel = OPEN(db_fn, O_RDWR)))
{
save_errno = errno;
if (FD_INVALID != (channel = OPEN(db_fn, O_RDONLY)))
gtm_putmsg(VARLSTCNT(10) ERR_DBRDONLY, 2, db_fn_len, db_fn, errno, 0,
MAKE_MSG_TYPE(ERR_TEXT, ERROR), 2, LEN_AND_LIT("Cannot upgrade read-only database"));
else
gtm_putmsg(VARLSTCNT(5) ERR_DBOPNERR, 2, db_fn_len, db_fn, save_errno);
mupip_exit(ERR_MUNOUPGRD);
}
/* get file status */
FSTAT_FILE(channel, &stat_buf, fstat_res);
if (-1 == fstat_res)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fstat"), CALLFROM, errno);
gtm_putmsg(VARLSTCNT(4) ERR_DBOPNERR, 2, db_fn_len, db_fn);
mupip_exit(ERR_MUNOUPGRD);
}
#if defined(__MVS__)
if (-1 == gtm_zos_tag_to_policy(channel, TAG_BINARY, &realfiletag))
TAG_POLICY_GTM_PUTMSG(db_fn, errno, realfiletag, TAG_BINARY);
#endif
v15_file_size = stat_buf.st_size;
#endif
v15_csd_size = SIZEOF(v15_sgmnt_data);
DO_FILE_READ(channel, 0, &v15_csd, v15_csd_size, status, status2);
if (SS_NORMAL != status)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, db_fn_len, db_fn, status);
mupip_exit(ERR_MUNOUPGRD);
}
if (!memcmp(v15_csd.label, GDS_LABEL, STR_LIT_LEN(GDS_LABEL)))
{
/* Check if the V5 database is old(supports only 128M blocks) if so update the V5 database to support
* to 224M blocks.
*/
#ifdef UNIX
DO_FILE_READ(channel, 0, &csd, SIZEOF(sgmnt_data), status, status2);
if (SS_NORMAL != status)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, db_fn_len, db_fn, status);
mupip_exit(ERR_MUNOUPGRD);
}
if (MASTER_MAP_SIZE_V5_OLD == csd.master_map_len)
{
/* We have detected the master map which supports only 128M blocks so we need to
* bump it up to one that supports 224M blocks. */
csd.master_map_len = MASTER_MAP_SIZE_V5;
assert(START_VBN_V5 == csd.start_vbn);
DEBUG_ONLY (
norm_vbn = DIVIDE_ROUND_UP(SIZEOF_FILE_HDR_V5, DISK_BLOCK_SIZE) + 1;
assert(START_VBN_V5 == norm_vbn);
)
csd.free_space = 0;
DB_DO_FILE_WRITE(channel, 0, &csd, SIZEOF(csd), status, status2);
if (SS_NORMAL != status)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, db_fn_len, db_fn, status);
mupip_exit(ERR_MUNOUPGRD);
}
memset(new_v5_master_map, BMP_EIGHT_BLKS_FREE, (MASTER_MAP_SIZE_V5 - MASTER_MAP_SIZE_V5_OLD));
DB_DO_FILE_WRITE(channel, SIZEOF(csd) + MASTER_MAP_SIZE_V5_OLD, new_v5_master_map,
(MASTER_MAP_SIZE_V5 - MASTER_MAP_SIZE_V5_OLD), status, status2);
if (SS_NORMAL != status)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, db_fn_len, db_fn, status);
mupip_exit(ERR_MUNOUPGRD);
}
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
UNIX_ONLY(mu_all_version_release_standalone(sem_inf));
gtm_putmsg(VARLSTCNT(4) ERR_TEXT, 2,
LEN_AND_LIT("Maximum master map size is now increased from 32K to 56K"));
gtm_putmsg(VARLSTCNT(8) ERR_MUPGRDSUCC, 6, db_fn_len, db_fn, RTS_ERROR_LITERAL("upgraded"),
gtm_release_name_len, gtm_release_name);
mupip_exit(SS_NORMAL);
}
#endif
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_TEXT, ERROR), 2, LEN_AND_LIT("Database already upgraded"));
mupip_exit(ERR_MUNOUPGRD);
} else if (memcmp(v15_csd.label, V15_GDS_LABEL, STR_LIT_LEN(V15_GDS_LABEL)))
{ /* It is not a version we can upgrade, that is, not V4.0-000 to V5.0-FT01 */
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
if (memcmp(v15_csd.label, GDS_LABEL, GDS_LABEL_SZ - 3))
gtm_putmsg(VARLSTCNT(4) ERR_DBNOTGDS, 2, db_fn_len, db_fn);
else
gtm_putmsg(VARLSTCNT(4) ERR_BADDBVER, 2, db_fn_len, db_fn);
mupip_exit(ERR_MUNOUPGRD);
}
/* It is V4.x or V5.0-FT01 version : Se proceed with upgrade */
if (v15_csd.createinprogress)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_TEXT, ERROR), 2, LEN_AND_LIT("Database creation in progress"));
mupip_exit(ERR_MUNOUPGRD);
}
if (v15_csd.freeze)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_TEXT, ERROR), 2, LEN_AND_LIT("Database is frozen"));
mupip_exit(ERR_MUNOUPGRD);
}
if (v15_csd.wc_blocked)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_TEXT, ERROR),
2, LEN_AND_LIT("Database modifications are disallowed because wc_blocked is set"));
mupip_exit(ERR_MUNOUPGRD);
}
if (v15_csd.file_corrupt)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_TEXT, ERROR), 2, LEN_AND_LIT("Database corrupt"));
mupip_exit(ERR_MUNOUPGRD);
}
if (v15_csd.intrpt_recov_tp_resolve_time || v15_csd.intrpt_recov_resync_seqno || v15_csd.recov_interrupted
|| v15_csd.intrpt_recov_jnl_state || v15_csd.intrpt_recov_repl_state)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_TYPE(ERR_TEXT, ERROR), 2, LEN_AND_LIT("Recovery was interrupted"));
mupip_exit(ERR_MUNOUPGRD);
}
if (GDSVCURR != v15_csd.certified_for_upgrade_to)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(6) ERR_MUUPGRDNRDY, 4, db_fn_len, db_fn, gtm_release_name_len, gtm_release_name);
mupip_exit(ERR_MUNOUPGRD);
}
max_max_rec_size = v15_csd.blk_size - SIZEOF(blk_hdr);
if (VMS_ONLY(9) UNIX_ONLY(8) > v15_csd.reserved_bytes)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(6) ERR_DBMINRESBYTES, 4, VMS_ONLY(9) UNIX_ONLY(8), v15_csd.reserved_bytes);
mupip_exit(ERR_MUNOUPGRD);
}
if (v15_csd.max_rec_size > max_max_rec_size)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
rts_error(VARLSTCNT(5) ERR_DBMAXREC2BIG, 3, v15_csd.max_rec_size, v15_csd.blk_size, max_max_rec_size);
mupip_exit(ERR_MUNOUPGRD);
}
gtm_putmsg(VARLSTCNT(6) ERR_MUINFOUINT4, 4, LEN_AND_LIT("Old file header size"), v15_csd_size, v15_csd_size);
gtm_putmsg(VARLSTCNT(6) ERR_MUINFOUINT8, 4, LEN_AND_LIT("Old file length"), &v15_file_size, &v15_file_size);
gtm_putmsg(VARLSTCNT(6) ERR_MUINFOUINT4, 4, LEN_AND_LIT("Old file start_vbn"), v15_csd.start_vbn, v15_csd.start_vbn);
gtm_putmsg(VARLSTCNT(6) ERR_MUINFOUINT4, 4, LEN_AND_LIT("Old file gds blk_size"), v15_csd.blk_size, v15_csd.blk_size);
gtm_putmsg(VARLSTCNT(6) ERR_MUINFOUINT4, 4, LEN_AND_LIT("Old file total_blks"),
v15_csd.trans_hist.total_blks, v15_csd.trans_hist.total_blks);
assert(ROUND_DOWN2(v15_csd.blk_size, DISK_BLOCK_SIZE) == v15_csd.blk_size);
assert(((off_t)v15_csd.start_vbn) * DISK_BLOCK_SIZE +
(off_t)v15_csd.trans_hist.total_blks * v15_csd.blk_size == v15_file_size VMS_ONLY(* DISK_BLOCK_SIZE));
/* Now call mu_upgrd_header() to do file header upgrade in memory */
mu_upgrd_header(&v15_csd, &csd);
csd.master_map_len = MASTER_MAP_SIZE_V4; /* V5 master map is not part of file header */
memcpy(new_master_map, v15_csd.master_map, MASTER_MAP_SIZE_V4);
DB_DO_FILE_WRITE(channel, 0, &csd, SIZEOF(csd), status, status2);
if (SS_NORMAL != status)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, db_fn_len, db_fn, status);
mupip_exit(ERR_MUNOUPGRD);
}
DB_DO_FILE_WRITE(channel, SIZEOF(csd), new_master_map, MASTER_MAP_SIZE_V4, status, status2);
if (SS_NORMAL != status)
{
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, db_fn_len, db_fn, status);
mupip_exit(ERR_MUNOUPGRD);
}
F_CLOSE(channel, rc); /* resets "channel" to FD_INVALID */
UNIX_ONLY(mu_all_version_release_standalone(sem_inf));
gtm_putmsg(VARLSTCNT(8) ERR_MUPGRDSUCC, 6, db_fn_len, db_fn, RTS_ERROR_LITERAL("upgraded"),
gtm_release_name_len, gtm_release_name);
mupip_exit(SS_NORMAL);
}
#ifdef UNIX
static void mupip_upgrade_cleanup(void)
{
if (sem_inf)
mu_all_version_release_standalone(sem_inf);
}
#endif