File: repl_instance.h

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 (262 lines) | stat: -rw-r--r-- 14,205 bytes parent folder | download | duplicates (2)
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/****************************************************************
 *								*
 * Copyright (c) 2001-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.	*
 *								*
 ****************************************************************/

#ifndef REPL_INSTANCE_INCLUDED
#define REPL_INSTANCE_INCLUDED

/* MAJOR format of the instance file; Any change to this means recreating instance file.
 * This needs to be changed whenever the layout of the instance file (file header and/or contents) changes in a major way.
 */
#define GDS_REPL_INST_LABEL 		"GDSRPLUNX05"
#define GDS_REPL_INST_LABEL_SZ		12

/* The current MINOR version. Changes to this would mean an on-the-fly upgrade of the instance file.
 * This needs to be changed whenever the changes to the file header layout of the instance file are small enough
 * that it is possible to do an online upgrade of the file header.
 */
#define GDS_REPL_INST_MINOR_LABEL 	1	/* can go upto 255 at which point the major version has to change */

#define	IN_REPL_INST_EDIT_FALSE		FALSE	/* to indicate we are not in a MUPIP REPLIC -EDITINSTANCE */
#define	IN_REPL_INST_EDIT_TRUE		TRUE	/* to indicate we are MUPIP REPLIC -EDITINSTANCE */
#define	IN_REPL_INST_EDIT_CHANGE_OFFSET	2	/* to indicate we are in MUPIP REPLIC -EDITINSTANCE -CHANGE */

/* Replication Instance file format
 *
 *	[size =  512 bytes] File-Header structure "repl_inst_hdr" (size 512 bytes)
 *	[size = 1024 bytes] Array of 16 "gtmsrc_lcl" structures (each size 64 bytes)
 *	[size = 64*n bytes] Variable-length Array of structure "repl_histinfo" (each size 64 bytes)
 *		Each "repl_histinfo" defines the beginning of a range of seqnos (identified by the "start_seqno" field)
 *		that was received from a particular invocation of a root primary instance. The range ends with the
 *		"start_seqno" field of the next histinfo record.
 * Note: "repl_histinfo" structure is defined in mdef.h (not in this file).
 *
 * An uptodate copy of the fixed length section of the instance file (file header and array of gtmsrc_lcl structures)
 * is maintained in the journal pool. The file on disk is not as uptodate but periodically flushed.
 */

#define DEF_INST_FN "mumps.repl"

