diff options
| author | osmiy <osmiy@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2006-12-19 11:43:20 +0000 |
|---|---|---|
| committer | osmiy <osmiy@97f52cf1-0a1b-0410-bd0e-c28be96e8082> | 2006-12-19 11:43:20 +0000 |
| commit | a8abf2aa3049bf6234ecc33fe42b82c8020c9b90 (patch) | |
| tree | defc9db7ace9ff854226bff56be4e43821998861 /src/libs/zbxsys | |
| parent | dafdb98ff917038600eae233c6a447aa82b66953 (diff) | |
| download | zabbix-a8abf2aa3049bf6234ecc33fe42b82c8020c9b90.tar.gz zabbix-a8abf2aa3049bf6234ecc33fe42b82c8020c9b90.tar.xz zabbix-a8abf2aa3049bf6234ecc33fe42b82c8020c9b90.zip | |
- improved sqlite3 database support [TEST VERSION] (Eugene)
git-svn-id: svn://svn.zabbix.com/trunk@3607 97f52cf1-0a1b-0410-bd0e-c28be96e8082
Diffstat (limited to 'src/libs/zbxsys')
| -rw-r--r-- | src/libs/zbxsys/mutexs.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/libs/zbxsys/mutexs.c b/src/libs/zbxsys/mutexs.c index 3784bf8f..56232237 100644 --- a/src/libs/zbxsys/mutexs.c +++ b/src/libs/zbxsys/mutexs.c @@ -269,3 +269,230 @@ int zbx_mutex_destroy(ZBX_MUTEX *mutex) return ZBX_MUTEX_OK; } + +#if defined(HAVE_SQLITE3) && !defined(_WINDOWS) + +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2006 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Tom May <tom@go2net.com> | + | Gavin Sherry <gavin@linuxworld.com.au> | + +----------------------------------------------------------------------+ + */ + +/* Semaphore functions using System V semaphores. Each semaphore + * actually consists of three semaphores allocated as a unit under the + * same key. Semaphore 0 (SYSVSEM_SEM) is the actual semaphore, it is + * initialized to max_acquire and decremented as processes acquire it. + * The value of semaphore 1 (SYSVSEM_USAGE) is a count of the number + * of processes using the semaphore. After calling semget(), if a + * process finds that the usage count is 1, it will set the value of + * SYSVSEM_SEM to max_acquire. This allows max_acquire to be set and + * track the PHP code without having a global init routine or external + * semaphore init code. Except see the bug regarding a race condition + * php_sysvsem_get(). Semaphore 2 (SYSVSEM_SETVAL) serializes the + * calls to GETVAL SYSVSEM_USAGE and SETVAL SYSVSEM_SEM. It can be + * acquired only when it is zero. + */ + +#define SYSVSEM_SEM 0 +#define SYSVSEM_USAGE 1 +#define SYSVSEM_SETVAL 2 + +int php_sem_get(ZBX_MUTEX* sem_ptr, char* path_name) +{ + int + key, + max_acquire = 1, + count; + + key_t sem_key; + + ZBX_MUTEX semid; + + struct sembuf sop[3]; + + assert(sem_ptr); + assert(path_name); + + *sem_ptr = 0; + + if( -1 == (sem_key = ftok(path_name, (int)'z') )) + { + zbx_error("Can not create IPC key for path '%s', try to create for path '.' [%s]", path_name, strerror(errno)); + if( -1 == (sem_key = ftok(".", (int)'z') )) + { + zbx_error("Can not create IPC key for path '.' [%s]", strerror(errno)); + return ZBX_MUTEX_ERROR; + } + } + + /* Get/create the semaphore. Note that we rely on the semaphores + * being zeroed when they are created. Despite the fact that + * the(?) Linux semget() man page says they are not initialized, + * the kernel versions 2.0.x and 2.1.z do in fact zero them. + */ + + semid = semget(sem_key, 3, 0666 | IPC_CREAT); + if (semid == -1) { + zbx_error("failed for key 0x%lx: %s", key, strerror(errno)); + return ZBX_MUTEX_ERROR; + } + + /* Find out how many processes are using this semaphore. Note + * that on Linux (at least) there is a race condition here because + * semaphore undo on process exit is not atomic, so we could + * acquire SYSVSEM_SETVAL before a crashed process has decremented + * SYSVSEM_USAGE in which case count will be greater than it + * should be and we won't set max_acquire. Fortunately this + * doesn't actually matter in practice. + */ + + /* Wait for sem 1 to be zero . . . */ + + sop[0].sem_num = SYSVSEM_SETVAL; + sop[0].sem_op = 0; + sop[0].sem_flg = 0; + + /* . . . and increment it so it becomes non-zero . . . */ + + sop[1].sem_num = SYSVSEM_SETVAL; + sop[1].sem_op = 1; + sop[1].sem_flg = SEM_UNDO; + + /* . . . and increment the usage count. */ + + sop[2].sem_num = SYSVSEM_USAGE; + sop[2].sem_op = 1; + sop[2].sem_flg = SEM_UNDO; + while (semop(semid, sop, 3) == -1) { + if (errno != EINTR) { + zbx_error("failed acquiring SYSVSEM_SETVAL for key 0x%lx: %s", key, strerror(errno)); + break; + } + } + + /* Get the usage count. */ + count = semctl(semid, SYSVSEM_USAGE, GETVAL, NULL); + if (count == -1) { + zbx_error("failed for key 0x%lx: %s", key, strerror(errno)); + } + + /* If we are the only user, then take this opportunity to set the max. */ + + if (count == 1) { + /* This is correct for Linux which has union semun. */ + union semun semarg; + semarg.val = max_acquire; + if (semctl(semid, SYSVSEM_SEM, SETVAL, semarg) == -1) { + zbx_error("failed for key 0x%lx: %s", key, strerror(errno)); + } + } + + /* Set semaphore 1 back to zero. */ + + sop[0].sem_num = SYSVSEM_SETVAL; + sop[0].sem_op = -1; + sop[0].sem_flg = SEM_UNDO; + while (semop(semid, sop, 1) == -1) { + if (errno != EINTR) { + zbx_error("failed releasing SYSVSEM_SETVAL for key 0x%lx: %s", key, strerror(errno)); + break; + } + } + + *sem_ptr = semid; + + return ZBX_MUTEX_OK; +} + +static int php_sysvsem_semop(ZBX_MUTEX* sem_ptr, int acquire) +{ + struct sembuf sop; + + assert(sem_ptr); + + if(!*sem_ptr) return ZBX_MUTEX_OK; + + sop.sem_num = SYSVSEM_SEM; + sop.sem_op = acquire ? -1 : 1; + sop.sem_flg = SEM_UNDO; + + while (semop(*sem_ptr, &sop, 1) == -1) { + if (errno != EINTR) { + zbx_error("failed to %s semaphore (id 0x%d): %s", acquire ? "acquire" : "release", *sem_ptr, strerror(errno)); + return ZBX_MUTEX_ERROR; + } + } + + return ZBX_MUTEX_OK; +} + +int php_sem_acquire(ZBX_MUTEX* sem_ptr) +{ + return php_sysvsem_semop(sem_ptr, 1); +} + +int php_sem_release(ZBX_MUTEX* sem_ptr) +{ + return php_sysvsem_semop(sem_ptr, 0); +} + +int php_sem_remove(ZBX_MUTEX* sem_ptr) +{ + union semun un; + struct semid_ds buf; + struct sembuf sop; + + + assert(sem_ptr); + + if(!*sem_ptr) return ZBX_MUTEX_OK; + + /* Decrement the usage count. */ + + sop.sem_num = SYSVSEM_USAGE; + sop.sem_op = -1; + sop.sem_flg = SEM_UNDO; + + if (semop(*sem_ptr, &sop, 1) == -1) { + zbx_error("failed in php_sem_remove for (id 0x%x): %s", *sem_ptr, strerror(errno)); + return ZBX_MUTEX_ERROR; + } + + un.buf = &buf; + if (semctl(*sem_ptr, 0, IPC_STAT, un) < 0) { + zbx_error("SysV semaphore (id 0x%x) does not (any longer) exist", *sem_ptr); + return ZBX_MUTEX_ERROR; + } + + if (semctl(*sem_ptr, 0, IPC_RMID, un) < 0) { + zbx_error("failed for SysV sempphore (id 0x%x): %s", *sem_ptr, strerror(errno)); + return ZBX_MUTEX_ERROR; + } + + *sem_ptr = 0; + + return ZBX_MUTEX_OK; +} + +#else // !HAVE_SQLITE3 || _WINDOWS + +int php_sem_get(ZBX_MUTEX* sem_ptr, char* path_name); { return ZBX_MUTEX_OK; } +int php_sem_acquire(ZBX_MUTEX* sem_ptr); { return ZBX_MUTEX_OK; } +int php_sem_release(ZBX_MUTEX* sem_ptr); { return ZBX_MUTEX_OK; } +int php_sem_remove(ZBX_MUTEX* sem_ptr) { return ZBX_MUTEX_OK; } + +#endif // HAVE_SQLITE3 && !_WINDOWS + |
