fis-gtm/sr_port/dse_maps.c

263 lines
8.3 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 "gtm_string.h"
#include "gtm_time.h"
#include "gdsroot.h"
#include "gdskill.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "gdsblk.h"
#include "gdsbml.h"
#include "min_max.h" /* needed for gdsblkops.h */
#include "gdsblkops.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 "cli.h"
#include "util.h"
#include "send_msg.h"
#include "dse.h"
/* Include prototypes */
#include "t_qread.h"
#include "dse_is_blk_free.h"
#include "bit_set.h"
#include "bit_clear.h"
#include "t_begin_crit.h"
#include "t_write.h"
#include "t_end.h"
#include "longset.h" /* needed for cws_insert.h */
#include "cws_insert.h"
#include "process_deferred_stale.h"
#include "gvcst_blk_build.h"
#define MAX_UTIL_LEN 80
GBLREF char *update_array, *update_array_ptr;
GBLREF uint4 update_array_size;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF block_id patch_curr_blk;
GBLREF gd_region *gv_cur_region;
GBLREF short crash_count;
GBLREF boolean_t unhandled_stale_timer_pop;
GBLREF srch_hist dummy_hist;
GBLREF unsigned char *non_tp_jfb_buff_ptr;
void dse_maps(void)
{
block_id blk, bml_blk;
blk_segment *bs1, *bs_ptr;
int4 blk_seg_cnt, blk_size; /* needed for BLK_INIT, BLK_SEG and BLK_FINI macros */
sm_uc_ptr_t bp;
char util_buff[MAX_UTIL_LEN];
int4 bml_size, bml_list_size, blk_index, bml_index;
int4 total_blks, blks_in_bitmap;
int4 bplmap, dummy_int;
unsigned char *bml_list;
cache_rec_ptr_t cr, dummy_cr;
bt_rec_ptr_t btr;
int util_len;
uchar_ptr_t blk_ptr;
boolean_t was_crit;
uint4 jnl_status;
srch_blk_status blkhist;
jnl_private_control *jpc;
jnl_buffer_ptr_t jbp;
sgmnt_addrs *csa;
sgmnt_data_ptr_t csd;
error_def(ERR_DSEBLKRDFAIL);
error_def(ERR_DBRDONLY);
error_def(ERR_DSEFAIL);
if (CLI_PRESENT == cli_present("BUSY") || CLI_PRESENT == cli_present("FREE") ||
CLI_PRESENT == cli_present("MASTER") || CLI_PRESENT == cli_present("RESTORE_ALL"))
{
if (gv_cur_region->read_only)
rts_error(VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region));
}
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
csa = cs_addrs;
assert(&FILE_INFO(gv_cur_region)->s_addrs == csa);
was_crit = csa->now_crit;
if (csa->critical)
crash_count = csa->critical->crashcnt;
csd = csa->hdr;
bplmap = csd->bplmap;
if (CLI_PRESENT == cli_present("BLOCK"))
{
if (!cli_get_hex("BLOCK", (uint4 *)&blk))
return;
if (blk < 0 || blk >= csa->ti->total_blks)
{
util_out_print("Error: invalid block number.", TRUE);
return;
}
patch_curr_blk = blk;
}
else
blk = patch_curr_blk;
if (CLI_PRESENT == cli_present("FREE"))
{
if (0 == bplmap)
{
util_out_print("Cannot perform map updates: bplmap field of file header is zero.", TRUE);
return;
}
if (blk / bplmap * bplmap == blk)
{
util_out_print("Cannot perform action on a map block.", TRUE);
return;
}
bml_blk = blk / bplmap * bplmap;
bm_setmap(bml_blk, blk, FALSE);
return;
}
if (CLI_PRESENT == cli_present("BUSY"))
{
if (0 == bplmap)
{
util_out_print("Cannot perform map updates: bplmap field of file header is zero.", TRUE);
return;
}
if (blk / bplmap * bplmap == blk)
{
util_out_print("Cannot perform action on a map block.", TRUE);
return;
}
bml_blk = blk / bplmap * bplmap;
bm_setmap(bml_blk, blk, TRUE);
return;
}
blk_size = csd->blk_size;
if (CLI_PRESENT == cli_present("MASTER"))
{
if (0 == bplmap)
{
util_out_print("Cannot perform maps updates: bplmap field of file header is zero.", TRUE);
return;
}
if (!was_crit)
grab_crit(gv_cur_region);
bml_blk = blk / bplmap * bplmap;
if (dba_mm == csd->acc_meth)
bp = (sm_uc_ptr_t)csa->acc_meth.mm.base_addr + (off_t)bml_blk * blk_size;
else
{
assert(dba_bg == csd->acc_meth);
if (!(bp = t_qread(bml_blk, &dummy_int, &dummy_cr)))
rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
}
if ((csa->ti->total_blks / bplmap) * bplmap == bml_blk)
total_blks = (csa->ti->total_blks - bml_blk);
else
total_blks = bplmap;
if (NO_FREE_SPACE == bml_find_free(0, bp + SIZEOF(blk_hdr), total_blks))
bit_clear(bml_blk / bplmap, csa->bmm);
else
bit_set(bml_blk / bplmap, csa->bmm);
if (bml_blk > csa->nl->highest_lbm_blk_changed)
csa->nl->highest_lbm_blk_changed = bml_blk;
if (!was_crit)
rel_crit(gv_cur_region);
return;
}
if (CLI_PRESENT == cli_present("RESTORE_ALL"))
{
if (0 == bplmap)
{
util_out_print("Cannot perform maps updates: bplmap field of file header is zero.", TRUE);
return;
}
total_blks = csa->ti->total_blks;
assert(ROUND_DOWN2(blk_size, 2 * SIZEOF(int4)) == blk_size);
bml_size = BM_SIZE(bplmap);
bml_list_size = (total_blks + bplmap - 1) / bplmap * bml_size;
bml_list = (unsigned char *)malloc(bml_list_size);
for (blk_index = 0, bml_index = 0; blk_index < total_blks; blk_index += bplmap, bml_index++)
bml_newmap((blk_hdr_ptr_t)(bml_list + bml_index * bml_size), bml_size, csa->ti->curr_tn);
if (!was_crit)
{
grab_crit(gv_cur_region);
csa->hold_onto_crit = TRUE; /* need to do this AFTER grab_crit */
}
blk = get_dir_root();
assert(blk < bplmap);
csa->ti->free_blocks = total_blks - DIVIDE_ROUND_UP(total_blks, bplmap);
bml_busy(blk, bml_list + SIZEOF(blk_hdr));
csa->ti->free_blocks = csa->ti->free_blocks - 1;
dse_m_rest(blk, bml_list, bml_size, &csa->ti->free_blocks, TRUE);
for (blk_index = 0, bml_index = 0; blk_index < total_blks; blk_index += bplmap, bml_index++)
{
t_begin_crit(ERR_DSEFAIL);
CHECK_TN(csa, csd, csd->trans_hist.curr_tn); /* can issue rts_error TNTOOLARGE */
CWS_RESET;
CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */
assert(csa->ti->early_tn == csa->ti->curr_tn);
blk_ptr = bml_list + bml_index * bml_size;
blkhist.blk_num = blk_index;
if (!(blkhist.buffaddr = t_qread(blkhist.blk_num, &blkhist.cycle, &blkhist.cr)))
rts_error(VARLSTCNT(1) ERR_DSEBLKRDFAIL);
BLK_INIT(bs_ptr, bs1);
BLK_SEG(bs_ptr, blk_ptr + SIZEOF(blk_hdr), bml_size - SIZEOF(blk_hdr));
BLK_FINI(bs_ptr, bs1);
t_write(&blkhist, (unsigned char *)bs1, 0, 0, LCL_MAP_LEVL, TRUE, FALSE, GDS_WRITE_KILLTN);
BUILD_AIMG_IF_JNL_ENABLED(csd, non_tp_jfb_buff_ptr, csa->ti->curr_tn);
t_end(&dummy_hist, NULL, csa->ti->curr_tn);
}
/* Fill in master map */
for (blk_index = 0, bml_index = 0; blk_index < total_blks; blk_index += bplmap, bml_index++)
{
blks_in_bitmap = (blk_index + bplmap <= total_blks) ? bplmap : total_blks - blk_index;
assert(1 < blks_in_bitmap); /* the last valid block in the database should never be a bitmap block */
if (NO_FREE_SPACE != bml_find_free(0, (bml_list + bml_index * bml_size) + SIZEOF(blk_hdr), blks_in_bitmap))
bit_set(blk_index / bplmap, csa->bmm);
else
bit_clear(blk_index / bplmap, csa->bmm);
if (blk_index > csa->nl->highest_lbm_blk_changed)
csa->nl->highest_lbm_blk_changed = blk_index;
}
if (!was_crit)
{
csa->hold_onto_crit = FALSE; /* need to do this before the rel_crit */
rel_crit(gv_cur_region);
}
if (unhandled_stale_timer_pop)
process_deferred_stale();
free(bml_list);
csd->kill_in_prog = csd->abandoned_kills = 0;
return;
}
MEMCPY_LIT(util_buff, "!/Block ");
util_len = SIZEOF("!/Block ") - 1;
util_len += i2hex_nofill(blk, (uchar_ptr_t)&util_buff[util_len], 8);
memcpy(&util_buff[util_len], " is marked !AD in its local bit map.!/",
SIZEOF(" is marked !AD in its local bit map.!/") - 1);
util_len += SIZEOF(" is marked !AD in its local bit map.!/") - 1;
util_buff[util_len] = 0;
if (!was_crit)
grab_crit(gv_cur_region);
util_out_print(util_buff, TRUE, 4, dse_is_blk_free(blk, &dummy_int, &dummy_cr) ? "free" : "busy");
if (!was_crit)
rel_crit(gv_cur_region);
return;
}