1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/****************************************************************
* *
* 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;
}
|