int gtmrecv_changelog(void) { uint4 changelog_desired = 0, changelog_accepted = 0; /* Grab the recvpool jnlpool option write lock */ if (0 > grab_sem(RECV, RECV_SERV_OPTIONS_SEM)) { util_out_print("Error grabbing recvpool option write lock. Could not initiate change log", TRUE); return (ABNORMAL_SHUTDOWN); } if (0 != recvpool.gtmrecv_local->changelog || 0 != recvpool.upd_proc_local->changelog) { util_out_print("Change log is already in progress. Not initiating change in log file or log interval", TRUE); rel_sem(RECV, RECV_SERV_OPTIONS_SEM); return (ABNORMAL_SHUTDOWN); } if ('\0' != gtmrecv_options.log_file[0]) /* trigger change in log file (for both receiver and update process) */ { changelog_desired |= REPLIC_CHANGE_LOGFILE; if (0 != strcmp(recvpool.gtmrecv_local->log_file, gtmrecv_options.log_file)) { changelog_accepted |= REPLIC_CHANGE_LOGFILE; strcpy(recvpool.gtmrecv_local->log_file, gtmrecv_options.log_file); util_out_print("Change log initiated with file !AD", TRUE, LEN_AND_STR(gtmrecv_options.log_file)); } else util_out_print("Log file is already !AD. Not initiating change in log file", TRUE, LEN_AND_STR(gtmrecv_options.log_file)); } if (0 != gtmrecv_options.rcvr_log_interval) /* trigger change in receiver log interval */ { changelog_desired |= REPLIC_CHANGE_LOGINTERVAL; if (gtmrecv_options.rcvr_log_interval != recvpool.gtmrecv_local->log_interval) { changelog_accepted |= REPLIC_CHANGE_LOGINTERVAL; recvpool.gtmrecv_local->log_interval = gtmrecv_options.rcvr_log_interval; util_out_print("Change initiated with receiver log interval !UL", TRUE, gtmrecv_options.rcvr_log_interval); } else util_out_print("Receiver log interval is already !UL. Not initiating change in log interval", TRUE, gtmrecv_options.rcvr_log_interval); } if (0 != gtmrecv_options.upd_log_interval) /* trigger change in update process log interval */ { changelog_desired |= REPLIC_CHANGE_UPD_LOGINTERVAL; if (gtmrecv_options.upd_log_interval != recvpool.upd_proc_local->log_interval) { changelog_accepted |= REPLIC_CHANGE_UPD_LOGINTERVAL; recvpool.upd_proc_local->log_interval = gtmrecv_options.upd_log_interval; util_out_print("Change initiated with update process log interval !UL", TRUE, gtmrecv_options.upd_log_interval); } else util_out_print("Update process log interval is already !UL. Not initiating change in log interval", TRUE, gtmrecv_options.upd_log_interval); } if (0 != changelog_accepted) recvpool.gtmrecv_local->changelog = changelog_accepted; else util_out_print("No change to log file or log interval", TRUE); rel_sem(RECV, RECV_SERV_OPTIONS_SEM); return ((0 != changelog_accepted && changelog_accepted == changelog_desired) ? NORMAL_SHUTDOWN : ABNORMAL_SHUTDOWN); }
int gtmrecv_statslog(void) { #ifdef VMS rts_error(VARLSTCNT(6) ERR_UNIMPLOP, 0, ERR_TEXT, 2, LEN_AND_LIT("Statistics logging not supported on VMS")); #endif /* Grab the recvpool option write lock */ if (0 > grab_sem(RECV, RECV_SERV_OPTIONS_SEM)) { util_out_print("Error grabbing recvpool option write lock. Could not initiate stats log", TRUE); return (ABNORMAL_SHUTDOWN); } if (gtmrecv_options.statslog == recvpool.gtmrecv_local->statslog) { util_out_print("STATSLOG is already !AD. Not initiating change in stats log", TRUE, gtmrecv_options.statslog ? strlen("ON") : strlen("OFF"), gtmrecv_options.statslog ? "ON" : "OFF"); rel_sem_immediate(RECV, RECV_SERV_OPTIONS_SEM); return (ABNORMAL_SHUTDOWN); } if (!gtmrecv_options.statslog) { recvpool.gtmrecv_local->statslog = FALSE; util_out_print("STATSLOG turned OFF", TRUE); rel_sem_immediate(RECV, RECV_SERV_OPTIONS_SEM); return (NORMAL_SHUTDOWN); } recvpool.gtmrecv_local->statslog = TRUE; util_out_print("Stats log turned on", TRUE); rel_sem_immediate(RECV, RECV_SERV_OPTIONS_SEM); return (NORMAL_SHUTDOWN); }
int gtmsource_secnd_update(boolean_t print_message) { if (grab_sem(SOURCE, SRC_SERV_OPTIONS_SEM) < 0) { util_out_print("Error grabbing jnlpool option write lock. Could not initiate change log", TRUE); return(ABNORMAL_SHUTDOWN); } grab_lock(jnlpool.jnlpool_dummy_reg, ASSERT_NO_ONLINE_ROLLBACK); jnlpool.jnlpool_ctl->upd_disabled = update_disable; rel_lock(jnlpool.jnlpool_dummy_reg); rel_sem(SOURCE, SRC_SERV_OPTIONS_SEM); if (print_message) util_out_print("Updates are now !AZ", TRUE, update_disable ? "disabled" : "enabled"); return(NORMAL_SHUTDOWN); }
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 gtmsource_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; unix_db_info *udi; struct shmid_ds shm_buf; /* Attempt cleaning up the IPCs */ attempt_ipc_cleanup = TRUE; /* Wait for the Source Server to detach and takeover the semaphore */ if (!auto_shutdown && 0 > grab_sem(SOURCE, SRC_SERV_COUNT_SEM)) { repl_log(stderr, FALSE, TRUE, "Error taking control of source server count semaphore : %s. Shutdown not complete\n", REPL_SEM_ERROR); *exit_status = ABNORMAL_SHUTDOWN; attempt_ipc_cleanup = FALSE; } udi = (unix_db_info *)FILE_INFO(jnlpool.jnlpool_dummy_reg); if (!auto_shutdown || !gtmsource_srv_count) expected_nattach = 1; /* Self, or parent */ else expected_nattach = 0; /* Source server already detached */ i_am_the_last_user = (((status = shmctl(udi->shmid, IPC_STAT, &shm_buf)) == 0) && (shm_buf.shm_nattch == expected_nattach)); if (!i_am_the_last_user) { if (status < 0) repl_log(stderr, FALSE, TRUE, "Error in jnlpool shmctl : %s\n", STRERROR(ERRNO)); else repl_log(stderr, FALSE, TRUE, "Not deleting jnlpool ipcs. %d processes still attached to jnlpool\n", shm_buf.shm_nattch - expected_nattach); attempt_ipc_cleanup = FALSE; *exit_status = ABNORMAL_SHUTDOWN; } if (attempt_ipc_cleanup) { if (INVALID_SHMID != udi->shmid && (auto_shutdown || (detach_status = SHMDT(jnlpool.jnlpool_ctl)) == 0) && (remove_status = shm_rmid(udi->shmid)) == 0) { jnlpool.jnlpool_ctl = jnlpool_ctl = NULL; pool_init = FALSE; repl_log(stdout, FALSE, FALSE, "Journal pool shared memory removed\n"); if (0 == (status = remove_sem_set(SOURCE))) repl_log(stdout, FALSE, TRUE, "Journal pool semaphore removed\n"); else { repl_log(stderr, FALSE, TRUE, "Error removing jnlpool semaphore : %s\n", STRERROR(status)); *exit_status = ABNORMAL_SHUTDOWN; } } else if (INVALID_SHMID != udi->shmid) { if (!auto_shutdown && detach_status < 0) repl_log(stderr, FALSE, FALSE, "Error detaching from jnlpool shared memory : %s. Shared memory not removed\n", STRERROR(ERRNO)); else if (remove_status != 0) { if (!auto_shutdown) { jnlpool.jnlpool_ctl = NULL; /* Detached successfully */ jnlpool_ctl = NULL; pool_init = FALSE; } repl_log(stderr, FALSE, 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, FALSE, 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, FALSE, TRUE, "Error in jnlpool shmctl : %s\n", STRERROR(ERRNO)); else repl_log(stderr, FALSE, 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, FALSE, FALSE, "Receive pool shared memory removed\n"); if (0 == (status = remove_sem_set(RECV))) repl_log(stdout, FALSE, TRUE, "Receive pool semaphore removed\n"); else { repl_log(stderr, FALSE, 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, FALSE, FALSE, "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, FALSE, TRUE, "Error removing receive pool shared memory : %s\n", STRERROR(ERRNO)); } *exit_status = ABNORMAL_SHUTDOWN; } } return attempt_ipc_cleanup; }
int gtmrecv_shutdown(boolean_t auto_shutdown, int exit_status) { uint4 savepid; boolean_t shut_upd_too = FALSE; int status; unix_db_info *udi; error_def(ERR_RECVPOOLSETUP); error_def(ERR_TEXT); repl_log(stdout, TRUE, TRUE, "Initiating shut down\n"); call_on_signal = NULL; /* So we don't reenter on error */ /* assert that auto shutdown should be invoked only if the current process is a receiver server */ assert(!auto_shutdown || gtmrecv_srv_count); if (auto_shutdown) { /* grab the ftok semaphore and recvpool access control lock IN THAT ORDER (to avoid deadlocks) */ repl_inst_ftok_sem_lock(); status = grab_sem(RECV, RECV_POOL_ACCESS_SEM); if (0 > status) { repl_log(stderr, TRUE, TRUE, "Error grabbing receive pool control semaphore : %s. Shutdown not complete\n", REPL_SEM_ERROR); return (ABNORMAL_SHUTDOWN); } } else { /* ftok semaphore and recvpool access semaphore should already be held from the previous call to "recvpool_init" */ DEBUG_ONLY(udi = (unix_db_info *)FILE_INFO(recvpool.recvpool_dummy_reg);) assert(udi->grabbed_ftok_sem); assert(holds_sem[RECV][RECV_POOL_ACCESS_SEM]); /* We do not want to hold the options semaphore to avoid deadlocks with receiver server startup (C9F12-002766) */ assert(!holds_sem[RECV][RECV_SERV_OPTIONS_SEM]); recvpool.gtmrecv_local->shutdown = SHUTDOWN; /* Wait for receiver server to die. But release ftok semaphore and recvpool access control semaphore before * waiting as the concurrently running receiver server might need these (e.g. if it is about to call the * function "repl_inst_was_rootprimary"). */ if (0 != rel_sem(RECV, RECV_POOL_ACCESS_SEM)) gtm_putmsg(VARLSTCNT(7) ERR_TEXT, 2, RTS_ERROR_LITERAL("Error in receiver server shutdown rel_sem"), REPL_SEM_ERRNO); repl_inst_ftok_sem_release(); /* Wait for receiver server to shut down */ while((SHUTDOWN == recvpool.gtmrecv_local->shutdown) && (0 < (savepid = recvpool.gtmrecv_local->recv_serv_pid)) && is_proc_alive(savepid, 0)) SHORT_SLEEP(GTMRECV_WAIT_FOR_SHUTDOWN); /* (Re)Grab the ftok semaphore and recvpool access control semaphore IN THAT ORDER (to avoid deadlocks) */ repl_inst_ftok_sem_lock(); status = grab_sem(RECV, RECV_POOL_ACCESS_SEM); if (0 > status) { repl_log(stderr, TRUE, TRUE, "Error regrabbing receive pool control semaphore : %s. Shutdown not complete\n", REPL_SEM_ERROR); return (ABNORMAL_SHUTDOWN); } exit_status = recvpool.gtmrecv_local->shutdown; if (SHUTDOWN == exit_status) { if (0 == savepid) /* No Receiver Process */ exit_status = NORMAL_SHUTDOWN; else /* Receiver Server Crashed */ { repl_log(stderr, FALSE, TRUE, "Receiver Server exited abnormally\n"); exit_status = ABNORMAL_SHUTDOWN; shut_upd_too = TRUE; } } }