fis-gtm/sr_port/cre_jnl_file.c

514 lines
21 KiB
C
Raw Normal View History

/****************************************************************
* *
* Copyright 2003, 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_stat.h"
#if defined(UNIX)
#include "gtm_fcntl.h"
#include "gtm_unistd.h"
#include "eintr_wrappers.h"
#include "gtm_permissions.h"
#if defined(__MVS__)
#include "gtm_zos_io.h"
#endif
#elif defined(VMS)
#include <rms.h>
#include <iodef.h>
#include <efndef.h>
#include "iosb_disk.h"
#endif
#include "gtm_file_stat.h"
#include "gtm_rename.h"
#include "error.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gtmio.h"
#include "util.h"
#include "gtmmsg.h"
#include "send_msg.h"
#include "iosp.h"
#include "repl_sp.h"
#include "is_file_identical.h"
#include "jnl_get_checksum.h"
#include "gtmimagename.h"
#include "get_fs_block_size.h"
#include "wbox_test_init.h"
#include "gt_timer.h"
#include "anticipatory_freeze.h"
/* Note : Now all system error messages are issued here. So callers do not need to issue them again */
#define STATUS_MSG(info) \
{ \
if (SS_NORMAL != info->status2) \
{ \
if (IS_GTM_IMAGE) \
send_msg(VARLSTCNT(12) ERR_JNLCRESTATUS, 7, CALLFROM, info->jnl_len, info->jnl, \
info->fn_len, info->fn, info->status, 0, info->status2); \
else \
gtm_putmsg(VARLSTCNT1(11) ERR_JNLCRESTATUS, 7, CALLFROM, info->jnl_len, info->jnl,\
info->fn_len, info->fn, info->status, PUT_SYS_ERRNO(info->status2)); \
} else if (SS_NORMAL != info->status) \
{ \
if (IS_GTM_IMAGE) \
send_msg(VARLSTCNT(10) ERR_JNLCRESTATUS, 7, CALLFROM, info->jnl_len, \
info->jnl, info->fn_len, info->fn, info->status); \
else \
gtm_putmsg(VARLSTCNT(10) ERR_JNLCRESTATUS, 7, CALLFROM, info->jnl_len, \
info->jnl, info->fn_len, info->fn, info->status); \
} \
}
#define RETURN_ON_ERROR(info) \
if (SYSCALL_ERROR(info->status) || SYSCALL_ERROR(info->status2)) \
{ \
int status; \
F_CLOSE(channel, status);/* resets "channel" to FD_INVALID */ \
if (NULL != jrecbuf_base) \
{ \
free(jrecbuf_base); \
jrecbuf_base = NULL; \
} \
return EXIT_ERR; \
}
#if defined(VMS)
#define ZERO_SIZE_IN_BLOCKS 127 /* 127 is RMS maximum blocks / write */
#define ZERO_SIZE (ZERO_SIZE_IN_BLOCKS * DISK_BLOCK_SIZE)
#endif
GBLREF jnl_gbls_t jgbl;
GBLREF boolean_t mupip_jnl_recover;
GBLREF jnl_process_vector *prc_vec;
ZOS_ONLY(error_def(ERR_BADTAG);)
error_def(ERR_FILERENAME);
error_def(ERR_JNLCRESTATUS);
error_def(ERR_JNLFNF);
error_def(ERR_PERMGENFAIL);
error_def(ERR_PREMATEOF);
error_def(ERR_RENAMEFAIL);
error_def(ERR_TEXT);
/* Create a journal file from info.
* If necessary, it renames journal file of same name.
* Note: jgbl.gbl_jrec_time must be set by callers
*/
uint4 cre_jnl_file(jnl_create_info *info)
{
mstr filestr;
int org_fn_len, rename_fn_len, fstat;
uint4 ustatus;
char *org_fn, rename_fn[MAX_FN_LEN];
if (!info->no_rename) /* ***MAY*** be rename is required */
{
if (SS_NORMAL != (info->status = prepare_unique_name((char *)info->jnl, info->jnl_len, "", "",
rename_fn, &rename_fn_len, &info->status2)))
{ /* prepare_unique_name calls append_time_stamp which needs to open the info->jnl file.
* We are here because append_time_stamp failed to open info->jnl or something else.
* So check if info->jnl is present in the system */
filestr.addr = (char *)info->jnl;
filestr.len = info->jnl_len;
if (FILE_NOT_FOUND != (fstat = gtm_file_stat(&filestr, NULL, NULL, FALSE, &ustatus)))
{
if (FILE_STAT_ERROR == fstat)
{
STATUS_MSG(info); /* for prepare_unique_name call */
info->status = ustatus;
info->status2 = SS_NORMAL;
}
STATUS_MSG(info);
return EXIT_ERR;
}
if (IS_GTM_IMAGE)
send_msg(VARLSTCNT(4) ERR_JNLFNF, 2, filestr.len, filestr.addr);
else
gtm_putmsg(VARLSTCNT(4) ERR_JNLFNF, 2, filestr.len, filestr.addr);
STATUS_MSG(info);
info->status = info->status2 = SS_NORMAL;
info->no_rename = TRUE; /* We wanted to rename, but not required */
info->no_prev_link = TRUE; /* No rename => no prev_link */
} else
{
/* Note if info->no_prev_link == TRUE, we do not keep previous link, though rename can happen */
if (JNL_ENABLED(info) && !info->no_prev_link)
{
memcpy(info->prev_jnl, rename_fn, rename_fn_len + 1);
info->prev_jnl_len = rename_fn_len;
} else
assert(info->no_prev_link);
}
} /* else we know for sure rename is not required */
return (cre_jnl_file_common(info, rename_fn, rename_fn_len));
}
/* This creates info->jnl and if (!info->no_rename) then it renames existing info->jnl to be rename_fn */
uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_len)
{
jnl_file_header *header;
unsigned char hdr_base[JNL_HDR_LEN + MAX_IO_BLOCK_SIZE];
struct_jrec_pfin *pfin_record;
struct_jrec_pini *pini_record;
struct_jrec_epoch *epoch_record;
struct_jrec_eof *eof_record;
unsigned char *create_fn, fn_buff[MAX_FN_LEN];
int create_fn_len, cre_jnl_rec_size, status, write_size, jrecbufbase_size;
fd_type channel;
char *jrecbuf, *jrecbuf_base;
gd_id jnlfile_id;
#if defined(VMS)
struct FAB fab;
struct NAM nam;
char es_buffer[MAX_FN_LEN], name_buffer[MAX_FN_LEN];
uint4 blk, block, zero_size;
io_status_block_disk iosb;
#elif defined(UNIX)
struct stat stat_buf;
int fstat_res;
ZOS_ONLY(int realfiletag;)
int stat_res;
int group_id;
struct stat sb;
int perm;
struct perm_diag_data pdd;
#endif
int idx;
trans_num db_tn;
uint4 temp_offset, temp_checksum, pfin_offset, eof_offset;
uint4 jnl_fs_block_size;
jrecbuf = NULL;
if (info->no_rename)
{ /* The only cases where no-renaming is possible are as follows
* (i) MUPIP SET JOURNAL where the new journal file name is different from the current journal file name
* (ii) For MUPIP BACKUP, MUPIP SET JOURNAL, GT.M Runtime and forw_phase_recovery,
* in case the current journal file does not exist (due to some abnormal condition).
* But in this case we cut the link and hence info->no_prev_link should be TRUE.
* The assert below tries to capture this as much as possible without introducing any new global variables.
*/
assert((IS_MUPIP_IMAGE && !jgbl.forw_phase_recovery) || (IS_GTM_IMAGE && info->no_prev_link));
create_fn_len = info->jnl_len;
create_fn = info->jnl;
assert(0 == create_fn[create_fn_len]);
} else
{
create_fn = &fn_buff[0];
if (SS_NORMAL != (info->status = prepare_unique_name((char *)info->jnl, (int)info->jnl_len, "", EXT_NEW,
(char *)create_fn, &create_fn_len, &info->status2)))
{
STATUS_MSG(info);
return EXIT_ERR;
}
}
#if defined(UNIX)
OPENFILE3((char *)create_fn, O_CREAT | O_EXCL | O_RDWR, 0600, channel);
if (-1 == channel)
{
info->status = errno;
STATUS_MSG(info);
return EXIT_ERR;
}
#if defined(__MVS__)
if (-1 == gtm_zos_set_tag(channel, TAG_BINARY, TAG_NOTTEXT, TAG_FORCE, &realfiletag))
TAG_POLICY_SEND_MSG((char *)create_fn, errno, realfiletag, TAG_BINARY);
#endif
FSTAT_FILE(channel, &stat_buf, fstat_res);
if (-1 == fstat_res)
{
info->status = errno;
STATUS_MSG(info);
F_CLOSE(channel, status);
return EXIT_ERR;
}
/* check database file again. It was checked earlier so should still be ok. */
STAT_FILE((sm_c_ptr_t)info->fn, &sb, stat_res);
if (-1 == stat_res)
{
info->status = errno;
STATUS_MSG(info);
F_CLOSE(channel, status);
return EXIT_ERR;
}
/* setup new group and permissions if indicated by the security rules.
*/
if (gtm_set_group_and_perm(&sb, &group_id, &perm, PERM_FILE, &pdd) < 0)
{
send_msg(VARLSTCNT(6+PERMGENDIAG_ARG_COUNT)
ERR_PERMGENFAIL, 4, RTS_ERROR_STRING("journal file"), RTS_ERROR_STRING(info->fn),
PERMGENDIAG_ARGS(pdd));
if (IS_GTM_IMAGE)
rts_error(VARLSTCNT(6+PERMGENDIAG_ARG_COUNT)
ERR_PERMGENFAIL, 4, RTS_ERROR_STRING("journal file"), RTS_ERROR_STRING(info->fn),
PERMGENDIAG_ARGS(pdd));
else
gtm_putmsg(VARLSTCNT(6+PERMGENDIAG_ARG_COUNT)
ERR_PERMGENFAIL, 4, RTS_ERROR_STRING("journal file"), RTS_ERROR_STRING(info->fn),
PERMGENDIAG_ARGS(pdd));
F_CLOSE(channel, status);
return EXIT_ERR;
}
/* if group not the same then change group of temporary file */
if ((-1 != group_id) && (group_id != stat_buf.st_gid) && (-1 == fchown(channel, -1, group_id)))
{
info->status = errno;
STATUS_MSG(info);
F_CLOSE(channel, status);
return EXIT_ERR;
}
if (-1 == FCHMOD(channel, perm))
{
info->status = errno;
STATUS_MSG(info);
F_CLOSE(channel, status); /* resets "channel" to FD_INVALID */
return EXIT_ERR;
}
jnl_fs_block_size = get_fs_block_size(channel);
/* We need to write the journal file header, followed by pini/epoch/pfin/eof records followed by 0-padding
* to ensure the final size of the journal file is filesystem-block-size aligned.
* To have a "jnl_fs_block_size" aligned buffer that is also a multiple of jnl_fs_block_size long,
* we need to allocate the needed size + 2 * jnl_fs_block_size. This will leave up to jnl_fs_block_size
* before the actual "used" part for alignment plus enough left after the "used" part to make up a buffer
* to write that is a multiple of jnl_fs_block_size.
*/
jrecbufbase_size = PINI_RECLEN + EPOCH_RECLEN + PFIN_RECLEN + EOF_RECLEN + (2 * jnl_fs_block_size);
jrecbuf_base = malloc(jrecbufbase_size);
jrecbuf = (char *)ROUND_UP2((uintszofptr_t)jrecbuf_base, jnl_fs_block_size);
memset(jrecbuf, 0, jnl_fs_block_size);
set_gdid_from_stat(&jnlfile_id, &stat_buf);
#elif defined(VMS)
nam = cc$rms_nam;
nam.nam$l_rsa = name_buffer;
nam.nam$b_rss = SIZEOF(name_buffer);
nam.nam$l_esa = es_buffer;
nam.nam$b_ess = SIZEOF(es_buffer);
nam.nam$b_nop = NAM$M_NOCONCEAL;
fab = cc$rms_fab;
fab.fab$l_nam = &nam;
fab.fab$b_org = FAB$C_SEQ;
fab.fab$b_rfm = FAB$C_FIX;
fab.fab$l_fop = FAB$M_UFO | FAB$M_MXV | FAB$M_CBT;
fab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_BIO;
fab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_UPI | FAB$M_NIL;
fab.fab$w_mrs = DISK_BLOCK_SIZE;
fab.fab$l_alq = info->alloc;
fab.fab$w_deq = info->extend;
fab.fab$l_fna = create_fn;
fab.fab$b_fns = create_fn_len;
info->status = sys$create(&fab);
if (0 == (info->status & 1))
{
info->status2 = fab.fab$l_stv; /* store secondary status information */
STATUS_MSG(info);
return EXIT_ERR;
}
channel = fab.fab$l_stv;
jrecbufbase_size = ZERO_SIZE;
jrecbuf_base = jrecbuf = malloc(ZERO_SIZE);
memset(jrecbuf, 0, ZERO_SIZE);
block = (JNL_HDR_LEN >> LOG2_DISK_BLOCK_SIZE);
assert(block * DISK_BLOCK_SIZE == JNL_HDR_LEN);
for (blk = block; blk < info->alloc; blk += ZERO_SIZE_IN_BLOCKS)
{
zero_size = (blk + ZERO_SIZE_IN_BLOCKS <= info->alloc) ?
ZERO_SIZE : (info->alloc - blk) * DISK_BLOCK_SIZE;
JNL_DO_FILE_WRITE(NULL, NULL, channel, blk * DISK_BLOCK_SIZE, jrecbuf, zero_size, info->status, info->status2);
STATUS_MSG(info);
RETURN_ON_ERROR(info);
}
memcpy(jnlfile_id.dvi, &nam.nam$t_dvi, SIZEOF(jnlfile_id.dvi));
memcpy(jnlfile_id.did, &nam.nam$w_did, SIZEOF(jnlfile_id.did));
memcpy(jnlfile_id.fid, &nam.nam$w_fid, SIZEOF(jnlfile_id.fid));
jnl_fs_block_size = get_fs_block_size(channel);
#endif
info->checksum = compute_checksum(INIT_CHECKSUM_SEED, (uint4 *)&jnlfile_id, SIZEOF(gd_id));
/* Journal file header size relies on this assert */
assert(256 == GTMCRYPT_RESERVED_HASH_LEN);
header = (jnl_file_header *)(ROUND_UP2((uintszofptr_t)hdr_base, jnl_fs_block_size));
/* We have already saved previous journal file name in info */
jfh_from_jnl_info(info, header);
header->recover_interrupted = mupip_jnl_recover;
assert(ROUND_UP2(JNL_HDR_LEN, jnl_fs_block_size) == JNL_HDR_LEN);
assert((unsigned char *)header + JNL_HDR_LEN <= ARRAYTOP(hdr_base));
/* Although the real journal file header is REAL_JNL_HDR_LEN, we write the entire journal file header
* including padding (64K in Unix) so we write 0-padding instead of some garbage. Not necessary
* but makes analysis of journal file using dump utilities (like od) much easier. Also 0-initialization
* might help us in the future when we add some fields in the file header. The cost of the extra padding
* write is not so much since it is only once per journal file at creation time. All future writes of the
* file header write only the real file header and not the 0-padding.
*/
JNL_DO_FILE_WRITE(info->csa, create_fn, channel, 0, header, JNL_HDR_LEN, info->status, info->status2);
STATUS_MSG(info);
RETURN_ON_ERROR(info);
assert(DISK_BLOCK_SIZE >= EPOCH_RECLEN + EOF_RECLEN + PFIN_RECLEN + PINI_RECLEN);
pini_record = (struct_jrec_pini *)&jrecbuf[0];
pini_record->prefix.jrec_type = JRT_PINI;
pini_record->prefix.forwptr = pini_record->suffix.backptr = PINI_RECLEN;
db_tn = info->csd->trans_hist.curr_tn;
pini_record->prefix.tn = db_tn;
pini_record->prefix.pini_addr = JNL_HDR_LEN;
pini_record->prefix.time = jgbl.gbl_jrec_time; /* callers must set it */
pini_record->suffix.suffix_code = JNL_REC_SUFFIX_CODE;
assert(prc_vec);
memcpy((unsigned char*)&pini_record->process_vector[CURR_JPV], (unsigned char*)prc_vec, SIZEOF(jnl_process_vector));
/* Already process_vector[ORIG_JPV] is memset 0 */
pini_record->filler = 0;
pini_record->prefix.checksum = INIT_CHECKSUM_SEED;
temp_checksum = compute_checksum(INIT_CHECKSUM_SEED, (uint4 *)pini_record, SIZEOF(struct_jrec_pini));
temp_offset = JNL_HDR_LEN;
ADJUST_CHECKSUM(temp_checksum, temp_offset, temp_checksum);
ADJUST_CHECKSUM(temp_checksum, info->checksum, pini_record->prefix.checksum);
/* EPOCHs are written unconditionally in Unix while they are written only for BEFORE_IMAGE in VMS */
if (JNL_HAS_EPOCH(info))
{
epoch_record = (struct_jrec_epoch *)&jrecbuf[PINI_RECLEN];
epoch_record->prefix.jrec_type = JRT_EPOCH;
epoch_record->prefix.forwptr = epoch_record->suffix.backptr = EPOCH_RECLEN;
epoch_record->prefix.tn = db_tn;
epoch_record->prefix.pini_addr = JNL_HDR_LEN;
epoch_record->prefix.time = jgbl.gbl_jrec_time;
epoch_record->blks_to_upgrd = info->blks_to_upgrd;
epoch_record->free_blocks = info->free_blocks;
epoch_record->total_blks = info->total_blks;
epoch_record->fully_upgraded = info->csd->fully_upgraded;
epoch_record->suffix.suffix_code = JNL_REC_SUFFIX_CODE;
epoch_record->jnl_seqno = info->reg_seqno;
UNIX_ONLY(
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
epoch_record->strm_seqno[idx] = info->csd->strm_reg_seqno[idx];
if (jgbl.forw_phase_recovery)
{ /* If MUPIP JOURNAL -ROLLBACK, might need some adjustment. See macro definition for comments */
MUR_ADJUST_STRM_REG_SEQNO_IF_NEEDED(info->csd, epoch_record->strm_seqno);
}
)
VMS_ONLY(
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
assert(0 == epoch_record->strm_seqno[idx]); /* should have been zeroed already by above memset */
)
epoch_record->filler = 0;
epoch_record->prefix.checksum = INIT_CHECKSUM_SEED;
temp_checksum = compute_checksum(INIT_CHECKSUM_SEED,
(uint4 *)epoch_record, SIZEOF(struct_jrec_epoch));
temp_offset = JNL_HDR_LEN + PINI_RECLEN;
ADJUST_CHECKSUM(temp_checksum, temp_offset, temp_checksum);
ADJUST_CHECKSUM(temp_checksum, info->checksum, epoch_record->prefix.checksum);
pfin_record = (struct_jrec_pfin *)&jrecbuf[PINI_RECLEN + EPOCH_RECLEN];
pfin_offset = JNL_HDR_LEN + PINI_RECLEN + EPOCH_RECLEN;
eof_record = (struct_jrec_eof *)&jrecbuf[PINI_RECLEN + EPOCH_RECLEN + PFIN_RECLEN];
eof_offset = JNL_HDR_LEN + PINI_RECLEN + EPOCH_RECLEN + PFIN_RECLEN;
cre_jnl_rec_size = PINI_RECLEN + EPOCH_RECLEN + PFIN_RECLEN + EOF_RECLEN;
} else
{
pfin_record = (struct_jrec_pfin *)&jrecbuf[PINI_RECLEN];
pfin_offset = JNL_HDR_LEN + PINI_RECLEN;
eof_record = (struct_jrec_eof *)&jrecbuf[PINI_RECLEN + PFIN_RECLEN];
eof_offset = JNL_HDR_LEN + PINI_RECLEN + PFIN_RECLEN;
cre_jnl_rec_size = PINI_RECLEN + PFIN_RECLEN + EOF_RECLEN;
}
pfin_record->prefix.jrec_type = JRT_PFIN;
pfin_record->prefix.forwptr = pfin_record->suffix.backptr = PFIN_RECLEN;
pfin_record->prefix.tn = db_tn;
pfin_record->prefix.pini_addr = JNL_HDR_LEN;
pfin_record->prefix.time = jgbl.gbl_jrec_time;
pfin_record->suffix.suffix_code = JNL_REC_SUFFIX_CODE;
pfin_record->filler = 0;
pfin_record->prefix.checksum = INIT_CHECKSUM_SEED;
temp_checksum = compute_checksum(INIT_CHECKSUM_SEED, (uint4 *)pfin_record, SIZEOF(struct_jrec_pfin));
ADJUST_CHECKSUM(temp_checksum, pfin_offset, temp_checksum);
ADJUST_CHECKSUM(temp_checksum, info->checksum, pfin_record->prefix.checksum);
eof_record->prefix.jrec_type = JRT_EOF;
eof_record->prefix.forwptr = eof_record->suffix.backptr = EOF_RECLEN;
eof_record->prefix.tn = db_tn;
eof_record->prefix.pini_addr = JNL_HDR_LEN;
eof_record->prefix.time = jgbl.gbl_jrec_time;
QWASSIGN(eof_record->jnl_seqno, info->reg_seqno);
eof_record->suffix.suffix_code = JNL_REC_SUFFIX_CODE;
eof_record->filler = 0;
eof_record->prefix.checksum = INIT_CHECKSUM_SEED;
temp_checksum = compute_checksum(INIT_CHECKSUM_SEED, (uint4 *)eof_record, SIZEOF(struct_jrec_eof));
ADJUST_CHECKSUM(temp_checksum, eof_offset, temp_checksum);
ADJUST_CHECKSUM(temp_checksum, info->checksum, eof_record->prefix.checksum);
/* Assert that the journal file header and journal records are all in sync with respect to the db tn. */
assert(header->bov_tn == db_tn);
assert(header->eov_tn == db_tn);
/* Write the journal records, but also 0-fill the tail of the journal file enough to fill
* an aligned filesystem-block-size boundary. Take into account that the file header is already written.
*/
write_size = ROUND_UP2((JNL_HDR_LEN + cre_jnl_rec_size), jnl_fs_block_size) - JNL_HDR_LEN;
assert((jrecbuf + write_size) <= (jrecbuf_base + jrecbufbase_size));
/* Assert that initial virtual-size of the journal file (which is nothing but the journal allocation)
* gives us enough space to keep the journal file header + padding + PINI/PFIN/EPOCH/EOF records.
* Do the assertion in units of 512-byte blocks as that keeps the values well under 4G. Keeping the
* units in bytes causes the highest autoswitchlimit value to round up to 4G effectively becoming 0
* on certain platforms and therefore failing the assert.
*/
assert(ROUND_UP2(header->virtual_size, jnl_fs_block_size/DISK_BLOCK_SIZE)
> DIVIDE_ROUND_UP(JNL_HDR_LEN + write_size, DISK_BLOCK_SIZE));
JNL_DO_FILE_WRITE(info->csa, create_fn, channel, JNL_HDR_LEN, jrecbuf, write_size, info->status, info->status2);
STATUS_MSG(info);
RETURN_ON_ERROR(info);
UNIX_ONLY(GTM_JNL_FSYNC(info->csa, channel, status);)
F_CLOSE(channel, status); /* resets "channel" to FD_INVALID */
free(jrecbuf_base);
jrecbuf_base = NULL;
if (info->no_rename)
return EXIT_NRM;
/* Say, info->jnl = a.mjl
* So system will have a.mjl and a.mjl_new for a crash before the following call
* Following does rename of a.mjl to a.mjl_timestamp.
* So system will have a.mjl_timestamp and a.mjl_new for a crash after this call
*/
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(info->csa); /* wait for instance freeze before journal file renames */
if (SS_NORMAL != (info->status = gtm_rename((char *)info->jnl, (int)info->jnl_len,
(char *)rename_fn, rename_fn_len, &info->status2)))
{
if (IS_GTM_IMAGE)
send_msg(VARLSTCNT(6) ERR_RENAMEFAIL, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn);
else
gtm_putmsg(VARLSTCNT(6) ERR_RENAMEFAIL, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn);
STATUS_MSG(info);
return EXIT_ERR;
}
/* Following does rename of a.mjl_new to a.mjl.
* So system will have a.mjl_timestamp as previous generation and a.mjl as new/current journal file
*/
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(info->csa); /* wait for instance freeze before journal file renames */
if (SS_NORMAL != (info->status = gtm_rename((char *)create_fn, create_fn_len,
(char *)info->jnl, (int)info->jnl_len, &info->status2)))
{
if (IS_GTM_IMAGE)
send_msg(VARLSTCNT(6) ERR_RENAMEFAIL, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn);
else
gtm_putmsg(VARLSTCNT(6) ERR_RENAMEFAIL, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn);
STATUS_MSG(info);
return EXIT_ERR;
}
if (IS_GTM_IMAGE)
send_msg(VARLSTCNT (6) ERR_FILERENAME, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn);
else
gtm_putmsg(VARLSTCNT (6) ERR_FILERENAME, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn);
DEBUG_ONLY(
if (gtm_white_box_test_case_enabled && (WBTEST_JNL_CREATE_INTERRUPT == gtm_white_box_test_case_number))
{
UNIX_ONLY(DBGFPF((stderr, "CRE_JNL_FILE: started a wait\n"))); /* this white-box test is for UNIX */
LONG_SLEEP(600);
assert(FALSE); /* Should be killed before that */
}
)
return EXIT_NRM;
}