2012-02-05 11:35:58 -05:00
|
|
|
/****************************************************************
|
|
|
|
* *
|
2012-10-29 18:54:31 -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 "cdb_sc.h"
|
|
|
|
#include "gdsroot.h"
|
|
|
|
#include "gdsblk.h"
|
|
|
|
#include "gtm_facility.h"
|
|
|
|
#include "fileinfo.h"
|
|
|
|
#include "gdsbt.h"
|
|
|
|
#include "gdsfhead.h"
|
|
|
|
#include "copy.h"
|
|
|
|
#include "filestruct.h" /* needed for jnl.h */
|
|
|
|
#include "gdscc.h" /* needed for tp.h */
|
|
|
|
#include "jnl.h" /* needed for tp.h */
|
|
|
|
#include "gdskill.h" /* needed for tp.h */
|
|
|
|
#include "buddy_list.h" /* needed for tp.h */
|
|
|
|
#include "hashtab_int4.h" /* needed for tp.h */
|
|
|
|
#include "tp.h" /* needed for T_BEGIN_READ_NONTP_OR_TP macro */
|
2012-10-29 18:54:31 -04:00
|
|
|
#ifdef UNIX /* needed for frame_pointer in GVCST_ROOT_SEARCH_AND_PREP macro */
|
|
|
|
# include "repl_msg.h"
|
|
|
|
# include "gtmsource.h"
|
|
|
|
# include "rtnhdr.h"
|
|
|
|
# include "stack_frame.h"
|
|
|
|
# include "wbox_test_init.h"
|
|
|
|
#endif
|
2012-02-05 11:35:58 -05:00
|
|
|
|
|
|
|
#include "t_end.h" /* prototypes */
|
|
|
|
#include "t_retry.h"
|
|
|
|
#include "t_begin.h"
|
|
|
|
#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search,gvcst_search_blk,gvcst_data prototype */
|
|
|
|
|
2012-10-29 18:54:31 -04:00
|
|
|
/* needed for spanning nodes */
|
|
|
|
#include "op.h"
|
|
|
|
#include "op_tcommit.h"
|
|
|
|
#include "error.h"
|
|
|
|
#include "tp_frame.h"
|
|
|
|
#include "tp_restart.h"
|
|
|
|
#include "gtmimagename.h"
|
|
|
|
|
|
|
|
LITREF mval literal_batch;
|
|
|
|
|
|
|
|
GBLREF gv_key *gv_currkey, *gv_altkey;
|
2012-02-05 11:35:58 -05:00
|
|
|
GBLREF gv_namehead *gv_target;
|
|
|
|
GBLREF sgmnt_addrs *cs_addrs;
|
|
|
|
GBLREF gd_region *gv_cur_region;
|
|
|
|
GBLREF uint4 dollar_tlevel;
|
|
|
|
GBLREF unsigned int t_tries;
|
|
|
|
|
2012-10-29 18:54:31 -04:00
|
|
|
error_def(ERR_DBROLLEDBACK);
|
2012-03-24 14:06:46 -04:00
|
|
|
error_def(ERR_GVDATAFAIL);
|
2012-10-29 18:54:31 -04:00
|
|
|
error_def(ERR_TPRETRY);
|
|
|
|
|
|
|
|
DEFINE_NSB_CONDITION_HANDLER(gvcst_data_ch)
|
2012-03-24 14:06:46 -04:00
|
|
|
|
2012-02-05 11:35:58 -05:00
|
|
|
mint gvcst_data(void)
|
2012-10-29 18:54:31 -04:00
|
|
|
{
|
|
|
|
bool found, sn_tpwrapped;
|
|
|
|
boolean_t est_first_pass;
|
|
|
|
int oldend;
|
|
|
|
mint val;
|
|
|
|
int save_dollar_tlevel;
|
|
|
|
|
|
|
|
DEBUG_ONLY(save_dollar_tlevel = dollar_tlevel);
|
|
|
|
val = gvcst_data2();
|
|
|
|
# ifdef UNIX
|
|
|
|
if (-1 != val)
|
|
|
|
{
|
|
|
|
assert(save_dollar_tlevel == dollar_tlevel);
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
oldend = gv_currkey->end;
|
|
|
|
if (!dollar_tlevel)
|
|
|
|
{
|
|
|
|
sn_tpwrapped = TRUE;
|
|
|
|
op_tstart((IMPLICIT_TSTART), TRUE, &literal_batch, 0);
|
|
|
|
ESTABLISH_NORET(gvcst_data_ch, est_first_pass);
|
|
|
|
GVCST_ROOT_SEARCH_AND_PREP(est_first_pass);
|
|
|
|
} else
|
|
|
|
sn_tpwrapped = FALSE;
|
|
|
|
/* fix up since it should only be externally counted as one $data */
|
|
|
|
INCR_GVSTATS_COUNTER(cs_addrs, cs_addrs->nl, n_data, (gtm_uint64_t) -1);
|
|
|
|
val = gvcst_data2();
|
|
|
|
if (-1 == val)
|
|
|
|
{ /* -1 implies node exists. Need to see if a proper descendant exists */
|
|
|
|
val = 1;
|
|
|
|
/* 0 1 0 0 <-- append that to gv_currkey */
|
|
|
|
gv_currkey->end = oldend + 2;
|
|
|
|
gv_currkey->base[oldend + 0] = 1;
|
|
|
|
gv_currkey->base[oldend + 1] = 0;
|
|
|
|
gv_currkey->base[oldend + 2] = 0;
|
|
|
|
found = gvcst_query(); /* want to save gv_altkey? */
|
|
|
|
if (found && (0 == memcmp(gv_currkey->base, gv_altkey->base, oldend)))
|
|
|
|
val += 10;
|
|
|
|
}
|
|
|
|
if (sn_tpwrapped)
|
|
|
|
{
|
|
|
|
op_tcommit();
|
|
|
|
REVERT; /* remove our condition handler */
|
|
|
|
}
|
|
|
|
RESTORE_CURRKEY(gv_currkey, oldend);
|
|
|
|
assert(save_dollar_tlevel == dollar_tlevel);
|
|
|
|
# endif
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
mint gvcst_data2(void)
|
2012-02-05 11:35:58 -05:00
|
|
|
{
|
|
|
|
blk_hdr_ptr_t bp;
|
2012-10-29 18:54:31 -04:00
|
|
|
boolean_t do_rtsib, is_dummy;
|
2012-02-05 11:35:58 -05:00
|
|
|
enum cdb_sc status;
|
|
|
|
mint val;
|
|
|
|
rec_hdr_ptr_t rp;
|
|
|
|
unsigned short match, rsiz;
|
|
|
|
srch_blk_status *bh;
|
|
|
|
srch_hist *rt_history;
|
|
|
|
sm_uc_ptr_t b_top;
|
2012-10-29 18:54:31 -04:00
|
|
|
int tmp_cmpc;
|
|
|
|
int data_len, cur_val_offset, realval = 0;
|
2012-02-05 11:35:58 -05:00
|
|
|
|
2012-10-29 18:54:31 -04:00
|
|
|
VMS_ONLY(assert((gv_target->root < cs_addrs->ti->total_blks) || dollar_tlevel));
|
2012-02-05 11:35:58 -05:00
|
|
|
T_BEGIN_READ_NONTP_OR_TP(ERR_GVDATAFAIL);
|
|
|
|
assert(t_tries < CDB_STAGNATE || cs_addrs->now_crit); /* we better hold crit in the final retry (TP & non-TP) */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* The following code is duplicated in gvcst_dataget. Any changes here might need to be reflected there as well */
|
|
|
|
rt_history = gv_target->alt_hist;
|
|
|
|
rt_history->h[0].blk_num = 0;
|
2012-10-29 18:54:31 -04:00
|
|
|
#if defined(DEBUG) && defined(UNIX)
|
|
|
|
if (gtm_white_box_test_case_enabled && (WBTEST_ANTIFREEZE_GVDATAFAIL == gtm_white_box_test_case_number))
|
|
|
|
{
|
|
|
|
t_retry(cdb_sc_blknumerr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2012-02-05 11:35:58 -05:00
|
|
|
if (cdb_sc_normal != (status = gvcst_search(gv_currkey, NULL)))
|
|
|
|
{
|
|
|
|
t_retry(status);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bh = gv_target->hist.h;
|
|
|
|
bp = (blk_hdr_ptr_t)bh->buffaddr;
|
|
|
|
rp = (rec_hdr_ptr_t)(bh->buffaddr + bh->curr_rec.offset);
|
|
|
|
b_top = bh->buffaddr + bp->bsiz;
|
|
|
|
match = bh->curr_rec.match;
|
|
|
|
do_rtsib = FALSE;
|
2012-10-29 18:54:31 -04:00
|
|
|
realval = 0;
|
2012-02-05 11:35:58 -05:00
|
|
|
if (gv_currkey->end + 1 == match)
|
|
|
|
{
|
|
|
|
val = 1;
|
|
|
|
GET_USHORT(rsiz, &rp->rsiz);
|
2012-10-29 18:54:31 -04:00
|
|
|
# ifdef UNIX
|
|
|
|
/* check for spanning node dummy value: a single zero byte */
|
|
|
|
cur_val_offset = SIZEOF(rec_hdr) + match - EVAL_CMPC((rec_hdr_ptr_t)rp);
|
|
|
|
data_len = rsiz - cur_val_offset;
|
|
|
|
is_dummy = IS_SN_DUMMY(data_len, (sm_uc_ptr_t)rp + cur_val_offset);
|
|
|
|
if (is_dummy)
|
|
|
|
{
|
|
|
|
realval = -1;
|
|
|
|
IF_SN_DISALLOWED_AND_NO_SPAN_IN_DB(realval = 0); /* resume since this is not a spanning node */
|
|
|
|
}
|
|
|
|
# endif
|
2012-02-05 11:35:58 -05:00
|
|
|
rp = (rec_hdr_ptr_t)((sm_uc_ptr_t)rp + rsiz);
|
|
|
|
if ((sm_uc_ptr_t)rp > b_top)
|
|
|
|
{
|
|
|
|
t_retry(cdb_sc_rmisalign);
|
|
|
|
continue;
|
|
|
|
} else if ((sm_uc_ptr_t)rp == b_top)
|
|
|
|
do_rtsib = TRUE;
|
2012-10-29 18:54:31 -04:00
|
|
|
else if (EVAL_CMPC(rp) >= gv_currkey->end)
|
2012-02-05 11:35:58 -05:00
|
|
|
val += 10;
|
|
|
|
} else if (match >= gv_currkey->end)
|
|
|
|
val = 10;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
val = 0;
|
|
|
|
if (rp == (rec_hdr_ptr_t)b_top)
|
|
|
|
do_rtsib = TRUE;
|
|
|
|
}
|
|
|
|
if (do_rtsib && (cdb_sc_endtree != (status = gvcst_rtsib(rt_history, 0))))
|
|
|
|
{
|
|
|
|
if ((cdb_sc_normal != status) || (cdb_sc_normal != (status = gvcst_search_blk(gv_currkey, rt_history->h))))
|
|
|
|
{
|
|
|
|
t_retry(status);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (rt_history->h[0].curr_rec.match >= gv_currkey->end)
|
|
|
|
{
|
|
|
|
assert(1 >= val);
|
|
|
|
val += 10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dollar_tlevel)
|
|
|
|
{
|
|
|
|
if ((trans_num)0 == t_end(&gv_target->hist, 0 == rt_history->h[0].blk_num ? NULL : rt_history,
|
|
|
|
TN_NOT_SPECIFIED))
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
status = tp_hist(0 == rt_history->h[0].blk_num ? NULL : rt_history);
|
|
|
|
if (cdb_sc_normal != status)
|
|
|
|
{
|
|
|
|
t_retry(status);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
INCR_GVSTATS_COUNTER(cs_addrs, cs_addrs->nl, n_data, 1);
|
2012-10-29 18:54:31 -04:00
|
|
|
return (0 != realval) ? realval : val;
|
2012-02-05 11:35:58 -05:00
|
|
|
}
|
|
|
|
}
|