]> git.sur5r.net Git - openldap/commitdiff
ITS#3978 move alock from back-bdb to slapd
authorHoward Chu <hyc@openldap.org>
Sun, 4 Sep 2005 15:21:57 +0000 (15:21 +0000)
committerHoward Chu <hyc@openldap.org>
Sun, 4 Sep 2005 15:21:57 +0000 (15:21 +0000)
servers/slapd/Makefile.in
servers/slapd/alock.c [new file with mode: 0644]
servers/slapd/back-bdb/Makefile.in
servers/slapd/back-bdb/alock.c [deleted file]
servers/slapd/back-bdb/alock.h [deleted file]
servers/slapd/back-hdb/Makefile.in

index 46ee8dac699793b90bffe8759556c950cb498046..003706cfa2dfc063cd8ef150cb7e792518f395be 100644 (file)
@@ -38,7 +38,7 @@ SRCS  = main.c globals.c bconfig.c config.c daemon.c \
                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 \
@@ -56,7 +56,7 @@ 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.
diff --git a/servers/slapd/alock.c b/servers/slapd/alock.c
new file mode 100644 (file)
index 0000000..cf90f9b
--- /dev/null
@@ -0,0 +1,629 @@
+/* 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 */
index 0eeb6a75cd56ceaba58e2bc303a7943c5ebc3f24..f439138a523a89bcc42706659835b1ac117fd1eb 100644 (file)
@@ -18,14 +18,14 @@ SRCS = init.c tools.c config.c \
        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
diff --git a/servers/slapd/back-bdb/alock.c b/servers/slapd/back-bdb/alock.c
deleted file mode 100644 (file)
index 92fc243..0000000
+++ /dev/null
@@ -1,624 +0,0 @@
-/* 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;
-}
diff --git a/servers/slapd/back-bdb/alock.h b/servers/slapd/back-bdb/alock.h
deleted file mode 100644 (file)
index 902077d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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
index 854e5c3b5411a3c8a9cdb5fdc39d3691a707fe08..e7fa1e7ec330d23aa30f663dc60f33d30bc6ae7e 100644 (file)
@@ -19,13 +19,13 @@ XXDIR = $(srcdir)/../back-bdb
 
 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