typedef struct repl_inst_hdr_struct
{
	unsigned char	label[GDS_REPL_INST_LABEL_SZ];	/* format of instance file. initialized to GDS_REPL_INST_LABEL */
	unsigned char	replinst_minorver;		/* minor version of the GT.M release that last touched this file */
	unsigned char	is_little_endian;		/* TRUE if little-endian, FALSE if big-endian */
	unsigned char	is_64bit;			/* TRUE if created by 64-bit GT.M, FALSE if created by 32-bit GT.M */
	unsigned char	filler_16[1];
	int4		jnlpool_semid;			/* id of IPC_PRIVATE semaphore created for jnlpool */
	int4		jnlpool_shmid;			/* id of IPC_PRIVATE shared memory created for jnlpool */
	int4		recvpool_semid;			/* id of IPC_PRIVATE semaphore created for recvpool */
	int4		recvpool_shmid;			/* id of IPC_PRIVATE semaphore created for recvpool */
	/* All time fields have a NON_GTM64_ONLY filler so all fields in the file header start
	 * at the same offset irrespective of whether time_t is 4-bytes or 8-bytes.
	 */
	time_t		jnlpool_semid_ctime;		/* creation time of IPC_PRIVATE semaphore for jnlpool */
	NON_GTM64_ONLY(int4	filler8bytealign_1;)
	time_t		jnlpool_shmid_ctime;		/* creation time of IPC_PRIVATE shared memory for jnlpool */
	NON_GTM64_ONLY(int4	filler8bytealign_2;)
	time_t		recvpool_semid_ctime;		/* creation time of IPC_PRIVATE semaphore for recvpool */
	NON_GTM64_ONLY(int4	filler8bytealign_3;)
	time_t		recvpool_shmid_ctime;		/* creation time of IPC_PRIVATE shared memory for recvpool */
	NON_GTM64_ONLY(int4	filler8bytealign_4;)
	repl_inst_uuid	inst_info;		/* Initialized at instance file creation time */
	repl_inst_uuid	lms_group_info;		/* Set to NULL at instance file creation time;
						 * Set to a non-NULL value ONLY IF current value is NULL and
						 *	a) the instance is brought up as a rootprimary.
						 *		In this case, the value is inherited from the "inst_info" field
						 *		of the current instance file
						 *	OR
						 *	b) the instance is brought up as a propagating primary.
						 *		In this case, the value is inherited from the "lms_group_info"
						 *		field of the instance file from the root primary instance
						 *		that this instance connects to directly or indirectly (through
						 *		a sequence of propagating primary instances in between).
						 */
	seq_num		jnl_seqno;		/* Holds the current seqno of the instance when the journal pool was last shutdown.
						 * Compared with db reg_seqno at open time to check if both are in sync.
						 */
	uint4		root_primary_cycle;	/* Incremented every time this instance is brought up as root primary */
	int4		num_histinfo;		/* Number of histinfo records currently USED in this file. Usually incremented as
						 * new histinfo records get added to the file. Usually maintained in tandem with
						 * "num_alloc_histinfo". When MUPIP ROLLBACK virtually truncates the histinfo
						 * history it only updates this field to reflect the decrement.
						 */
	int4		num_alloc_histinfo;	/* Actual number of histinfo record slots ALLOCATED in this file. Incremented
						 * whenever a new histinfo record is allocated at the end of the instance file.
						 * Not incremented if a new histinfo record reuses virtually truncated space
						 * (possible by MUPIP ROLLBACK). This field is never decremented.
						 */
	boolean_t	crash;			/* This is set to TRUE if the journal pool exists and set to FALSE whenever
						 * it is cleanly shutdown. Used to identify abnormal shutdowns and require rollback.
						 */
	boolean_t	was_rootprimary;	/* Set to TRUE when this instance starts up as a root primary. Set to FALSE when
						 * this instance is brought up as a propagating primary and the receiver server
						 * connects to the new primary source server successfully.
						 */
	boolean_t	is_supplementary;	/* Whether this instance is a supplementary instance or not */
	int4		last_histinfo_num[MAX_SUPPL_STRMS];	/* Maintained whether "is_supplementary" is TRUE or FALSE.
								 * the slot number corresponding to the most recent history record
							 	 * written for each stream */
	seq_num		strm_seqno[MAX_SUPPL_STRMS];		/* Maintained only if "is_supplementary" is TRUE.
								 * The current jnl seqno of each stream when the jnl pool was last
								 * shutdown. Used to initialize similarly-named field in the
								 * jnlpool_ctl structure at jnlpool_init time. Not as frequently
								 * updated/maintained as the jnlpool_ctl->strm_seqno[] field */
	repl_inst_uuid	strm_group_info[MAX_SUPPL_STRMS - 1];	/* Maintained only if "is_supplementary" is TRUE.
								 * The "lms_group_info" field of the non-supplementary source
								 * that connects to this supplementary root primary instance.
								 * Initialized by a -UPDATERESYNC= receiver server startup on a
								 * supplementary root primary instance. Used by the receiver server
								 * on the supplementary instance when it connects to a source
								 * server from the non-supplementary instance. Note: We dont need
								 * this for the 0th stream as its group info is the "lms_group_info"
								 * member of the instance file header. Hence the MAX_SUPPL_STRMS-1.
								 */
	boolean_t	file_corrupt;		/* Set to TRUE by online rollback at start up. Set to FALSE when online rollback
						 * completes successfully.
						 */
	boolean_t	filler_ftok_counter_halted;/* Used only in V6.3-000. Kept as a filler to be safe */
	boolean_t	qdbrundown;		/* TRUE if -QDBRUNDOWN was specified at time of instance file creation.
						 * FALSE otherwise.
						 */
	unsigned char   filler_1024[44];
} repl_inst_hdr;

/* Any changes to the following structure might have to be reflected in "gtmsource_local_struct" structure in gtmsource.h as well.
 * All fields here have a corresponding parallel field in the latter structure.
 */
typedef struct gtmsrc_lcl_struct
{
	unsigned char	secondary_instname[MAX_INSTNAME_LEN];	/* Secondary instance corresponding to this structure */
	seq_num		resync_seqno;				/* Next seqno to be sent from this primary instance.
								 * Maintained in parallel with "read_jnl_seqno" in the corresponding
								 * gtmsource_local structure in the journal pool.
								 */
	seq_num		connect_jnl_seqno;			/* jnl_seqno of the instance when last connection with secondary
								 * was made. Used to determine least recently used slot for reuse */
	unsigned char	filler_64[32];				/* For future expansion */
} gtmsrc_lcl;

#define	COPY_GTMSOURCELOCAL_TO_GTMSRCLCL(sourcelocal, srclcl)							\
{														\
	memcpy(&(srclcl)->secondary_instname[0], &(sourcelocal)->secondary_instname[0], MAX_INSTNAME_LEN - 1);	\
	(srclcl)->resync_seqno = (sourcelocal)->read_jnl_seqno;							\
	(srclcl)->connect_jnl_seqno = (sourcelocal)->connect_jnl_seqno;						\
}

#define	COPY_GTMSRCLCL_TO_GTMSOURCELOCAL(srclcl, sourcelocal)							\
{														\
	memcpy(&(sourcelocal)->secondary_instname[0], &(srclcl)->secondary_instname[0], MAX_INSTNAME_LEN - 1);	\
	(sourcelocal)->read_jnl_seqno = (srclcl)->resync_seqno;							\
	(sourcelocal)->connect_jnl_seqno = (srclcl)->connect_jnl_seqno;						\
}

#define	COPY_JCTL_STRMSEQNO_TO_INSTHDR_IF_NEEDED								\
{														\
	int				idx;									\
	GBLREF	jnlpool_addrs_ptr_t	jnlpool;	/* used by the below macro */				\
														\
	/* Keep the file header copy of "strm_seqno" uptodate with jnlpool_ctl */				\
	if (jnlpool->repl_inst_filehdr->is_supplementary)							\
	{													\
		for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)							\
			jnlpool->repl_inst_filehdr->strm_seqno[idx] = jnlpool->jnlpool_ctl->strm_seqno[idx];	\
	}													\
}

/* The below assert ensures that on a supplementary instance, an update to any stream only occurs if there is a history record
 * corresponding to that stream in the instance file. If this is not the case, those history-less updates will have no way of
 * being replicated (propagated downstream) from this instance as there is no history record to identify the update originator.
 */
#define	ASSERT_INST_FILE_HDR_HAS_HISTREC_FOR_STRM(STRM_IDX, JNLPOOL)					\
{													\
	assert(INVALID_HISTINFO_NUM != JNLPOOL->repl_inst_filehdr->last_histinfo_num[STRM_IDX]);	\
}

#define	OK_TO_LOG_FALSE		FALSE
#define	OK_TO_LOG_TRUE		TRUE

#define INST_NOT_GLD			(struct gd_addr_struct *)1
#define IS_INST_FROM_GLD(REPL_GLD)	(INST_NOT_GLD != REPL_GLD)	/* where repl_inst_get_name found instance file name */

#define GET_INSTFILE_NAME(sendmsg, err_act)										\
{															\
	if (((SS_NORMAL == (status = TRANS_LOG_NAME(&log_nam, &trans_name, temp_inst_fn,				\
					SIZEOF(temp_inst_fn), sendmsg))) || (inst_from_gld && (SS_NOLOGNAM == status)))	\
		&& (0 != trans_name.len))										\
	{														\
		temp_inst_fn[trans_name.len] = '\0';									\
		if (!get_full_path(trans_name.addr, trans_name.len, fn, fn_len, bufsize, &ustatus) && err_act)		\
		{													\
			gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_REPLINSTACC, 2, trans_name.len, trans_name.addr,	\
				ERR_TEXT, 2, RTS_ERROR_LITERAL("full path could not be found"), ustatus);		\
		} else													\
			ret = TRUE;											\
	}														\
}

#define SETUP_INST_INFO(GDPTR, LOGNAM, INSTFROMGLD)			\
{									\
	if (IS_MUMPS_IMAGE && GDPTR && GDPTR->instinfo)			\
	{	/* use global directory information */			\
		LOGNAM.addr = GDPTR->instinfo->instfilename;		\
		LOGNAM.len = STRLEN(GDPTR->instinfo->instfilename);	\
		INSTFROMGLD = TRUE;					\
	} else								\
	{								\
		LOGNAM.addr = GTM_REPL_INSTANCE;			\
		LOGNAM.len = SIZEOF(GTM_REPL_INSTANCE) - 1;		\
		INSTFROMGLD = FALSE;					\
	}								\
}

typedef enum {
	return_on_error,
	issue_rts_error,
	issue_gtm_putmsg
} instname_act;

/* return and gd_ptr are really gd_addr * but gdsfhead.h would be needed */
struct gd_addr_struct	*repl_inst_get_name(char *, unsigned int *, unsigned int, instname_act error_action,
						struct gd_addr_struct *gd_ptr);
void		repl_inst_create(void);
void		repl_inst_edit(void);
void		repl_inst_read(char *fn, off_t offset, sm_uc_ptr_t buff, size_t buflen);
void		repl_inst_write(char *fn, off_t offset, sm_uc_ptr_t buff, size_t buflen);
void		repl_inst_sync(char *fn);
void		repl_inst_jnlpool_reset(void);
void		repl_inst_recvpool_reset(void);
void		repl_inst_ftok_sem_lock(void);
void		repl_inst_ftok_sem_release(void);
int4		repl_inst_histinfo_get(int4 index, repl_histinfo *histinfo);
int4		repl_inst_histinfo_find_seqno(seq_num seqno, int4 strm_idx, repl_histinfo *histinfo);
int4		repl_inst_wrapper_histinfo_find_seqno(seq_num seqno, int4 strm_idx, repl_histinfo *local_histinfo);
void		repl_inst_histinfo_add(repl_histinfo *histinfo);
seq_num		repl_inst_histinfo_truncate(seq_num rollback_seqno);
void		repl_inst_flush_filehdr(void);
void		repl_inst_flush_gtmsrc_lcl(void);
void		repl_inst_flush_jnlpool(boolean_t reset_recvpool_fields, boolean_t reset_crash);
boolean_t	repl_inst_was_rootprimary(void);
int4		repl_inst_reset_zqgblmod_seqno_and_tn(void);

boolean_t	gtmsource_get_cmp_info(int4 *repl_zlib_cmp_level_ptr);
void            repl_cmp_solve_src_timeout(void);
void            repl_cmp_solve_rcv_timeout(void);
boolean_t	gtmsource_get_instance_info(boolean_t *secondary_was_rootprimary, seq_num *strm_jnl_seqno);
boolean_t	gtmsource_get_remote_histinfo(seq_num seqno, repl_histinfo *histinfo);
boolean_t	gtmsource_check_remote_strm_histinfo(seq_num seqno, boolean_t *rollback_first);
void		gtmsource_histinfo_get(int4 index, repl_histinfo *histinfo);
boolean_t	gtmsource_is_histinfo_identical(repl_histinfo *remote_histinfo, repl_histinfo *local_histinfo,
										seq_num jnl_seqno, boolean_t ok_to_log);
seq_num		gtmsource_find_resync_seqno(repl_histinfo *local_histinfo, repl_histinfo *remote_histinfo);
void		gtmsource_set_next_histinfo_seqno(boolean_t detect_new_histinfo);

#endif /* REPL_INSTANCE_INCLUDED */