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
|
/****************************************************************
* *
* Copyright (c) 2006-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 "gtm_stdlib.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
#include "gtm_unistd.h"
#include "gtm_fcntl.h"
#include "gtm_stat.h"
#include "gtm_time.h"
#include "gtm_inet.h"
#include <sys/sem.h>
#include <sys/mman.h>
#include <errno.h>
#include "eintr_wrappers.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "cli.h"
#include "gtmrecv.h"
#include "iosp.h"
#include "gtmio.h"
#include "gtm_logicals.h"
#include "trans_log_name.h"
#include "gtmmsg.h"
#include "repl_sem.h"
#include "repl_instance.h"
#include "gtm_rename.h"
GBLREF boolean_t in_repl_inst_create; /* used by repl_inst_read/repl_inst_write */
GBLREF uint4 process_id;
error_def(ERR_FILEEXISTS);
error_def(ERR_FILERENAME);
error_def(ERR_LOGTOOLONG);
error_def(ERR_RENAMEFAIL);
error_def(ERR_REPLINSTACC);
error_def(ERR_REPLINSTNMLEN);
error_def(ERR_REPLINSTNMUNDEF);
error_def(ERR_REPLINSTSTNDALN);
error_def(ERR_TEXT);
/* Description:
* Creates replication instance file.
* Parameters:
* None
* Return Value:
* None
*/
void repl_inst_create(void)
{
unsigned int inst_fn_len;
unsigned short inst_name_len;
int rename_fn_len;
char rename_fn[MAX_FN_LEN + 1];
char inst_fn[MAX_FN_LEN + 1], inst_name[MAX_FN_LEN + 1];
char machine_name[MAX_MCNAMELEN], buff_unaligned[REPL_INST_HDR_SIZE + GTMSRC_LCL_SIZE + 8];
char *buff_8byte_aligned;
int idx, status;
struct stat stat_buf;
repl_inst_hdr_ptr_t repl_instance;
gtmsrc_lcl_ptr_t gtmsrc_lcl_array;
mstr log_nam, trans_name;
uint4 status2;
jnl_tm_t now;
assertpro(repl_inst_get_name(inst_fn, &inst_fn_len, MAX_FN_LEN + 1, issue_rts_error, NULL)); /* rts_error should prevent
* return if there is a problem.
*/
/* Although the maximum length of an instance name is MAX_INSTNAME_LEN-1 characters, the input buffer needs to hold a lot
* more since the input instance name might be longer. Hence inst_name (containing MAX_FN_LEN+1 = 257 bytes) is used.
*/
inst_name_len = 0;
if (cli_present("NAME"))
{
inst_name_len = SIZEOF(inst_name);
if (!cli_get_str("NAME", &inst_name[0], &inst_name_len))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2, RTS_ERROR_TEXT("Error parsing NAME qualifier"));
} else
{
log_nam.addr = GTM_REPL_INSTNAME;
log_nam.len = SIZEOF(GTM_REPL_INSTNAME) - 1;
trans_name.addr = &inst_name[0];
if (SS_NORMAL != (status = TRANS_LOG_NAME(&log_nam, &trans_name, inst_name, SIZEOF(inst_name),
dont_sendmsg_on_log2long)))
{
if (SS_LOG2LONG == status)
rts_error_csa(CSA_ARG(NULL)
VARLSTCNT(5) ERR_LOGTOOLONG, 3, log_nam.len, log_nam.addr, SIZEOF(inst_name) - 1);
else
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_REPLINSTNMUNDEF);
}
inst_name_len = trans_name.len;
}
if ((MAX_INSTNAME_LEN <= inst_name_len) || (0 == inst_name_len))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_REPLINSTNMLEN, 2, inst_name_len, inst_name);
inst_name[inst_name_len] = '\0';
buff_8byte_aligned = &buff_unaligned[0];
buff_8byte_aligned = (char *)ROUND_UP2((INTPTR_T)buff_8byte_aligned, 8);
repl_instance = (repl_inst_hdr_ptr_t)&buff_8byte_aligned[0];
gtmsrc_lcl_array = (gtmsrc_lcl_ptr_t)&buff_8byte_aligned[REPL_INST_HDR_SIZE];
memset(machine_name, 0, SIZEOF(machine_name));
if (GETHOSTNAME(machine_name, MAX_MCNAMELEN, status))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_TEXT, 2, RTS_ERROR_TEXT("Unable to get the hostname"), errno);
STAT_FILE(inst_fn, &stat_buf, status);
if (-1 != status)
{
if (cli_present("NOREPLACE")) /* the file exists, so error out */
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_FILEEXISTS, 2, inst_fn_len, inst_fn);
in_repl_inst_create = TRUE; /* used by an assert in the call to "repl_inst_read" below */
repl_inst_read(inst_fn, (off_t)0, (sm_uc_ptr_t)repl_instance, SIZEOF(repl_inst_hdr));
in_repl_inst_create = FALSE;
if ((INVALID_SEMID != repl_instance->jnlpool_semid) || (INVALID_SHMID != repl_instance->jnlpool_shmid)
|| (INVALID_SEMID != repl_instance->recvpool_semid) || (INVALID_SHMID != repl_instance->recvpool_shmid))
{
assert(FALSE || WBTEST_ENABLED(WBTEST_REPLINSTSTNDALN));
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_REPLINSTSTNDALN, 2, inst_fn_len, inst_fn);
}
JNL_SHORT_TIME(now);
rename_fn_len = ARRAYSIZE(rename_fn);
if (SS_NORMAL != (status = prepare_unique_name((char *)inst_fn, inst_fn_len, "", "",
rename_fn, &rename_fn_len, now, &status2)))
{
gtm_putmsg_csa(CSA_ARG(NULL)
VARLSTCNT(4) ERR_TEXT, 2, LEN_AND_LIT("Error preparing unique name for renaming instance file"));
if (SS_NORMAL != status2)
rts_error_csa(CSA_ARG(NULL)
VARLSTCNT(7) ERR_REPLINSTACC, 2, inst_fn_len, inst_fn, status, 0, status2);
else
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLINSTACC, 2, inst_fn_len, inst_fn, status);
}
if (SS_NORMAL != (status = gtm_rename((char *)inst_fn, (int)inst_fn_len,
(char *)rename_fn, rename_fn_len, &status2)))
{
if (SS_NORMAL != status2)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_RENAMEFAIL, 4, inst_fn_len, inst_fn,
rename_fn_len, rename_fn, status, 0, status2);
else
rts_error_csa(CSA_ARG(NULL)
VARLSTCNT(7) ERR_RENAMEFAIL, 4, inst_fn_len, inst_fn, rename_fn_len, rename_fn, status);
} else /* successfully renamed the existing file; print a message */
gtm_putmsg_csa(CSA_ARG(NULL)
VARLSTCNT(6) ERR_FILERENAME, 4, inst_fn_len, inst_fn, rename_fn_len, rename_fn);
} else if (ENOENT != errno) /* some error happened */
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_REPLINSTACC, 2, inst_fn_len, inst_fn, errno);
/* The instance file consists of 3 parts.
* File header ("repl_inst_hdr" structure)
* Array of 16 "gtmsrc_lcl" structures
* Variable length array of "repl_histinfo" structures
* Of these the last part is not allocated at file creation time. The rest have to be initialized now.
*/
/************************** Initialize "repl_inst_hdr" section ***************************/
memset(repl_instance, 0, SIZEOF(repl_inst_hdr));
memcpy(&repl_instance->label[0], GDS_REPL_INST_LABEL, GDS_REPL_INST_LABEL_SZ-1);
repl_instance->replinst_minorver = GDS_REPL_INST_MINOR_LABEL;
repl_instance->is_little_endian = GTM_IS_LITTLE_ENDIAN;
repl_instance->is_64bit = GTM_IS_64BIT;
repl_instance->jnlpool_semid = INVALID_SEMID;
repl_instance->jnlpool_shmid = INVALID_SHMID;
repl_instance->recvpool_semid = INVALID_SEMID;
repl_instance->recvpool_shmid = INVALID_SHMID;
/********* initialize "inst_info" structure member of "repl_inst_hdr" ***********/
/* machine_name was obtained from GETHOSTNAME above. It is an array of MAX_MCNAMELEN (256) bytes. The actual
* machine name might be longer than can fit in the "created_nodename" field which is MAX_NODENAME_LEN (16) in size.
* Take care to copy only as much as needed leaving one character for the null-termination.
*/
assert(MAX_NODENAME_LEN <= MAX_MCNAMELEN); /* '=' is valid since we have space to store MAX_NODENAME_LEN characters */
memcpy(repl_instance->inst_info.created_nodename, machine_name, MAX_NODENAME_LEN);
/* if machine_name is less than MAX_NODENAME_LEN then set the last valid character of created_nodename array to '\0' which
* is relied by repl_inst_dump_filehdr
*/
if (MAX_NODENAME_LEN > STRLEN(machine_name))
repl_instance->inst_info.created_nodename[MAX_NODENAME_LEN - 1] = '\0';
DBG_CHECK_CREATED_NODENAME(repl_instance->inst_info.created_nodename);
memcpy(repl_instance->inst_info.this_instname, inst_name, inst_name_len);
JNL_SHORT_TIME(repl_instance->inst_info.created_time);
assert(process_id == getpid());
repl_instance->inst_info.creator_pid = process_id;
/* repl_instance->lms_group_info should be initialized to NULL at this point.
* That is the case already because of the memset above. So nothing more needed for now.
*/
repl_instance->jnl_seqno = 0;
repl_instance->root_primary_cycle = 0;
repl_instance->num_histinfo = 0;
repl_instance->num_alloc_histinfo = 0;
repl_instance->crash = FALSE;
repl_instance->was_rootprimary = FALSE;
repl_instance->is_supplementary = cli_present("SUPPLEMENTARY");
repl_instance->qdbrundown = (CLI_PRESENT == cli_present("QDBRUNDOWN"));
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
repl_instance->last_histinfo_num[idx] = INVALID_HISTINFO_NUM;
/* strm_seqno[] and strm_group_info[] are already initialized to 0 as part of the memset above. Nothing more needed
* except the 0th stream seqno. This needs to be set to 1 so the first local update done on a supplementary instance
* correctly uses the stream seqno of 1. For non-zero stream #s, a UPDATERESYNC= startup of the receiver to be done
* anyways from a supplementary root primary instance and so that will initialize the strm_seqno[] to a non-zero
* value before any updates from that stream occur.
*/
if (repl_instance->is_supplementary)
repl_instance->strm_seqno[0] = 1; /* Initialize 0th stream starting sequence number */
/************************** Initialize "gtmsrc_lcl" section ***************************/
memset(gtmsrc_lcl_array, 0, GTMSRC_LCL_SIZE);
/************************** Write stuff to file on disk ***********************************/
in_repl_inst_create = TRUE; /* used by repl_inst_write to determine if O_CREAT needs to be specified in the open */
repl_inst_write(inst_fn, (off_t)0, (sm_uc_ptr_t)repl_instance, REPL_INST_HDR_SIZE + GTMSRC_LCL_SIZE);
in_repl_inst_create = FALSE;
}
|