File: secshr_finish_CMT18_to_CMT19.c

package info (click to toggle)
fis-gtm 6.3-007-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 36,284 kB
  • sloc: ansic: 328,861; asm: 5,182; csh: 5,102; sh: 1,918; awk: 291; makefile: 69; sed: 13
file content (182 lines) | stat: -rw-r--r-- 6,661 bytes parent folder | download
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/****************************************************************
 *								*
 * Copyright (c) 2017 Fidelity National Information		*
 * Services, Inc. and/or its subsidiaries. All rights reserved.	*
 *								*
 *	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 "add_inter.h"
#include "gdsbt.h"
#include "gdsblk.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "gdscc.h"
#include "gdskill.h"
#include "copy.h"
#include "jnl.h"
#include "buddy_list.h"		/* needed for tp.h */
#include "hashtab_int4.h"	/* needed for tp.h */
#include "tp.h"
#include "repl_msg.h"		/* needed for jnlpool_addrs_ptr_t */
#include "gtmsource.h"		/* needed for jnlpool_addrs_ptr_t */
#include "secshr_db_clnup.h"
#include "sec_shr_blk_build.h"
#include "cert_blk.h"		/* for CERT_BLK_IF_NEEDED macro */
#include "interlock.h"
#include "relqueopi.h"		/* for INSQTI and INSQHI macros */
#include "caller_id.h"
#include "db_snapshot.h"
#include "gdsbgtr.h"

GBLREF	cw_set_element		cw_set[];
GBLREF	unsigned char		cw_set_depth;
GBLREF	trans_num		start_tn;
GBLREF	unsigned int		cr_array_index;
#ifdef DEBUG
GBLREF	cache_rec_ptr_t		cr_array[]; /* Maximum number of blocks that can be in transaction */
#endif

GBLREF	uint4			process_id;

error_def(ERR_WCBLOCKED);

