135 lines
5.1 KiB
C
135 lines
5.1 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 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 "gdsroot.h"
|
|
#include "gdskill.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "gdscc.h"
|
|
#include "filestruct.h"
|
|
#include "jnl.h"
|
|
#include "buddy_list.h" /* needed for tp.h */
|
|
#include "hashtab_int4.h" /* needed for tp.h */
|
|
#include "tp.h"
|
|
#include "gds_map_moved.h"
|
|
#include "hashtab_mname.h"
|
|
#include "dpgbldir.h"
|
|
#include "gtmimagename.h"
|
|
|
|
GBLREF sgmnt_addrs *cs_addrs;
|
|
GBLREF sgmnt_data_ptr_t cs_data;
|
|
GBLREF gd_addr *gd_header;
|
|
|
|
void gds_map_moved(sm_uc_ptr_t new_base, sm_uc_ptr_t old_base, sm_uc_ptr_t old_top, off_t new_eof)
|
|
{
|
|
int hist_index;
|
|
sm_long_t adj;
|
|
srch_hist *hist, *dir_hist, *dir_alt_hist, *hist1, *hist2;
|
|
ht_ent_mname *tabent, *topent;
|
|
gv_namehead *gvt;
|
|
gvnh_reg_t *gvnh_reg;
|
|
hash_table_mname *tbl;
|
|
gd_addr *addr_ptr;
|
|
|
|
assert(cs_addrs->now_crit);
|
|
/* It's possible to arrive here via mupip_backup --> wcs_flu --> wcs_mm_recover --> gds_map_moved and have
|
|
* cs_addrs->dir_tree be NULL. To distinguish that case, we can also check if this this is the GTM image
|
|
* in the following assert and then return because there's nothing to do here.
|
|
*/
|
|
assert(!IS_GTM_IMAGE || ((NULL != cs_addrs->dir_tree) && (NULL != &cs_addrs->dir_tree->hist)));
|
|
/* This initialization has to be done irrespective of whether new_base is different from old_base or not. */
|
|
cs_data = cs_addrs->hdr = (sgmnt_data_ptr_t)new_base;
|
|
cs_addrs->db_addrs[1] = new_base + new_eof - 1;
|
|
cs_addrs->bmm = MM_ADDR(cs_data);
|
|
cs_addrs->acc_meth.mm.base_addr = (sm_uc_ptr_t)((sm_uc_ptr_t)cs_data + (cs_data->start_vbn - 1) * DISK_BLOCK_SIZE);
|
|
if (NULL != cs_addrs->sgm_info_ptr)
|
|
cs_addrs->sgm_info_ptr->tp_csd = cs_addrs->hdr;
|
|
bt_init(cs_addrs);
|
|
if (NULL == cs_addrs->dir_tree)
|
|
return;
|
|
/* The following adjustment needs to be done only if new_base is different from old_base */
|
|
if (new_base == old_base)
|
|
return;
|
|
adj = (sm_long_t)(new_base - old_base);
|
|
assert(0 != adj);
|
|
dir_hist = &cs_addrs->dir_tree->hist;
|
|
dir_alt_hist = cs_addrs->dir_tree->alt_hist;
|
|
for (hist = dir_hist; (NULL != hist); hist = (hist == dir_hist) ? dir_alt_hist : NULL)
|
|
{
|
|
for (hist_index = 0; HIST_TERMINATOR != hist->h[hist_index].blk_num; hist_index++)
|
|
{
|
|
assert(MAX_BT_DEPTH >= hist_index);
|
|
if ((old_base <= hist->h[hist_index].buffaddr) &&
|
|
(old_top > hist->h[hist_index].buffaddr))
|
|
{
|
|
hist->h[hist_index].buffaddr += adj;
|
|
assert(new_base <= hist->h[hist_index].buffaddr);
|
|
} else
|
|
{
|
|
/* It has to be a private copy */
|
|
assert((hist->h[hist_index].first_tp_srch_status != 0) ||
|
|
(((off_chain *)&(hist->h[hist_index].blk_num))->flag != 0));
|
|
}
|
|
}
|
|
}
|
|
/* It is possible that more than one global directory has regions mapping to the same physical database file.
|
|
* In this case, the search histories in the gv_targets hash tables of all those glds should be fixed. Hence,
|
|
* we go through all open glds (instead of just the currently active gd_header).
|
|
*/
|
|
assert(NULL != get_next_gdr(NULL)); /* assert that we have at least one open global directory */
|
|
for (addr_ptr = get_next_gdr(NULL); NULL != addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
|
|
{
|
|
tbl = addr_ptr->tab_ptr;
|
|
assert(NULL != tbl);
|
|
for (tabent = tbl->base, topent = tbl->top; tabent < topent; tabent++)
|
|
{
|
|
if ((HTENT_VALID_MNAME(tabent, gvnh_reg_t, gvnh_reg)) && (NULL != (gvt = gvnh_reg->gvt))
|
|
&& (cs_addrs == gvt->gd_csa) && (0 < gvt->clue.end))
|
|
{
|
|
hist1 = &gvt->hist;
|
|
hist2 = gvt->alt_hist;
|
|
for (hist = hist1; (NULL != hist); hist = (hist == hist1) ? hist2 : NULL)
|
|
{
|
|
if (((hist == hist1) && (hist == dir_hist))
|
|
|| ((hist == hist2) && (hist == dir_alt_hist)))
|
|
continue;
|
|
for (hist_index = 0; HIST_TERMINATOR != hist->h[hist_index].blk_num; hist_index++)
|
|
{
|
|
assert(MAX_BT_DEPTH >= hist_index);
|
|
if ((old_base <= hist->h[hist_index].buffaddr)
|
|
&& (old_top > hist->h[hist_index].buffaddr))
|
|
{
|
|
hist->h[hist_index].buffaddr += adj;
|
|
assert(new_base <= hist->h[hist_index].buffaddr);
|
|
} else if ((hist == hist2) && (0 < gvt->clue.end))
|
|
{ /* alt_hist is not updated when clue is set so the buffaddr can
|
|
* point to a prior instance of the file's mapping. So, reset alt_hist.
|
|
*/
|
|
hist->h[hist_index].blk_num = HIST_TERMINATOR;
|
|
} else
|
|
{ /* It's already been adjusted or it has to be a private copy */
|
|
assert(((new_base <= hist->h[hist_index].buffaddr)
|
|
&& (hist->h[hist_index].buffaddr < new_base + (old_top - old_base)))
|
|
|| (0 != hist->h[hist_index].first_tp_srch_status)
|
|
|| (0 != ((off_chain *)&(hist->h[hist_index].blk_num))->flag));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|