summaryrefslogtreecommitdiffstats
path: root/src/libs/zbxsys
diff options
context:
space:
mode:
authorosmiy <osmiy@97f52cf1-0a1b-0410-bd0e-c28be96e8082>2006-12-19 11:43:20 +0000
committerosmiy <osmiy@97f52cf1-0a1b-0410-bd0e-c28be96e8082>2006-12-19 11:43:20 +0000
commita8abf2aa3049bf6234ecc33fe42b82c8020c9b90 (patch)
treedefc9db7ace9ff854226bff56be4e43821998861 /src/libs/zbxsys
parentdafdb98ff917038600eae233c6a447aa82b66953 (diff)
downloadzabbix-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.c227
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
+