void secshr_finish_CMT18_to_CMT19(sgmnt_addrs *csa)
{
	boolean_t		is_bg;
	cache_rec_ptr_t		cr;
	char			*wcblocked_ptr;
	cw_set_element		*cs, *cs_ptr, *cs_top, *first_cw_set, *next_cs;
	node_local_ptr_t	cnl;
	sgm_info		*si;
	sgmnt_data_ptr_t	csd;
	sm_uc_ptr_t		blk_ptr;
	trans_num		currtn;
#	ifdef DEBUG
	boolean_t		cr_stopped_seen;
	cache_rec_ptr_t		*crArray;
	unsigned int		crArrayIndex;
#	endif

	if (FALSE == csa->t_commit_crit)	/* Step CMT19 is already done. Nothing more to do. */
		return;
	assert(!csa->now_crit || csa->hold_onto_crit);	/* Caller "secshr_db_clnup" should have ensured we released crit
							 * before coming here. The only exception is if csa->hold_onto_crit
							 * is set (e.g. dse) so account for that in the assert.
							 */
	csd = csa->hdr;
	is_bg = (dba_bg == csd->acc_meth);
	if (!is_bg)
	{	/* Step CMT18 already done as part of CMT10a for MM in "secshr_finish_CMT08_to_CMT14" */
		csa->t_commit_crit = FALSE;	/* Step CMT19 */
		return;	/* If MM, phase2 commit is already done */
	}
	/* Since we are in phase2 of commit (don't have crit), use value stored in "start_tn" or "si->start_tn" as currtn */
	if (dollar_tlevel)
	{
		si = csa->sgm_info_ptr;
		first_cw_set = si->first_cw_set;
		currtn = si->start_tn;	/* tn at which phase1 happened in crit */
	} else
	{
		first_cw_set = (0 != cw_set_depth) ? cw_set : NULL;
		currtn = start_tn;	/* tn at which phase1 happened in crit */
	}
	if (NULL != first_cw_set)
	{
		assert(T_COMMIT_CRIT_PHASE2 == csa->t_commit_crit);
		assert(currtn < csa->ti->curr_tn);
		cnl = csa->nl;
		cs = first_cw_set;
		cs_top = (dollar_tlevel ? NULL : (cs + cw_set_depth));
		DEBUG_ONLY(cr_stopped_seen = FALSE;)
		for (next_cs = cs; cs_top != cs; cs = next_cs)
		{
			if (dollar_tlevel)
			{
				next_cs = next_cs->next_cw_set;
				TRAVERSE_TO_LATEST_CSE(cs);
			} else
				next_cs = cs + 1;
#			ifdef DEBUG
			if ((NULL != cs->cr) && (0 != cs->cr->stopped))
				cr_stopped_seen = TRUE;
#			endif
			if (gds_t_committed == cs->mode)
				continue;
			/* At this point, a positive value of "cs->old_mode" implies phase1 did not complete on "cs".
			 * This is possible for example if "secshr_finish_CMT08_to_CMT14" could not find a cr in the
			 * global buffers for this cs. In that case, skip this cr. Error messages corresponding to this
			 * missed block commit would have been recorded in "secshr_finish_CMT08_to_CMT14".
			 * There is one more possibility and that is if it there was a cse with mode > gds_t_committed
			 * (for example gds_t_write_root etc.) and phase1 was finished in t_end/tp_tend but an error occurred
			 * in phase2 when "secshr_db_clnup" took control. In that case, t_end/tp_tend would have set cs->old_mode
			 * to a positive value but that should be > gds_t_committed. Assert that.
			 */
			if (0 <= cs->old_mode)
			{
				assert(gds_t_committed < cs->old_mode);
				continue;
			}
			assert(gds_t_writemap != cs->mode);
			cr = cs->cr;
			ASSERT_IS_WITHIN_SHM_BOUNDS((sm_uc_ptr_t)cr, csa);
			blk_ptr = (sm_uc_ptr_t)GDS_ANY_REL2ABS(csa, cr->buffaddr);
			if (0 != secshr_finish_CMT18(csa, csd, is_bg, cs, blk_ptr, currtn))
				continue;	/* error during CMT18, move on to next cs */
		}
#		ifdef DEBUG
		if (!cr_stopped_seen)
		{	/* We did not pick any crs in "secshr_finish_CMT08_to_CMT14" (those with cr->stopped non-zero).
			 * This means we can be sure when phase2 of commit is done, all crs have been unpinned. Assert accordingly.
			 */
			if (dollar_tlevel)
			{
				crArray = si->cr_array;
				crArrayIndex = si->cr_array_index;
			} else
			{
				crArray = cr_array;
				crArrayIndex = cr_array_index;
			}
			ASSERT_CR_ARRAY_IS_UNPINNED(csd, crArray, crArrayIndex);
		}
#		endif
		if (dollar_tlevel)
			si->cr_array_index = 0;
		else
			cr_array_index = 0; /* Take this opportunity to reset cr_array_index */
		/* Now that phase2 of commit (all block builds) is done, set wc_blocked to trigger cache recovery */
		/* If csa->t_commit_crit is TRUE, even if csa->now_crit is FALSE, we might need cache
		 * cleanup (e.g. cleanup of orphaned cnl->wcs_phase2_commit_pidcnt counter in case
		 * a process gets shot in the midst of DECR_WCS_PHASE2_COMMIT_PIDCNT macro before
		 * decrementing the shared counter but after committing the transaction otherwise)
		 * so set wc_blocked.
		 */
		SET_TRACEABLE_VAR(cnl->wc_blocked, TRUE);
		wcblocked_ptr = WCBLOCKED_PHASE2_CLNUP_LIT;
		BG_TRACE_PRO_ANY(csa, wcb_secshr_db_clnup_phase2_clnup);
		send_msg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_WCBLOCKED, 6, LEN_AND_STR(wcblocked_ptr),
			process_id, &csd->trans_hist.curr_tn, DB_LEN_STR(csa->region));
		/* Now that wc_blocked has been set, clean up the phase2 commit for this pid */
		if (csa->wcs_pidcnt_incremented)
			DECR_WCS_PHASE2_COMMIT_PIDCNT(csa, cnl);
		/* Phase 2 commits are completed for the current region. See if we had done a snapshot
		 * init (csa->snapshot_in_prog == TRUE). If so, try releasing the resources obtained
		 * while snapshot init.
		 */
		if (SNAPSHOTS_IN_PROG(csa))
		{
			assert(NULL != first_cw_set);
			SS_RELEASE_IF_NEEDED(csa, cnl);
		}
	}
	csa->t_commit_crit = FALSE;	/* Step CMT19 */
}