fis-gtm/sr_port/mur_insert_prev.c

159 lines
5.7 KiB
C

/****************************************************************
* *
* 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 "min_max.h"
#include "gtm_string.h"
#ifdef VMS
#include "iosb_disk.h"
#endif
#include "gdsroot.h"
#include "gdsbt.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "buddy_list.h"
#include "hashtab_int4.h" /* needed for muprec.h */
#include "hashtab_int8.h" /* needed for muprec.h */
#include "hashtab_mname.h" /* needed for muprec.h */
#include "muprec.h"
#include "mur_read_file.h"
#include "iosp.h"
#include "gtmmsg.h"
GBLREF mur_opt_struct mur_options;
error_def(ERR_DBJNLNOTMATCH);
error_def(ERR_JNLBADRECFMT);
error_def(ERR_JNLCYCLE);
error_def(ERR_JNLTNOUTOFSEQ);
error_def(ERR_MUJNLPREVGEN);
boolean_t mur_insert_prev(jnl_ctl_list **jjctl)
{
reg_ctl_list *rctl;
jnl_ctl_list *new_jctl, *cur_jctl, *jctl;
redirect_list *rl_ptr;
boolean_t proceed;
jctl = *jjctl;
rctl = jctl->reg_ctl;
assert(rctl->jctl_head == jctl);
assert(rctl->jctl == jctl);
new_jctl = (jnl_ctl_list *)malloc(SIZEOF(jnl_ctl_list));
memset(new_jctl, 0, SIZEOF(jnl_ctl_list));
memcpy(new_jctl->jnl_fn, jctl->jfh->prev_jnl_file_name, jctl->jfh->prev_jnl_file_name_length);
new_jctl->jnl_fn_len = jctl->jfh->prev_jnl_file_name_length;
assert(0 != new_jctl->jnl_fn_len);
if (FALSE == mur_fopen(new_jctl))
{
free(new_jctl);
return FALSE; /* "mur_fopen" would have printed the appropriate error message */
}
if (SS_NORMAL != (new_jctl->status = mur_fread_eof(new_jctl, rctl)))
{
gtm_putmsg(VARLSTCNT(6) ERR_JNLBADRECFMT, 3, new_jctl->jnl_fn_len, new_jctl->jnl_fn,
new_jctl->rec_offset, new_jctl->status);
free(new_jctl);
return FALSE;
}
/* It is NOT possible for a previous generation journal file to have jfh->crash to be TRUE. Assert that.
* This also indicates that jctl->properly_closed will always be TRUE for a previous generation journal
* file. The only exception is if the current generation journal file is created by recovery. In this
* case the previous generation journal file (not created by recover) can have the crash field set to TRUE.
*/
assert((new_jctl->properly_closed && !new_jctl->jfh->crash) || (jctl->jfh->recover_interrupted &&
!new_jctl->jfh->recover_interrupted));
assert(!mur_options.forward || (!(jctl->jfh->recover_interrupted && !new_jctl->jfh->recover_interrupted)));
/* Skip the continuty of journal files check if both of these are true:
* 1) if current generation was created by recover and
* 2) the new one to be inserted was not created by recover
*/
if (!(jctl->jfh->recover_interrupted && !new_jctl->jfh->recover_interrupted))
{
if (!new_jctl->properly_closed)
{
proceed = (FALSE == mur_report_error(jctl, MUR_PREVJNLNOEOF)); /* message report left to mur_report_error */
if (mur_options.update || !proceed)
{
free(new_jctl);
return FALSE;
}
}
if ((!mur_options.forward || !mur_options.notncheck) && (new_jctl->jfh->eov_tn != jctl->jfh->bov_tn))
{
gtm_putmsg(VARLSTCNT(8) ERR_JNLTNOUTOFSEQ, 6,
&new_jctl->jfh->eov_tn, new_jctl->jnl_fn_len, new_jctl->jnl_fn,
&jctl->jfh->bov_tn, jctl->jnl_fn_len, jctl->jnl_fn);
free(new_jctl);
return FALSE;
}
}
if ((rctl->gd->dyn.addr->fname_len != new_jctl->jfh->data_file_name_length) ||
(0 != memcmp(new_jctl->jfh->data_file_name, rctl->gd->dyn.addr->fname, rctl->gd->dyn.addr->fname_len)))
{
for (rl_ptr = mur_options.redirect; (NULL != rl_ptr); rl_ptr = rl_ptr->next)
{
if ((new_jctl->jfh->data_file_name_length == rl_ptr->org_name_len)
&& (0 == memcmp(new_jctl->jfh->data_file_name,
rl_ptr->org_name, rl_ptr->org_name_len)))
break;
}
if (NULL == rl_ptr)
{
gtm_putmsg(VARLSTCNT(8) ERR_DBJNLNOTMATCH, 6, DB_LEN_STR(rctl->gd), new_jctl->jnl_fn_len,
new_jctl->jnl_fn, new_jctl->jfh->data_file_name_length,
new_jctl->jfh->data_file_name);
free(new_jctl);
return FALSE;
}
}
for (cur_jctl = rctl->jctl_head; cur_jctl; cur_jctl = cur_jctl->next_gen)
{
if (new_jctl->jfh->prev_jnl_file_name_length == cur_jctl->jnl_fn_len &&
0 == memcmp(new_jctl->jfh->prev_jnl_file_name, cur_jctl->jnl_fn, cur_jctl->jnl_fn_len))
{
gtm_putmsg(VARLSTCNT(6) ERR_JNLCYCLE, 4, cur_jctl->jnl_fn_len, cur_jctl->jnl_fn, DB_LEN_STR(rctl->gd));
free(new_jctl);
return FALSE;
}
if (new_jctl->jfh->turn_around_offset && cur_jctl->jfh->turn_around_offset)
{
if (rctl->recov_interrupted)
{ /* Possible if a first recovery with a turn-around-point (T2) got interrupted and a second
* recovery with a new turn-around-point (T1 which is in a previous generation journal file)
* was re-interrupted while in the middle of mur_process_intrpt_recov just after it had
* recorded the new turn-around-point (T1) but before it had erased the former one (T2).
* In this case, erase the turn-around-point T2 so this recovery goes back to T1. Here we
* erase the value only in memory. The value on disk is reset later in mur_process_intrpt_recov.
*/
cur_jctl->jfh->turn_around_offset = 0;
cur_jctl->jfh->turn_around_time = 0;
} else
GTMASSERT; /* out of design situation */
}
}
new_jctl->prev_gen = NULL;
new_jctl->next_gen = jctl;
jctl->prev_gen = new_jctl;
rctl->jctl = rctl->jctl_head = new_jctl;
assert(new_jctl->reg_ctl == rctl);
*jjctl = new_jctl;
gtm_putmsg(VARLSTCNT(6) ERR_MUJNLPREVGEN, 4, new_jctl->jnl_fn_len, new_jctl->jnl_fn, DB_LEN_STR(rctl->gd));
return TRUE;
}