164 lines
5.8 KiB
C
164 lines
5.8 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 "gdsroot.h"
|
||
|
#include "gdsblk.h"
|
||
|
#include "gtm_facility.h"
|
||
|
#include "fileinfo.h"
|
||
|
#include "gdsbt.h"
|
||
|
#include "gdsfhead.h"
|
||
|
#include "gdscc.h"
|
||
|
#include "gdskill.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 "copy.h"
|
||
|
#include "tp_incr_commit.h"
|
||
|
|
||
|
GBLREF uint4 dollar_tlevel;
|
||
|
GBLREF sgm_info *first_sgm_info;
|
||
|
GBLREF sgmnt_data_ptr_t cs_data;
|
||
|
GBLREF global_tlvl_info *global_tlvl_info_head;
|
||
|
GBLREF buddy_list *global_tlvl_info_list;
|
||
|
|
||
|
/* commit for transaction level greater than one */
|
||
|
|
||
|
void tp_incr_commit(void)
|
||
|
{
|
||
|
sgm_info *si;
|
||
|
cw_set_element *cse, *orig_cse, *prev_cse, *next_cse, *low_cse, *lower_cse;
|
||
|
tlevel_info *tli, *prev_tli = NULL, *last_prev_tli = NULL;
|
||
|
global_tlvl_info *gtli, *prev_gtli;
|
||
|
srch_blk_status *tp_srch_status;
|
||
|
ht_ent_int4 *tabent;
|
||
|
|
||
|
for (si = first_sgm_info; si != NULL; si = si->next_sgm_info)
|
||
|
{
|
||
|
for (cse = si->first_cw_set; cse; cse = orig_cse->next_cw_set)
|
||
|
{
|
||
|
orig_cse = cse;
|
||
|
TRAVERSE_TO_LATEST_CSE(cse);
|
||
|
assert(dollar_tlevel >= cse->t_level);
|
||
|
if (dollar_tlevel == cse->t_level)
|
||
|
{
|
||
|
cse->t_level--;
|
||
|
low_cse = cse->low_tlevel;
|
||
|
if (low_cse && low_cse->t_level == cse->t_level) /* delete the duplicate link */
|
||
|
{
|
||
|
lower_cse = low_cse->low_tlevel;
|
||
|
assert((low_cse->done && low_cse->new_buff) || (n_gds_t_op < cse->mode));
|
||
|
if (lower_cse)
|
||
|
{
|
||
|
assert(lower_cse->t_level < cse->t_level);
|
||
|
lower_cse->high_tlevel = cse;
|
||
|
cse->low_tlevel = lower_cse;
|
||
|
if (!cse->new_buff)
|
||
|
{ /* if we never needed to build in the new level, copy the built copy
|
||
|
* (if any) of the older level before going back to that level
|
||
|
*/
|
||
|
assert(!cse->done);
|
||
|
cse->new_buff = low_cse->new_buff;
|
||
|
} else if (low_cse->new_buff)
|
||
|
free_element(si->new_buff_list, (char *)low_cse->new_buff);
|
||
|
free_element(si->tlvl_cw_set_list, (char *)low_cse);
|
||
|
orig_cse = cse;
|
||
|
} else
|
||
|
{ /* In this case, there are only two elements in the horizontal list out of
|
||
|
* which we are going to delete one. We prefer to copy the second link into
|
||
|
* the first and delete the second (rather than simply deleting the first), since
|
||
|
* the first element may be an intermediate element in the vertical list and
|
||
|
* buddy list wont permit use of both free_element() and free_last_n_elements()
|
||
|
* with a given list together. This might disturb the tp_srch_status->cse, so
|
||
|
* reset it properly. Note that if cse->mode is gds_t_create, there will be no
|
||
|
* tp_srch_status entry allotted for cse->blk (one will be there only for the
|
||
|
* chain.flag representation of this to-be-created block). Same case with mode of
|
||
|
* kill_t_create as it also corresponds to a non-existent block#. Therefore dont
|
||
|
* try looking up the hashtable for this block in those cases.
|
||
|
*/
|
||
|
assert((gds_t_create == cse->mode) || (kill_t_create == cse->mode)
|
||
|
|| (gds_t_write == cse->mode) || (kill_t_write == cse->mode));
|
||
|
if ((gds_t_create != cse->mode) && (kill_t_create != cse->mode))
|
||
|
{
|
||
|
if (NULL != (tabent = lookup_hashtab_int4(si->blks_in_use,
|
||
|
(uint4 *)&cse->blk)))
|
||
|
tp_srch_status = tabent->value;
|
||
|
else
|
||
|
tp_srch_status = NULL;
|
||
|
assert(!tp_srch_status || tp_srch_status->cse == cse);
|
||
|
if (tp_srch_status)
|
||
|
tp_srch_status->cse = low_cse;
|
||
|
}
|
||
|
assert(low_cse == orig_cse);
|
||
|
/* Members that may not be uptodate in cse need to be copied back from low_cse.
|
||
|
* They are next_cw_set, prev_cw_set, new_buff and done.
|
||
|
*/
|
||
|
prev_cse = low_cse->prev_cw_set;
|
||
|
next_cse = low_cse->next_cw_set;
|
||
|
if (!cse->new_buff)
|
||
|
{ /* if we never needed to build in the new level, copy the
|
||
|
* built copy of the older level before going back to that level
|
||
|
*/
|
||
|
assert(!cse->done);
|
||
|
cse->new_buff = low_cse->new_buff;
|
||
|
} else if (low_cse->new_buff)
|
||
|
free_element(si->new_buff_list, (char *)low_cse->new_buff);
|
||
|
memcpy(low_cse, cse, SIZEOF(cw_set_element));
|
||
|
low_cse->next_cw_set = next_cse;
|
||
|
low_cse->prev_cw_set = prev_cse;
|
||
|
low_cse->high_tlevel = NULL;
|
||
|
low_cse->low_tlevel = NULL;
|
||
|
free_element(si->tlvl_cw_set_list, (char *)cse);
|
||
|
orig_cse = low_cse;
|
||
|
}
|
||
|
} else
|
||
|
assert(low_cse || orig_cse == cse);
|
||
|
}
|
||
|
}/* for (cse) */
|
||
|
|
||
|
/* delete the tlvl_info for this t_level */
|
||
|
for (tli = si->tlvl_info_head; tli; tli = tli->next_tlevel_info)
|
||
|
{
|
||
|
if (tli->t_level >= dollar_tlevel)
|
||
|
break;
|
||
|
prev_tli = tli;
|
||
|
}
|
||
|
assert(!tli || !tli->next_tlevel_info);
|
||
|
if (prev_tli)
|
||
|
prev_tli->next_tlevel_info = NULL;
|
||
|
else
|
||
|
si->tlvl_info_head = NULL;
|
||
|
if (tli)
|
||
|
free_last_n_elements(si->tlvl_info_list, 1);
|
||
|
|
||
|
}/* for (si) */
|
||
|
/* delete the global (across all segments) tlvl info for this t_level */
|
||
|
for (prev_gtli = NULL, gtli = global_tlvl_info_head; gtli; gtli = gtli->next_global_tlvl_info)
|
||
|
{
|
||
|
if (dollar_tlevel <= gtli->t_level)
|
||
|
break;
|
||
|
prev_gtli = gtli;
|
||
|
}
|
||
|
assert(!global_tlvl_info_head || gtli);
|
||
|
assert(!gtli || !gtli->next_global_tlvl_info);
|
||
|
assert(!prev_gtli || (gtli && (dollar_tlevel == gtli->t_level)));
|
||
|
FREE_GBL_TLVL_INFO(gtli);
|
||
|
if (prev_gtli)
|
||
|
prev_gtli->next_global_tlvl_info = NULL;
|
||
|
else
|
||
|
global_tlvl_info_head = NULL;
|
||
|
}
|