194 lines
7.0 KiB
C
194 lines
7.0 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2006, 2011 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. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include "gtm_unistd.h" /* for close */
|
|
#include "gtm_string.h"
|
|
|
|
#include "gtm_ipc.h"
|
|
#include <sys/shm.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/wait.h>
|
|
#include <errno.h>
|
|
#include "gtm_inet.h"
|
|
|
|
#include "gdsroot.h"
|
|
#include "gdsblk.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "filestruct.h"
|
|
#include "iosp.h"
|
|
#include "repl_shutdcode.h"
|
|
#include "gtmrecv.h"
|
|
#include "repl_dbg.h"
|
|
#include "gtm_stdio.h"
|
|
#include "gtm_event_log.h"
|
|
#include "eintr_wrappers.h"
|
|
#include "jnl.h"
|
|
#include "repl_filter.h"
|
|
#include "repl_msg.h"
|
|
#include "repl_sem.h"
|
|
#include "repl_log.h"
|
|
#include "is_proc_alive.h"
|
|
#include "gtmsource.h"
|
|
#include "gtmio.h"
|
|
|
|
GBLREF uint4 process_id;
|
|
GBLREF recvpool_addrs recvpool;
|
|
GBLREF int gtmrecv_filter;
|
|
GBLREF boolean_t gtmrecv_logstats;
|
|
GBLREF int gtmrecv_listen_sock_fd;
|
|
GBLREF int gtmrecv_sock_fd;
|
|
GBLREF int gtmrecv_log_fd;
|
|
GBLREF int gtmrecv_statslog_fd;
|
|
GBLREF FILE *gtmrecv_log_fp;
|
|
GBLREF FILE *gtmrecv_statslog_fp;
|
|
GBLREF qw_num repl_recv_data_recvd;
|
|
GBLREF qw_num repl_recv_data_processed;
|
|
GBLREF repl_msg_ptr_t gtmrecv_msgp;
|
|
GBLREF uchar_ptr_t repl_filter_buff;
|
|
GBLREF jnlpool_addrs jnlpool;
|
|
GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
|
|
GBLREF boolean_t pool_init;
|
|
|
|
int gtmrecv_endupd(void)
|
|
{
|
|
pid_t savepid;
|
|
int exit_status;
|
|
pid_t waitpid_res;
|
|
|
|
repl_log(stdout, TRUE, TRUE, "Initiating shut down of Update Process\n");
|
|
recvpool.upd_proc_local->upd_proc_shutdown = SHUTDOWN;
|
|
/* Wait for update process to shut down */
|
|
while((SHUTDOWN == recvpool.upd_proc_local->upd_proc_shutdown)
|
|
&& (0 < (savepid = (pid_t)recvpool.upd_proc_local->upd_proc_pid)) && is_proc_alive(savepid, 0))
|
|
{
|
|
SHORT_SLEEP(GTMRECV_WAIT_FOR_UPD_SHUTDOWN);
|
|
WAITPID(savepid, &exit_status, WNOHANG, waitpid_res); /* Release defunct update process if dead */
|
|
}
|
|
exit_status = recvpool.upd_proc_local->upd_proc_shutdown;
|
|
if (SHUTDOWN == exit_status)
|
|
{
|
|
if (0 == savepid) /* No Update Process */
|
|
exit_status = NORMAL_SHUTDOWN;
|
|
else /* Update Process Crashed */
|
|
{
|
|
repl_log(stderr, TRUE, TRUE, "Update Process exited abnormally, INTEGRITY CHECK might be warranted\n");
|
|
exit_status = ABNORMAL_SHUTDOWN;
|
|
}
|
|
}
|
|
/* Wait for the Update Process to detach */
|
|
if (0 == grab_sem(RECV, UPD_PROC_COUNT_SEM))
|
|
{
|
|
if(0 != (errno = rel_sem(RECV, UPD_PROC_COUNT_SEM)))
|
|
repl_log(stderr, TRUE, TRUE, "Error releasing the Update Process Count semaphore : %s\n", REPL_SEM_ERROR);
|
|
repl_log(stdout, TRUE, TRUE, "Update Process exited\n");
|
|
} else
|
|
{
|
|
repl_log(stderr, TRUE, TRUE, "Error in update proc count semaphore : %s\n", REPL_SEM_ERROR);
|
|
exit_status = ABNORMAL_SHUTDOWN;
|
|
}
|
|
return (exit_status);
|
|
}
|
|
|
|
int gtmrecv_end1(boolean_t auto_shutdown)
|
|
{
|
|
int4 strm_idx;
|
|
int exit_status, idx;
|
|
int fclose_res, rc;
|
|
seq_num log_seqno, log_seqno1, jnlpool_seqno, jnlpool_strm_seqno[MAX_SUPPL_STRMS];
|
|
uint4 savepid;
|
|
|
|
exit_status = gtmrecv_end_helpers(TRUE);
|
|
exit_status = gtmrecv_endupd();
|
|
log_seqno = recvpool.recvpool_ctl->jnl_seqno;
|
|
log_seqno1 = recvpool.upd_proc_local->read_jnl_seqno;
|
|
strm_idx = recvpool.gtmrecv_local->strm_index;
|
|
/* Detach from receive pool */
|
|
recvpool.gtmrecv_local->shutdown = exit_status;
|
|
recvpool.gtmrecv_local->recv_serv_pid = 0;
|
|
if (recvpool.recvpool_ctl && 0 > SHMDT(recvpool.recvpool_ctl))
|
|
repl_log(stderr, TRUE, TRUE, "Error detaching from Receive Pool : %s\n", REPL_STR_ERROR);
|
|
recvpool.recvpool_ctl = NULL;
|
|
assert((NULL != jnlpool_ctl) && (jnlpool_ctl == jnlpool.jnlpool_ctl));
|
|
if (NULL != jnlpool.jnlpool_ctl)
|
|
{ /* Reset fields that might have been initialized by the receiver server after connecting to the primary.
|
|
* It is ok not to hold the journal pool lock while updating jnlpool_ctl fields since this will be the
|
|
* only process updating those fields.
|
|
*/
|
|
jnlpool.jnlpool_ctl->primary_instname[0] = '\0';
|
|
jnlpool.jnlpool_ctl->gtmrecv_pid = 0;
|
|
jnlpool_seqno = jnlpool.jnlpool_ctl->jnl_seqno;
|
|
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
|
|
jnlpool_strm_seqno[idx] = jnlpool.jnlpool_ctl->strm_seqno[idx];
|
|
/* Also take this opportunity to detach from the journal pool except in the auto_shutdown case. This is because
|
|
* the fields "jnlpool_ctl->repl_inst_filehdr->recvpool_semid" and "jnlpool_ctl->repl_inst_filehdr->recvpool_shmid"
|
|
* need to be reset by "gtmrecv_jnlpool_reset" (called from "gtmrecv_shutdown") which is invoked a little later.
|
|
*/
|
|
if (!auto_shutdown)
|
|
{
|
|
if (0 > SHMDT(jnlpool.jnlpool_ctl))
|
|
repl_log(stderr, TRUE, TRUE, "Error detaching from Journal Pool : %s\n", REPL_STR_ERROR);
|
|
jnlpool.jnlpool_ctl = jnlpool_ctl = NULL;
|
|
jnlpool.repl_inst_filehdr = NULL;
|
|
jnlpool.gtmsrc_lcl_array = NULL;
|
|
jnlpool.gtmsource_local_array = NULL;
|
|
jnlpool.jnldata_base = NULL;
|
|
pool_init = FALSE;
|
|
}
|
|
} else
|
|
jnlpool_seqno = 0;
|
|
gtmrecv_free_msgbuff();
|
|
gtmrecv_free_filter_buff();
|
|
recvpool.recvpool_ctl = NULL;
|
|
/* Close the connection with the Receiver */
|
|
if (FD_INVALID != gtmrecv_listen_sock_fd)
|
|
CLOSEFILE_RESET(gtmrecv_listen_sock_fd, rc); /* resets "gtmrecv_listen_sock_fd" to FD_INVALID */
|
|
if (FD_INVALID != gtmrecv_sock_fd)
|
|
CLOSEFILE_RESET(gtmrecv_sock_fd, rc); /* resets "gtmrecv_sock_fd" to FD_INVALID */
|
|
repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Current Jnlpool Seqno : %llu\n", jnlpool_seqno);
|
|
for (idx = 0; idx < MAX_SUPPL_STRMS; idx++)
|
|
{
|
|
if (jnlpool_strm_seqno[idx])
|
|
repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Stream # %d : Current Jnlpool Stream Seqno : %llu\n",
|
|
idx, jnlpool_strm_seqno[idx]);
|
|
}
|
|
if (0 < strm_idx)
|
|
repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Receiver server has Stream # %d\n", strm_idx);
|
|
repl_log(gtmrecv_log_fp, TRUE, TRUE, "REPL INFO - Current Update process Read Seqno : %llu\n", log_seqno1);
|
|
repl_log(gtmrecv_log_fp, TRUE, TRUE, "REPL INFO - Current Receive Pool Seqno : %llu\n", log_seqno);
|
|
/* If log_seqno/log_seqno1 is 0, then do not decrement it as that will be interpreted as a huge positive seqno. Keep it 0 */
|
|
if (log_seqno)
|
|
log_seqno--;
|
|
if (log_seqno1)
|
|
log_seqno1--;
|
|
repl_log(gtmrecv_log_fp, TRUE, FALSE, "REPL INFO - Last Recvd Seqno : %llu Jnl Total : %llu Msg Total : %llu\n",
|
|
log_seqno, repl_recv_data_processed, repl_recv_data_recvd);
|
|
repl_log(gtmrecv_log_fp, TRUE, TRUE, "REPL INFO - Last Seqno processed by update process : %llu\n", log_seqno1);
|
|
gtm_event_log_close();
|
|
if (gtmrecv_filter & EXTERNAL_FILTER)
|
|
repl_stop_filter();
|
|
if (auto_shutdown)
|
|
return (exit_status);
|
|
else
|
|
gtmrecv_exit(exit_status - NORMAL_SHUTDOWN);
|
|
|
|
return -1; /* This will never get executed, added to make compiler happy */
|
|
}
|
|
|
|
void gtmrecv_end(void)
|
|
{
|
|
gtmrecv_end1(FALSE);
|
|
}
|