backglue.c backover.c ctxcsn.c ldapsync.c frontend.c \
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
- aci.c \
+ aci.c alock.c \
$(@PLAT@_SRCS)
OBJS = main.o globals.o bconfig.o config.o daemon.o \
backglue.o backover.o ctxcsn.o ldapsync.o frontend.o \
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
- aci.o \
+ aci.o alock.o \
$(@PLAT@_OBJS)
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
--- /dev/null
+/* alock.c - access lock library */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2005 The OpenLDAP Foundation.
+ * Portions Copyright 2004-2005 Symas Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was initially developed by Matthew Backes at Symas
+ * Corporation for inclusion in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#if SLAPD_BDB || SLAPD_HDB
+
+#include "alock.h"
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/errno.h>
+#include <ac/assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
+#ifdef _WIN32
+#include <stdio.h>
+#include <io.h>
+#include <sys/locking.h>
+#endif
+
+
+static int
+alock_grab_lock ( int fd, int slot )
+{
+ int res;
+
+#if defined( HAVE_LOCKF )
+ res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
+#elif defined( HAVE_FCNTL )
+ struct flock lock_info;
+ (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
+
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
+ lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
+
+ res = fcntl (fd, F_SETLKW, &lock_info);
+#elif defined( _WIN32 )
+ if( _lseek( fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET ) < 0 )
+ return -1;
+ /*
+ * _lock will try for the lock once per second, returning EDEADLOCK
+ * after ten tries. We just loop until we either get the lock
+ * or some other error is returned.
+ */
+ while((res = _locking( fd, _LK_LOCK, ALOCK_SLOT_SIZE )) < 0 ) {
+ if( errno != EDEADLOCK )
+ break;
+ }
+#else
+# error alock needs lockf, fcntl, or _locking
+#endif
+ if (res == -1) {
+ assert (errno != EDEADLK);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+alock_release_lock ( int fd, int slot )
+{
+ int res;
+
+#if defined( HAVE_LOCKF )
+ res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
+ if (res == -1) return -1;
+#elif defined ( HAVE_FCNTL )
+ struct flock lock_info;
+ (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
+
+ lock_info.l_type = F_UNLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
+ lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
+
+ res = fcntl (fd, F_SETLKW, &lock_info);
+ if (res == -1) return -1;
+#elif defined( _WIN32 )
+ res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
+ if (res == -1) return -1;
+#else
+# error alock needs lockf, fcntl, or _locking
+#endif
+
+ return 0;
+}
+
+static int
+alock_test_lock ( int fd, int slot )
+{
+ int res;
+
+#if defined( HAVE_LOCKF )
+ res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+
+ res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
+ if (res == -1) {
+ if (errno == EACCES || errno == EAGAIN) {
+ return ALOCK_LOCKED;
+ } else {
+ return -1;
+ }
+ }
+#elif defined( HAVE_FCNTL )
+ struct flock lock_info;
+ (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
+
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_SET;
+ lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
+ lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
+
+ res = fcntl (fd, F_GETLK, &lock_info);
+ if (res == -1) return -1;
+
+ if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
+#elif defined( _WIN32 )
+ res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
+ if (res == -1) return -1;
+ res = _locking( fd, _LK_NBLCK, ALOCK_SLOT_SIZE );
+ _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
+ if (res == -1) {
+ if( errno == EACCES ) {
+ return ALOCK_LOCKED;
+ } else {
+ return -1;
+ }
+ }
+#else
+# error alock needs lockf, fcntl, or _locking
+#endif
+
+ return 0;
+}
+
+/* Read a 64bit LE value */
+static unsigned long int
+alock_read_iattr ( unsigned char * bufptr )
+{
+ unsigned long int val = 0;
+ int count;
+
+ assert (bufptr != NULL);
+
+ bufptr += sizeof (unsigned long int);
+ for (count=0; count <= sizeof (unsigned long int); ++count) {
+ val <<= 8;
+ val += (unsigned long int) *bufptr--;
+ }
+
+ return val;
+}
+
+/* Write a 64bit LE value */
+static void
+alock_write_iattr ( unsigned char * bufptr,
+ unsigned long int val )
+{
+ int count;
+
+ assert (bufptr != NULL);
+
+ for (count=0; count < 8; ++count) {
+ *bufptr++ = (unsigned char) (val & 0xff);
+ val >>= 8;
+ }
+}
+
+static int
+alock_read_slot ( alock_info_t * info,
+ alock_slot_t * slot_data )
+{
+ unsigned char slotbuf [ALOCK_SLOT_SIZE];
+ int res, size, size_total, err;
+
+ assert (info != NULL);
+ assert (slot_data != NULL);
+ assert (info->al_slot > 0);
+
+ res = lseek (info->al_fd,
+ (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
+ SEEK_SET);
+ if (res == -1) return -1;
+
+ size_total = 0;
+ while (size_total < ALOCK_SLOT_SIZE) {
+ size = read (info->al_fd,
+ slotbuf + size_total,
+ ALOCK_SLOT_SIZE - size_total);
+ if (size == 0) return -1;
+ if (size < 0) {
+ err = errno;
+ if (err != EINTR && err != EAGAIN) return -1;
+ } else {
+ size_total += size;
+ }
+ }
+
+ if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
+ return 1;
+ }
+ slot_data->al_lock = alock_read_iattr (slotbuf+8);
+ slot_data->al_stamp = alock_read_iattr (slotbuf+16);
+ slot_data->al_pid = alock_read_iattr (slotbuf+24);
+
+ if (slot_data->al_appname) free (slot_data->al_appname);
+ slot_data->al_appname = calloc (1, ALOCK_MAX_APPNAME);
+ strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
+ (slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
+
+ return 0;
+}
+
+static int
+alock_write_slot ( alock_info_t * info,
+ alock_slot_t * slot_data )
+{
+ unsigned char slotbuf [ALOCK_SLOT_SIZE];
+ int res, size, size_total, err;
+
+ assert (info != NULL);
+ assert (slot_data != NULL);
+ assert (info->al_slot > 0);
+
+ (void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
+
+ alock_write_iattr (slotbuf, ALOCK_MAGIC);
+ assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
+ alock_write_iattr (slotbuf+8, slot_data->al_lock);
+ alock_write_iattr (slotbuf+16, slot_data->al_stamp);
+ alock_write_iattr (slotbuf+24, slot_data->al_pid);
+
+ strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
+ slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
+
+ res = lseek (info->al_fd,
+ (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
+ SEEK_SET);
+ if (res == -1) return -1;
+
+ size_total = 0;
+ while (size_total < ALOCK_SLOT_SIZE) {
+ size = write (info->al_fd,
+ slotbuf + size_total,
+ ALOCK_SLOT_SIZE - size_total);
+ if (size == 0) return -1;
+ if (size < 0) {
+ err = errno;
+ if (err != EINTR && err != EAGAIN) return -1;
+ } else {
+ size_total += size;
+ }
+ }
+
+ return 0;
+}
+
+static int
+alock_query_slot ( alock_info_t * info )
+{
+ int res;
+ alock_slot_t slot_data;
+
+ assert (info != NULL);
+ assert (info->al_slot > 0);
+
+ (void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
+ alock_read_slot (info, &slot_data);
+
+ if (slot_data.al_appname != NULL) free (slot_data.al_appname);
+ slot_data.al_appname = NULL;
+
+ if (slot_data.al_lock == ALOCK_UNLOCKED) return ALOCK_UNLOCKED;
+
+ res = alock_test_lock (info->al_fd, info->al_slot);
+ if (res < 0) return -1;
+ if (res > 0) {
+ if (slot_data.al_lock == ALOCK_UNIQUE) {
+ return ALOCK_UNIQUE;
+ } else {
+ return ALOCK_LOCKED;
+ }
+ }
+
+ return ALOCK_DIRTY;
+}
+
+int
+alock_open ( alock_info_t * info,
+ const char * appname,
+ const char * envdir,
+ int locktype )
+{
+ struct stat statbuf;
+ alock_info_t scan_info;
+ alock_slot_t slot_data;
+ char * filename;
+ int res, max_slot;
+ int dirty_count, live_count;
+
+ assert (info != NULL);
+ assert (appname != NULL);
+ assert (envdir != NULL);
+ assert (locktype >= 1 && locktype <= 2);
+
+ slot_data.al_lock = locktype;
+ slot_data.al_stamp = time(NULL);
+ slot_data.al_pid = getpid();
+ slot_data.al_appname = calloc (1, ALOCK_MAX_APPNAME);
+ strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
+ slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
+
+ filename = calloc (1, strlen (envdir) + strlen ("/alock") + 1);
+ strcpy (filename, envdir);
+ strcat (filename, "/alock");
+ info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
+ free (filename);
+ if (info->al_fd < 0) {
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ info->al_slot = 0;
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = fstat (info->al_fd, &statbuf);
+ if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+
+ max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
+ dirty_count = 0;
+ live_count = 0;
+ scan_info.al_fd = info->al_fd;
+ for (scan_info.al_slot = 1;
+ scan_info.al_slot < max_slot;
+ ++ scan_info.al_slot) {
+ if (scan_info.al_slot != info->al_slot) {
+ res = alock_query_slot (&scan_info);
+
+ if (res == ALOCK_UNLOCKED
+ && info->al_slot == 0) {
+ info->al_slot = scan_info.al_slot;
+
+ } else if (res == ALOCK_LOCKED) {
+ ++live_count;
+
+ } else if (res == ALOCK_UNIQUE
+ && locktype == ALOCK_UNIQUE) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_BUSY;
+
+ } else if (res == ALOCK_DIRTY) {
+ ++dirty_count;
+
+ } else if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+
+ }
+ }
+ }
+
+ if (dirty_count && live_count) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+
+ if (info->al_slot == 0) info->al_slot = max_slot + 1;
+ res = alock_grab_lock (info->al_fd,
+ info->al_slot);
+ if (res == -1) {
+ close (info->al_fd);
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ res = alock_write_slot (info, &slot_data);
+ free (slot_data.al_appname);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ if (dirty_count) return ALOCK_RECOVER;
+ return ALOCK_CLEAN;
+}
+
+int
+alock_scan ( alock_info_t * info )
+{
+ struct stat statbuf;
+ alock_info_t scan_info;
+ int res, max_slot;
+ int dirty_count, live_count;
+
+ assert (info != NULL);
+
+ scan_info.al_fd = info->al_fd;
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = fstat (info->al_fd, &statbuf);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
+ dirty_count = 0;
+ live_count = 0;
+ for (scan_info.al_slot = 1;
+ scan_info.al_slot < max_slot;
+ ++ scan_info.al_slot) {
+ if (scan_info.al_slot != info->al_slot) {
+ res = alock_query_slot (&scan_info);
+
+ if (res == ALOCK_LOCKED) {
+ ++live_count;
+
+ } else if (res == ALOCK_DIRTY) {
+ ++dirty_count;
+
+ } else if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+
+ }
+ }
+ }
+
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ if (dirty_count) {
+ if (live_count) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ } else {
+ return ALOCK_RECOVER;
+ }
+ }
+
+ return ALOCK_CLEAN;
+}
+
+int
+alock_close ( alock_info_t * info )
+{
+ alock_slot_t slot_data;
+ int res;
+
+ (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ /* mark our slot as clean */
+ res = alock_read_slot (info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ if (slot_data.al_appname != NULL)
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ slot_data.al_lock = ALOCK_UNLOCKED;
+ res = alock_write_slot (info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ if (slot_data.al_appname != NULL)
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ if (slot_data.al_appname != NULL) {
+ free (slot_data.al_appname);
+ slot_data.al_appname = NULL;
+ }
+
+ res = alock_release_lock (info->al_fd, info->al_slot);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = close (info->al_fd);
+ if (res == -1) return ALOCK_UNSTABLE;
+
+ return ALOCK_CLEAN;
+}
+
+int
+alock_recover ( alock_info_t * info )
+{
+ struct stat statbuf;
+ alock_slot_t slot_data;
+ alock_info_t scan_info;
+ int res, max_slot;
+
+ assert (info != NULL);
+
+ scan_info.al_fd = info->al_fd;
+
+ (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
+
+ res = alock_grab_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ res = fstat (info->al_fd, &statbuf);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
+ for (scan_info.al_slot = 1;
+ scan_info.al_slot < max_slot;
+ ++ scan_info.al_slot) {
+ if (scan_info.al_slot != info->al_slot) {
+ res = alock_query_slot (&scan_info);
+
+ if (res == ALOCK_LOCKED
+ || res == ALOCK_UNIQUE) {
+ /* recovery attempt on an active db? */
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+
+ } else if (res == ALOCK_DIRTY) {
+ /* mark it clean */
+ res = alock_read_slot (&scan_info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+ slot_data.al_lock = ALOCK_UNLOCKED;
+ res = alock_write_slot (&scan_info, &slot_data);
+ if (res == -1) {
+ close (info->al_fd);
+ if (slot_data.al_appname != NULL)
+ free (slot_data.al_appname);
+ return ALOCK_UNSTABLE;
+ }
+ if (slot_data.al_appname != NULL) {
+ free (slot_data.al_appname);
+ slot_data.al_appname = NULL;
+ }
+
+ } else if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+
+ }
+ }
+ }
+
+ res = alock_release_lock (info->al_fd, 0);
+ if (res == -1) {
+ close (info->al_fd);
+ return ALOCK_UNSTABLE;
+ }
+
+ return ALOCK_CLEAN;
+}
+
+#endif /* SLAPD_BDB || SLAPD_HDB */
extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c \
- nextid.c cache.c trans.c alock.c
+ nextid.c cache.c trans.c
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo \
- nextid.lo cache.lo trans.lo alock.lo
+ nextid.lo cache.lo trans.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
+++ /dev/null
-/* alock.c - access lock library */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Matthew Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#include "portable.h"
-#include "alock.h"
-
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/unistd.h>
-#include <ac/errno.h>
-#include <ac/assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-
-#ifdef _WIN32
-#include <stdio.h>
-#include <io.h>
-#include <sys/locking.h>
-#endif
-
-
-static int
-alock_grab_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = lockf (fd, F_LOCK, (off_t) ALOCK_SLOT_SIZE);
-#elif defined( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_WRLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLKW, &lock_info);
-#elif defined( _WIN32 )
- if( _lseek( fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET ) < 0 )
- return -1;
- /*
- * _lock will try for the lock once per second, returning EDEADLOCK
- * after ten tries. We just loop until we either get the lock
- * or some other error is returned.
- */
- while((res = _locking( fd, _LK_LOCK, ALOCK_SLOT_SIZE )) < 0 ) {
- if( errno != EDEADLOCK )
- break;
- }
-#else
-# error alock needs lockf, fcntl, or _locking
-#endif
- if (res == -1) {
- assert (errno != EDEADLK);
- return -1;
- }
- return 0;
-}
-
-static int
-alock_release_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = lockf (fd, F_ULOCK, (off_t) ALOCK_SLOT_SIZE);
- if (res == -1) return -1;
-#elif defined ( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_UNLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_SETLKW, &lock_info);
- if (res == -1) return -1;
-#elif defined( _WIN32 )
- res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
- if (res == -1) return -1;
-#else
-# error alock needs lockf, fcntl, or _locking
-#endif
-
- return 0;
-}
-
-static int
-alock_test_lock ( int fd, int slot )
-{
- int res;
-
-#if defined( HAVE_LOCKF )
- res = lseek (fd, (off_t) (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
-
- res = lockf (fd, F_TEST, (off_t) ALOCK_SLOT_SIZE);
- if (res == -1) {
- if (errno == EACCES || errno == EAGAIN) {
- return ALOCK_LOCKED;
- } else {
- return -1;
- }
- }
-#elif defined( HAVE_FCNTL )
- struct flock lock_info;
- (void) memset ((void *) &lock_info, 0, sizeof (struct flock));
-
- lock_info.l_type = F_WRLCK;
- lock_info.l_whence = SEEK_SET;
- lock_info.l_start = (off_t) (ALOCK_SLOT_SIZE * slot);
- lock_info.l_len = (off_t) ALOCK_SLOT_SIZE;
-
- res = fcntl (fd, F_GETLK, &lock_info);
- if (res == -1) return -1;
-
- if (lock_info.l_type != F_UNLCK) return ALOCK_LOCKED;
-#elif defined( _WIN32 )
- res = _lseek (fd, (ALOCK_SLOT_SIZE * slot), SEEK_SET);
- if (res == -1) return -1;
- res = _locking( fd, _LK_NBLCK, ALOCK_SLOT_SIZE );
- _locking( fd, _LK_UNLCK, ALOCK_SLOT_SIZE );
- if (res == -1) {
- if( errno == EACCES ) {
- return ALOCK_LOCKED;
- } else {
- return -1;
- }
- }
-#else
-# error alock needs lockf, fcntl, or _locking
-#endif
-
- return 0;
-}
-
-/* Read a 64bit LE value */
-static unsigned long int
-alock_read_iattr ( unsigned char * bufptr )
-{
- unsigned long int val = 0;
- int count;
-
- assert (bufptr != NULL);
-
- bufptr += sizeof (unsigned long int);
- for (count=0; count <= sizeof (unsigned long int); ++count) {
- val <<= 8;
- val += (unsigned long int) *bufptr--;
- }
-
- return val;
-}
-
-/* Write a 64bit LE value */
-static void
-alock_write_iattr ( unsigned char * bufptr,
- unsigned long int val )
-{
- int count;
-
- assert (bufptr != NULL);
-
- for (count=0; count < 8; ++count) {
- *bufptr++ = (unsigned char) (val & 0xff);
- val >>= 8;
- }
-}
-
-static int
-alock_read_slot ( alock_info_t * info,
- alock_slot_t * slot_data )
-{
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
- int res, size, size_total, err;
-
- assert (info != NULL);
- assert (slot_data != NULL);
- assert (info->al_slot > 0);
-
- res = lseek (info->al_fd,
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
- SEEK_SET);
- if (res == -1) return -1;
-
- size_total = 0;
- while (size_total < ALOCK_SLOT_SIZE) {
- size = read (info->al_fd,
- slotbuf + size_total,
- ALOCK_SLOT_SIZE - size_total);
- if (size == 0) return -1;
- if (size < 0) {
- err = errno;
- if (err != EINTR && err != EAGAIN) return -1;
- } else {
- size_total += size;
- }
- }
-
- if (alock_read_iattr (slotbuf) != ALOCK_MAGIC) {
- return 1;
- }
- slot_data->al_lock = alock_read_iattr (slotbuf+8);
- slot_data->al_stamp = alock_read_iattr (slotbuf+16);
- slot_data->al_pid = alock_read_iattr (slotbuf+24);
-
- if (slot_data->al_appname) free (slot_data->al_appname);
- slot_data->al_appname = calloc (1, ALOCK_MAX_APPNAME);
- strncpy (slot_data->al_appname, (char *)slotbuf+32, ALOCK_MAX_APPNAME-1);
- (slot_data->al_appname) [ALOCK_MAX_APPNAME-1] = '\0';
-
- return 0;
-}
-
-static int
-alock_write_slot ( alock_info_t * info,
- alock_slot_t * slot_data )
-{
- unsigned char slotbuf [ALOCK_SLOT_SIZE];
- int res, size, size_total, err;
-
- assert (info != NULL);
- assert (slot_data != NULL);
- assert (info->al_slot > 0);
-
- (void) memset ((void *) slotbuf, 0, ALOCK_SLOT_SIZE);
-
- alock_write_iattr (slotbuf, ALOCK_MAGIC);
- assert (alock_read_iattr (slotbuf) == ALOCK_MAGIC);
- alock_write_iattr (slotbuf+8, slot_data->al_lock);
- alock_write_iattr (slotbuf+16, slot_data->al_stamp);
- alock_write_iattr (slotbuf+24, slot_data->al_pid);
-
- strncpy ((char *)slotbuf+32, slot_data->al_appname, ALOCK_MAX_APPNAME-1);
- slotbuf[ALOCK_SLOT_SIZE-1] = '\0';
-
- res = lseek (info->al_fd,
- (off_t) (ALOCK_SLOT_SIZE * info->al_slot),
- SEEK_SET);
- if (res == -1) return -1;
-
- size_total = 0;
- while (size_total < ALOCK_SLOT_SIZE) {
- size = write (info->al_fd,
- slotbuf + size_total,
- ALOCK_SLOT_SIZE - size_total);
- if (size == 0) return -1;
- if (size < 0) {
- err = errno;
- if (err != EINTR && err != EAGAIN) return -1;
- } else {
- size_total += size;
- }
- }
-
- return 0;
-}
-
-static int
-alock_query_slot ( alock_info_t * info )
-{
- int res;
- alock_slot_t slot_data;
-
- assert (info != NULL);
- assert (info->al_slot > 0);
-
- (void) memset ((void *) &slot_data, 0, sizeof (alock_slot_t));
- alock_read_slot (info, &slot_data);
-
- if (slot_data.al_appname != NULL) free (slot_data.al_appname);
- slot_data.al_appname = NULL;
-
- if (slot_data.al_lock == ALOCK_UNLOCKED) return ALOCK_UNLOCKED;
-
- res = alock_test_lock (info->al_fd, info->al_slot);
- if (res < 0) return -1;
- if (res > 0) {
- if (slot_data.al_lock == ALOCK_UNIQUE) {
- return ALOCK_UNIQUE;
- } else {
- return ALOCK_LOCKED;
- }
- }
-
- return ALOCK_DIRTY;
-}
-
-int
-alock_open ( alock_info_t * info,
- const char * appname,
- const char * envdir,
- int locktype )
-{
- struct stat statbuf;
- alock_info_t scan_info;
- alock_slot_t slot_data;
- char * filename;
- int res, max_slot;
- int dirty_count, live_count;
-
- assert (info != NULL);
- assert (appname != NULL);
- assert (envdir != NULL);
- assert (locktype >= 1 && locktype <= 2);
-
- slot_data.al_lock = locktype;
- slot_data.al_stamp = time(NULL);
- slot_data.al_pid = getpid();
- slot_data.al_appname = calloc (1, ALOCK_MAX_APPNAME);
- strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
- slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';
-
- filename = calloc (1, strlen (envdir) + strlen ("/alock") + 1);
- strcpy (filename, envdir);
- strcat (filename, "/alock");
- info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
- free (filename);
- if (info->al_fd < 0) {
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- info->al_slot = 0;
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- dirty_count = 0;
- live_count = 0;
- scan_info.al_fd = info->al_fd;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res == ALOCK_UNLOCKED
- && info->al_slot == 0) {
- info->al_slot = scan_info.al_slot;
-
- } else if (res == ALOCK_LOCKED) {
- ++live_count;
-
- } else if (res == ALOCK_UNIQUE
- && locktype == ALOCK_UNIQUE) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_BUSY;
-
- } else if (res == ALOCK_DIRTY) {
- ++dirty_count;
-
- } else if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- if (dirty_count && live_count) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
-
- if (info->al_slot == 0) info->al_slot = max_slot + 1;
- res = alock_grab_lock (info->al_fd,
- info->al_slot);
- if (res == -1) {
- close (info->al_fd);
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- res = alock_write_slot (info, &slot_data);
- free (slot_data.al_appname);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- if (dirty_count) return ALOCK_RECOVER;
- return ALOCK_CLEAN;
-}
-
-int
-alock_scan ( alock_info_t * info )
-{
- struct stat statbuf;
- alock_info_t scan_info;
- int res, max_slot;
- int dirty_count, live_count;
-
- assert (info != NULL);
-
- scan_info.al_fd = info->al_fd;
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- dirty_count = 0;
- live_count = 0;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res == ALOCK_LOCKED) {
- ++live_count;
-
- } else if (res == ALOCK_DIRTY) {
- ++dirty_count;
-
- } else if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- if (dirty_count) {
- if (live_count) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- } else {
- return ALOCK_RECOVER;
- }
- }
-
- return ALOCK_CLEAN;
-}
-
-int
-alock_close ( alock_info_t * info )
-{
- alock_slot_t slot_data;
- int res;
-
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- /* mark our slot as clean */
- res = alock_read_slot (info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- if (slot_data.al_appname != NULL)
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- slot_data.al_lock = ALOCK_UNLOCKED;
- res = alock_write_slot (info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- if (slot_data.al_appname != NULL)
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- if (slot_data.al_appname != NULL) {
- free (slot_data.al_appname);
- slot_data.al_appname = NULL;
- }
-
- res = alock_release_lock (info->al_fd, info->al_slot);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = close (info->al_fd);
- if (res == -1) return ALOCK_UNSTABLE;
-
- return ALOCK_CLEAN;
-}
-
-int
-alock_recover ( alock_info_t * info )
-{
- struct stat statbuf;
- alock_slot_t slot_data;
- alock_info_t scan_info;
- int res, max_slot;
-
- assert (info != NULL);
-
- scan_info.al_fd = info->al_fd;
-
- (void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));
-
- res = alock_grab_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- res = fstat (info->al_fd, &statbuf);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
- for (scan_info.al_slot = 1;
- scan_info.al_slot < max_slot;
- ++ scan_info.al_slot) {
- if (scan_info.al_slot != info->al_slot) {
- res = alock_query_slot (&scan_info);
-
- if (res == ALOCK_LOCKED
- || res == ALOCK_UNIQUE) {
- /* recovery attempt on an active db? */
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- } else if (res == ALOCK_DIRTY) {
- /* mark it clean */
- res = alock_read_slot (&scan_info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
- slot_data.al_lock = ALOCK_UNLOCKED;
- res = alock_write_slot (&scan_info, &slot_data);
- if (res == -1) {
- close (info->al_fd);
- if (slot_data.al_appname != NULL)
- free (slot_data.al_appname);
- return ALOCK_UNSTABLE;
- }
- if (slot_data.al_appname != NULL) {
- free (slot_data.al_appname);
- slot_data.al_appname = NULL;
- }
-
- } else if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
-
- }
- }
- }
-
- res = alock_release_lock (info->al_fd, 0);
- if (res == -1) {
- close (info->al_fd);
- return ALOCK_UNSTABLE;
- }
-
- return ALOCK_CLEAN;
-}
+++ /dev/null
-/* alock.h - access lock header */
-/* $OpenLDAP$ */
-/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
- *
- * Copyright 2005 The OpenLDAP Foundation.
- * Portions Copyright 2004-2005 Symas Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-/* ACKNOWLEDGEMENTS:
- * This work was initially developed by Matthew Backes at Symas
- * Corporation for inclusion in OpenLDAP Software.
- */
-
-#ifndef _ALOCK_H_
-#define _ALOCK_H_
-
-#include "portable.h"
-#include <ac/time.h>
-#include <ac/unistd.h>
-
-/* environment states (all the slots together) */
-#define ALOCK_CLEAN (0)
-#define ALOCK_RECOVER (1)
-#define ALOCK_BUSY (2)
-#define ALOCK_UNSTABLE (3)
-
-/* lock user types and states */
-#define ALOCK_UNLOCKED (0)
-#define ALOCK_LOCKED (1)
-#define ALOCK_UNIQUE (2)
-#define ALOCK_DIRTY (3)
-
-/* constants */
-#define ALOCK_SLOT_SIZE (1024)
-#define ALOCK_SLOT_IATTRS (4)
-#define ALOCK_MAX_APPNAME (ALOCK_SLOT_SIZE - 8 * ALOCK_SLOT_IATTRS)
-#define ALOCK_MAGIC (0x12345678)
-
-LDAP_BEGIN_DECL
-
-typedef struct alock_info {
- int al_fd;
- int al_slot;
-} alock_info_t;
-
-typedef struct alock_slot {
- unsigned int al_lock;
- time_t al_stamp;
- pid_t al_pid;
- char * al_appname;
-} alock_slot_t;
-
-extern int alock_open LDAP_P(( alock_info_t * info, const char * appname,
- const char * envdir, int locktype ));
-extern int alock_scan LDAP_P(( alock_info_t * info ));
-extern int alock_close LDAP_P(( alock_info_t * info ));
-extern int alock_recover LDAP_P(( alock_info_t * info ));
-
-LDAP_END_DECL
-
-#endif
XXSRCS = init.c tools.c config.c \
add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
- extended.c referral.c operational.c alock.c \
+ extended.c referral.c operational.c \
attr.c index.c key.c dbcache.c filterindex.c trans.c \
dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c
SRCS = $(XXSRCS)
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
- extended.lo referral.lo operational.lo alock.lo \
+ extended.lo referral.lo operational.lo \
attr.lo index.lo key.lo dbcache.lo filterindex.lo trans.lo \
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo