fis-gtm/sr_unix/repl_msg.h

434 lines
20 KiB
C
Raw Normal View History

/****************************************************************
* *
2024-07-19 11:43:27 -04:00
* Copyright 2006, 2013 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. *
* *
****************************************************************/
#ifndef _REPL_MSG_H
#define _REPL_MSG_H
enum
{
REPL_INVALID = -1, /* -1 */
REPL_START_JNL_SEQNO = 0, /* 0 */
REPL_TR_JNL_RECS, /* 1 */
REPL_ROLLBACK_FIRST, /* 2 */
REPL_OBSOLETE_WILL_RESTART, /* 3 */ /* Obsoleted effective V4.4-002 since we no longer support dual site config with
* V4.1 versions. But slot# preserved to not perturb other message #s */
REPL_XOFF, /* 4 */
REPL_XON, /* 5 */
REPL_BADTRANS, /* 6 */
REPL_HEARTBEAT, /* 7 */
REPL_FETCH_RESYNC, /* 8 */
REPL_RESYNC_SEQNO, /* 9 */
REPL_OBSOLETE_STOPSRCFILTER, /* 10 */ /* message no longer used but slot# 10 preserved to not perturb other message #s */
REPL_XOFF_ACK_ME, /* 11 */
REPL_XOFF_ACK, /* 12 */
REPL_WILL_RESTART_WITH_INFO, /* 13 */
REPL_MULTISITE_MSG_START, /* 14 */ /* All messages after this are newly introduced for multi-site support only */
REPL_OLD_NEED_INSTANCE_INFO, /* 15 */
REPL_OLD_INSTANCE_INFO, /* 16 */
REPL_NEED_HISTINFO, /* 17 */
REPL_OLD_TRIPLEINFO1, /* 18 */
REPL_OLD_TRIPLEINFO2, /* 19 */
REPL_OLD_TRIPLE, /* 20 */
REPL_INST_NOHIST, /* 21 */
REPL_LOSTTNCOMPLETE, /* 22 */
REPL_CMP_TEST, /* 23 */
REPL_CMP_SOLVE, /* 24 */
REPL_CMP2UNCMP, /* 25 */ /* used to signal a transition to uncompressed messages in case of errors */
REPL_TR_CMP_JNL_RECS, /* 26 */ /* used to send compressed messages whose pre-compressed length is < 2**24 */
REPL_TR_CMP_JNL_RECS2, /* 27 */ /* used to send compressed messages whose pre-compressed length is >= 2**24 */
REPL_NEED_INSTINFO, /* 28 */
REPL_INSTINFO, /* 29 */
REPL_HISTINFO, /* 30 */ /* used to exchange history information as part of a replication handshake */
REPL_HISTREC, /* 31 */ /* sent in the middle of a journal record stream to signal start of new history */
REPL_NEED_STRMINFO, /* 32 */ /* sent by a supplementary source server to a supplementary receiver server */
REPL_STRMINFO, /* 33 */ /* sent in response to a REPL_NEED_STRMINFO message */
2024-07-19 11:43:27 -04:00
REPL_LOGFILE_INFO, /* 34 */ /* sent (at time of handshake) to communicate to one another the $CWD/logfile */
REPL_MSGTYPE_LAST=256 /* 256 */
/* any new message need to be added before REPL_MSGTYPE_LAST */
};
#define REPL_PROTO_VER_UNINITIALIZED (char)0xFF /* -1, the least of the versions to denote an uninitialized version field */
#define REPL_PROTO_VER_DUALSITE (char)0x0 /* Versions GT.M V5.0 and prior that dont support multi site replication */
#define REPL_PROTO_VER_MULTISITE (char)0x1 /* Versions V5.1-000 and above that support multi site replication */
2024-07-19 11:43:27 -04:00
#define REPL_PROTO_VER_MULTISITE_CMP (char)0x2 /* Versions V5.3-003 and above that support multisite replication with
* the ability to compress the logical records in the replication pipe.
*/
2024-07-19 11:43:27 -04:00
#define REPL_PROTO_VER_SUPPLEMENTARY (char)0x3 /* Versions V5.5-000 and above that support supplementary instances */
#define REPL_PROTO_VER_REMOTE_LOGPATH (char)0x4 /* Versions V6.0-003 and above that send remote $CWD as part of handshake */
#define REPL_PROTO_VER_THIS REPL_PROTO_VER_REMOTE_LOGPATH
/* The current/latest version of the communication protocol between the
* primary (source server) and secondary (receiver server or rollback)
*/
2024-07-19 11:43:27 -04:00
/* Below macro defines the maximum size of the replication logfile path information that will be sent across to the other side.
* While the actual path max is defined by GTM_PATH_MAX, the value of GTM_PATH_MAX differ across different platforms and so we
* cannot always be sure if this side can store the remote side's logfile path. Since REPL_LOGFILE_INFO message is sent across
* only during handshake, malloc too is an overkill. So, have a fixed size buffer (see repl_logfile_info_msg_t beow) bounded by
* the below size.
*/
#define REPL_LOGFILE_PATH_MAX 1023
/* A few of these flag bits (e.g. START_FLAG_SRCSRV_IS_VMS) are no longer used but they should not be removed just in case prior
* versions that used those bitslots communicate with a newer version that assigns a different meaning to those slots. Any new
* slot additions need to happen at the end of the list. No replacements of unused slots.
*/
#define START_FLAG_NONE 0x00000000
#define START_FLAG_STOPSRCFILTER 0x00000001
#define START_FLAG_UPDATERESYNC 0x00000002
#define START_FLAG_HASINFO 0x00000004
#define START_FLAG_COLL_M 0x00000008
#define START_FLAG_VERSION_INFO 0x00000010
#define START_FLAG_TRIGGER_SUPPORT 0x00000020
#define START_FLAG_SRCSRV_IS_VMS 0x00000040 /* Obsolete but preserve slot */
#define START_FLAG_NORESYNC 0x00000080
#define MIN_REPL_MSGLEN 32 /* To keep compiler happy with
* the definition of repl_msg_t as well
* as to accommodate a seq_num */
#define REPL_MSG_CMPINFOLEN (SIZEOF(repl_cmpinfo_msg_t))
#define REPL_MSG_CMPDATALEN 256 /* length of data part of message exchanged between source/receiver to test compression */
#define REPL_MSG_CMPDATAMASK 0xff
#define MAX_CMP_EXPAND_FACTOR 2 /* the worst case factor by which compression could actually expand input data */
#define REPL_MSG_CMPEXPDATALEN (MAX_CMP_EXPAND_FACTOR * REPL_MSG_CMPDATALEN)
/* The "datalen" field of the REPL_CMP_SOLVE message is set to the following value by the receiver server in case of errors. */
#define REPL_RCVR_CMP_TEST_FAIL (-1)
#define REPL_MSG_ALIGN 8 /* every message sent across the pipe is expected to be at least 8-byte aligned */
#define REPL_MSG_TYPE (uint4)(SIZEOF(int4))
#define REPL_MSG_LEN (uint4)(SIZEOF(int4))
#define REPL_MSG_HDRLEN (uint4)(REPL_MSG_TYPE + REPL_MSG_LEN) /* For type and len fields */
typedef struct /* Used also to send a message of type REPL_INST_NOHIST */
{
int4 type;
int4 len; /* Is 8-byte aligned for ALL messages except REPL_TR_CMP_JNL_RECS message */
unsigned char msg[MIN_REPL_MSGLEN - REPL_MSG_HDRLEN];
/* All that we need is msg[1], but keep the compiler happy with
* this definition for msg. Also provide space to accommodate a seq_num
* so that a static definition would suffice instead of malloc'ing a
* small message buffer */
} repl_msg_t;
/* To send a REPL_TR_CMP_JNL_RECS type of message, we include the pre-compressed length as part of the 4-byte type field
* to keep the replication message header overhead to the current 8-bytes. Define macros to access those fields.
* If the pre-compressed length cannot fit in 24 bits, then we send a REPL_TR_CMP_JNL_RECS2 message which has 8-more
* byte overhead as part of the replication message header. It is considered ok to take this extra 8-byte hit for huge messages.
* The threshold is defined as 2**23 (instead of 2**24) so we ensure the most significant bit is 0 and does not give us
* problems while doing >> operations (e.g. (((repl_msg_ptr_t)buffp)->type >> REPL_TR_CMP_MSG_TYPE_BITS);
*/
#define REPL_TR_CMP_MSG_TYPE_BITS 8
#define REPL_TR_CMP_MSG_UNCMPLEN_BITS 24
#define REPL_TR_CMP_THRESHOLD (1 << (REPL_TR_CMP_MSG_UNCMPLEN_BITS - 1))
#define REPL_TR_CMP_MSG_TYPE_MASK ((1 << REPL_TR_CMP_MSG_TYPE_BITS) - 1)
/* Defines for sending REPL_TR_CMP_JNL_RECS2 message */
#define REPL_MSG_UNCMPLEN SIZEOF(int4)
#define REPL_MSG_CMPLEN SIZEOF(int4)
#define REPL_MSG_HDRLEN2 (REPL_MSG_HDRLEN + REPL_MSG_UNCMPLEN + REPL_MSG_CMPLEN) /* 16-byte header */
typedef struct /* Used also to send a message of type REPL_TR_CMP_JNL_RECS2 */
{
int4 type;
int4 len;
int4 uncmplen;
int4 cmplen;
unsigned char msg[MIN_REPL_MSGLEN - REPL_MSG_HDRLEN2];
/* All that we need is msg[1], but keep the compiler happy with
* this definition for msg. Also provide space to accommodate a seq_num
* so that a static definition would suffice instead of malloc'ing a
* small message buffer */
} repl_cmpmsg_t;
2024-07-19 11:43:27 -04:00
/* This should ideally match the TCP send/recv buffer size of source/receiver server. However, since the maximum TCP buffer
* varies by system, and on many systems it is less than 2 MB or even 1 MB, we keep GTMRECV_TCP_RECV_BUFSIZE and
* GTMSOURCE_TCP_SEND_BUFSIZE at 1 MB to avoid extra attempts to send/receive TCP packets before the limit is lowered enough
* for the OS to support it.
*/
#define MAX_REPL_MSGLEN (2 * 1024 * 1024)
#define MAX_TR_BUFFSIZE (MAX_REPL_MSGLEN - REPL_MSG_HDRLEN2) /* allow for biggest replication message header */
typedef struct /* used to send a message of type REPL_START_JNL_SEQNO */
{
int4 type;
int4 len;
unsigned char start_seqno[SIZEOF(seq_num)];
uint4 start_flags;
unsigned char jnl_ver;
char proto_ver; /* Needs to be "signed char" in order to be able to do signed comparisons of this with
* the macros REPL_PROTO_VER_DUALSITE (0) and REPL_PROTO_VER_UNINITIALIZED (-1) */
char node_endianness; /* 'L' if this machine is little endian, 'B' if it is big endian */
char is_supplementary; /* TRUE for a supplementary instance; FALSE otherwise */
char filler_32[8];
} repl_start_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_WILL_RESTART_WITH_INFO or REPL_ROLLBACK_FIRST or REPL_RESYNC_SEQNO */
{
int4 type;
int4 len;
unsigned char start_seqno[SIZEOF(seq_num)];
unsigned char jnl_ver;
char start_flags[4];
char proto_ver; /* Needs to be "signed char" in order to be able to do signed comparisons of this with
* the macros REPL_PROTO_VER_DUALSITE (0) and REPL_PROTO_VER_UNINITIALIZED (-1) */
char node_endianness; /* 'L' if this machine is little endian, 'B' if it is big endian */
char is_supplementary; /* TRUE for a supplementary instance; FALSE otherwise */
char filler_32[8];
} repl_start_reply_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_FETCH_RESYNC */
{
int4 type;
int4 len;
seq_num resync_seqno;
char proto_ver; /* Needs to be "signed char" in order to be able to do signed comparisons of this with
* the macros REPL_PROTO_VER_DUALSITE (0) and REPL_PROTO_VER_UNINITIALIZED (-1) */
char node_endianness; /* 'L' if this machine is little endian, 'B' if it is big endian */
char is_supplementary; /* TRUE for a supplementary instance; FALSE otherwise */
char filler_32[13];
} repl_resync_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_OLD_NEED_INSTANCE_INFO */
{
int4 type;
int4 len;
unsigned char instname[MAX_INSTNAME_LEN];
char proto_ver; /* Needs to be "signed char" in order to be able to do signed comparisons of this with
* the macros REPL_PROTO_VER_DUALSITE (0) and REPL_PROTO_VER_UNINITIALIZED (-1) */
char node_endianness; /* 'L' if this machine is little endian, 'B' if it is big endian */
char is_rootprimary; /* Whether the source server that is sending this message is a root primary or not. */
char filler_32[5];
} repl_old_needinst_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_NEED_INSTINFO */
{
int4 type;
int4 len;
unsigned char instname[MAX_INSTNAME_LEN];
repl_inst_uuid lms_group_info;
char proto_ver; /* Needs to be "signed char" in order to be able to do signed comparisons of this with
* the macros REPL_PROTO_VER_DUALSITE (0) and REPL_PROTO_VER_UNINITIALIZED (-1) */
char is_rootprimary; /* Whether the source server that is sending this message is a root primary or not. */
char is_supplementary; /* TRUE for a supplementary instance; FALSE otherwise */
char filler_32[5];
} repl_needinst_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_OLD_INSTANCE_INFO */
{
int4 type;
int4 len;
unsigned char instname[MAX_INSTNAME_LEN]; /* The name of this replication instance */
unsigned char was_rootprimary;
char filler_32[7];
} repl_old_instinfo_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_INSTINFO */
{
int4 type;
int4 len;
unsigned char instname[MAX_INSTNAME_LEN]; /* The name of this replication instance */
seq_num strm_jnl_seqno; /* Whenever a supplementary receiver handshakes with a non-supplementary source,
* the current jnl seqno (which is across all streams) is sent in the initial
* REPL_START_JNL_SEQNO message. Only after the source server sends the
* REPL_NEED_INSTINFO message does the receiver know which non-supplementary stream
* the source corresponds to and can therefore determine the stream specific
* jnl seqno. Once this is known, instead of re-sending the REPL_START_JNL_SEQNO
* message, the receiver sends this new seqno in the "strm_jnl_seqno" field as
* part of the REPL_INSTINFO message. In cases where the receiver is not
* supplementary or if the soruce is supplementary, this field is set to 0.
*/
repl_inst_uuid lms_group_info;
unsigned char was_rootprimary;
char filler_32[7];
} repl_instinfo_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send messages of type REPL_CMP_TEST or REPL_CMP_SOLVE */
{
int4 type;
int4 len;
int4 datalen; /* length of compressed or uncompressed data */
char proto_ver;
char filler_16[3];
char data[REPL_MSG_CMPDATALEN]; /* compressed (if REPL_CMP_TEST) or uncompressed (if REPL_CMP_SOLVE) data */
char overflowdata[(MAX_CMP_EXPAND_FACTOR - 1) * REPL_MSG_CMPDATALEN];
/* buffer to hold overflow in case compression expands data */
} repl_cmpinfo_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_NEED_HISTINFO */
{
int4 type;
int4 len;
seq_num seqno; /* The histinfo requested is that of "seqno-1" */
int4 strm_num; /* used only in case of supplementary instances */
int4 histinfo_num; /* if not INVALID_HISTINFO_NUM, then we want the histinfo_num'th history record
* on the remote side. in this case ignore seqno & strm_num.
*/
char filler_32[8];
} repl_needhistinfo_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_OLD_TRIPLEINFO1 */
{
int4 type;
int4 len;
seq_num start_seqno; /* the starting seqno of the histinfo range */
unsigned char instname[MAX_INSTNAME_LEN];
} repl_histinfo1_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_OLD_TRIPLEINFO2 */
{
int4 type;
int4 len;
seq_num start_seqno; /* the starting seqno of the histinfo range */
uint4 cycle;
int4 histinfo_num;
char filler_32[8];
} repl_histinfo2_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_HISTINFO */
{
int4 type;
int4 len;
repl_histinfo history;
} repl_histinfo_msg_t; /* The first two fields should be as in repl_msg_t */
/* A REPL_OLD_TRIPLE message is sent in such a form that the receiver server can copy it (after removing the 8-byte header
* containing the "type" and "len") as such into the receive pool. The update process treats this content as yet another
* journal record type. Therefore we need to introduce a new journal record type (JRT_TRIPLE) for this purpose and define a
* structure (repl_old_triple_jnl_t) that has this type information and the triple related information. This will then be a
* member of the REPL_OLD_TRIPLE message.
* Note: GT.M versions that support supplementary instances send a REPL_HISTREC message instead of REPL_OLD_TRIPLE.
*/
typedef struct /* sub-structure used to send a message of type REPL_OLD_TRIPLE */
{
uint4 jrec_type : 8; /* This definition is copied from that of "jrec_prefix" */
uint4 forwptr : 24; /* This definition is copied from that of "jrec_prefix" */
uint4 cycle; /* The cycle of the instance at the time of generating this triple */
seq_num start_seqno; /* The starting seqno of the triple range */
unsigned char instname[MAX_INSTNAME_LEN]; /* The instance name that generated this triple */
unsigned char rcvd_from_instname[MAX_INSTNAME_LEN]; /* instance name this triple was received from (on the secondary) */
} repl_old_triple_jnl_t;
typedef struct /* used to send a message of type REPL_OLD_TRIPLE */
{
int4 type;
int4 len;
repl_old_triple_jnl_t triplecontent;
} repl_old_triple_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* sub-structure used to send a message of type REPL_HISTREC */
{
uint4 jrec_type : 8; /* This definition is copied from that of "jrec_prefix" */
uint4 forwptr : 24; /* This definition is copied from that of "jrec_prefix" */
uint4 filler_8byte_align;
repl_histinfo histcontent; /* the structure containing the history information */
} repl_histrec_jnl_t;
typedef struct /* used to send a message of type REPL_HISTREC */
{
int4 type;
int4 len;
repl_histrec_jnl_t histjrec; /* the journal record containing the history information */
} repl_histrec_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_NEED_STRMINFO */
{
int4 type;
int4 len;
seq_num seqno; /* The strminfo requested is that of "seqno-1" */
char filler_32[16];
} repl_needstrminfo_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct /* used to send a message of type REPL_STRMINFO */
{
int4 type;
int4 len;
int4 last_histinfo_num[MAX_SUPPL_STRMS];
} repl_strminfo_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct
{
int4 type;
int4 len;
unsigned char ack_seqno[SIZEOF(seq_num)];
unsigned char ack_time[SIZEOF(gtm_time4_t)];
unsigned char filler_32[12];
} repl_heartbeat_msg_t; /* The first two fields should be as in repl_msg_t */
typedef struct
{
struct
{
sm_off_t fl;
sm_off_t bl;
} que;
repl_heartbeat_msg_t heartbeat;
} repl_heartbeat_que_entry_t;
typedef struct /* Used to send a message of type REPL_BADTRANS or REPL_CMP2UNCMP */
{
int4 type;
int4 len;
seq_num start_seqno; /* The seqno that source server should restart sending from */
char filler_32[16];
} repl_badtrans_msg_t;
2024-07-19 11:43:27 -04:00
typedef struct
{
int4 type;
int4 len;
int4 fullpath_len;
uint4 pid;
char proto_ver;
char filler_32[15]; /* to ensure that at least 32 bytes are sent across (gtmrecv_fetchresync relies on this) */
char fullpath[REPL_LOGFILE_PATH_MAX + 1]; /* + 1 for null-terminator */
} repl_logfile_info_msg_t;
#define REPL_LOGFILE_INFO_MSGHDR_SZ OFFSETOF(repl_logfile_info_msg_t, fullpath[0])
#if defined(__osf__) && defined(__alpha)
# pragma pointer_size(save)
# pragma pointer_size(long)
#endif
typedef repl_msg_t *repl_msg_ptr_t;
typedef repl_cmpmsg_t *repl_cmpmsg_ptr_t;
typedef repl_start_msg_t *repl_start_msg_ptr_t;
typedef repl_start_reply_msg_t *repl_start_reply_msg_ptr_t;
typedef repl_resync_msg_t *repl_resync_msg_ptr_t;
typedef repl_old_needinst_msg_t *repl_old_needinst_msg_ptr_t;
typedef repl_needinst_msg_t *repl_needinst_msg_ptr_t;
typedef repl_old_instinfo_msg_t *repl_old_instinfo_msg_ptr_t;
typedef repl_instinfo_msg_t *repl_instinfo_msg_ptr_t;
typedef repl_needhistinfo_msg_t *repl_needhistinfo_msg_ptr_t;
typedef repl_histinfo1_msg_t *repl_histinfo1_msg_ptr_t;
typedef repl_histinfo2_msg_t *repl_histinfo2_msg_ptr_t;
typedef repl_old_triple_jnl_t *repl_old_triple_jnl_ptr_t;
typedef repl_histrec_jnl_t *repl_histrec_jnl_ptr_t;
typedef repl_histinfo_msg_t *repl_histinfo_msg_ptr_t;
typedef repl_needstrminfo_msg_t *repl_needstrminfo_msg_ptr_t;
typedef repl_strminfo_msg_t *repl_strminfo_msg_ptr_t;
typedef repl_heartbeat_msg_t *repl_heartbeat_msg_ptr_t;
typedef repl_cmpinfo_msg_t *repl_cmpinfo_msg_ptr_t;
#if defined(__osf__) && defined(__alpha)
# pragma pointer_size(restore)
#endif
void gtmsource_repl_send(repl_msg_ptr_t msg, char *msgtypestr, seq_num optional_seqno, int4 optional_strm_num);
void gtmsource_send_new_histrec(void);
void gtmrecv_repl_send(repl_msg_ptr_t msgp, int4 type, int4 len, char *msgtypestr, seq_num optional_seqno);
void gtmrecv_send_histinfo(repl_histinfo *histinfo);
void gtmrecv_check_and_send_instinfo(repl_needinst_msg_ptr_t need_instinfo_msg, boolean_t is_rcvr_srvr);
2024-07-19 11:43:27 -04:00
uint4 repl_logfileinfo_get(char *logfile, repl_logfile_info_msg_t *msgp, boolean_t cross_endian, FILE *logfp);
#endif