2012-02-05 11:35:58 -05:00
|
|
|
/****************************************************************
|
|
|
|
* *
|
2012-03-24 14:06:46 -04:00
|
|
|
* Copyright 2001, 2012 Fidelity Information Services, Inc *
|
2012-02-05 11:35:58 -05:00
|
|
|
* *
|
|
|
|
* 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_ipc.h"
|
|
|
|
#include "gtm_unistd.h"
|
|
|
|
#include "gtm_string.h"
|
|
|
|
#include "gtm_inet.h"
|
|
|
|
#include "gtm_fcntl.h"
|
|
|
|
|
|
|
|
#include <sys/sem.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stddef.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 "gtmrecv.h"
|
|
|
|
#include "repl_msg.h"
|
|
|
|
#include "gtmsource.h"
|
|
|
|
#include "gtm_logicals.h"
|
|
|
|
#include "jnl.h"
|
|
|
|
#include "repl_sem.h"
|
|
|
|
#include "repl_shutdcode.h"
|
|
|
|
#include "io.h"
|
|
|
|
#include "trans_log_name.h"
|
|
|
|
#include "repl_instance.h"
|
|
|
|
#include "gtmmsg.h"
|
|
|
|
#include "gtm_sem.h"
|
|
|
|
#include "mu_rndwn_replpool.h"
|
|
|
|
#include "ftok_sems.h"
|
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \
|
|
|
|
{ \
|
|
|
|
gtm_putmsg(VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \
|
|
|
|
gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
|
|
|
|
return -1; \
|
|
|
|
}
|
|
|
|
|
2012-02-05 11:35:58 -05:00
|
|
|
GBLREF jnlpool_addrs jnlpool;
|
|
|
|
GBLREF recvpool_addrs recvpool;
|
|
|
|
GBLREF gd_region *gv_cur_region;
|
2012-03-24 14:06:46 -04:00
|
|
|
GBLREF jnl_gbls_t jgbl;
|
|
|
|
#ifdef UNIX
|
|
|
|
GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS];
|
|
|
|
#endif
|
2012-02-05 11:35:58 -05:00
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
error_def(ERR_REPLACCSEM);
|
2012-02-05 11:35:58 -05:00
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
int mu_replpool_remove_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_type, boolean_t remove_sem)
|
|
|
|
{
|
|
|
|
int save_errno, instfilelen, status, sem_id, semval;
|
|
|
|
uint4 semnum;
|
|
|
|
char *instfilename;
|
|
|
|
gd_region *replreg;
|
|
|
|
DEBUG_ONLY(unix_db_info *udi;)
|
2012-02-05 11:35:58 -05:00
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
assert((NULL != jnlpool.jnlpool_dummy_reg) && (jnlpool.jnlpool_dummy_reg == recvpool.recvpool_dummy_reg));
|
2012-02-05 11:35:58 -05:00
|
|
|
replreg = jnlpool.jnlpool_dummy_reg;
|
2012-03-24 14:06:46 -04:00
|
|
|
DEBUG_ONLY(udi = FILE_INFO(jnlpool.jnlpool_dummy_reg));
|
|
|
|
assert(udi->grabbed_ftok_sem || jgbl.mur_rollback); /* Rollback already holds standalone access so no need for ftok lock */
|
2012-02-05 11:35:58 -05:00
|
|
|
instfilename = (char *)replreg->dyn.addr->fname;
|
2012-03-24 14:06:46 -04:00
|
|
|
instfilelen = replreg->dyn.addr->fname_len;
|
|
|
|
assert((NULL != instfilename) && (0 != instfilelen) && ('\0' == instfilename[instfilelen]));
|
|
|
|
assert((JNLPOOL_SEGMENT == pool_type) || (RECVPOOL_SEGMENT == pool_type));
|
|
|
|
if (JNLPOOL_SEGMENT == pool_type)
|
2012-02-05 11:35:58 -05:00
|
|
|
{
|
2012-03-24 14:06:46 -04:00
|
|
|
sem_id = repl_inst_filehdr->jnlpool_semid;
|
|
|
|
semval = semctl(sem_id, SRC_SERV_COUNT_SEM, GETVAL);
|
|
|
|
assert((1 == semval) || jgbl.onlnrlbk); /* semval MUST be 1 because we incremented in mu_replpool_grab_sem and we
|
|
|
|
* never released it. Only exception is if we are ONLINE ROLLBACK */
|
|
|
|
remove_sem &= (1 == semval); /* we can remove the sem if the caller intends to and the counter semaphore is 1 */
|
|
|
|
if (0 < semval)
|
|
|
|
{
|
|
|
|
status = decr_sem(SOURCE, SRC_SERV_COUNT_SEM);
|
|
|
|
if (SS_NORMAL != status)
|
|
|
|
{
|
|
|
|
save_errno = errno;
|
|
|
|
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semop()");
|
|
|
|
}
|
|
|
|
} else if (-1 == semval)
|
|
|
|
{
|
|
|
|
save_errno = errno;
|
|
|
|
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semctl()");
|
|
|
|
}
|
|
|
|
holds_sem[SOURCE][SRC_SERV_COUNT_SEM] = FALSE;
|
|
|
|
assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]);
|
|
|
|
assert(1 == semctl(sem_id, JNL_POOL_ACCESS_SEM, GETVAL)); /* we hold the access control semaphore */
|
|
|
|
status = rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM);
|
|
|
|
assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */
|
|
|
|
holds_sem[SOURCE][JNL_POOL_ACCESS_SEM] = FALSE;
|
|
|
|
/* Now that we have released the access control semaphore, see if we can remove the semaphore altogether from the
|
|
|
|
* system. For this, we should be holding the FTOK on the replication instance AND the counter semaphore should be
|
|
|
|
* 0. If we are called from mu_rndwn_repl_instance, we are guaranteed we will be holding the FTOK. But, if we are
|
|
|
|
* ROLLBACK (online or noonline), we need not hold the FTOK, if somebody else (possibly a source or receiver server
|
|
|
|
* startup command) is holding it. In that case, we don't remove the semaphore, because any process that is waiting
|
|
|
|
* on the access control will now get an EIDRM error which is NOT user friendly. So, just release the access
|
|
|
|
* control and let the waiting process do the clean up.
|
|
|
|
*/
|
|
|
|
if (remove_sem)
|
|
|
|
{
|
|
|
|
status = remove_sem_set(SOURCE);
|
|
|
|
if (SS_NORMAL != status)
|
|
|
|
{
|
|
|
|
save_errno = errno;
|
|
|
|
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "sem_rmid()");
|
|
|
|
}
|
|
|
|
repl_inst_filehdr->jnlpool_semid = INVALID_SEMID;
|
|
|
|
repl_inst_filehdr->jnlpool_semid_ctime = 0;
|
|
|
|
}
|
|
|
|
} else
|
2012-02-05 11:35:58 -05:00
|
|
|
{
|
2012-03-24 14:06:46 -04:00
|
|
|
sem_id = repl_inst_filehdr->recvpool_semid;
|
|
|
|
for (semnum = RECV_SERV_COUNT_SEM; semnum <= UPD_PROC_COUNT_SEM; semnum++)
|
|
|
|
{
|
|
|
|
semval = semctl(sem_id, semnum, GETVAL);
|
|
|
|
assert((1 == semval) || jgbl.onlnrlbk);
|
|
|
|
remove_sem &= (1 == semval);
|
|
|
|
if (0 < semval)
|
|
|
|
{
|
|
|
|
status = decr_sem(RECV, semnum);
|
|
|
|
if (SS_NORMAL != status)
|
|
|
|
{
|
|
|
|
save_errno = errno;
|
|
|
|
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semop()");
|
|
|
|
}
|
|
|
|
} else if (-1 == semval)
|
|
|
|
{
|
|
|
|
save_errno = errno;
|
|
|
|
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semctl()");
|
|
|
|
}
|
|
|
|
holds_sem[RECV][semnum] = FALSE;
|
|
|
|
}
|
|
|
|
assert(holds_sem[RECV][RECV_POOL_ACCESS_SEM] && holds_sem[RECV][RECV_SERV_OPTIONS_SEM]);
|
|
|
|
assert(1 == semctl(sem_id, RECV_POOL_ACCESS_SEM, GETVAL) && (1 == semctl(sem_id, RECV_SERV_OPTIONS_SEM, GETVAL)));
|
|
|
|
status = rel_sem_immediate(RECV, RECV_SERV_OPTIONS_SEM);
|
|
|
|
assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */
|
|
|
|
status = rel_sem_immediate(RECV, RECV_POOL_ACCESS_SEM);
|
|
|
|
assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */
|
|
|
|
holds_sem[RECV][RECV_POOL_ACCESS_SEM] = FALSE;
|
|
|
|
holds_sem[RECV][RECV_SERV_OPTIONS_SEM] = FALSE;
|
|
|
|
/* Now that we have released the access control semaphore, see if we can remove the semaphore altogether from the
|
|
|
|
* system. For this, we should be holding the FTOK on the replication instance AND the counter semaphore should be
|
|
|
|
* 0. If we are called from mu_rndwn_repl_instance, we are guaranteed we will be holding the FTOK. But, if we are
|
|
|
|
* ROLLBACK (online or noonline), we need not hold the FTOK, if somebody else (possibly a source or receiver server
|
|
|
|
* startup command) is holding it. In that case, we don't remove the semaphore, because any process that is waiting
|
|
|
|
* on the access control will now get an EIDRM error which is NOT user friendly. So, just release the access
|
|
|
|
* control and let the waiting process do the clean up.
|
|
|
|
*/
|
|
|
|
if (remove_sem)
|
|
|
|
{
|
|
|
|
status = remove_sem_set(RECV);
|
|
|
|
if (SS_NORMAL != status)
|
|
|
|
{
|
|
|
|
save_errno = errno;
|
|
|
|
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "sem_rmid()");
|
|
|
|
}
|
|
|
|
repl_inst_filehdr->recvpool_semid = INVALID_SEMID;
|
|
|
|
repl_inst_filehdr->recvpool_semid_ctime = 0;
|
|
|
|
}
|
2012-02-05 11:35:58 -05:00
|
|
|
}
|
2012-03-24 14:06:46 -04:00
|
|
|
return SS_NORMAL;
|
2012-02-05 11:35:58 -05:00
|
|
|
}
|