/**************************************************************** * * * 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 #include #include #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" 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; 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) { repl_log(stderr, TRUE, TRUE, "Error fetching source server count semaphore value : %s. Shutdown not complete\n", REPL_SEM_ERROR); 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 */ detach_status = SHMDT(jnlpool.jnlpool_ctl); 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 jnlpool shared memory : %s. Shared memory not removed\n", STRERROR(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; 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))) rel_sem(RECV, RECV_SERV_COUNT_SEM); if (status < 0) { repl_log(stderr, TRUE, TRUE, "Error taking control of Receiver Server/Update Process count semaphore : %s. Shutdown not complete\n", REPL_SEM_ERROR); *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; }