8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 03:23:03 +01:00
firebird-mirror/src/utilities/drop.cpp

438 lines
9.8 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: UNIX resource removal program
* MODULE: drop.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Drop shared memory and semaphores
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*
* 2002.10.27 Sean Leyne - Completed removal of obsolete "DELTA" port
* 2002.10.27 Sean Leyne - Completed removal of obsolete "IMP" port
*
2002-10-30 07:40:58 +01:00
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
*
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2004-04-29 00:36:29 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include "../jrd/common.h"
#include "../jrd/isc.h"
#include "../lock/lock.h"
#include "../lock/lock_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/license.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_proto.h"
2002-12-07 14:32:34 +01:00
#include "../common/config/config.h"
2001-05-23 15:26:42 +02:00
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
2004-05-17 02:21:46 +02:00
const int FTOK_KEY = 15;
2001-05-23 15:26:42 +02:00
2003-08-10 02:41:39 +02:00
#ifndef HAVE_MMAP
2001-05-23 15:26:42 +02:00
static void dummy_init(void);
2003-08-10 02:41:39 +02:00
#endif
2001-05-23 15:26:42 +02:00
static SLONG get_key(TEXT *);
2004-05-06 10:38:50 +02:00
static void remove_resource(const TEXT*, SLONG, SLONG, const TEXT*);
2001-05-23 15:26:42 +02:00
static int sem_exclusive(SLONG, SLONG);
2003-08-10 00:32:39 +02:00
#ifndef HAVE_MMAP
2001-05-23 15:26:42 +02:00
static int shm_exclusive(SLONG, SLONG);
2003-08-10 00:32:39 +02:00
#endif
2001-05-23 15:26:42 +02:00
#ifdef MANAGER_PROCESS
static void shut_manager(const TEXT*);
2001-05-23 15:26:42 +02:00
#endif
static int orig_argc;
static SCHAR **orig_argv;
int CLIB_ROUTINE main( int argc, char *argv[])
{
/**************************************
*
* m a i n
*
**************************************
*
* Functional description
* Drop Lock Table and associated semaphores.
*
**************************************/
2003-08-26 08:56:42 +02:00
bool sw_lockmngr = false;
bool sw_events = false;
bool sw_version = false;
bool sw_nobridge = false;
bool sw_shutmngr = false;
2001-05-23 15:26:42 +02:00
orig_argc = argc;
orig_argv = argv;
SCHAR** const end = argv + argc;
2001-05-23 15:26:42 +02:00
while (++argv < end)
if (**argv == '-')
for (const char* p = *argv + 1; *p; p++)
2001-05-23 15:26:42 +02:00
switch (UPPER(*p)) {
case 'E':
2003-08-26 08:56:42 +02:00
sw_events = true;
2001-05-23 15:26:42 +02:00
break;
case 'L':
2003-08-26 08:56:42 +02:00
sw_lockmngr = true;
2001-05-23 15:26:42 +02:00
break;
case 'A':
2003-08-26 08:56:42 +02:00
sw_events = sw_lockmngr = true;
2001-05-23 15:26:42 +02:00
break;
case 'S':
2003-08-26 08:56:42 +02:00
sw_shutmngr = sw_nobridge = true;
2001-05-23 15:26:42 +02:00
break;
case 'N':
2003-08-26 08:56:42 +02:00
sw_nobridge = true;
2001-05-23 15:26:42 +02:00
break;
case 'Z':
2003-08-26 08:56:42 +02:00
sw_version = true;
2001-05-23 15:26:42 +02:00
break;
default:
2004-04-29 00:36:29 +02:00
printf("***Ignoring unknown switch %c.\n", *p);
2001-05-23 15:26:42 +02:00
break;
}
if (sw_version)
2004-04-29 00:36:29 +02:00
printf("gds_drop version %s\n", GDS_VERSION);
2001-05-23 15:26:42 +02:00
if (sw_events)
2002-12-07 14:32:34 +01:00
remove_resource(EVENT_FILE, Config::getEventMemSize(), EVENT_SEMAPHORES,
2001-05-23 15:26:42 +02:00
"events");
if (sw_lockmngr)
2002-12-07 14:32:34 +01:00
remove_resource(LOCK_FILE, Config::getLockMemSize(), Config::getLockSemCount(),
2001-05-23 15:26:42 +02:00
"lock manager");
#ifdef MANAGER_PROCESS
if (sw_shutmngr)
shut_manager("lock manager");
#endif
exit(FINI_OK);
}
2003-08-10 02:41:39 +02:00
#ifndef HAVE_MMAP
2001-05-23 15:26:42 +02:00
static void dummy_init(void)
{
/**************************************
*
* d u m m y _ i n i t
*
**************************************
*
* Functional description
* A dummy callback routine for ISC_map_file.
*
**************************************/
}
2003-08-10 02:41:39 +02:00
#endif
2001-05-23 15:26:42 +02:00
static SLONG get_key( TEXT * filename)
{
/*************************************
*
* g e t _ k e y
*
*************************************
*
* Functional description
* Find the semaphore/shared memory key for a file.
*
************************************/
TEXT expanded_filename[128], hostname[64];
#ifdef NOHOSTNAME
strcpy(expanded_filename, filename);
#else
sprintf(expanded_filename, filename,
ISC_get_host(hostname, sizeof(hostname)));
#endif
/* Produce shared memory key for file */
return ftok(expanded_filename, FTOK_KEY);
}
#ifndef HAVE_MMAP
2001-05-23 15:26:42 +02:00
static void remove_resource(
2004-05-06 10:38:50 +02:00
const TEXT* filename,
SLONG shm_length, SLONG sem_count, const TEXT* label)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* r e m o v e _ r e s o u r c e ( n o n - m m a p )
*
**************************************
*
* Functional description
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
SH_MEM_T shmem_data;
TEXT expanded_filename[MAXPATHLEN];
pid_t pid;
2001-05-23 15:26:42 +02:00
#ifdef MANAGER_PROCESS
/* Shutdown lock manager process so that shared memory
and semaphores can be attached exclusively. */
if (!(strcmp(label, "lock manager"))) {
if (!(pid = vfork())) {
execl(orig_argv[0], orig_argv[0], "-s", 0);
_exit(FINI_ERROR);
}
// wait(pid) // this is wrong wait takes a *int anyway.
waitpid(pid, 0, 0);
2001-05-23 15:26:42 +02:00
}
#endif
gds__prefix_lock(expanded_filename, filename);
shmem_data.sh_mem_semaphores = sem_count;
if (!ISC_map_file
2007-11-12 16:18:49 +01:00
#ifdef HP11
(status_vector, expanded_filename,
2007-11-17 11:18:10 +01:00
(void (*) (void*, sh_mem*, bool)) dummy_init, 0, shm_length,
2007-11-12 16:18:49 +01:00
&shmem_data))
#else
2001-05-23 15:26:42 +02:00
(status_vector, expanded_filename, dummy_init, 0, shm_length,
&shmem_data))
2007-11-12 16:18:49 +01:00
#endif
{
2004-04-29 00:36:29 +02:00
printf("\n***Unable to access %s resources:\n", label);
2001-05-23 15:26:42 +02:00
gds__print_status(status_vector);
return;
}
const SLONG key = get_key(expanded_filename);
if (key == -1) {
2004-04-29 00:36:29 +02:00
printf("\n***Unable to get the key value of the %s file.\n",
2001-05-23 15:26:42 +02:00
label);
return;
}
SLONG shmid, semid;
2001-05-23 15:26:42 +02:00
if ((shmid = shm_exclusive(key, shmem_data.sh_mem_length_mapped)) == -1 ||
(semid = sem_exclusive(key, sem_count)) == -1)
{
2004-04-29 00:36:29 +02:00
printf("\n***File or semaphores for %s are currently in use.\n",
2001-05-23 15:26:42 +02:00
label);
return;
}
if (shmctl(shmid, IPC_RMID, 0) == -1)
2004-04-29 00:36:29 +02:00
printf("\n***Error trying to drop %s file. ERRNO = %d.\n", label,
2001-05-23 15:26:42 +02:00
errno);
else
2004-04-29 00:36:29 +02:00
printf("Successfully removed %s file.\n", label);
2001-05-23 15:26:42 +02:00
if (semctl(semid, sem_count, IPC_RMID, 0) == -1)
2004-04-29 00:36:29 +02:00
printf("\n***Error trying to drop %s semaphores. ERRNO = %d.\n",
2001-05-23 15:26:42 +02:00
label, errno);
else
2004-04-29 00:36:29 +02:00
printf("Successfully removed %s semaphores.\n", label);
2001-05-23 15:26:42 +02:00
}
#endif
#ifdef HAVE_MMAP
2001-05-23 15:26:42 +02:00
static void remove_resource(
2004-05-06 10:38:50 +02:00
const TEXT* filename,
SLONG shm_length, SLONG sem_count, const TEXT* label)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* r e m o v e _ r e s o u r c e ( m m a p )
*
**************************************
*
* Functional description
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
TEXT expanded_filename[MAXPATHLEN];
int pid;
#ifdef DARWIN
2001-07-12 07:46:06 +02:00
union semun semctlArg;
#endif
2001-05-23 15:26:42 +02:00
#ifdef MANAGER_PROCESS
/* Shutdown lock manager process so that shared memory
and semaphores can be attached exclusively. */
if (!(strcmp(label, "lock manager"))) {
if (!(pid = vfork())) {
execl(orig_argv[0], orig_argv[0], "-s", 0);
_exit(FINI_ERROR);
}
#ifdef SCO_EV /* 5.5 SCO Port: SCO needs waitpid() to function properly */
waitpid(pid, 0, 0);
#else
2004-11-24 10:22:07 +01:00
waitpid(pid, NULL, 0);
2001-05-23 15:26:42 +02:00
#endif
}
#endif
gds__prefix_lock(expanded_filename, filename);
const SLONG key = get_key(expanded_filename);
if (key == -1) {
2004-04-29 00:36:29 +02:00
printf("\n***Unable to get the key value of the %s file.\n",
2001-05-23 15:26:42 +02:00
label);
return;
}
const SLONG semid = sem_exclusive(key, sem_count);
if (semid == -1) {
2004-04-29 00:36:29 +02:00
printf("\n***Semaphores for %s are currently in use.\n", label);
2001-05-23 15:26:42 +02:00
return;
}
#ifdef DARWIN
2001-07-12 07:46:06 +02:00
semctlArg.val = 0;
if (semctl(semid, sem_count, IPC_RMID, semctlArg) == -1)
#else
2001-05-23 15:26:42 +02:00
if (semctl(semid, sem_count, IPC_RMID, 0) == -1)
#endif
2004-04-29 00:36:29 +02:00
printf("\n***Error trying to drop %s semaphores. ERRNO = %d.\n",
2001-05-23 15:26:42 +02:00
label, errno);
else
2004-04-29 00:36:29 +02:00
printf("Successfully removed %s semaphores.\n", label);
2001-05-23 15:26:42 +02:00
}
#endif
static int sem_exclusive( SLONG key, SLONG count)
{
/**************************************
*
* s e m _ e x c l u s i v e
*
**************************************
*
* Functional description
* Check to see if we are the only ones accessing
* semaphores. Return a semaphore id if so,
* -1 otherwise.
*
**************************************/
int semid;
#if !(defined sun || defined LINUX || defined FREEBSD || defined NETBSD || defined SINIXZ)
2001-05-23 15:26:42 +02:00
return semget(key, (int) count, IPC_EXCL);
#else
if ((semid = semget(key, (int) count, IPC_EXCL)) != -1)
return semid;
else
return semget(key, (int) count, IPC_EXCL | IPC_CREAT);
#endif
}
#ifndef HAVE_MMAP
2001-05-23 15:26:42 +02:00
static int shm_exclusive( SLONG key, SLONG length)
{
/**************************************
*
* s h m _ e x c l u s i v e
*
**************************************
*
* Functional description
* Check to see if we are the only ones accessing
* shared memory. Return a shared memory id
* if so, -1 otherwise.
*
**************************************/
struct shmid_ds buf;
const int id = shmget(key, (int) length, IPC_ALLOC);
if (id == -1 ||
2001-05-23 15:26:42 +02:00
shmctl(id, IPC_STAT, &buf) == -1 || buf.shm_nattch != 1)
{
2001-05-23 15:26:42 +02:00
return -1;
}
2001-05-23 15:26:42 +02:00
return id;
}
#endif
#ifdef MANAGER_PROCESS
static void shut_manager(const TEXT* label)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s h u t _ m a n a g e r
*
**************************************
*
* Functional description
* Shut down the lock manager process preparatory
* to releasing shared resources.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
SLONG owner_handle;
2001-05-23 15:26:42 +02:00
if (!(strcmp(label, "lock manager"))) {
owner_handle = 0;
LOCK_init(status_vector, false, getpid(), 0, &owner_handle);
2001-05-23 15:26:42 +02:00
/* In case if lock manager is not running, LOCK_init starts it.
It takes time for the manager to be started, hence immediately
following LOCK_shut_manager can not shut it down, because there is
no manager running yet. To avoid this situation sleep for
a second before calling LOCK_shut_manager */
sleep(1);
LOCK_shut_manager();
}
}
#endif