From: Howard Chu Date: Sun, 4 Sep 2005 15:21:57 +0000 (+0000) Subject: ITS#3978 move alock from back-bdb to slapd X-Git-Tag: OPENLDAP_REL_ENG_2_2_MP~494 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=464fc6b68abab64cd09430b4b8fd3c7034452330;p=openldap ITS#3978 move alock from back-bdb to slapd --- diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 46ee8dac69..003706cfa2 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -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 index 0000000000..cf90f9b946 --- /dev/null +++ b/servers/slapd/alock.c @@ -0,0 +1,629 @@ +/* alock.c - access lock library */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * 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 + * . + */ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#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 */ diff --git a/servers/slapd/back-bdb/Makefile.in b/servers/slapd/back-bdb/Makefile.in index 0eeb6a75cd..f439138a52 100644 --- a/servers/slapd/back-bdb/Makefile.in +++ b/servers/slapd/back-bdb/Makefile.in @@ -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 index 92fc243edc..0000000000 --- a/servers/slapd/back-bdb/alock.c +++ /dev/null @@ -1,624 +0,0 @@ -/* alock.c - access lock library */ -/* $OpenLDAP$ */ -/* This work is part of OpenLDAP Software . - * - * 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 - * . - */ -/* ACKNOWLEDGEMENTS: - * This work was initially developed by Matthew Backes at Symas - * Corporation for inclusion in OpenLDAP Software. - */ - -#include "portable.h" -#include "alock.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#include -#include -#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 index 902077de96..0000000000 --- a/servers/slapd/back-bdb/alock.h +++ /dev/null @@ -1,69 +0,0 @@ -/* alock.h - access lock header */ -/* $OpenLDAP$ */ -/* This work is part of OpenLDAP Software . - * - * 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 - * . - */ -/* 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 -#include - -/* 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 diff --git a/servers/slapd/back-hdb/Makefile.in b/servers/slapd/back-hdb/Makefile.in index 854e5c3b54..e7fa1e7ec3 100644 --- a/servers/slapd/back-hdb/Makefile.in +++ b/servers/slapd/back-hdb/Makefile.in @@ -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