2012-02-05 11:35:58 -05:00
|
|
|
/****************************************************************
|
|
|
|
* *
|
2012-03-24 14:06:46 -04:00
|
|
|
* Copyright 2001, 2012 Fidelity Information Services, Inc *
|
2012-02-05 11:35:58 -05:00
|
|
|
* *
|
|
|
|
* 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;
|
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
error_def(ERR_DBJNLNOTMATCH);
|
|
|
|
error_def(ERR_JNLBADRECFMT);
|
|
|
|
error_def(ERR_JNLCYCLE);
|
|
|
|
error_def(ERR_JNLTNOUTOFSEQ);
|
|
|
|
error_def(ERR_MUJNLPREVGEN);
|
|
|
|
|
|
|
|
|
2012-02-05 11:35:58 -05:00
|
|
|
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;
|
|
|
|
}
|
2012-03-24 14:06:46 -04:00
|
|
|
/* 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));
|
2012-02-05 11:35:58 -05:00
|
|
|
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;
|
|
|
|
}
|