fis-gtm/sr_unix/repl_ipc_cleanup.c

224 lines
7.6 KiB
C

/****************************************************************
* *
* Copyright 2001, 2012 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_inet.h"
#include <sys/shm.h>
#include <errno.h>
#include <sys/sem.h>
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "gtmrecv.h"
#include "repl_dbg.h"
#include "gtm_stdio.h"
#include "gtm_string.h"
#include "repl_shutdcode.h"
#include "repl_sem.h"
#include "repl_sp.h"
#include "repl_log.h"
#include "ipcrmid.h"
#include "repl_instance.h"
#include "wbox_test_init.h"
#include "have_crit.h"
#include "gtm_ipc.h"
GBLREF jnlpool_addrs jnlpool;
GBLREF boolean_t pool_init;
GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
GBLREF int gtmsource_srv_count;
GBLREF int gtmrecv_srv_count;
GBLREF recvpool_addrs recvpool;
GBLREF int recvpool_shmid;
int gtmsource_ipc_cleanup(boolean_t auto_shutdown, int *exit_status, int4 *num_src_servers_running)
{
boolean_t i_am_the_last_user, attempt_ipc_cleanup;
int status, detach_status, remove_status, semval, save_errno;
unix_db_info *udi;
struct shmid_ds shm_buf;
/* Attempt cleaning up the IPCs */
attempt_ipc_cleanup = TRUE;
*num_src_servers_running = 0;
if (!auto_shutdown)
{ /* If the value of counter semaphore is not 0 (some other source server is still up), cannot cleanup ipcs */
semval = get_sem_info(SOURCE, SRC_SERV_COUNT_SEM, SEM_INFO_VAL);
if (-1 == semval)
{
save_errno = errno;
repl_log(stderr, TRUE, TRUE, "Error fetching source server count semaphore value : %s. "
"Shutdown not complete\n", STRERROR(save_errno));
attempt_ipc_cleanup = FALSE;
*exit_status = ABNORMAL_SHUTDOWN;
}
if (0 != semval)
{
repl_log(stderr, TRUE, TRUE, "Not deleting jnlpool ipcs. %d source servers still attached to jnlpool\n",
semval);
*num_src_servers_running = semval;
attempt_ipc_cleanup = FALSE;
*exit_status = ABNORMAL_SHUTDOWN;
}
}
udi = (unix_db_info *)FILE_INFO(jnlpool.jnlpool_dummy_reg);
assert(INVALID_SHMID != udi->shmid);
if (attempt_ipc_cleanup)
{
i_am_the_last_user = (((status = shmctl(udi->shmid, IPC_STAT, &shm_buf)) == 0) && (1 == shm_buf.shm_nattch));
if (!i_am_the_last_user)
{
if (status < 0)
repl_log(stderr, TRUE, TRUE, "Error in jnlpool shmctl : %s\n", STRERROR(ERRNO));
else
repl_log(stderr, TRUE, TRUE, "Not deleting jnlpool ipcs. %d processes still attached to jnlpool\n",
shm_buf.shm_nattch - 1);
attempt_ipc_cleanup = FALSE;
*exit_status = ABNORMAL_SHUTDOWN;
} else if (INVALID_SHMID != udi->shmid)
{
if (INVALID_SEMID != jnlpool.repl_inst_filehdr->recvpool_semid DEBUG_ONLY(&&
!(gtm_white_box_test_case_enabled &&
(WBTEST_UPD_PROCESS_ERROR == gtm_white_box_test_case_number))))
repl_log(stderr, TRUE, TRUE, "Receiver pool semaphore IDs were not removed\n");
if ((INVALID_SHMID != jnlpool.repl_inst_filehdr->recvpool_shmid) DEBUG_ONLY(&&
!(gtm_white_box_test_case_enabled &&
(WBTEST_UPD_PROCESS_ERROR == gtm_white_box_test_case_number))))
repl_log(stderr, TRUE, TRUE, "Receiver pool shared memory not removed\n");
repl_inst_flush_jnlpool(TRUE, TRUE);
}
}
/* detach from shared memory irrespective of whether we need to cleanup ipcs or not */
JNLPOOL_SHMDT(detach_status, save_errno);
if (0 == detach_status)
{
jnlpool.jnlpool_ctl = NULL; /* Detached successfully */
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
{
repl_log(stderr, TRUE, TRUE, "Error detaching from Journal Pool : %s\n", STRERROR(save_errno));
attempt_ipc_cleanup = FALSE;
*num_src_servers_running = 0;
*exit_status = ABNORMAL_SHUTDOWN;
}
if ((attempt_ipc_cleanup) && (INVALID_SHMID != udi->shmid))
{
remove_status = shm_rmid(udi->shmid);
if (0 == remove_status)
{
repl_log(stdout, TRUE, FALSE, "Journal pool shared memory removed\n");
if (0 == remove_sem_set(SOURCE))
repl_log(stdout, TRUE, TRUE, "Journal pool semaphore removed\n");
else
{
repl_log(stderr, TRUE, TRUE, "Error removing jnlpool semaphore : %s\n", STRERROR(ERRNO));
*exit_status = ABNORMAL_SHUTDOWN;
}
} else
{
repl_log(stderr, TRUE, TRUE, "Error removing jnlpool shared memory : %s\n", STRERROR(ERRNO));
*exit_status = ABNORMAL_SHUTDOWN;
}
}
return attempt_ipc_cleanup;
}
int gtmrecv_ipc_cleanup(boolean_t auto_shutdown, int *exit_status)
{
boolean_t i_am_the_last_user, attempt_ipc_cleanup;
int status, detach_status, remove_status, expected_nattach, save_errno;
struct shmid_ds shm_buf;
/* Attempt cleaning up the IPCs */
attempt_ipc_cleanup = TRUE;
/* Wait for the Receiver Server and Update Process to detach and takeover the semaphores.
* Note that the Receiver Server has already waited for the Update Process to detach.
* It is done here as a precaution against Receiver Server crashes.
*/
if (!auto_shutdown)
status = grab_sem(RECV, RECV_SERV_COUNT_SEM);
else
status = 0;
if (0 == status && 0 > (status = grab_sem(RECV, UPD_PROC_COUNT_SEM)))
{
save_errno = errno;
status = rel_sem(RECV, RECV_SERV_COUNT_SEM);
assert(0 == status);
repl_log(stderr, TRUE, TRUE, "Error taking control of Receiver Server/Update Process count semaphore : %s. "
"Shutdown not complete\n", STRERROR(save_errno));
*exit_status = ABNORMAL_SHUTDOWN;
attempt_ipc_cleanup = FALSE;
}
/* Now we have locked out all users from the receive pool */
if (!auto_shutdown || !gtmrecv_srv_count)
expected_nattach = 1; /* Self, or parent */
else
expected_nattach = 0; /* Receiver server already detached */
i_am_the_last_user = (((status = shmctl(recvpool_shmid, IPC_STAT, &shm_buf)) == 0)
&& (shm_buf.shm_nattch == expected_nattach));
if (!i_am_the_last_user)
{
if (status < 0)
repl_log(stderr, TRUE, TRUE, "Error in jnlpool shmctl : %s\n", STRERROR(errno));
else
repl_log(stderr, TRUE, TRUE,
"Not deleting receive pool ipcs. %d processes still attached to receive pool\n",
shm_buf.shm_nattch - expected_nattach);
attempt_ipc_cleanup = FALSE;
*exit_status = ABNORMAL_SHUTDOWN;
}
if (attempt_ipc_cleanup)
{
if (INVALID_SHMID != recvpool_shmid && (auto_shutdown || (detach_status = SHMDT(recvpool.recvpool_ctl)) == 0)
&& (remove_status = shm_rmid(recvpool_shmid)) == 0)
{
recvpool.recvpool_ctl = NULL;
repl_log(stdout, TRUE, FALSE, "Receive pool shared memory removed\n");
if (0 == (status = remove_sem_set(RECV)))
repl_log(stdout, TRUE, TRUE, "Receive pool semaphore removed\n");
else
{
repl_log(stderr, TRUE, TRUE, "Error removing receive pool semaphore : %s\n", STRERROR(status));
*exit_status = ABNORMAL_SHUTDOWN;
}
} else if (INVALID_SHMID != recvpool_shmid)
{
if (!auto_shutdown && detach_status < 0)
repl_log(stderr, TRUE, TRUE,
"Error detaching from receive pool shared memory : %s. Shared memory not removed\n",
STRERROR(ERRNO));
else if (remove_status != 0)
{
if (!auto_shutdown)
recvpool.recvpool_ctl = NULL; /* Detached successfully */
repl_log(stderr, TRUE, TRUE, "Error removing receive pool shared memory : %s\n", STRERROR(ERRNO));
}
*exit_status = ABNORMAL_SHUTDOWN;
}
}
return attempt_ipc_cleanup;
}