File: dbinit_ch.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 (158 lines) | stat: -rwxr-xr-x 5,354 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
/****************************************************************
 *								*
 * Copyright (c) 2001-2018 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 "gtm_ipc.h"

#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "gtm_unistd.h"

#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "error.h"
#include "filestruct.h"
#include "gvcst_protos.h"
#include "jnl.h"
#include "do_semop.h"
#include "mmseg.h"
#include "ipcrmid.h"
#include "util.h"
#include "ftok_sems.h"
#include "gtmimagename.h"
#include "gtmio.h"
#include "have_crit.h"

GBLREF gd_region		*db_init_region;

error_def(ERR_VERMISMATCH);

CONDITION_HANDLER(dbinit_ch)
{
	START_CH(TRUE);
	db_init_err_cleanup(FALSE);
	NEXTCH
}

void db_init_err_cleanup(boolean_t retry_dbinit)
{
	unix_db_info		*udi;
	gd_segment		*seg;
	sgmnt_addrs		*csa;
	int			rc, lcl_new_dbinit_ipc;
	boolean_t		ftok_counter_halted, access_counter_halted, decrement_ftok_counter;

	/* Here, we can not rely on the validity of csa->hdr because this function can be triggered anywhere in db_init().Because
	 * we don't have access to file header, we can not know if counters are disabled so we go by our best guess, not disabled,
	 * during cleanup.
	 */
	assert(NULL != db_init_region);
	seg = db_init_region->dyn.addr;
	udi = NULL;
	if (NULL != seg->file_cntl)
		udi = FILE_INFO(db_init_region);
	if (NULL != udi)
	{
		if (FD_INVALID != udi->fd && !retry_dbinit)
			CLOSEFILE_RESET(udi->fd, rc);	/* resets "udi->fd" to FD_INVALID */
		assert(FD_INVALID == udi->fd || retry_dbinit);
		csa = &udi->s_addrs;
#		ifdef _AIX
		if ((NULL != csa->hdr) && (dba_mm == db_init_region->dyn.addr->acc_meth))
		{
			assert((NULL != csa->db_addrs[1]) && (csa->db_addrs[1] > csa->db_addrs[0]));
			munmap((caddr_t)csa->db_addrs[0], (size_t)(csa->db_addrs[1] - csa->db_addrs[0]));
		}
#		endif
		if (NULL != csa->jnl)
		{
			free(csa->jnl);
			csa->jnl = NULL;
		}
		/* If shared memory is not available or if this is a VERMISMATCH error situation (where we do not know the exact
		 * position of csa->nl->ftok_counter_halted or if it even exists in the other version), we have to be pessimistic
		 * and assume the counters are halted. This avoids prematurely removing the semaphores.
		 */
		if ((NULL != csa->nl) && ((int)ERR_VERMISMATCH != SIGNAL))
		{
			ftok_counter_halted = csa->nl->ftok_counter_halted;
			access_counter_halted = csa->nl->access_counter_halted;
			if (csa->now_crit)
			{	/* Ensure that we don't hold crit before detaching shared memory */
				assert(!csa->now_crit);
				rel_crit(db_init_region);
			}
			shmdt((caddr_t)csa->nl);
			csa->nl = (node_local_ptr_t)NULL;
		} else
		{
			ftok_counter_halted = TRUE;
			access_counter_halted = TRUE;
		}
		if (udi->shm_created && (INVALID_SHMID != udi->shmid))
		{
			shm_rmid(udi->shmid);
			udi->shmid = INVALID_SHMID;
			udi->shm_created = FALSE;
		}
		if (udi->sem_created && (INVALID_SEMID != udi->semid))
		{
			sem_rmid(udi->semid);
			udi->semid = INVALID_SEMID;
			udi->sem_created = FALSE;
			udi->grabbed_access_sem = FALSE;
			udi->counter_acc_incremented = FALSE;
		}
		if (udi->counter_acc_incremented && !access_counter_halted)
		{
			assert((INVALID_SEMID != udi->semid) && !db_init_region->read_only);
			/* decrement the read-write sem */
			do_semop(udi->semid, DB_COUNTER_SEM, -DB_COUNTER_SEM_INCR, SEM_UNDO | IPC_NOWAIT);
			udi->counter_acc_incremented = FALSE;
		}
		if (udi->grabbed_access_sem)
		{
			do_semop(udi->semid, DB_CONTROL_SEM, -1, SEM_UNDO | IPC_NOWAIT); /* release the startup-shutdown sem */
			udi->grabbed_access_sem = FALSE;
		}
		decrement_ftok_counter = udi->counter_ftok_incremented
						? (ftok_counter_halted ? DECR_CNT_SAFE : DECR_CNT_TRUE)
						: DECR_CNT_FALSE;
		if (udi->grabbed_ftok_sem)
		{
			ftok_sem_release(db_init_region, decrement_ftok_counter, TRUE);
			assert(FALSE == udi->counter_ftok_incremented);
		} else if (udi->counter_ftok_incremented)
			do_semop(udi->ftok_semid, DB_COUNTER_SEM, -DB_COUNTER_SEM_INCR, SEM_UNDO | IPC_NOWAIT);
		/* Below reset needed for "else if" case above but do it for "if" case too (in pro) just in case */
		udi->counter_ftok_incremented = FALSE;
		udi->grabbed_ftok_sem = FALSE;
		if (!IS_GTCM_GNP_SERVER_IMAGE && !retry_dbinit) /* gtcm_gnp_server reuses file_cntl */
		{
			free(seg->file_cntl->file_info);
			free(seg->file_cntl);
			seg->file_cntl = NULL;
		}
	}
	/* Enable interrupts in case we are here with intrpt_ok_state == INTRPT_IN_GVCST_INIT due to an rts error.
	 * Normally we would have the new state stored in "prev_intrpt_state" but that is not possible here because
	 * the corresponding DEFER_INTERRUPTS happened in gvcst_init.c (a different function) so we have an assert
	 * there that the previous state was INTRPT_OK_TO_INTERRUPT and use that instead of prev_intrpt_state here.
	 */
	if (!retry_dbinit)
		ENABLE_INTERRUPTS(INTRPT_IN_GVCST_INIT, INTRPT_OK_TO_INTERRUPT);
}